note description: "API interface to issue services." author: "Peter Wyss " date: "$Date$" revision: "$Revision$" class ISSUE_SERVICE inherit API_SERVICE redefine make end create make feature {NONE} -- Initialization make (a_node: A_NODE) -- Creates the service do precursor(a_node) is_internal := false end feature -- Basic operations issue_add (a_session: STRING; a_project: INTEGER_REF; a_title: STRING; a_description: STRING; a_tags: STRING; a_is_private: BOOLEAN_REF): INTEGER_REF -- Create a new issue and issue workitem. local l_msg: O_ISSUE_ADD_MESSAGE l_issue_add_reply_msg: O_ISSUE_ADD_REPLY_MESSAGE do Result := 0 -- 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 elseif a_title = Void or else a_title.is_empty then last_fault := err_invalid_title elseif a_description = Void then last_fault := err_invalid_description elseif not valid_tags (a_tags) then last_fault := err_invalid_tags 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_STRING_VALUE}.make (a_title), create {A_STRING_VALUE}.make (a_description), create {A_STRING_VALUE}.make (a_tags), create {A_BOOLEAN_VALUE}.make (a_is_private.item), create {A_BOOLEAN_VALUE}.make (is_internal.item), create {A_INTEGER_VALUE}.make (0), create {A_INTEGER_VALUE}.make (0)) send_and_wait_for_reply (l_msg) if is_ok then l_issue_add_reply_msg ?= last_reply check valid_reply: l_issue_add_reply_msg /= Void end create Result Result.set_item (l_issue_add_reply_msg.project_issue_id.value.to_integer) end end end issue_add_2 (a_session: STRING; a_project: INTEGER_REF; a_title: STRING; a_description: STRING; a_tags: STRING; a_is_private: BOOLEAN_REF; a_deadline, a_work_amount: INTEGER_REF): INTEGER_REF -- Create a new issue and issue workitem. local l_msg: O_ISSUE_ADD_MESSAGE l_issue_add_reply_msg: O_ISSUE_ADD_REPLY_MESSAGE do Result := 0 -- 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 elseif a_title = Void or else a_title.is_empty then last_fault := err_invalid_title elseif a_description = Void then last_fault := err_invalid_description elseif a_deadline < 0 then last_fault := err_invalid_deadline elseif a_work_amount < 0 then last_fault := err_invalid_work_amount elseif not valid_tags (a_tags) then last_fault := err_invalid_tags 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_STRING_VALUE}.make (a_title), create {A_STRING_VALUE}.make (a_description), create {A_STRING_VALUE}.make (a_tags), create {A_BOOLEAN_VALUE}.make (a_is_private.item), create {A_BOOLEAN_VALUE}.make (is_internal.item), create {A_INTEGER_VALUE}.make (a_deadline.item), create {A_INTEGER_VALUE}.make (a_work_amount.item)) send_and_wait_for_reply (l_msg) if is_ok then l_issue_add_reply_msg ?= last_reply check valid_reply: l_issue_add_reply_msg /= Void end create Result Result.set_item (l_issue_add_reply_msg.project_issue_id.value.to_integer) end end end issue_update (a_session: STRING; a_project: INTEGER_REF; a_issue_id: INTEGER_REF; a_title: STRING; a_description: STRING; a_tags: STRING; a_is_private: BOOLEAN_REF): BOOLEAN_REF -- update an issue and issue workitem. local l_msg: O_ISSUE_UPDATE_MESSAGE l_issue_update_reply_msg: O_ISSUE_UPDATE_REPLY_MESSAGE do Result := False -- 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 elseif a_issue_id <= 0 then last_fault := err_invalid_issue elseif a_title = Void or else a_title.is_empty then last_fault := err_invalid_title elseif a_description = Void then last_fault := err_invalid_description elseif not valid_tags (a_tags) then last_fault := err_invalid_tags else -- generate and send message -- create l_msg.make (a_session, a_project, a_issue_id, a_title, a_description, a_tags, a_is_private, is_internal, 0, 0) create l_msg.make ( create {A_STRING_VALUE}.make (a_session), create {A_INTEGER_VALUE}.make (a_project.item), create {A_INTEGER_VALUE}.make (a_issue_id.item), create {A_STRING_VALUE}.make (a_title), create {A_STRING_VALUE}.make (a_description), create {A_STRING_VALUE}.make (a_tags), create {A_BOOLEAN_VALUE}.make (a_is_private.item), create {A_BOOLEAN_VALUE}.make (is_internal.item), create {A_INTEGER_VALUE}.make (0), create {A_INTEGER_VALUE}.make (0)) send_and_wait_for_reply (l_msg) if is_ok then l_issue_update_reply_msg ?= last_reply create Result Result.set_item (True) end end end issue_update_2 (a_session: STRING; a_project: INTEGER_REF; a_issue_id: INTEGER_REF; a_title: STRING; a_description: STRING; a_tags: STRING; a_is_private: BOOLEAN_REF; a_deadline: INTEGER_REF; a_work_amount: INTEGER_REF): BOOLEAN_REF -- update an issue and issue workitem. local l_msg: O_ISSUE_UPDATE_MESSAGE l_issue_update_reply_msg: O_ISSUE_UPDATE_REPLY_MESSAGE do Result := False -- 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 elseif a_issue_id <= 0 then last_fault := err_invalid_issue elseif a_title = Void or else a_title.is_empty then last_fault := err_invalid_title elseif a_description = Void then last_fault := err_invalid_description elseif a_deadline < 0 then last_fault := err_invalid_deadline elseif a_work_amount < 0 then last_fault := err_invalid_work_amount elseif not valid_tags (a_tags) then last_fault := err_invalid_tags 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_INTEGER_VALUE}.make (a_issue_id.item), create {A_STRING_VALUE}.make (a_title), create {A_STRING_VALUE}.make (a_description), create {A_STRING_VALUE}.make (a_tags), create {A_BOOLEAN_VALUE}.make (a_is_private.item), create {A_BOOLEAN_VALUE}.make (is_internal.item), create {A_INTEGER_VALUE}.make (a_deadline.item), create {A_INTEGER_VALUE}.make (a_work_amount.item)) send_and_wait_for_reply (l_msg) if is_ok then l_issue_update_reply_msg ?= last_reply create Result Result.set_item (True) end end end issue_comment (a_session: STRING; a_project: INTEGER_REF; a_project_issue_id: INTEGER_REF; a_description: STRING): BOOLEAN_REF -- Add reply to an issue without changing its tags local l_msg: O_ISSUE_COMMENT_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 elseif a_project_issue_id <= 0 then last_fault := err_invalid_issue elseif a_description = Void then last_fault := err_invalid_description else -- generate and send message -- create l_msg.make (a_session, a_project, a_project_issue_id, a_description, is_internal, false, 0, 0, "") create l_msg.make ( create {A_STRING_VALUE}.make (a_session), create {A_INTEGER_VALUE}.make (a_project.item), create {A_INTEGER_VALUE}.make (a_project_issue_id.item), create {A_STRING_VALUE}.make (a_description), create {A_BOOLEAN_VALUE}.make (is_internal.item), create {A_BOOLEAN_VALUE}.make (false), create {A_INTEGER_VALUE}.make (0), create {A_INTEGER_VALUE}.make (0), create {A_STRING_VALUE}.make ("")) send_and_wait_for_reply (l_msg) if is_ok then create Result Result.set_item (True) end end end issue_comment_extended (a_session: STRING; a_project: INTEGER_REF; a_project_issue_id: INTEGER_REF; a_description: STRING; a_tags: STRING): BOOLEAN_REF -- Add reply to an issue which contains changed tags local l_msg: O_ISSUE_COMMENT_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 elseif a_project_issue_id <= 0 then last_fault := err_invalid_issue elseif a_description = Void then last_fault := err_invalid_description elseif not valid_tags (a_tags) then last_fault := err_invalid_tags 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_INTEGER_VALUE}.make (a_project_issue_id.item), create {A_STRING_VALUE}.make (a_description), create {A_BOOLEAN_VALUE}.make (is_internal.item), create {A_BOOLEAN_VALUE}.make (true), create {A_INTEGER_VALUE}.make (0), create {A_INTEGER_VALUE}.make (0), create {A_STRING_VALUE}.make (a_tags)) -- create l_msg.make_extended (a_session, a_project, a_project_issue_id, a_description, 0, 0, a_tags, is_internal) send_and_wait_for_reply (l_msg) if is_ok then create Result Result.set_item (True) end end end issue_comment_extended_2 (a_session: STRING; a_project: INTEGER_REF; a_project_issue_id: INTEGER_REF; a_description: STRING; a_tags: STRING; a_deadline: INTEGER_REF; a_work_amount: INTEGER_REF): BOOLEAN_REF -- Add reply to an issue which contains changed tags local l_msg: O_ISSUE_COMMENT_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 elseif a_project_issue_id <= 0 then last_fault := err_invalid_issue elseif a_description = Void then last_fault := err_invalid_description elseif a_deadline < 0 then last_fault := err_invalid_deadline elseif a_work_amount < 0 then last_fault := err_invalid_work_amount elseif not valid_tags (a_tags) then last_fault := err_invalid_tags else -- generate and send message -- create l_msg.make_extended (a_session, a_project, a_project_issue_id, a_description, a_deadline, a_work_amount, a_tags, is_internal) create l_msg.make ( create {A_STRING_VALUE}.make (a_session), create {A_INTEGER_VALUE}.make (a_project.item), create {A_INTEGER_VALUE}.make (a_project_issue_id.item), create {A_STRING_VALUE}.make (a_description), create {A_BOOLEAN_VALUE}.make (is_internal.item), create {A_BOOLEAN_VALUE}.make (true), create {A_INTEGER_VALUE}.make (a_deadline.item), create {A_INTEGER_VALUE}.make (a_work_amount.item), create {A_STRING_VALUE}.make (a_tags)) send_and_wait_for_reply (l_msg) if is_ok then create Result Result.set_item (True) end end end issue_delete (a_session: STRING; a_project_id, a_project_issue_id: INTEGER_REF): BOOLEAN_REF -- Delete the issue with `a_project_issue_id' from the project `a_project_id' local l_msg: O_ISSUE_DELETE_MESSAGE do if not is_valid_session (a_session) then last_fault := err_invalid_session elseif a_project_id <= 0 then last_fault := err_invalid_project elseif a_project_issue_id <= 0 then last_fault := err_invalid_issue else create l_msg.make (a_session, a_project_id.item, a_project_issue_id.item, false) send_and_wait_for_reply (l_msg) if is_ok then create Result Result.set_item (True) end end end issue_list (a_session: STRING; a_project: INTEGER_REF): ARRAY [DS_HASH_TABLE [ANY, STRING]] -- List issues for a_project local l_msg: O_ISSUE_LIST_MESSAGE l_issue_list_reply_msg: O_ISSUE_LIST_REPLY_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 create l_msg.make (create {A_STRING_VALUE}.make (a_session), create {A_INTEGER_VALUE}.make (a_project.item)) send_and_wait_for_reply (l_msg) if is_ok then l_issue_list_reply_msg ?= last_reply check issue_list_reply_message: l_issue_list_reply_msg /= Void end Result := convert_issue_list(l_issue_list_reply_msg.issue_list.map) end end end issue_list_changed (a_session: STRING; a_project: INTEGER_REF; a_date: INTEGER_REF): ARRAY [DS_HASH_TABLE [ANY, STRING]] -- List issues in a_project that have changed since a_date local l_msg: O_ISSUE_LIST_CHANGED_MESSAGE l_issue_list_reply_msg: O_ISSUE_LIST_REPLY_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 elseif a_date < 0 then last_fault := err_invalid_date else create l_msg.make (create {A_STRING_VALUE}.make (a_session), create {A_INTEGER_VALUE}.make (a_project.item), create {A_INTEGER_VALUE}.make (a_date.item)) send_and_wait_for_reply (l_msg) if is_ok then l_issue_list_reply_msg ?= last_reply check issue_list_reply_message: l_issue_list_reply_msg /= Void end Result := convert_issue_list (l_issue_list_reply_msg.issue_list.map) end end end issue_list_tags (a_session: STRING; a_project: INTEGER_REF): ARRAY [STRING] -- List all tags used in a_project local l_msg: O_ISSUE_LIST_TAGS_MESSAGE l_issue_list_tags_reply_msg: O_ISSUE_LIST_TAGS_REPLY_MESSAGE l_issue_list: DS_ARRAYED_LIST[A_STRING_VALUE] i: INTEGER 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 create l_msg.make (create {A_STRING_VALUE}.make (a_session), create {A_INTEGER_VALUE}.make (a_project.item)) send_and_wait_for_reply (l_msg) if is_ok then l_issue_list_tags_reply_msg ?= last_reply check issue_list_tags_reply_message: l_issue_list_tags_reply_msg /= Void end l_issue_list := l_issue_list_tags_reply_msg.tag_list.sequence create Result.make (1, l_issue_list.count) from i := 1 until i > l_issue_list.count loop Result.force (l_issue_list.item (i).value, i) -- Increment i := i + 1 end end end end issue_retrieve (a_session: STRING; a_issue_id: INTEGER_REF; a_project: INTEGER_REF): DS_HASH_TABLE [ANY, STRING] -- Retrieve issue local l_msg: O_ISSUE_RETRIEVE_MESSAGE l_issue_reply_msg: O_ISSUE_RETRIEVE_REPLY_MESSAGE l_issue_revision_list: DS_ARRAYED_LIST [O_ISSUE_REVISION_MESSAGE] l_issue_revision: O_ISSUE_REVISION_MESSAGE i: INTEGER l_issue_id_ref: INTEGER_REF l_creation_time_ref: INTEGER_REF l_last_modified_ref: INTEGER_REF l_is_private_ref: BOOLEAN_REF l_revision_count_ref: INTEGER_REF l_rev_creation_time_ref: INTEGER_REF l_deadline_ref: INTEGER_REF l_work_amount_ref: INTEGER_REF l_text_type_ref: INTEGER_REF do -- argument validiation if not is_valid_session (a_session) then last_fault := err_invalid_session elseif a_issue_id <= 0 then last_fault := err_invalid_issue elseif a_project <= 0 then last_fault := err_invalid_project else create l_msg.make (create {A_STRING_VALUE}.make (a_session), create {A_INTEGER_VALUE}.make (a_issue_id.item), create {A_INTEGER_VALUE}.make (a_project.item)) send_and_wait_for_reply (l_msg) if is_ok then l_issue_reply_msg ?= last_reply check issue_reply_message: l_issue_reply_msg /= Void end create Result.make (7) create l_issue_id_ref l_issue_id_ref.set_item (a_issue_id) Result.force (l_issue_id_ref, "issue_id") create l_creation_time_ref l_creation_time_ref.set_item (l_issue_reply_msg.creation_time.value.to_integer) Result.force (l_creation_time_ref, "creation_time") create l_last_modified_ref l_last_modified_ref.set_item (l_issue_reply_msg.last_modified.value.to_integer) Result.force (l_last_modified_ref, "last_modified") create l_is_private_ref l_is_private_ref.set_item (l_issue_reply_msg.is_private.value) Result.force (l_is_private_ref, "is_private") Result.force (l_issue_reply_msg.user.value, "user") Result.force (l_issue_reply_msg.title.value, "title") Result.force (l_issue_reply_msg.tags.value, "tags") create l_deadline_ref l_deadline_ref.set_item (l_issue_reply_msg.deadline.value.to_integer) Result.force (l_deadline_ref, "deadline") create l_work_amount_ref l_work_amount_ref.set_item (l_issue_reply_msg.work_amount.value.to_integer) Result.force (l_work_amount_ref, "work_amount") l_issue_revision_list := l_issue_reply_msg.revisions.sequence check l_issue_revisions_valid: l_issue_revision_list /= Void end create l_revision_count_ref l_revision_count_ref.set_item (l_issue_revision_list.count) Result.force (l_revision_count_ref, "revision_count") from l_issue_revision_list.start i := 1 until l_issue_revision_list.after loop l_issue_revision := l_issue_revision_list.item_for_iteration check issue_revision_valid: l_issue_revision /= Void end create l_rev_creation_time_ref l_rev_creation_time_ref.set_item (l_issue_revision.creation_time.value.to_integer) Result.force (l_rev_creation_time_ref, "revision_creationtime_" + i.out) Result.force (l_issue_revision.user.value, "revision_user_" + i.out) Result.force (l_issue_revision.text.value, "revision_text_" + i.out) create l_text_type_ref l_text_type_ref.set_item (l_issue_revision.text_type.value.to_integer) Result.force (l_text_type_ref.twin, "revision_text_type_" + i.out) Result.force (l_issue_revision.tags.value, "revision_tags_" + i.out) -- Increment l_issue_revision_list.forth i := i + 1 end end end end issue_search (a_session: STRING; a_project: INTEGER_REF; a_search_criteria: DS_HASH_TABLE [ANY, STRING]): ARRAY [DS_HASH_TABLE [ANY, STRING]] -- search issues in a_project according to a_search_criteria local l_msg: O_ISSUE_SEARCH_MESSAGE l_issue_list_reply_msg: O_ISSUE_LIST_REPLY_MESSAGE l_search_criteria: DS_HASH_TABLE[A_STRING_VALUE, A_STRING_VALUE] l_criterion_value: STRING do -- FIXME validate struct -- 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 elseif a_search_criteria = Void then last_fault := err_invalid_search_criteria else -- convert DS_HASH_TABLE [ANY, STRING] to HASH_TABLE[A_STRING_VALUE, A_STRING_VALUE] create l_search_criteria.make (a_search_criteria.count) from a_search_criteria.start until a_search_criteria.after loop l_criterion_value ?= a_search_criteria.item_for_iteration if l_criterion_value = Void then last_fault := err_invalid_search_criteria else l_search_criteria.force (create {A_STRING_VALUE}.make (l_criterion_value), create {A_STRING_VALUE}.make (a_search_criteria.key_for_iteration)) end a_search_criteria.forth end create l_msg.make ( create {A_STRING_VALUE}.make (a_session), create {A_INTEGER_VALUE}.make (a_project.item), create {A_MAP_VALUE[A_STRING_VALUE]}.make (l_search_criteria)) send_and_wait_for_reply (l_msg) if is_ok then -- result conversion l_issue_list_reply_msg ?= last_reply check issue_list_reply_message: l_issue_list_reply_msg /= Void end Result := convert_issue_list (l_issue_list_reply_msg.issue_list.map) end end end issue_retrieve_planning_data (a_session: STRING; a_project_id, a_project_issue_id: INTEGER_REF): DS_HASH_TABLE[ANY, STRING] -- retrieves the issue planning data for an issue local l_msg: O_ISSUE_RETRIEVE_PLANNING_DATA_MESSAGE l_reply: O_ISSUE_RETRIEVE_PLANNING_DATA_REPLY_MESSAGE l_deadline_ref: INTEGER_REF l_work_amount_ref: INTEGER_REF do if not is_valid_session (a_session) then last_fault := err_invalid_session elseif a_project_issue_id <= 0 then last_fault := err_invalid_issue elseif a_project_id <= 0 then last_fault := err_invalid_project else create l_msg.make ( create {A_STRING_VALUE}.make (a_session), create {A_INTEGER_VALUE}.make (a_project_id.item), create {A_INTEGER_VALUE}.make (a_project_issue_id.item)) send_and_wait_for_reply (l_msg) if is_ok then l_reply ?= last_reply check valid_reply: l_reply /= Void end create Result.make (2) create l_deadline_ref l_deadline_ref.set_item (l_reply.deadline.value.to_integer) Result.force (l_deadline_ref, "deadline") create l_work_amount_ref l_work_amount_ref.set_item (l_reply.work_amount.value.to_integer) Result.force (l_work_amount_ref, "work_amount") end end end issue_add_attachment (a_session: STRING; a_project_id, a_project_issue_id: INTEGER_REF; a_file_name, a_description: STRING): INTEGER_REF -- adds a file attachment to an existing issue local l_msg: O_ISSUE_ADD_ATTACHMENT_MESSAGE l_add_attachment_reply_msg: O_ISSUE_ADD_ATTACHMENT_STORAGE_REPLY_MESSAGE do if not is_valid_session (a_session) then last_fault := err_invalid_session elseif a_project_issue_id <= 0 then last_fault := err_invalid_issue elseif a_project_id <= 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_id.item), create {A_INTEGER_VALUE}.make (a_project_issue_id.item), create {A_STRING_VALUE}.make (a_file_name), create {A_STRING_VALUE}.make (a_description), create {A_BOOLEAN_VALUE}.make (false)) send_and_wait_for_reply (l_msg) if is_ok then l_add_attachment_reply_msg ?= last_reply check valid_reply: l_add_attachment_reply_msg /= Void end create Result Result.set_item (l_add_attachment_reply_msg.issue_attachment_id.value.to_integer) end end end issue_retrieve_attachments (a_session: STRING; a_project_id, a_project_issue_id: INTEGER_REF): ARRAY[DS_HASH_TABLE[ANY, STRING]] -- retrieve all attachment for an issue local l_msg: O_ISSUE_RETRIEVE_ATTACHMENTS_MESSAGE l_reply: O_ISSUE_RETRIEVE_ATTACHMENTS_REPLY_MESSAGE do if not is_valid_session (a_session) then last_fault := err_invalid_session elseif a_project_id <= 0 then last_fault := err_invalid_project elseif a_project_issue_id <= 0 then last_fault := err_invalid_issue else create l_msg.make (create {A_STRING_VALUE}.make (a_session), create {A_INTEGER_VALUE}.make (a_project_id.item), create {A_INTEGER_VALUE}.make (a_project_issue_id.item)) send_and_wait_for_reply (l_msg) if is_ok then l_reply ?= last_reply check valid_reply: l_reply /= Void end Result := convert_issue_attachment_list (l_reply.issue_attachment_list.sequence).to_array end end end issue_remove_attachment (a_session: STRING; a_project_id, a_project_issue_id: INTEGER_REF; a_file_name: STRING): BOOLEAN_REF -- remove an attachment from an issue local l_msg: O_ISSUE_REMOVE_ATTACHMENT_MESSAGE l_reply: A_GENERAL_STATUS_MESSAGE do if not is_valid_session (a_session) then last_fault := err_invalid_session elseif a_project_id <= 0 then last_fault := err_invalid_project elseif a_project_issue_id <= 0 then last_fault := err_invalid_issue else create l_msg.make ( create {A_STRING_VALUE}.make (a_session), create {A_INTEGER_VALUE}.make (a_project_id.item), create {A_INTEGER_VALUE}.make (a_project_issue_id.item), create {A_STRING_VALUE}.make (a_file_name), create {A_BOOLEAN_VALUE}.make (false)) send_and_wait_for_reply (l_msg) if is_ok then l_reply ?= last_reply check valid_reply: l_reply /= Void end create Result Result.set_item (True) end end end issue_remove_all_attachments (a_session: STRING; a_project_id, a_project_issue_id: INTEGER_REF): BOOLEAN_REF -- remove an attachment from an issue local l_msg: O_ISSUE_REMOVE_ALL_ATTACHMENTS_MESSAGE l_reply: A_GENERAL_STATUS_MESSAGE do if not is_valid_session (a_session) then last_fault := err_invalid_session elseif a_project_id <= 0 then last_fault := err_invalid_project elseif a_project_issue_id <= 0 then last_fault := err_invalid_issue else create l_msg.make (a_session, a_project_id.item, a_project_issue_id.item, false) send_and_wait_for_reply (l_msg) if is_ok then l_reply ?= last_reply check valid_reply: l_reply /= Void end create Result Result.set_item (True) end end end issue_add_subscription (a_session: STRING; a_project_id, a_project_issue_id: INTEGER_REF): BOOLEAN_REF -- add the issue subscription for the session user local l_msg: O_ISSUE_ADD_SUBSCRIPTION_MESSAGE l_reply: A_GENERAL_STATUS_MESSAGE do if not is_valid_session (a_session) then last_fault := err_invalid_session elseif a_project_id <= 0 then last_fault := err_invalid_project elseif a_project_issue_id <= 0 then last_fault := err_invalid_issue else create l_msg.make (create {A_STRING_VALUE}.make (a_session), create {A_INTEGER_VALUE}.make (a_project_id.item), create {A_INTEGER_VALUE}.make (a_project_issue_id.item)) send_and_wait_for_reply (l_msg) if is_ok then l_reply ?= last_reply check valid_reply: l_reply /= Void end create Result Result.set_item (True) end end end issue_remove_subscription (a_session: STRING; a_project_id, a_project_issue_id: INTEGER_REF): BOOLEAN_REF -- remove the issue subscription for the session user local l_msg: O_ISSUE_REMOVE_SUBSCRIPTION_MESSAGE l_reply: A_GENERAL_STATUS_MESSAGE do if not is_valid_session (a_session) then last_fault := err_invalid_session elseif a_project_id <= 0 then last_fault := err_invalid_project elseif a_project_issue_id <= 0 then last_fault := err_invalid_issue else create l_msg.make (create {A_STRING_VALUE}.make (a_session), create {A_INTEGER_VALUE}.make (a_project_id.item), create {A_INTEGER_VALUE}.make (a_project_issue_id.item)) send_and_wait_for_reply (l_msg) if is_ok then l_reply ?= last_reply check valid_reply: l_reply /= Void end 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 (issue_add_name) then create {TUPLE [STRING, INTEGER_REF, STRING, STRING, STRING, BOOLEAN_REF]}Result elseif a_name.is_equal (issue_add_2_name) then create {TUPLE [STRING, INTEGER_REF, STRING, STRING, STRING, BOOLEAN_REF, INTEGER_REF, INTEGER_REF]}Result elseif a_name.is_equal(issue_update_name) then create {TUPLE [STRING, INTEGER_REF, INTEGER_REF, STRING, STRING, STRING, BOOLEAN_REF]}Result elseif a_name.is_equal(issue_update_2_name) then create {TUPLE [STRING, INTEGER_REF, INTEGER_REF, STRING, STRING, STRING, BOOLEAN_REF, INTEGER_REF, INTEGER_REF]}Result elseif a_name.is_equal (issue_comment_name) then create {TUPLE [STRING, INTEGER_REF, INTEGER_REF, STRING]}Result elseif a_name.is_equal (issue_comment_extended_name) then create {TUPLE [STRING, INTEGER_REF, INTEGER_REF, STRING, STRING]}Result elseif a_name.is_equal (issue_comment_extended_2_name) then create {TUPLE [STRING, INTEGER_REF, INTEGER_REF, STRING, STRING, INTEGER_REF, INTEGER_REF]}Result elseif a_name.is_equal (issue_delete_name) then create {TUPLE [STRING, INTEGER_REF, INTEGER_REF]}Result elseif a_name.is_equal (issue_list_name) then create {TUPLE [STRING, INTEGER_REF]}Result elseif a_name.is_equal (issue_retrieve_name) then create {TUPLE [STRING, INTEGER_REF, INTEGER_REF]}Result elseif a_name.is_equal (issue_search_name) then create {TUPLE [STRING, INTEGER_REF, DS_HASH_TABLE [ANY, STRING]]}Result elseif a_name.is_equal (issue_list_tags_name) then create {TUPLE [STRING, INTEGER_REF]}Result elseif a_name.is_equal (issue_list_changed_name) then create {TUPLE [STRING, INTEGER_REF, INTEGER_REF]}Result elseif a_name.is_equal (issue_retrieve_planning_data_name) then create {TUPLE [STRING, INTEGER_REF, INTEGER_REF]}Result elseif a_name.is_equal (issue_add_attachment_name) then create {TUPLE [STRING, INTEGER_REF, INTEGER_REF, STRING, STRING]}Result elseif a_name.is_equal (issue_retrieve_attachments_name) then create {TUPLE [STRING, INTEGER_REF, INTEGER_REF]}Result elseif a_name.is_equal (issue_remove_attachment_name) then create {TUPLE [STRING, INTEGER_REF, INTEGER_REF, STRING]}Result elseif a_name.is_equal (issue_remove_all_attachments_name) then create {TUPLE [STRING, INTEGER_REF, INTEGER_REF]}Result elseif a_name.is_equal (issue_add_subscription_name) then create {TUPLE [STRING, INTEGER_REF, INTEGER_REF]}Result elseif a_name.is_equal (issue_remove_subscription_name) then create {TUPLE [STRING, INTEGER_REF, INTEGER_REF]}Result end end feature -- Initialisation self_register -- Register all actions for this service do register_with_help (agent issue_add, issue_add_name, "Add issue.") register_with_help (agent issue_add_2, issue_add_2_name, "Add issue. Version 2") register_with_help (agent issue_update, issue_update_name, "Update issue.") register_with_help (agent issue_update_2, issue_update_2_name, "Update issue. Version 2") register_with_help (agent issue_comment, issue_comment_name, "Add issue reply.") register_with_help (agent issue_comment_extended, issue_comment_extended_name, "Add issue reply with new tags.") register_with_help (agent issue_comment_extended_2, issue_comment_extended_2_name, "Add issue reply with new tags. Version 2") register_with_help (agent issue_delete, issue_delete_name, "Delete an issue from a project.") register_with_help (agent issue_list, issue_list_name, "List issues.") register_with_help (agent issue_list_tags, issue_list_tags_name, "List all tags used in a project.") register_with_help (agent issue_list_changed, issue_list_changed_name, "List all changed issues in a project.") register_with_help (agent issue_retrieve, issue_retrieve_name, "Retrieve an issue.") register_with_help (agent issue_search, issue_search_name, "search issues.") register_with_help (agent issue_retrieve_planning_data, issue_retrieve_planning_data_name, "Retrieves the planning data of an issue") register_with_help (agent issue_add_attachment, issue_add_attachment_name, "Add attachment to an issue.") register_with_help (agent issue_retrieve_attachments, issue_retrieve_attachments_name, "Retrieve all attachments of an issue.") register_with_help (agent issue_remove_attachment, issue_remove_attachment_name, "Remove an attachment from an issue.") register_with_help (agent issue_remove_all_attachments, issue_remove_all_attachments_name, "Remove all attachments of an issue.") register_with_help (agent issue_add_subscription, issue_add_subscription_name, "Add the issue subscription for the user, who invoked the call") register_with_help (agent issue_remove_subscription, issue_remove_subscription_name, "Remove the issue subscription for the user, who invoked the call") end feature -- Helper convert_issue_list(a_issue_map: DS_HASH_TABLE[O_ISSUE_ISSUE_MESSAGE, A_STRING_VALUE]): ARRAY [DS_HASH_TABLE [ANY, STRING]] -- Converts a hashtable of O_ISSUE_ISSUE_MESSAGE into an hash table based representation. -- This is used in the issue_list_* calls to convert O_ISSUE_LIST_REPLY_MESSAGE.issue_list local i: INTEGER l_issue: O_ISSUE_ISSUE_MESSAGE l_issue_ht: DS_HASH_TABLE [ANY, STRING] l_issue_id_ref: INTEGER_REF l_creation_time_ref: INTEGER_REF l_last_modified_ref: INTEGER_REF l_deadline_ref: INTEGER_REF l_work_amount_ref: INTEGER_REF do create Result.make (0, a_issue_map.count-1) from i := 0 until i >= a_issue_map.count loop l_issue := a_issue_map.item (create {A_STRING_VALUE}.make (i.out)) create l_issue_ht.make (8) create l_issue_id_ref l_issue_id_ref.set_item (l_issue.issue_id.value.to_integer) l_issue_ht.force (l_issue_id_ref, "issue_id") create l_creation_time_ref l_creation_time_ref.set_item (l_issue.creation_time.value.to_integer) l_issue_ht.force (l_creation_time_ref, "creation_time") create l_last_modified_ref l_last_modified_ref.set_item (l_issue.last_modified.value.to_integer) l_issue_ht.force (l_last_modified_ref, "last_modified") create l_deadline_ref l_deadline_ref.set_item (l_issue.deadline.value.to_integer) l_issue_ht.force (l_deadline_ref, "deadline") create l_work_amount_ref l_work_amount_ref.set_item (l_issue.work_amount.value.to_integer) l_issue_ht.force (l_work_amount_ref, "work_amount") l_issue_ht.force (l_issue.user.value, "user") l_issue_ht.force (l_issue.title.value, "title") l_issue_ht.force (l_issue.tags.value, "tags") Result.force (l_issue_ht, i) -- Increment i := i + 1 end end convert_issue_attachment_list (an_attachment_list: DS_ARRAYED_LIST [O_ISSUE_ISSUE_ATTACHMENT_MESSAGE]): DS_ARRAYED_LIST[DS_HASH_TABLE[ANY, STRING]] local l_attachment: O_ISSUE_ISSUE_ATTACHMENT_MESSAGE l_issue_attachment_ht: DS_HASH_TABLE [ANY, STRING] l_id_ref: INTEGER_REF do create Result.make (an_attachment_list.count) from an_attachment_list.start until an_attachment_list.after loop l_attachment := an_attachment_list.item_for_iteration create l_issue_attachment_ht.make (3) create l_id_ref l_id_ref.set_item (l_attachment.issue_attachment_id.value.to_integer) l_issue_attachment_ht.force (l_id_ref, "issue_attachment_id") l_issue_attachment_ht.force (l_attachment.file_name.value, "file_name") l_issue_attachment_ht.force (l_attachment.description.value, "description") Result.force_last (l_issue_attachment_ht) -- Increment an_attachment_list.forth end end feature {INTERNAL_ISSUE_SERVICE} -- queries is_internal: BOOLEAN -- true if the operations of this service can only be called from the frontend -- The main reason for this flag was to minimize code duplication between this class -- and INTERNAL_ISSUE_SERVICE. feature {NONE} -- Validation valid_tags(a_tags: STRING): BOOLEAN -- returns true if the tags are valid local l_tags: LIST [STRING] l_tag: STRING l_status_present: BOOLEAN do if a_tags = Void then -- if this occurs something went seriously wrong Result := False else l_tags := a_tags.split (',') if l_tags.is_empty then -- no tags specified Result := False else Result := True l_status_present := False from l_tags.start until l_tags.after loop l_tag := l_tags.item l_tag.right_adjust l_tag.left_adjust if l_tag.count > 0 then if (l_tag.is_equal ("status::open") or l_tag.is_equal ("status::closed")) then if l_status_present then -- multiple status tags Result := False else l_status_present := True end end end l_tags.forth end if not l_status_present then -- status tag is missing Result := False end end end end feature {NONE} -- Implementation issue_add_name: STRING = "add" issue_add_2_name: STRING = "add_2" issue_update_name: STRING = "update" issue_update_2_name: STRING = "update_2" issue_comment_name: STRING = "comment" issue_comment_extended_name: STRING = "comment_extended" issue_comment_extended_2_name: STRING = "comment_extended_2" issue_delete_name: STRING = "delete" issue_list_name: STRING = "list" issue_list_changed_name: STRING = "list_changed" issue_list_tags_name: STRING = "list_tags" issue_retrieve_name: STRING = "retrieve" issue_search_name: STRING = "search" issue_retrieve_planning_data_name: STRING = "retrieve_planning_data" issue_add_attachment_name: STRING = "add_attachment" issue_retrieve_attachments_name: STRING = "retrieve_attachments" issue_remove_attachment_name: STRING = "remove_attachment" issue_remove_all_attachments_name: STRING = "remove_all_attachments" issue_add_subscription_name: STRING = "add_subscription" issue_remove_subscription_name: STRING = "remove_subscription" end