indexing description: "Provide an interface to workitem data." author: "$Author$>" date: "$Date$" revision: "$Revision$" class WORKITEM_INTERFACE inherit BASE_INTERFACE redefine make end O_WORKITEM_CONSTANTS create make feature {NONE} -- Initialization make (a_node: like node; a_db_handler: like db_handler; a_policy_cache: like policy_cache) is -- Initialize. do Precursor (a_node, a_db_handler, a_policy_cache) end feature -- Commands workitem_detail (a_workitem_id: INTEGER; a_workitem_type: INTEGER; a_project_id: INTEGER; a_project: STRING; a_user_id: INTEGER; a_user: STRING; is_detailed: BOOLEAN): DS_HASH_TABLE[ANY, STRING] is -- retrieve workitem details (check access rights if a_user_id > 0) require workitem_id_ok: a_workitem_id > 0 workitem_type_ok: a_workitem_type > 0 local l_commit: WORKITEM_COMMIT l_wiki: WORKITEM_WIKI l_comment: WORKITEM_COMMENT l_blog: WORKITEM_BLOG l_release: TUPLE[workitem_id: INTEGER; release_id: INTEGER; name: STRING; description: STRING; version: STRING; files: ARRAYED_LIST[TUPLE[name: STRING; platform: STRING]]] l_release_file: TUPLE[name: STRING; platform: STRING] l_issue: TUPLE [workitem_id: INTEGER; issue_id: INTEGER; project_issue_id: INTEGER; title: STRING; description: STRING; is_private: BOOLEAN; is_new: BOOLEAN] l_url: STRING l_project_lower: STRING i: INTEGER l_user_project_association: INTEGER is_allowed: BOOLEAN do create l_url.make_empty if a_workitem_type = 1 then -- issue workitem issue_access.retrieve_issue_workitem_by_id (a_workitem_id) if issue_access.is_found then l_issue := issue_access.last_issue_workitem if a_user_id = 0 then -- always allow on user_id 0 is_allowed := True elseif l_issue.is_private then l_user_project_association := user_access.retrieve_user_project_association_group (a_project_id, a_user_id) is_allowed := (l_user_project_association = 3 or l_user_project_association = 4) else is_allowed := True end if is_allowed then create Result.make (2) Result.force (l_issue.project_issue_id.out, "project_issue_id") Result.force (l_issue.title, "title") -- FIXME (De) Should the following line be removed? description should only be sent if is_detailed. Result.force (l_issue.description, "description") if l_issue.is_new then Result.force ("1", "is_new") else Result.force ("0", "is_new") end l_project_lower := a_project.out l_project_lower.to_lower Result.force ("http://" + l_project_lower + "." + config_parser.get("origo_domain") + "/issues/" + l_issue.project_issue_id.out, "url") if is_detailed then Result.force (l_issue.description, "description") end end else create Result.make (0) end elseif a_workitem_type = 2 then -- release workitem is_allowed := True release_access.retrieve_release_workitem_by_id (a_workitem_id) if release_access.is_found then create Result.make (3) l_release := release_access.last_release_workitem Result.force (l_release.name, "name") Result.force (l_release.description, "description") Result.force (l_release.version, "version") l_project_lower := a_project.out l_project_lower.to_lower Result.force ("http://" + l_project_lower + "." + config_parser.get("origo_domain") + "/download/" + l_release.release_id.out, "url") if is_detailed then Result.force (l_release.files.count.out, "file_count") from l_release.files.start i := 1 until l_release.files.after loop l_release_file := l_release.files.item Result.force (l_release_file.name, "file_name_" + i.out) Result.force (l_release_file.platform, "file_platform_" + i.out) l_release.files.forth i := i + 1 end end else create Result.make (0) end elseif a_workitem_type = 3 then -- commit workitem if a_user_id = 0 then -- always allow on user_id 0 is_allowed := True elseif project_access.is_projects_closed_source(a_project_id) then l_user_project_association := user_access.retrieve_user_project_association_group (a_project_id, a_user_id) is_allowed := (l_user_project_association = 3 or l_user_project_association = 4) else is_allowed := True end if is_allowed then commit_access.retrieve_commit_workitem_by_id (a_workitem_id) if commit_access.is_found then create Result.make (3) l_commit := commit_access.last_commit_workitem Result.force (l_commit.revision.out, "revision") if l_commit.log = Void then Result.force ("", "log") else Result.force (l_commit.log.out, "log") end l_project_lower := a_project.out l_project_lower.to_lower Result.force ("http://svn." + config_parser.get("origo_domain") + "/wsvn/" + l_project_lower + "/?rev=" + l_commit.revision.out + "&sc=1", "url") if is_detailed then if l_commit.diff = Void then Result.force ("", "diff") else Result.force (l_commit.diff.out, "diff") end end else create Result.make (0) end end elseif a_workitem_type = 4 then --wiki workitem wiki_access.retrieve_wiki_workitem_by_id (a_workitem_id) if wiki_access.is_found then l_wiki := wiki_access.last_wiki_workitem if a_user_id = 0 then -- always allow on user_id 0 is_allowed := True elseif l_wiki.private = 1 then l_user_project_association := user_access.retrieve_user_project_association_group (a_project_id, a_user_id) is_allowed := (l_user_project_association = 3 or l_user_project_association = 4) else is_allowed := True end if is_allowed then create Result.make (3) Result.force (l_wiki.title, "title") if is_detailed then Result.force (l_wiki.diff, "diff") Result.force (l_wiki.revision.out, "revision") Result.force (l_wiki.old_revision.out, "old_revision") end l_url.copy (l_wiki.title) l_url.to_lower l_url.replace_substring_all (" ", "_") l_url.replace_substring_all ("(", "") l_url.replace_substring_all (")", "") l_project_lower := a_project.out l_project_lower.to_lower Result.force ("http://" + l_project_lower + "." + config_parser.get("origo_domain") + "/wiki/" + l_url, "url") if l_wiki.old_revision > 0 then Result.force ("http://" + l_project_lower + "." + config_parser.get("origo_domain") + "/wiki_diff/" + l_url + "/" + l_wiki.old_revision.out + "/" + l_wiki.revision.out, "diffurl") end end else create Result.make (0) end elseif a_workitem_type = 5 then --blog workitem is_allowed := True blog_access.retrieve_blog_workitem_by_id (a_workitem_id) if blog_access.is_found then create Result.make (1) l_blog := blog_access.last_blog_workitem Result.force (l_blog.title, "title") if is_detailed then Result.force (l_blog.diff, "diff") Result.force (l_blog.revision.out, "revision") Result.force (l_blog.old_revision.out, "old_revision") end l_url.copy(l_blog.title) l_url.to_lower l_url.replace_substring_all (" ", "_") l_url.replace_substring_all ("(", "") l_url.replace_substring_all (")", "") l_url := a_user + "/" + l_url l_url.to_lower l_project_lower := a_project.out l_project_lower.to_lower Result.force ("http://" + l_project_lower + "." + config_parser.get("origo_domain") + "/blog/" + l_url, "url") if l_blog.old_revision > 0 then Result.force ("http://" + l_project_lower + "." + config_parser.get("origo_domain") + "/blog_diff/" + l_url + "/" + l_blog.old_revision.out + "/" + l_blog.revision.out, "diffurl") end else create Result.make (0) end elseif a_workitem_type = 6 then --comment workitem is_allowed := True comment_access.retrieve_comment_workitem_by_id (a_workitem_id) if comment_access.is_found then create Result.make (2) l_comment := comment_access.last_comment_workitem Result.force (l_comment.title, "title") Result.force (l_comment.is_new.out, "is_new") Result.force (l_comment.comment_type, "comment_type") if is_detailed then Result.force (l_comment.text, "text") end l_url := l_comment.reference_url Result.force (l_url, "url") else create Result.make (0) end else create Result.make (0) end if not is_allowed then create Result.make (0) end end workitem_list (a_msg: O_MESSAGE) is -- List workitems. require a_msg_ok: a_msg /= Void local l_msg: O_WORKITEM_LIST_MESSAGE l_reply: O_WORKITEM_LIST_REPLY_MESSAGE l_workitems: DS_HASH_TABLE [TUPLE [workitem_id: INTEGER; type: INTEGER; creation_time: INTEGER; project_id: INTEGER; project: STRING; user: STRING; data: DS_HASH_TABLE[ANY, STRING]; is_read: BOOLEAN], INTEGER] l_workitem_t: TUPLE [workitem_id: INTEGER; type: INTEGER; creation_time: INTEGER; project_id: INTEGER; project: STRING; user: STRING; data: DS_HASH_TABLE[ANY, STRING]; is_read: BOOLEAN] l_query_result: ARRAYED_LIST[TUPLE [workitem_id: INTEGER; type: INTEGER; creation_time: INTEGER; project_id: INTEGER; project: STRING; user: STRING; is_read: BOOLEAN]] l_status: O_GENERAL_STATUS_MESSAGE i: INTEGER do l_msg ?= a_msg check workitem_list_message: l_msg /= Void end user_access.retrieve_user_by_session (l_msg.session) if user_access.is_found then -- retrieve workitems and map them into a HASH_TABLE l_query_result := workitem_access.retrieve_workitems (user_access.last_user.user_id, l_msg.limit, l_msg.unread_only) from create l_workitems.make (l_query_result.count) l_query_result.start i := 1 until l_query_result.after loop create l_workitem_t l_workitem_t.workitem_id := l_query_result.item.workitem_id l_workitem_t.type := l_query_result.item.type l_workitem_t.creation_time := l_query_result.item.creation_time l_workitem_t.project_id := l_query_result.item.project_id l_workitem_t.project := l_query_result.item.project.out l_workitem_t.user := l_query_result.item.user.out l_workitem_t.is_read := l_query_result.item.is_read -- retreive workitem details l_workitem_t.data := workitem_detail (l_query_result.item.workitem_id, l_workitem_t.type, l_workitem_t.project_id, l_workitem_t.project, user_access.last_user.user_id, l_workitem_t.user, False) if l_workitem_t.data.count > 0 then l_workitems.force (l_workitem_t, i) i := i + 1 end l_query_result.forth end create l_reply.make(l_workitems) node.send_message_reply (l_reply, a_msg) else create l_status.make (False, err_session_timeout) node.send_message_reply (l_status, a_msg) end end workitem_list_projects (a_msg: O_MESSAGE) is -- List workitems with limited nr. of workitems for each project. require a_msg_ok: a_msg /= Void local l_msg: O_WORKITEM_LIST_PROJECTS_MESSAGE l_reply: O_WORKITEM_LIST_REPLY_MESSAGE l_workitems: DS_HASH_TABLE [TUPLE [workitem_id: INTEGER; type: INTEGER; creation_time: INTEGER; project_id: INTEGER; project: STRING; user: STRING; data: DS_HASH_TABLE[ANY, STRING]; is_read: BOOLEAN], INTEGER] l_query_result: ARRAYED_LIST[TUPLE [workitem_id: INTEGER; type: INTEGER; creation_time: INTEGER; project_id: INTEGER; project: STRING; user: STRING; is_read: BOOLEAN]] l_status: O_GENERAL_STATUS_MESSAGE do l_msg ?= a_msg check workitem_list_projects_message: l_msg /= Void end user_access.retrieve_user_by_session (l_msg.session) if user_access.is_found then -- retrieve workitems and map them into a HASH_TABLE l_query_result := workitem_access.retrieve_workitems_projects (user_access.last_user.user_id, l_msg.limit, l_msg.unread_only) l_workitems := convert_workitems (l_query_result) create l_reply.make(l_workitems) node.send_message_reply (l_reply, a_msg) else create l_status.make (False, err_session_timeout) node.send_message_reply (l_status, a_msg) end end workitem_list_project (a_msg: O_MESSAGE) is -- List workitems with limited nr. of workitems for a project. require a_msg_ok: a_msg /= Void local l_msg: O_WORKITEM_LIST_PROJECT_MESSAGE l_reply: O_WORKITEM_LIST_REPLY_MESSAGE l_workitems: DS_HASH_TABLE [TUPLE [workitem_id: INTEGER; type: INTEGER; creation_time: INTEGER; project_id: INTEGER; project: STRING; user: STRING; data: DS_HASH_TABLE[ANY, STRING]; is_read: BOOLEAN], INTEGER] l_query_result: ARRAYED_LIST[TUPLE [workitem_id: INTEGER; type: INTEGER; creation_time: INTEGER; project_id: INTEGER; project: STRING; user: STRING; is_read: BOOLEAN]] l_status: O_GENERAL_STATUS_MESSAGE do l_msg ?= a_msg check workitem_list_project_message: l_msg /= Void end user_access.retrieve_user_by_session (l_msg.session) if user_access.is_found then -- retrieve workitems and map them into a HASH_TABLE l_query_result := workitem_access.retrieve_workitems_project (l_msg.project_id, user_access.last_user.user_id, l_msg.limit, l_msg.unread_only) l_workitems := convert_workitems (l_query_result) create l_reply.make(l_workitems) node.send_message_reply (l_reply, a_msg) else create l_status.make (False, err_session_timeout) node.send_message_reply (l_status, a_msg) end end workitem_retrieve (a_msg: O_MESSAGE) is -- Retrieve workitem. require a_msg_ok: a_msg /= Void local l_msg: O_WORKITEM_RETRIEVE_MESSAGE l_reply: O_WORKITEM_RETRIEVE_REPLY_MESSAGE l_workitem_t: TUPLE [type: INTEGER; creation_time: INTEGER; project_id: INTEGER; project: STRING; user: STRING; data: DS_HASH_TABLE[ANY, STRING]] l_status: O_GENERAL_STATUS_MESSAGE do l_msg ?= a_msg check workitem_message: l_msg /= Void end user_access.retrieve_user_by_session (l_msg.session) if user_access.is_found then -- retrieve workitem workitem_access.retrieve_workitem_by_id (l_msg.workitem_id) if workitem_access.is_found then create l_workitem_t l_workitem_t.type := workitem_access.last_workitem.type l_workitem_t.creation_time := workitem_access.last_workitem.creation_time l_workitem_t.project_id := workitem_access.last_workitem.project_id l_workitem_t.project := workitem_access.last_workitem.project.out l_workitem_t.user := workitem_access.last_workitem.user.out -- retreive workitem details l_workitem_t.data := workitem_detail (workitem_access.last_workitem.workitem_id, l_workitem_t.type, l_workitem_t.project_id, l_workitem_t.project, user_access.last_user.user_id, l_workitem_t.user, True) if l_workitem_t.data.count > 0 then create l_reply.make (l_workitem_t.type, l_workitem_t.creation_time, l_workitem_t.project_id, l_workitem_t.project, l_workitem_t.user, l_workitem_t.data) node.send_message_reply (l_reply, a_msg) else create l_status.make (False, err_access_denied) node.send_message_reply (l_status, a_msg) end else create l_status.make (False, err_invalid_workitem) node.send_message_reply (l_status, a_msg) end else create l_status.make (False, err_session_timeout) node.send_message_reply (l_status, a_msg) end end workitem_set_read_status (a_msg: O_MESSAGE) is -- Mark workitem as read or unread corresponding to read_status require a_msg_ok: a_msg /= Void local l_msg: O_WORKITEM_SET_READ_STATUS_MESSAGE l_status: O_GENERAL_STATUS_MESSAGE l_session: SESSION do l_msg ?= a_msg check valid_msg: l_msg /= Void end -- session valid? user_access.retrieve_session_by_id (l_msg.session) if user_access.is_found then l_session := user_access.last_session user_access.retrieve_user_by_id (l_session.user_id) if user_access.is_found then workitem_access.retrieve_workitem_by_id (l_msg.workitem_id) if workitem_access.is_found then if l_msg.read_status then workitem_access.insert_read_workitem (l_session.user_id, l_msg.workitem_id) else workitem_access.delete_read_workitem (l_session.user_id, l_msg.workitem_id) end create l_status.make (True, "") else create l_status.make (False, err_invalid_workitem) end else create l_status.make (False, err_invalid_user) end else create l_status.make (False, err_session_timeout) end -- send status node.send_message_reply (l_status, a_msg) end workitem_set_read_status_project (a_msg: O_MESSAGE) is -- Mark all workitems in project as read or unread corresponding to read_status require a_msg_ok: a_msg /= Void local l_msg: O_WORKITEM_SET_READ_STATUS_PROJECT_MESSAGE l_status: O_GENERAL_STATUS_MESSAGE l_session: SESSION l_workitems: ARRAYED_LIST[INTEGER] do l_msg ?= a_msg check valid_msg: l_msg /= Void end -- session valid? user_access.retrieve_session_by_id (l_msg.session) if user_access.is_found then l_session := user_access.last_session user_access.retrieve_user_by_id (l_session.user_id) if user_access.is_found then project_access.retrieve_project_by_id (l_msg.project_id) if project_access.is_found then l_workitems := workitem_access.retrieve_workitem_ids_project (project_access.last_project.project_id) if l_msg.read_status then from l_workitems.start until l_workitems.after loop workitem_access.insert_read_workitem (l_session.user_id, l_workitems.item.to_integer) l_workitems.forth end else from l_workitems.start until l_workitems.after loop workitem_access.delete_read_workitem (l_session.user_id, l_workitems.item.to_integer) l_workitems.forth end end create l_status.make (True, "") else create l_status.make (False, err_invalid_project) end else create l_status.make (False, err_invalid_user) end else create l_status.make (False, err_session_timeout) end -- send status node.send_message_reply (l_status, a_msg) end workitem_mail (a_msg: O_MESSAGE) is -- Get mail content and addresses of users who are to be informed about a workitem. require a_msg_ok: a_msg /= Void local l_addresses_reply_msg: O_WORKITEM_MAIL_REPLY_MESSAGE l_msg: O_WORKITEM_MAIL_MESSAGE l_addresses: ARRAYED_LIST [STRING] l_subject: STRING l_body: STRING l_title_striped: STRING l_workitem_t: TUPLE [type: INTEGER; creation_time: INTEGER; project_id: INTEGER; project: STRING; user: STRING; data: DS_HASH_TABLE[ANY, STRING]] i: INTEGER l_file_count: INTEGER l_creation_time: DATE_TIME issue_tags: STRING project_issue_id : INTEGER l_formatted_timestamp: STRING do l_msg ?= a_msg check valid_message: l_msg /= Void end workitem_access.retrieve_workitem_by_id (l_msg.workitem_id) if workitem_access.is_found then create l_workitem_t l_workitem_t.type := workitem_access.last_workitem.type l_workitem_t.creation_time := workitem_access.last_workitem.creation_time l_workitem_t.project_id := workitem_access.last_workitem.project_id l_workitem_t.project := workitem_access.last_workitem.project.out l_workitem_t.user := workitem_access.last_workitem.user.out -- retrieve workitem details l_workitem_t.data := workitem_detail (workitem_access.last_workitem.workitem_id, l_workitem_t.type, l_workitem_t.project_id, l_workitem_t.project, 0, l_workitem_t.user, True) -- calculate date from timestamp create l_creation_time.make (1970, 1, 1, 0, 0, 0) l_creation_time.second_add (l_workitem_t.creation_time) l_formatted_timestamp := l_creation_time.formatted_out ("yyyy-[0]mm-[0]dd [0]hh:[0]mi:[0]ss") + " UTC" l_title_striped ?= l_workitem_t.data.item ("title") if l_title_striped /= Void then l_title_striped.replace_substring_all ("%N", " ") end -- create mail content if l_workitem_t.type = 1 then -- issue issue_access.retrieve_issue_workitem_by_id (l_msg.workitem_id) issue_tags := "" if issue_access.is_found then project_issue_id := issue_access.last_issue_workitem.project_issue_id issue_access.retrieve_issue_by_project_issue_id (l_workitem_t.project_id, project_issue_id) if issue_access.is_found then issue_tags := issue_access.last_issue.tags end end if l_workitem_t.data.item ("is_new").out.is_equal ("1") then l_subject := "[" + l_workitem_t.project + "] Issue - New - " + l_title_striped l_body := "New Issue" else l_subject := "[" + l_workitem_t.project + "] Issue - Change - " + l_title_striped l_body := "Changed Issue" end l_body := l_body + "%N%NProject: " + l_workitem_t.project + "%NUser: " + l_workitem_t.user + "%NDate: " + l_formatted_timestamp + "%NLink: " + l_workitem_t.data.item ("url").out + "%N%NTitle: " + l_title_striped + "%N%NTags: " + issue_tags.out + "%N%NText:%N" + l_workitem_t.data.item ("description").out elseif l_workitem_t.type = 2 then -- release l_subject := "[" + l_workitem_t.project + "] Release - New - " + l_workitem_t.data.item ("name").out + " - " + l_workitem_t.data.item ("version").out l_body := "Release" + "%N%NProject: " + l_workitem_t.project + "%NUser: " + l_workitem_t.user + "%NDate: " + l_formatted_timestamp + "%N%NName: " + l_workitem_t.data.item ("name").out + "%NVersion: " + l_workitem_t.data.item ("version").out + "%NLink: " + l_workitem_t.data.item ("url").out + "%N%NDescription:%N" + l_workitem_t.data.item ("description").out + "%N%NFiles:" l_file_count := l_workitem_t.data.item ("file_count").out.to_integer from i := 1 until i > l_file_count loop l_body := l_body + "%N" + l_workitem_t.data.item ("file_name_" + i.out).out + " (" + l_workitem_t.data.item ("file_platform_" + i.out).out + ")" i := i + 1 end elseif l_workitem_t.type = 3 then -- commit l_subject := "[" + l_workitem_t.project + "] Commit - Rev " + l_workitem_t.data.item ("revision").out l_body := "SVN Commit" + "%N%NProject: " + l_workitem_t.project + "%NUser: " + l_workitem_t.user + "%NDate: " + l_formatted_timestamp + "%NRevision: " + l_workitem_t.data.item ("revision").out + "%NLink: " + l_workitem_t.data.item ("url").out + "%N%NLog:%N" + l_workitem_t.data.item ("log").out + "%N%N" + l_workitem_t.data.item ("diff").out elseif l_workitem_t.type = 4 then -- wiki if l_workitem_t.data.item ("old_revision").out.is_equal ("0") then l_subject := "[" + l_workitem_t.project + "] Wiki - New - " + l_title_striped l_body := "New Wiki Page" + "%N%NProject: " + l_workitem_t.project + "%NUser: " + l_workitem_t.user + "%NDate: " + l_formatted_timestamp + "%NTitle: " + l_title_striped + "%NLink: " + l_workitem_t.data.item ("url").out + "%N%NDiff:%N" + l_workitem_t.data.item ("diff").out else l_subject := "[" + l_workitem_t.project + "] Wiki - Change - " + l_title_striped l_body := "Changed Wiki Page" + "%N%NProject: " + l_workitem_t.project + "%NUser: " + l_workitem_t.user + "%NDate: " + l_formatted_timestamp + "%NTitle: " + l_title_striped + "%NLink: " + l_workitem_t.data.item ("url").out + "%NDiff Link: " + l_workitem_t.data.item ("diffurl").out + "%N%NDiff:%N" + l_workitem_t.data.item ("diff").out end elseif l_workitem_t.type = 5 then -- blog if l_workitem_t.data.item ("old_revision").out.is_equal ("0") then l_subject := "[" + l_workitem_t.project + "] Blog - New - " + l_title_striped l_body := "New Blog Entry" + "%N%NProject: " + l_workitem_t.project + "%NUser: " + l_workitem_t.user + "%NDate: " + l_formatted_timestamp + "%NTitle: " + l_title_striped + "%NLink: " + l_workitem_t.data.item ("url").out + "%N%NDiff:%N" + l_workitem_t.data.item ("diff").out else l_subject := "[" + l_workitem_t.project + "] Blog - Change - " + l_title_striped l_body := "Changed Blog Entry" + "%N%NProject: " + l_workitem_t.project + "%NUser: " + l_workitem_t.user + "%NDate: " + l_formatted_timestamp + "%NTitle: " + l_title_striped + "%NLink: " + l_workitem_t.data.item ("url").out + "%NDiff Link: " + l_workitem_t.data.item ("diffurl").out + "%N%NDiff:%N" + l_workitem_t.data.item ("diff").out end elseif l_workitem_t.type = 6 then -- comment if l_workitem_t.data.item ("is_new").out.is_equal ("true") then l_subject := "[" + l_workitem_t.project + "] Comment - New - " + l_title_striped l_body := "New Comment" + "%N%NProject: " + l_workitem_t.project.out + "%NUser: " + l_workitem_t.user.out + "%NDate: " + l_formatted_timestamp + "%NTitle: " + l_title_striped + "%NLink: " + l_workitem_t.data.item ("url").out + "%N%NComment:%N" + l_workitem_t.data.item ("text").out else l_subject := "[" + l_workitem_t.project + "] Comment - Change - " + l_title_striped l_body := "Changed Comment" + "%N%NProject: " + l_workitem_t.project.out + "%NUser: " + l_workitem_t.user.out + "%NDate: " + l_formatted_timestamp + "%NTitle: " + l_title_striped + "%NLink: " + l_workitem_t.data.item ("url").out + "%N%NComment:%N" + l_workitem_t.data.item ("text").out end end l_addresses := workitem_access.retrieve_mail_addresses (l_msg.workitem_id) else create l_addresses.make (0) l_subject := "" l_body := "" end create l_addresses_reply_msg.make (l_subject, l_body, l_workitem_t.user, l_addresses) node.send_message_reply (l_addresses_reply_msg, a_msg) end feature {NONE} -- Conversion convert_workitems (query_result: ARRAYED_LIST[TUPLE [workitem_id: INTEGER; type: INTEGER; creation_time: INTEGER; project_id: INTEGER; project: STRING; user: STRING; is_read: BOOLEAN]]) : DS_HASH_TABLE [TUPLE [workitem_id: INTEGER; type: INTEGER; creation_time: INTEGER; project_id: INTEGER; project: STRING; user: STRING; data: DS_HASH_TABLE[ANY, STRING]; is_read: BOOLEAN], INTEGER] is -- Converts list representations of workitems (as retrieved from select queries) -- into hash table based representations used for messaging local l_workitem_t: TUPLE [workitem_id: INTEGER; type: INTEGER; creation_time: INTEGER; project_id: INTEGER; project: STRING; user: STRING; data: DS_HASH_TABLE[ANY, STRING]; is_read: BOOLEAN] i: INTEGER do from create Result.make (query_result.count) query_result.start i := 1 until query_result.after loop create l_workitem_t l_workitem_t.workitem_id := query_result.item.workitem_id l_workitem_t.type := query_result.item.type l_workitem_t.creation_time := query_result.item.creation_time l_workitem_t.project_id := query_result.item.project_id l_workitem_t.project := query_result.item.project.out l_workitem_t.user := query_result.item.user.out l_workitem_t.is_read := query_result.item.is_read -- retrieve workitem details l_workitem_t.data := workitem_detail (query_result.item.workitem_id, l_workitem_t.type, l_workitem_t.project_id, l_workitem_t.project, user_access.last_user.user_id, l_workitem_t.user, False) if l_workitem_t.data.count > 0 then Result.force (l_workitem_t, i) i := i + 1 end query_result.forth end end config_parser: ORIGO_CONF_PARSER -- Parser for the origo.conf configuration file once create Result.make_default end end