note description: "API interface to workitem services." author: "Peter Wyss " date: "$Date$" revision: "$Revision$" class WORKITEM_SERVICE inherit API_SERVICE O_PROJECT_CONSTANTS create make feature -- Basic operations workitem_count (a_session: STRING; a_project_id_list: ARRAY[ANY]; a_unread_only: BOOLEAN_REF; a_filter_type: INTEGER_REF): INTEGER_REF -- Returns the number of workitems for the user. local l_msg: O_WORKITEM_COUNT_MESSAGE l_reply: O_WORKITEM_COUNT_REPLY_MESSAGE i: INTEGER l_int: INTEGER_REF l_list: ARRAY[A_INTEGER_VALUE] do -- argument validiation check_anonymous_session (a_session) if not is_valid_session (a_session) then last_fault := err_invalid_session else create l_list.make (a_project_id_list.lower, a_project_id_list.upper) from i := a_project_id_list.lower until i > a_project_id_list.count loop l_int ?= a_project_id_list.item (i) if l_int /= Void then l_list.force (l_int.item, i) end -- Increment i := i + 1 end create l_msg.make (a_session, l_list, a_unread_only.item, a_filter_type.item) send_and_wait_for_reply (l_msg) if is_ok then l_reply ?= last_reply check reply_ok: l_reply /= Void end create Result Result.set_item (l_reply.workitem_count) end end end workitem_list (a_session: STRING; a_project_id_list: ARRAY[ANY]; a_unread_only: BOOLEAN_REF; a_filter_type: INTEGER_REF; a_start: INTEGER_REF; a_limit: INTEGER_REF; a_sort_column: STRING; a_sort_order: STRING): ARRAY [DS_HASH_TABLE [ANY, STRING]] -- List max a_limit (unread) workitems for session user local l_msg: O_WORKITEM_LIST_MESSAGE l_workitem_list_reply_msg: O_WORKITEM_LIST_REPLY_MESSAGE l_list: DS_ARRAYED_LIST [A_INTEGER_VALUE] i: INTEGER l_int: INTEGER_REF l_boolean: BOOLEAN_REF a_reply_list: DS_ARRAYED_LIST [O_WORKITEM_WORKITEM_MESSAGE] a_reply_item: O_WORKITEM_WORKITEM_MESSAGE l_ht: DS_HASH_TABLE [ANY, STRING] do -- argument validiation check_anonymous_session (a_session) if not is_valid_session (a_session) then last_fault := err_invalid_session elseif a_filter_type < 0 then last_fault := err_invalid_filter_type elseif a_start < 0 then last_fault := err_invalid_index elseif a_limit <= 0 then last_fault := err_invalid_limit else create l_list.make_default from i := a_project_id_list.lower until i > a_project_id_list.count loop l_int ?= a_project_id_list.item (i) -- Only pass along proper project IDs if l_int /= Void and then l_int > 0 then l_list.force_last (l_int.item) end -- inc i := i + 1 end if l_list.count > 0 then create l_msg.make (a_session, l_list, a_unread_only.item, a_filter_type.item, a_start.item, a_limit.item, a_sort_column, a_sort_order) send_and_wait_for_reply (l_msg) if is_ok then l_workitem_list_reply_msg ?= last_reply check workitem_list_reply_message: l_workitem_list_reply_msg /= Void end a_reply_list := l_workitem_list_reply_msg.workitem_list.sequence create Result.make (1, a_reply_list.count) from a_reply_list.start i := 1 until a_reply_list.after loop a_reply_item := a_reply_list.item_for_iteration create l_ht.make (10) create l_int l_int.set_item (a_reply_item.id) l_ht.force (l_int, "id") create l_int l_int.set_item (a_reply_item.type_id) l_ht.force (l_int, "type_id") create l_int l_int.set_item (a_reply_item.timestamp) l_ht.force (l_int, "timestamp") create l_int l_int.set_item (a_reply_item.project_id) l_ht.force (l_int, "project_id") l_ht.force (a_reply_item.project_name.value, "project_name") create l_int l_int.set_item (a_reply_item.user_id) l_ht.force (l_int, "user_id") l_ht.force (a_reply_item.user_name.value, "user_name") l_ht.force (a_reply_item.ref.value, "reference") l_ht.force (a_reply_item.title.value, "title") create l_boolean l_boolean.set_item (a_reply_item.is_new.value) l_ht.force (l_boolean, "is_new") create l_boolean l_boolean.set_item (a_reply_item.is_read.value) l_ht.force (l_boolean, "is_read") -- Enter into Result array Result.force (l_ht, i) -- Increment a_reply_list.forth i := i + 1 end end else last_fault := err_project_not_found end end end workitem_new_activity (a_session: STRING): ARRAY [INTEGER_REF] -- Retrieves a list of projects, i.e. their ID's, that contain new workitems for a given user local l_msg: O_WORKITEM_NEW_ACTIVITY_MESSAGE l_reply: O_WORKITEM_NEW_ACTIVITY_REPLY_MESSAGE l_int: INTEGER_REF l_list: DS_ARRAYED_LIST [A_INTEGER_VALUE] l_reply_list: DS_ARRAYED_LiST [INTEGER_REF] do -- argument validiation check_anonymous_session (a_session) if not is_valid_session (a_session) then last_fault := err_invalid_session else create l_msg.make (a_session) send_and_wait_for_reply (l_msg) if is_ok then l_reply ?= last_reply check reply_ok: l_reply /= Void end l_list := l_reply.project_id_list.sequence create l_reply_list.make (l_list.count) from l_list.start until l_list.after loop create l_int l_int.set_item (l_list.item_for_iteration) l_reply_list.force_last (l_int) -- Increment l_list.forth end Result := l_reply_list.to_array end end end workitem_retrieve (a_session: STRING; a_workitem_id_list: ARRAY[ANY]): DS_HASH_TABLE [DS_HASH_TABLE [ANY, STRING], STRING] -- Retrieve workitem local l_msg: O_WORKITEM_RETRIEVE_MESSAGE l_workitem_reply_msg: O_WORKITEM_RETRIEVE_REPLY_MESSAGE a_reply_list: DS_ARRAYED_LIST[O_WORKITEM_FULL_WORKITEM_MESSAGE] a_reply_item: O_WORKITEM_FULL_WORKITEM_MESSAGE l_list: ARRAY[A_INTEGER_VALUE] i: INTEGER l_int: INTEGER_REF l_boolean: BOOLEAN_REF l_ht: DS_HASH_TABLE [ANY, STRING] do -- argument validiation if not is_valid_session (a_session) then last_fault := err_invalid_session elseif a_workitem_id_list = Void or else a_workitem_id_list.is_empty then last_fault := err_invalid_workitem else create l_list.make (a_workitem_id_list.lower, a_workitem_id_list.upper) from i := a_workitem_id_list.lower until i > a_workitem_id_list.count loop l_int ?= a_workitem_id_list.item (i) l_list.force (l_int.item, i) -- inc i := i + 1 end create l_msg.make (a_session, create {A_SEQUENCE_VALUE[A_INTEGER_VALUE]}.make_from_array (l_list)) send_and_wait_for_reply (l_msg) if is_ok then l_workitem_reply_msg ?= last_reply check full_workitems_from_storage_node: l_workitem_reply_msg /= Void end a_reply_list := l_workitem_reply_msg.workitem_list.sequence create Result.make (a_reply_list.count) from a_reply_list.start i := 1 until a_reply_list.after loop a_reply_item := a_reply_list.item_for_iteration create l_ht.make (10) create l_int l_int.set_item (a_reply_item.id) l_ht.force (l_int, "id") create l_int l_int.set_item (a_reply_item.type_id) l_ht.force (l_int, "type_id") create l_int l_int.set_item (a_reply_item.timestamp) l_ht.force (l_int, "timestamp") create l_int l_int.set_item (a_reply_item.project_id) l_ht.force (l_int, "project_id") l_ht.force (a_reply_item.project_name.value, "project_name") create l_int l_int.set_item (a_reply_item.user_id) l_ht.force (l_int, "user_id") l_ht.force (a_reply_item.user_name.value, "user_name") l_ht.force (a_reply_item.ref.value, "reference") l_ht.force (a_reply_item.title.value, "title") -- -- Here the extended details begin -- -- Note: these are optional, and depend on the value of "type_id" -- -- As integers aren't nullable, we use 0 (zero) to check for an optional value if a_reply_item.revision /= Void and then not a_reply_item.revision.value.is_equal ("0") then l_ht.force(a_reply_item.revision.value, "revision") end if a_reply_item.previous_revision /= Void and then not a_reply_item.previous_revision.value.is_equal ("0") then l_ht.force(a_reply_item.previous_revision.value, "previous_revision") end if a_reply_item.diff /= Void then l_ht.force (a_reply_item.diff.value, "diff") end if a_reply_item.comment_text /= Void then l_ht.force (a_reply_item.comment_text.value, "comment_text") end if a_reply_item.is_new /= Void then create l_boolean l_boolean.set_item (a_reply_item.is_new) l_ht.force (l_boolean, "is_new") end if a_reply_item.comment_type.value /= 0 then create l_int l_int.set_item (a_reply_item.comment_type) l_ht.force(l_int, "comment_type") end if a_reply_item.log /= Void then l_ht.force (a_reply_item.log.value, "log") end -- Issues (tags, project_issue_id, description, attachments) if a_reply_item.tags /= Void then l_ht.force (convert_issue_tags (a_reply_item.tags.sequence).to_array, "tags") end if a_reply_item.project_issue_id.value /= 0 then create l_int l_int.set_item (a_reply_item.project_issue_id) l_ht.force(l_int, "project_issue_id") end if a_reply_item.deadline.value /= 0 then create l_int l_int.set_item (a_reply_item.deadline) l_ht.force(l_int, "deadline") end if a_reply_item.work_amount.value /= 0 then create l_int l_int.set_item (a_reply_item.work_amount) l_ht.force(l_int, "work_amount") end if a_reply_item.description /= Void then l_ht.force (a_reply_item.description.value, "description") end if a_reply_item.attachments /= Void then l_ht.force (convert_issue_attachments (a_reply_item.attachments.sequence).to_array, "attachments") end -- Release (release_id, release_version, release_description, release_files) if a_reply_item.release_id.value /= 0 then create l_int l_int.set_item (a_reply_item.release_id) l_ht.force(l_int, "release_id") end if a_reply_item.release_version /= Void then l_ht.force (a_reply_item.release_version.value, "release_version") end if a_reply_item.release_description /= Void then l_ht.force (a_reply_item.release_description.value, "release_description") end if a_reply_item.release_files /= Void then l_ht.force (convert_release_files (a_reply_item.release_files.sequence).to_array, "release_files") end -- Wiki if a_reply_item.is_private /= Void then create l_boolean l_boolean.set_item (a_reply_item.is_private) l_ht.force (l_boolean, "is_private") end -- Enter into Result hash-table Result.force (l_ht, l_ht.item ("id").out) -- Increment a_reply_list.forth i := i + 1 end end end end workitem_set_read_status (a_session: STRING; a_workitem: INTEGER_REF; a_read_status: BOOLEAN_REF): BOOLEAN_REF -- Set workitem read status to a_read_status local l_msg: O_WORKITEM_SET_READ_STATUS_MESSAGE do -- argument validiation if not is_valid_session (a_session) then last_fault := err_invalid_session elseif a_workitem <= 0 then last_fault := err_invalid_workitem else -- generate and send message create l_msg.make (create {A_STRING_VALUE}.make (a_session), create {A_INTEGER_VALUE}.make (a_workitem.item), create {A_BOOLEAN_VALUE}.make (a_read_status.item)) send_and_wait_for_reply (l_msg) if is_ok then create Result Result.set_item (True) end end end workitem_set_read_status_project (a_session: STRING; a_project: INTEGER_REF; a_read_status: BOOLEAN_REF): BOOLEAN_REF -- Set workitem read status for a_project to a_read_status local l_msg: O_WORKITEM_SET_READ_STATUS_PROJECT_MESSAGE do -- argument validiation if not is_valid_session (a_session) then last_fault := err_invalid_session elseif a_project <= 0 then last_fault := err_invalid_project else -- generate and send message create l_msg.make (create {A_STRING_VALUE}.make (a_session), create {A_INTEGER_VALUE}.make (a_project.item), create {A_BOOLEAN_VALUE}.make (a_read_status.item)) send_and_wait_for_reply (l_msg) if is_ok then create Result Result.set_item (True) end end end feature -- Creation new_tuple (a_name: STRING): TUPLE -- Tuple of default-valued arguments to pass to call `a_name'. do if a_name.is_equal (workitem_count_name) then create {TUPLE [STRING, ARRAY[ANY], BOOLEAN_REF, INTEGER_REF]}Result elseif a_name.is_equal (workitem_list_name) then create {TUPLE [STRING, ARRAY[ANY], BOOLEAN_REF, INTEGER_REF, INTEGER_REF, INTEGER_REF, STRING, STRING]}Result elseif a_name.is_equal (workitem_new_activity_name) then create {TUPLE [STRING]}Result elseif a_name.is_equal (workitem_retrieve_name) then create {TUPLE [STRING, ARRAY[ANY]]}Result elseif a_name.is_equal (workitem_set_read_status_name) then create {TUPLE [STRING, INTEGER_REF, BOOLEAN_REF]}Result elseif a_name.is_equal (workitem_set_read_status_project_name) then create {TUPLE [STRING, INTEGER_REF, BOOLEAN_REF]}Result end end feature -- Initialisation self_register -- Register all actions for this service do register_with_help (agent workitem_count, workitem_count_name, "Retrieve the number of workitems for a user.") register_with_help (agent workitem_list, workitem_list_name, "Get up to limit (unread) workitems.") register_with_help (agent workitem_new_activity, workitem_new_activity_name, "Retrieves a list of project IDs that contain new workitems for a given user") register_with_help (agent workitem_retrieve, workitem_retrieve_name, "Retrieve workitem with workitem_id.") register_with_help (agent workitem_set_read_status, workitem_set_read_status_name, "Mark workitem with workitem_id as read or unread according to read_status.") register_with_help (agent workitem_set_read_status_project, workitem_set_read_status_project_name, "Mark workitems in project with project_id as read or unread according to read_status.") end feature {NONE} -- Conversion convert_issue_tags (a_tag_list: DS_ARRAYED_LIST[A_STRING_VALUE]): DS_ARRAYED_LIST[STRING] require list_exists: a_tag_list /= Void do create Result.make (a_tag_list.count) from a_tag_list.start until a_tag_list.after loop Result.force_last (a_tag_list.item_for_iteration.value) -- Increment a_tag_list.forth end ensure created: Result /= Void same_count: Result.count = a_tag_list.count end convert_issue_attachments (a_attachment_list: DS_ARRAYED_LIST[O_WORKITEM_ISSUE_ATTACHMENT_MESSAGE]): DS_ARRAYED_LIST [DS_HASH_TABLE [ANY, STRING]] require list_exists: a_attachment_list /= Void local l_attachment: O_WORKITEM_ISSUE_ATTACHMENT_MESSAGE l_ht: DS_HASH_TABLE [ANY, STRING] do create Result.make (a_attachment_list.count) from a_attachment_list.start until a_attachment_list.after loop l_attachment := a_attachment_list.item_for_iteration create l_ht.make (3) l_ht.force (l_attachment.issue_attachment_id.value.as_integer_32, "id") l_ht.force (l_attachment.file_name.value, "file_name") l_ht.force (l_attachment.description.value, "description") Result.force_last (l_ht) -- Increment a_attachment_list.forth end ensure created: Result /= Void same_count: Result.count = a_attachment_list.count end convert_release_files (a_file_list: DS_ARRAYED_LIST[O_WORKITEM_RELEASE_FILE_MESSAGE]): DS_ARRAYED_LIST [DS_HASH_TABLE [ANY, STRING]] require list_exists: a_file_list /= Void local l_file: O_WORKITEM_RELEASE_FILE_MESSAGE l_ht: DS_HASH_TABLE [ANY, STRING] do create Result.make (a_file_list.count) from a_file_list.start until a_file_list.after loop l_file := a_file_list.item_for_iteration create l_ht.make (2) l_ht.force (l_file.name.value, "name") l_ht.force (l_file.platform.value, "platform") Result.force_last (l_ht) -- Increment a_file_list.forth end ensure created: Result /= Void same_count: Result.count = a_file_list.count end feature {NONE} -- Implementation workitem_count_name: STRING = "count" workitem_list_name: STRING = "list" workitem_new_activity_name: STRING = "new_activity" workitem_retrieve_name: STRING = "retrieve" workitem_set_read_status_name: STRING = "set_read_status" workitem_set_read_status_project_name: STRING = "set_read_status_project" end