indexing description: "Provide an interface to project data." author: "Patrick Ruckstuhl " date: "$Date$" revision: "$Revision$" class PROJECT_INTERFACE inherit BASE_INTERFACE redefine make end O_CONFIG_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 project_create (a_msg: O_MESSAGE) is -- Create a new project according to a_msg. require a_msg_ok: a_msg /= Void local l_pc_msg: O_PROJECT_CREATE_MESSAGE l_project: PROJECT l_status: O_GENERAL_STATUS_MESSAGE l_config: O_GENERIC_MESSAGE l_projectname: STRING do l_pc_msg ?= a_msg check project_create_message: l_pc_msg /= Void end l_projectname := l_pc_msg.name.out l_projectname.to_lower create l_project.make l_project.set_name (l_projectname) l_project.set_description (l_pc_msg.description) l_project.set_logo ("no") l_project.set_closed_source (l_pc_msg.is_closed_source) l_project.set_hidden(l_pc_msg.is_hidden) project_access.retrieve_project_by_name (l_project.name) if project_access.is_found then create l_status.make (False, err_project_name_already_used) node.send_message_reply (l_status, a_msg) else project_access.insert_project (l_project) project_access.insert_project_settings (project_access.last_insert_id) create l_config.make (config_namespace, config_project_create_data_type) l_config.add_argument ("project_id", project_access.last_insert_id.out) node.send_message_reply (l_config, a_msg) end end project_retrieve_id (a_msg: O_MESSAGE) is -- Retrieve project id of project specified in a_msg or return an error. require a_msg_ok: a_msg /= Void local l_get_msg: O_PROJECT_RETRIEVE_ID_MESSAGE l_status: O_GENERAL_STATUS_MESSAGE l_reply: O_PROJECT_RETRIEVE_ID_REPLY_MESSAGE l_projectname: STRING do l_get_msg ?= a_msg check project_retrieve_id_message: l_get_msg /= Void end l_projectname := l_get_msg.project_name l_projectname.to_lower project_access.retrieve_project_by_name (l_projectname) if not project_access.is_found then create l_status.make (False, err_project_not_found) node.send_message_reply (l_status, a_msg) else create l_reply.make (project_access.last_project.project_id) node.send_message_reply (l_reply, a_msg) end end project_list (a_msg: O_MESSAGE) is -- List all existing projects. require a_msg_ok: a_msg /= Void local l_pla_msg: O_PROJECT_LIST_ALL_MESSAGE l_msg: O_PROJECT_LIST_MESSAGE l_lst: LIST [PROJECT] l_projects: HASH_TABLE [STRING, INTEGER] l_proj: PROJECT do l_pla_msg ?= a_msg check project_list_all_message: l_pla_msg /= Void end -- retrieve projects and map them into a HASH_TABLE project_access.retrieve_all_projects(l_pla_msg.show_hidden) from l_lst := project_access.last_project_list create l_projects.make (l_lst.count) l_lst.start until l_lst.after loop l_proj := l_lst.item l_projects.force (l_proj.name, l_proj.project_id) l_lst.forth end create l_msg.make (l_projects) node.send_message_reply (l_msg, a_msg) end project_list_partial (a_msg: O_MESSAGE) is -- Return a customized project list starting at a given index and containing a specific number of projects. -- (used for both the internal and external api call - reason: code sharing) require a_msg_ok: a_msg /= Void local l_plp_msg: O_PROJECT_LIST_PARTIAL_MESSAGE l_plp_internal_msg: O_PROJECT_LIST_PARTIAL_INTERNAL_MESSAGE l_reply: O_PROJECT_LIST_MESSAGE l_project_list: LIST [PROJECT] l_projects: HASH_TABLE [STRING, INTEGER] l_project: PROJECT do -- retrieve projects and map them into a HASH_TABLE (name->id) l_plp_msg ?= a_msg if l_plp_msg = Void then l_plp_internal_msg ?= a_msg check project_list_partial_message: l_plp_internal_msg /= Void end project_access.retrieve_partial_projects(l_plp_internal_msg.show_hidden, l_plp_internal_msg.start_index, l_plp_internal_msg.count) else project_access.retrieve_partial_projects(l_plp_msg.show_hidden, l_plp_msg.start_index, l_plp_msg.count) end from l_project_list := project_access.last_project_list create l_projects.make (l_project_list.count) l_project_list.start until l_project_list.after loop l_project := l_project_list.item l_projects.force (l_project.name, l_project.project_id) l_project_list.forth end create l_reply.make (l_projects) node.send_message_reply (l_reply, a_msg) end project (a_msg: O_MESSAGE) is -- Get project information. require a_msg_ok: a_msg /= Void local l_msg: O_PROJECT_MESSAGE l_reply: O_PROJECT_REPLY_MESSAGE l_project: PROJECT l_closed_source: BOOLEAN l_status: O_GENERAL_STATUS_MESSAGE do l_msg ?= a_msg check workitem_message: l_msg /= Void end project_access.retrieve_project_by_id (l_msg.project_id) if project_access.is_found then -- retrieve project l_project := project_access.last_project l_closed_source := l_project.closed_source.is_equal ("true") create l_reply.make (l_project.project_id, l_project.name, l_project.description, l_project.logo, l_closed_source) node.send_message_reply (l_reply, a_msg) else create l_status.make (False, err_invalid_project) node.send_message_reply (l_status, a_msg) end end project_change_group (a_msg: O_MESSAGE) is -- Change access_group of a user for a project. require a_msg_ok: a_msg /= Void local l_msg: O_PROJECT_CHANGE_GROUP_MESSAGE l_status: O_GENERAL_STATUS_MESSAGE l_grp: INTEGER l_user: STRING l_user_ret: USER l_project: INTEGER l_members : LIST [USER] l_was_already_member : BOOLEAN do l_msg ?= a_msg check valid_msg: l_msg /= Void end l_project := l_msg.project l_user := l_msg.user l_grp := l_msg.group -- is the access group valid? if l_grp = 0 or policy_cache.project_access_groups.has (l_grp) then -- is session valid? user_access.retrieve_user_by_session (l_msg.session) if user_access.is_found then -- is user valid? user_access.retrieve_user_by_name (l_user, False) if user_access.is_found then l_user_ret := user_access.last_user -- is project valid? project_access.retrieve_project_by_id (l_project) if project_access.is_found then -- update the workitem subscriptions if l_grp = 0 then -- remove all workitem subscriptions if user hasn't already bookmarked project if not user_access.has_bookmarked_project (l_project, l_user_ret.user_id) then user_access.delete_project_workitem_subscriptions (l_user_ret.user_id, l_project) end else -- don't modify subscriptions if user has a bookmark on this project -- or if the user was previously a member/owner -- else subscribe to all workitems if l_grp = 4 then project_access.retrieve_members (l_project, 3) elseif l_grp = 3 then project_access.retrieve_members (l_project, 4) end l_members := project_access.last_member_list l_was_already_member := False if l_members /= Void then from l_members.start until l_members.after or l_was_already_member loop l_was_already_member := l_members.item.user_id = l_user_ret.user_id l_members.forth end end if not user_access.has_bookmarked_project (l_project, l_user_ret.user_id) and not l_was_already_member then user_access.insert_all_project_workitem_subscriptions (l_user_ret.user_id, l_project) end end -- update the user role user_access.update_user_project_association (l_project, l_user_ret.user_id, l_grp) -- retrieve the user and team associations and add them to the cache in case the user was logged in policy_cache.retrieve_associations (l_user_ret.user_id) 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_invalid_session) end else create l_status.make (False, err_invalid_group) end -- send status node.send_message_reply (l_status, a_msg) end project_list_of_user (a_msg: O_MESSAGE) is -- List all projects of which a user is developer or owner require a_msg_ok: a_msg /= Void local l_msg: O_PROJECT_LIST_OF_USER_MESSAGE l_reply: O_PROJECT_LIST_OF_USER_REPLY_MESSAGE l_user_projects: HASH_TABLE [TUPLE[project_name: STRING; group: INTEGER], INTEGER] l_list_tuple: TUPLE[project_name: STRING; group: INTEGER] l_query_result: ARRAYED_LIST[TUPLE[project_id: INTEGER; project_name: STRING; group: INTEGER]] l_status: O_GENERAL_STATUS_MESSAGE do l_msg ?= a_msg check project_list_of_user_message: l_msg /= Void end user_access.retrieve_user_by_name (l_msg.user, False) if user_access.is_found then -- retrieve projects and map them into a HASH_TABLE l_query_result := project_access.retrieve_projects_of_user(l_msg.user) from create l_user_projects.make (l_query_result.count) l_query_result.start until l_query_result.after loop create l_list_tuple l_list_tuple.project_name := l_query_result.item.project_name l_list_tuple.group := l_query_result.item.group l_user_projects.force (l_list_tuple, l_query_result.item.project_id) l_query_result.forth end create l_reply.make (l_user_projects) node.send_message_reply (l_reply, a_msg) else create l_status.make (False, err_invalid_user) node.send_message_reply (l_status, a_msg) end end project_members (a_msg: O_MESSAGE) is -- List project members. require a_msg_ok: a_msg /= Void local l_msg: O_PROJECT_MEMBERS_MESSAGE l_reply: O_USER_LIST_MESSAGE l_lst: LIST [USER] l_members: HASH_TABLE [STRING, INTEGER] l_usr: USER do l_msg ?= a_msg check project_members_message: l_msg /= Void end -- retrieve users and map them into a HASH_TABLE project_access.retrieve_members (l_msg.project, l_msg.group) from l_lst := project_access.last_member_list create l_members.make (l_lst.count) l_lst.start until l_lst.after loop l_usr := l_lst.item l_members.force (l_usr.name, l_usr.user_id) l_lst.forth end create l_reply.make (l_members) node.send_message_reply (l_reply, a_msg) end project_bookmarkers (a_msg: O_MESSAGE) is -- List project bookmarkers. require a_msg_ok: a_msg /= Void local l_msg: O_PROJECT_LIST_BOOKMARKERS_MESSAGE l_reply: O_USER_LIST_MESSAGE l_user_list: LIST [USER] l_bookmarkers: HASH_TABLE [STRING, INTEGER] l_user: USER do l_msg ?= a_msg check valid_message: l_msg /= Void end -- retrieve users and map them into a HASH_TABLE project_access.retrieve_bookmarkers (l_msg.project_id) from l_user_list := project_access.last_bookmarker_list create l_bookmarkers.make (l_user_list.count) l_user_list.start until l_user_list.after loop l_user := l_user_list.item l_bookmarkers.force (l_user.name, l_user.user_id) l_user_list.forth end create l_reply.make (l_bookmarkers) node.send_message_reply (l_reply, a_msg) end project_list_communities (a_msg: O_MESSAGE) is -- List communities of a project. require a_msg_ok: a_msg /= Void local l_msg: O_PROJECT_LIST_COMMUNITIES_MESSAGE l_reply: O_COMMUNITY_LIST_REPLY_MESSAGE l_status: O_GENERAL_STATUS_MESSAGE l_list: LIST [COMMUNITY] l_communities: DS_ARRAYED_LIST [STRING] l_community: COMMUNITY do l_msg ?= a_msg check valid_message: l_msg /= Void end user_access.retrieve_user_by_session (l_msg.session) if user_access.is_found then project_access.retrieve_project_by_id (l_msg.project_id) if project_access.is_found then -- retrieve communities and map them into a LIST community_access.retrieve_communities_of_project (l_msg.project_id) from l_list := community_access.last_community_list create l_communities.make (l_list.count) l_list.start until l_list.after loop l_community := l_list.item l_communities.force_last (l_community.name) l_list.forth end create l_reply.make (l_communities) node.send_message_reply (l_reply, a_msg) else create l_status.make (False, err_invalid_project) node.send_message_reply (l_status, a_msg) end else create l_status.make (False, err_invalid_session) node.send_message_reply (l_status, a_msg) end end project_change_description (a_msg: O_MESSAGE) is -- Change description of a project require a_msg_ok: a_msg /= Void local l_msg: O_PROJECT_CHANGE_DESCRIPTION_MESSAGE l_status: O_GENERAL_STATUS_MESSAGE do l_msg ?= a_msg check valid_msg: l_msg /= Void end user_access.retrieve_user_by_session (l_msg.session) if user_access.is_found then project_access.retrieve_project_by_id (l_msg.project_id) if project_access.is_found then project_access.update_project_description (l_msg.project_id, l_msg.description) create l_status.make (True, Void) else create l_status.make (False, err_invalid_project) end else create l_status.make (False, err_invalid_session) end -- send status node.send_message_reply (l_status, a_msg) end project_change_logo (a_msg: O_MESSAGE) is -- Change logo of a project require a_msg_ok: a_msg /= Void local l_msg: O_PROJECT_CHANGE_LOGO_MESSAGE l_status: O_GENERAL_STATUS_MESSAGE do l_msg ?= a_msg check valid_msg: l_msg /= Void end project_access.retrieve_project_by_id (l_msg.project_id) if project_access.is_found then project_access.update_project_logo (l_msg.project_id, l_msg.logo) create l_status.make (True, Void) else create l_status.make (False, err_invalid_project) end -- send status node.send_message_reply (l_status, a_msg) end project_list_internal (a_msg: O_MESSAGE) is -- List all existing projects. require a_msg_ok: a_msg /= Void local l_pla_msg: O_PROJECT_LIST_ALL_INTERNAL_MESSAGE l_msg: O_PROJECT_LIST_MESSAGE l_lst: LIST [PROJECT] l_projects: HASH_TABLE [STRING, INTEGER] l_proj: PROJECT do l_pla_msg ?= a_msg check project_list_all_message: l_pla_msg /= Void end -- retrieve projects and map them into a HASH_TABLE project_access.retrieve_all_projects(l_pla_msg.show_hidden) from l_lst := project_access.last_project_list create l_projects.make (l_lst.count) l_lst.start until l_lst.after loop l_proj := l_lst.item l_projects.force (l_proj.name, l_proj.project_id) l_lst.forth end create l_msg.make (l_projects) node.send_message_reply (l_msg, a_msg) end project_internal (a_msg: O_MESSAGE) is -- Get project information. require a_msg_ok: a_msg /= Void local l_msg: O_PROJECT_INTERNAL_MESSAGE l_reply: O_PROJECT_REPLY_MESSAGE l_project: PROJECT l_closed_source: BOOLEAN l_status: O_GENERAL_STATUS_MESSAGE do l_msg ?= a_msg check workitem_message: l_msg /= Void end project_access.retrieve_project_by_id (l_msg.project_id) if project_access.is_found then -- retrieve project l_project := project_access.last_project l_closed_source := l_project.closed_source.is_equal ("true") create l_reply.make (l_project.project_id, l_project.name, l_project.description, l_project.logo, l_closed_source) node.send_message_reply (l_reply, a_msg) else create l_status.make (False, err_invalid_project) node.send_message_reply (l_status, a_msg) end end project_request_add (a_msg: O_MESSAGE) is -- Create a new project request according to a_msg. require a_msg_ok: a_msg /= Void local l_msg: O_PROJECT_REQUEST_ADD_MESSAGE l_project_request: PROJECT_REQUEST l_status: O_GENERAL_STATUS_MESSAGE l_projectname: STRING do l_msg ?= a_msg check project_request_add_message: l_msg /= Void end l_projectname := l_msg.name.out l_projectname.to_lower create l_project_request.make l_project_request.set_name (l_projectname) l_project_request.set_description (l_msg.description) l_project_request.set_closed_source (l_msg.is_closed_source) l_project_request.set_message (l_msg.message) user_access.retrieve_user_by_session (l_msg.session) if user_access.is_found then l_project_request.set_user_id (user_access.last_user.user_id) --check if name is used in active project project_access.retrieve_project_by_name (l_projectname) if project_access.is_found then create l_status.make (False, err_project_name_already_used) else --check if name is used in project request project_access.retrieve_project_request_by_name (l_projectname) if project_access.is_found then create l_status.make (False, err_project_name_already_used) else project_access.insert_project_request (l_project_request) create l_status.make (True, Void) end end else create l_status.make (False, err_invalid_user) end node.send_message_reply (l_status, a_msg) end project_request_retrieve (a_msg: O_MESSAGE) is -- Get project request. require a_msg_ok: a_msg /= Void local l_msg: O_PROJECT_REQUEST_RETRIEVE_MESSAGE l_reply: O_PROJECT_REQUEST_RETRIEVE_REPLY_MESSAGE l_project_request: PROJECT_REQUEST l_status: O_GENERAL_STATUS_MESSAGE do l_msg ?= a_msg check valid_message: l_msg /= Void end project_access.retrieve_project_request_by_name (l_msg.request_project_name) if project_access.is_found then -- retrieve project request l_project_request := project_access.last_project_request user_access.retrieve_user_by_id (l_project_request.user_id) if user_access.is_found then create l_reply.make (l_project_request.request_id, user_access.last_user.name, user_access.last_user.email, l_project_request.name, l_project_request.description, l_project_request.closed_source, l_project_request.message) node.send_message_reply (l_reply, a_msg) else create l_status.make (False, err_invalid_user) node.send_message_reply (l_status, a_msg) end else create l_status.make (False, err_invalid_project_request) node.send_message_reply (l_status, a_msg) end end project_retrieve_statistics (a_msg: O_MESSAGE) is -- retrieve project statistics (used for both the internal and external api call - code sharing) require a_msg_ok: a_msg /= Void local l_msg: O_PROJECT_RETRIEVE_STATISTICS_MESSAGE l_msg_internal: O_PROJECT_RETRIEVE_STATISTICS_INTERNAL_MESSAGE l_reply: O_PROJECT_RETRIEVE_STATISTICS_REPLY_MESSAGE l_statistics: DS_HASH_TABLE[INTEGER, STRING] do l_msg ?= a_msg if l_msg = Void then l_msg_internal ?= a_msg check valid_message: l_msg_internal /= Void end end -- retrieve statistics l_statistics := project_access.retrieve_statistics create l_reply.make (l_statistics.item ("project_count"), l_statistics.item ("open_source_count")) node.send_message_reply (l_reply, a_msg) end project_change_settings (a_msg: O_MESSAGE) is -- Change project settings require a_msg_ok: a_msg /= Void local l_pc_msg: O_PROJECT_CHANGE_SETTINGS_MESSAGE l_status: O_GENERAL_STATUS_MESSAGE l_user_ret: USER l_setting_type: STRING l_setting_value: STRING do l_pc_msg ?= a_msg check valid_message: l_pc_msg /= Void end user_access.retrieve_user_by_session (l_pc_msg.session) if user_access.is_found then project_access.retrieve_project_by_id (l_pc_msg.project_id) if project_access.is_found then l_user_ret := user_access.last_user from l_pc_msg.settings.start until l_pc_msg.settings.after loop l_setting_type := l_pc_msg.settings.item.setting_type l_setting_value := l_pc_msg.settings.item.setting_value project_access.update_project_settings (l_pc_msg.project_id, l_setting_type, l_setting_value) l_pc_msg.settings.forth end create l_status.make (True, Void) else create l_status.make (False, err_invalid_project) end else create l_status.make (False, err_invalid_user) end node.send_message_reply (l_status, a_msg) end end