Fisheye: Tag 85ef8aca5722a36582117db1e8b988e2c16b6369 refers to a dead (removed) revision in file `lams_admin/src/java/org/lamsfoundation/lams/admin/web/ConfigAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 85ef8aca5722a36582117db1e8b988e2c16b6369 refers to a dead (removed) revision in file `lams_admin/src/java/org/lamsfoundation/lams/admin/web/DisabledUserManageAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 85ef8aca5722a36582117db1e8b988e2c16b6369 refers to a dead (removed) revision in file `lams_admin/src/java/org/lamsfoundation/lams/admin/web/ImportExcelAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 85ef8aca5722a36582117db1e8b988e2c16b6369 refers to a dead (removed) revision in file `lams_admin/src/java/org/lamsfoundation/lams/admin/web/ImportExcelForm.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 85ef8aca5722a36582117db1e8b988e2c16b6369 refers to a dead (removed) revision in file `lams_admin/src/java/org/lamsfoundation/lams/admin/web/ImportExcelSaveAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 85ef8aca5722a36582117db1e8b988e2c16b6369 refers to a dead (removed) revision in file `lams_admin/src/java/org/lamsfoundation/lams/admin/web/LoginMaintainAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 85ef8aca5722a36582117db1e8b988e2c16b6369 refers to a dead (removed) revision in file `lams_admin/src/java/org/lamsfoundation/lams/admin/web/LoginSaveAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 85ef8aca5722a36582117db1e8b988e2c16b6369 refers to a dead (removed) revision in file `lams_admin/src/java/org/lamsfoundation/lams/admin/web/OrgManageAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 85ef8aca5722a36582117db1e8b988e2c16b6369 refers to a dead (removed) revision in file `lams_admin/src/java/org/lamsfoundation/lams/admin/web/OrgManageBean.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 85ef8aca5722a36582117db1e8b988e2c16b6369 refers to a dead (removed) revision in file `lams_admin/src/java/org/lamsfoundation/lams/admin/web/OrgSaveAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 85ef8aca5722a36582117db1e8b988e2c16b6369 refers to a dead (removed) revision in file `lams_admin/src/java/org/lamsfoundation/lams/admin/web/OrganisationAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 85ef8aca5722a36582117db1e8b988e2c16b6369 refers to a dead (removed) revision in file `lams_admin/src/java/org/lamsfoundation/lams/admin/web/ScheduledJobDTO.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 85ef8aca5722a36582117db1e8b988e2c16b6369 refers to a dead (removed) revision in file `lams_admin/src/java/org/lamsfoundation/lams/admin/web/ScheduledJobListAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 85ef8aca5722a36582117db1e8b988e2c16b6369 refers to a dead (removed) revision in file `lams_admin/src/java/org/lamsfoundation/lams/admin/web/ServerListAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 85ef8aca5722a36582117db1e8b988e2c16b6369 refers to a dead (removed) revision in file `lams_admin/src/java/org/lamsfoundation/lams/admin/web/ServerMaintainAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 85ef8aca5722a36582117db1e8b988e2c16b6369 refers to a dead (removed) revision in file `lams_admin/src/java/org/lamsfoundation/lams/admin/web/ServerSaveAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 85ef8aca5722a36582117db1e8b988e2c16b6369 refers to a dead (removed) revision in file `lams_admin/src/java/org/lamsfoundation/lams/admin/web/ToolContentListAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 85ef8aca5722a36582117db1e8b988e2c16b6369 refers to a dead (removed) revision in file `lams_admin/src/java/org/lamsfoundation/lams/admin/web/UserAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 85ef8aca5722a36582117db1e8b988e2c16b6369 refers to a dead (removed) revision in file `lams_admin/src/java/org/lamsfoundation/lams/admin/web/UserBean.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 85ef8aca5722a36582117db1e8b988e2c16b6369 refers to a dead (removed) revision in file `lams_admin/src/java/org/lamsfoundation/lams/admin/web/UserListDTO.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 85ef8aca5722a36582117db1e8b988e2c16b6369 refers to a dead (removed) revision in file `lams_admin/src/java/org/lamsfoundation/lams/admin/web/UserManageAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 85ef8aca5722a36582117db1e8b988e2c16b6369 refers to a dead (removed) revision in file `lams_admin/src/java/org/lamsfoundation/lams/admin/web/UserOrgAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 85ef8aca5722a36582117db1e8b988e2c16b6369 refers to a dead (removed) revision in file `lams_admin/src/java/org/lamsfoundation/lams/admin/web/UserOrgRoleAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 85ef8aca5722a36582117db1e8b988e2c16b6369 refers to a dead (removed) revision in file `lams_admin/src/java/org/lamsfoundation/lams/admin/web/UserOrgRoleForm.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 85ef8aca5722a36582117db1e8b988e2c16b6369 refers to a dead (removed) revision in file `lams_admin/src/java/org/lamsfoundation/lams/admin/web/UserOrgRoleSaveAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 85ef8aca5722a36582117db1e8b988e2c16b6369 refers to a dead (removed) revision in file `lams_admin/src/java/org/lamsfoundation/lams/admin/web/UserOrgSaveAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 85ef8aca5722a36582117db1e8b988e2c16b6369 refers to a dead (removed) revision in file `lams_admin/src/java/org/lamsfoundation/lams/admin/web/UserRolesAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 85ef8aca5722a36582117db1e8b988e2c16b6369 refers to a dead (removed) revision in file `lams_admin/src/java/org/lamsfoundation/lams/admin/web/UserRolesSaveAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 85ef8aca5722a36582117db1e8b988e2c16b6369 refers to a dead (removed) revision in file `lams_admin/src/java/org/lamsfoundation/lams/admin/web/UserSaveAction.java'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 85ef8aca5722a36582117db1e8b988e2c16b6369 refers to a dead (removed) revision in file `lams_admin/src/java/org/lamsfoundation/lams/admin/web/UserSearchAction.java'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/ConfigAction.java =================================================================== diff -u --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/ConfigAction.java (revision 0) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/ConfigAction.java (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -0,0 +1,141 @@ +/**************************************************************** + * Copyright (C) 2006 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ +package org.lamsfoundation.lams.admin.web.action; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang.StringUtils; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.struts.action.DynaActionForm; +import org.lamsfoundation.lams.admin.service.AdminServiceProxy; +import org.lamsfoundation.lams.config.ConfigurationItem; +import org.lamsfoundation.lams.util.Configuration; +import org.lamsfoundation.lams.util.MessageService; +import org.lamsfoundation.lams.web.action.LamsDispatchAction; + +/** + * ConfigAction + * + * @author Mitchell Seaton + */ +/** + * struts doclets + * + * + * + * + * + */ +public class ConfigAction extends LamsDispatchAction { + + private static Configuration configurationService; + private static MessageService messageService; + + private Configuration getConfiguration() { + if (configurationService == null) { + configurationService = AdminServiceProxy.getConfiguration(getServlet().getServletContext()); + } + return configurationService; + } + + private MessageService getMessageService() { + if (messageService == null) { + messageService = AdminServiceProxy.getMessageService(getServlet().getServletContext()); + } + return messageService; + } + + @Override + public ActionForward unspecified(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + + request.setAttribute("config", getConfiguration().arrangeItems(Configuration.ITEMS_NON_LDAP)); + + return mapping.findForward("config"); + } + + public ActionForward save(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + + if (isCancelled(request)) { + return mapping.findForward("sysadmin"); + } + + DynaActionForm configForm = (DynaActionForm) form; + String[] keys = (String[]) configForm.get("key"); + String[] values = (String[]) configForm.get("value"); + + String errorForward = "config"; + + for (int i = 0; i < keys.length; i++) { + ConfigurationItem item = getConfiguration().getConfigItemByKey(keys[i]); + + if (item != null) { + // return to ldap page if that's where we came from + if (StringUtils.contains(item.getHeaderName(), "config.header.ldap")) { + errorForward = "ldap"; + } + + if (item.getRequired()) { + if (!(values[i] != null && values[i].length() > 0)) { + request.setAttribute("error", getRequiredError(item.getDescriptionKey())); + request.setAttribute("config", getConfiguration().arrangeItems(Configuration.ITEMS_NON_LDAP)); + return mapping.findForward(errorForward); + } + } + String format = item.getFormat(); + if (format != null && format.equals(ConfigurationItem.LONG_FORMAT)) { + try { + Long.parseLong(values[i]); + } catch (NumberFormatException e) { + request.setAttribute("error", getNumericError(item.getDescriptionKey())); + request.setAttribute("config", getConfiguration().arrangeItems(Configuration.ITEMS_NON_LDAP)); + return mapping.findForward(errorForward); + } + } + Configuration.updateItem(keys[i], values[i]); + } + } + getConfiguration().persistUpdate(); + + Configuration.refreshCache(); + + return mapping.findForward("sysadmin"); + } + + private String getRequiredError(String arg) { + String[] args = new String[1]; + args[0] = getMessageService().getMessage(arg); + return getMessageService().getMessage("error.required", args); + } + + private String getNumericError(String arg) { + String[] args = new String[1]; + args[0] = getMessageService().getMessage(arg); + return getMessageService().getMessage("error.numeric", args); + } + +} Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/DisabledUserManageAction.java =================================================================== diff -u --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/DisabledUserManageAction.java (revision 0) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/DisabledUserManageAction.java (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -0,0 +1,73 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + +package org.lamsfoundation.lams.admin.web.action; + +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; +import org.apache.struts.action.Action; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.lamsfoundation.lams.admin.service.AdminServiceProxy; +import org.lamsfoundation.lams.usermanagement.Role; +import org.lamsfoundation.lams.usermanagement.User; +import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; + +/** + * @author jliew + * + * + * + * + */ +public class DisabledUserManageAction extends Action { + + private static final Logger log = Logger.getLogger(DisabledUserManageAction.class); + + @Override + public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + + IUserManagementService service = AdminServiceProxy.getService(getServlet().getServletContext()); + + if (!(request.isUserInRole(Role.SYSADMIN) || service.isUserGlobalGroupAdmin())) { + request.setAttribute("errorName", "DisabledUserManageAction"); + request.setAttribute("errorMessage", AdminServiceProxy.getMessageService(getServlet().getServletContext()) + .getMessage("error.need.sysadmin")); + return mapping.findForward("error"); + } + + List users = service.findByProperty(User.class, "disabledFlag", true); + log.debug("got " + users.size() + " disabled users"); + request.setAttribute("users", users); + + return mapping.findForward("disabledlist"); + } + +} Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/ImportExcelAction.java =================================================================== diff -u --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/ImportExcelAction.java (revision 0) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/ImportExcelAction.java (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -0,0 +1,61 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + +package org.lamsfoundation.lams.admin.web.action; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts.action.Action; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.lamsfoundation.lams.admin.web.form.ImportExcelForm; +import org.lamsfoundation.lams.util.WebUtil; + +/** + * @author jliew + * + * + * + * + * + * + * + */ +public class ImportExcelAction extends Action { + + @Override + public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + + Integer orgId = WebUtil.readIntParam(request, "orgId", true); + //if (orgId==null) orgId = (Integer)request.getAttribute("orgId"); + + ImportExcelForm importExcelForm = (ImportExcelForm) form; + importExcelForm.setOrgId(orgId); + + return mapping.findForward("importexcel"); + } + +} Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/ImportExcelSaveAction.java =================================================================== diff -u --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/ImportExcelSaveAction.java (revision 0) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/ImportExcelSaveAction.java (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -0,0 +1,109 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + +package org.lamsfoundation.lams.admin.web.action; + +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts.action.Action; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.struts.upload.FormFile; +import org.lamsfoundation.lams.admin.service.AdminServiceProxy; +import org.lamsfoundation.lams.admin.service.IImportService; +import org.lamsfoundation.lams.admin.web.form.ImportExcelForm; +import org.lamsfoundation.lams.web.session.SessionManager; + +/** + * @author jliew + * + * + * + * + * + * + * + * + * + * + * + * + */ +public class ImportExcelSaveAction extends Action { + + @Override + public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + + if (isCancelled(request)) { + return mapping.findForward("sysadmin"); + } + + IImportService importService = AdminServiceProxy.getImportService(getServlet().getServletContext()); + ImportExcelForm importExcelForm = (ImportExcelForm) form; + FormFile file = importExcelForm.getFile(); + + // validation + if (file == null || file.getFileSize() <= 0) { + return mapping.findForward("import"); + } + + String sessionId = SessionManager.getSession().getId(); + SessionManager.getSession().setAttribute(IImportService.IMPORT_FILE, file); + // use a new thread only if number of users is > threshold + if (importService.getNumRows(file) < IImportService.THRESHOLD) { + List results = importService.parseSpreadsheet(file, sessionId); + SessionManager.getSession(sessionId).setAttribute(IImportService.IMPORT_RESULTS, results); + return mapping.findForward("results"); + } else { + Thread t = new Thread(new ImportExcelThread(sessionId)); + t.start(); + return mapping.findForward("status"); + } + } + + private class ImportExcelThread implements Runnable { + private String sessionId; + + public ImportExcelThread(String sessionId) { + this.sessionId = sessionId; + } + + @Override + public void run() { + IImportService importService = AdminServiceProxy.getImportService(getServlet().getServletContext()); + try { + FormFile file = (FormFile) SessionManager.getSession(sessionId) + .getAttribute(IImportService.IMPORT_FILE); + List results = importService.parseSpreadsheet(file, sessionId); + SessionManager.getSession(sessionId).setAttribute(IImportService.IMPORT_RESULTS, results); + } catch (Exception e) { + } + } + } + +} Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/ImportGroupsAction.java =================================================================== diff -u -r51fb2a37254f24bb2a805d4ffd54482c779f43fa -r85ef8aca5722a36582117db1e8b988e2c16b6369 --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/ImportGroupsAction.java (.../ImportGroupsAction.java) (revision 51fb2a37254f24bb2a805d4ffd54482c779f43fa) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/ImportGroupsAction.java (.../ImportGroupsAction.java) (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -35,7 +35,7 @@ import org.apache.struts.upload.FormFile; import org.lamsfoundation.lams.admin.service.AdminServiceProxy; import org.lamsfoundation.lams.admin.service.IImportService; -import org.lamsfoundation.lams.admin.web.ImportExcelForm; +import org.lamsfoundation.lams.admin.web.form.ImportExcelForm; /** * @author jliew Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/LoginMaintainAction.java =================================================================== diff -u --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/LoginMaintainAction.java (revision 0) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/LoginMaintainAction.java (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -0,0 +1,95 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ +package org.lamsfoundation.lams.admin.web.action; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.Charset; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts.action.Action; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.struts.action.DynaActionForm; +import org.lamsfoundation.lams.util.Configuration; +import org.lamsfoundation.lams.util.ConfigurationKeys; + +/** + *

+ * View Source + *

+ * + * @author Fei Yang + */ + +/** + * struts doclets + * + * + * + * + * + * + */ +public class LoginMaintainAction extends Action { + + private static final String NEWS_PAGE_PATH_SUFFIX = File.separatorChar + "lams-www.war" + File.separatorChar + + "news.html"; + + @Override + public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + + DynaActionForm loginMaintainForm = (DynaActionForm) form; + loginMaintainForm.set("news", loadNews()); + return mapping.findForward("loginmaintain"); + } + + private String loadNews() throws IOException { + BufferedReader bReader = null; + try { + InputStreamReader ir = new InputStreamReader( + new FileInputStream(Configuration.get(ConfigurationKeys.LAMS_EAR_DIR) + NEWS_PAGE_PATH_SUFFIX), + Charset.forName("UTF-8")); + bReader = new BufferedReader(ir); + StringBuilder news = new StringBuilder(); + String line = bReader.readLine(); + while (line != null) { + news.append(line).append('\n'); + line = bReader.readLine(); + } + return news.toString(); + } finally { + if (bReader != null) { + bReader.close(); + } + } + } + +} Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/LoginSaveAction.java =================================================================== diff -u --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/LoginSaveAction.java (revision 0) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/LoginSaveAction.java (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -0,0 +1,78 @@ +/**************************************************************** + * Copyright (C) 2006 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +package org.lamsfoundation.lams.admin.web.action; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileOutputStream; +import java.io.OutputStreamWriter; +import java.nio.charset.Charset; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.struts.action.DynaActionForm; +import org.lamsfoundation.lams.util.Configuration; +import org.lamsfoundation.lams.util.ConfigurationKeys; +import org.lamsfoundation.lams.web.action.LamsDispatchAction; + +/** + * Use DispatchAction for future extension convenience, e.g. add preview feature + * + * @author Fei Yang + */ +public class LoginSaveAction extends LamsDispatchAction { + + private static final String NEWS_PAGE_PATH_SUFFIX = File.separatorChar + "lams-www.war" + File.separatorChar + + "news.html"; + + public ActionForward save(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + + if (isCancelled(request)) { + return mapping.findForward("sysadmin"); + } + + DynaActionForm loginMaintainForm = (DynaActionForm) form; + BufferedWriter bWriter = null; + try { + OutputStreamWriter ow = new OutputStreamWriter(new FileOutputStream( + Configuration.get(ConfigurationKeys.LAMS_EAR_DIR) + NEWS_PAGE_PATH_SUFFIX), + Charset.forName("UTF-8")); + bWriter = new BufferedWriter(ow); + bWriter.write(loginMaintainForm.getString("news")); + bWriter.flush(); + } finally { + if (bWriter != null) { + bWriter.close(); + } + } + + return mapping.findForward("sysadmin"); + } + +} Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/OrgManageAction.java =================================================================== diff -u --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/OrgManageAction.java (revision 0) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/OrgManageAction.java (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -0,0 +1,232 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ +package org.lamsfoundation.lams.admin.web.action; + +import java.io.IOException; +import java.util.List; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang.StringEscapeUtils; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.tomcat.util.json.JSONArray; +import org.apache.tomcat.util.json.JSONException; +import org.apache.tomcat.util.json.JSONObject; +import org.lamsfoundation.lams.admin.service.AdminServiceProxy; +import org.lamsfoundation.lams.admin.web.form.OrgManageForm; +import org.lamsfoundation.lams.security.ISecurityService; +import org.lamsfoundation.lams.usermanagement.Organisation; +import org.lamsfoundation.lams.usermanagement.OrganisationState; +import org.lamsfoundation.lams.usermanagement.OrganisationType; +import org.lamsfoundation.lams.usermanagement.Role; +import org.lamsfoundation.lams.usermanagement.dto.UserDTO; +import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; +import org.lamsfoundation.lams.usermanagement.service.UserManagementService; +import org.lamsfoundation.lams.util.MessageService; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.action.LamsDispatchAction; +import org.lamsfoundation.lams.web.session.SessionManager; +import org.lamsfoundation.lams.web.util.AttributeNames; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.WebApplicationContextUtils; + +/** + *

+ * View Source + *

+ * + * @author Fei Yang + */ +public class OrgManageAction extends LamsDispatchAction { + + private static IUserManagementService userManagementService; + + @SuppressWarnings("unchecked") + @Override + public ActionForward unspecified(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + initServices(); + + // Get organisation whose child organisations we will populate the OrgManageForm with + Integer orgId = WebUtil.readIntParam(request, "org", true); + if (orgId == null) { + orgId = (Integer) request.getAttribute("org"); + } + if ((orgId == null) || (orgId == 0)) { + response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Missing organisation ID"); + return null; + } + + // get logged in user's id + Integer userId = ((UserDTO) SessionManager.getSession().getAttribute(AttributeNames.USER)).getUserID(); + ISecurityService securityService = AdminServiceProxy.getSecurityService(getServlet().getServletContext()); + + Organisation org = null; + boolean isRootOrganisation = false; + Organisation rootOrganisation = userManagementService.getRootOrganisation(); + if (orgId.equals(rootOrganisation.getOrganisationId())) { + org = rootOrganisation; + isRootOrganisation = true; + } else { + org = (Organisation) userManagementService.findById(Organisation.class, orgId); + } + + // check if user is allowed to view and edit groups + if (!request.isUserInRole(Role.SYSADMIN) && !(isRootOrganisation + ? request.isUserInRole(Role.GROUP_ADMIN) || request.isUserInRole(Role.GROUP_MANAGER) + : securityService.hasOrgRole(orgId, userId, new String[] { Role.GROUP_ADMIN, Role.GROUP_MANAGER }, + "manage courses", false))) { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "User is not a manager or admin in the organisation"); + return null; + } + + // get number of users figure + // TODO use hql that does a count instead of getting whole objects + int numUsers = org == rootOrganisation ? userManagementService.getCountUsers() + : userManagementService.getUsersFromOrganisation(orgId).size(); + String key = org == rootOrganisation ? "label.users.in.system" : "label.users.in.group"; + MessageService messageService = AdminServiceProxy.getMessageService(getServlet().getServletContext()); + request.setAttribute("numUsers", messageService.getMessage(key, new String[] { String.valueOf(numUsers) })); + + // Set OrgManageForm + OrgManageForm orgManageForm = (OrgManageForm) form; + if (orgManageForm == null) { + orgManageForm = new OrgManageForm(); + orgManageForm.setStateId(OrganisationState.ACTIVE); + } else if (orgManageForm.getStateId() == null) { + orgManageForm.setStateId(OrganisationState.ACTIVE); + } + orgManageForm.setParentId(orgId); + orgManageForm.setParentName(org.getName()); + orgManageForm.setType(org.getOrganisationType().getOrganisationTypeId()); + + // Get list of child organisations depending on requestor's role and the organisation's type + if (orgManageForm.getType().equals(OrganisationType.CLASS_TYPE)) { + // display class info, with parent group's 'courseAdminCan...' permissions. + // note the org is not saved, properties set only for passing to view component. + Organisation pOrg = org.getParentOrganisation(); + org.setCourseAdminCanAddNewUsers(pOrg.getCourseAdminCanAddNewUsers()); + org.setCourseAdminCanBrowseAllUsers(pOrg.getCourseAdminCanBrowseAllUsers()); + org.setCourseAdminCanChangeStatusOfCourse(pOrg.getCourseAdminCanChangeStatusOfCourse()); + request.setAttribute("org", org); + + // display parent org breadcrumb link + request.setAttribute("parentGroupName", pOrg.getName()); + request.setAttribute("parentGroupId", pOrg.getOrganisationId()); + } else { + request.setAttribute("OrgManageForm", orgManageForm); + + // display org info + request.setAttribute("org", org); + } + + // let the jsp know whether to display links + request.setAttribute("createGroup", + request.isUserInRole(Role.SYSADMIN) || userManagementService.isUserGlobalGroupAdmin()); + request.setAttribute("editGroup", true); + request.setAttribute("manageGlobalRoles", request.isUserInRole(Role.SYSADMIN)); + return mapping.findForward("orglist"); + } + + /** + * Returns list of organisations for . + */ + public ActionForward getOrgs(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse res) throws IOException, ServletException, JSONException { + initServices(); + + Integer parentOrgId = WebUtil.readIntParam(request, "parentOrgId"); + Integer stateId = WebUtil.readIntParam(request, "stateId"); + Integer typeIdParam = WebUtil.readIntParam(request, "type"); + // the organisation type of the children + Integer typeId = (typeIdParam.equals(OrganisationType.ROOT_TYPE) ? OrganisationType.COURSE_TYPE + : OrganisationType.CLASS_TYPE); + String searchString = WebUtil.readStrParam(request, "fcol[1]", true); + + // paging parameters of tablesorter + int size = WebUtil.readIntParam(request, "size"); + int page = WebUtil.readIntParam(request, "page"); + Integer isSort1 = WebUtil.readIntParam(request, "column[0]", true); + Integer isSort2 = WebUtil.readIntParam(request, "column[1]", true); + Integer isSort3 = WebUtil.readIntParam(request, "column[2]", true); + Integer isSort4 = WebUtil.readIntParam(request, "column[3]", true); + + String sortBy = ""; + String sortOrder = ""; + if (isSort1 != null) { + sortBy = "id"; + sortOrder = isSort1.equals(0) ? "ASC" : "DESC"; + + } else if (isSort2 != null) { + sortBy = "name"; + sortOrder = isSort2.equals(0) ? "ASC" : "DESC"; + + } else if (isSort3 != null) { + sortBy = "code"; + sortOrder = isSort3.equals(0) ? "ASC" : "DESC"; + + } else if (isSort4 != null) { + sortBy = "description"; + sortOrder = isSort4.equals(0) ? "ASC" : "DESC"; + + } + + List organisations = userManagementService.getPagedCourses(parentOrgId, typeId, stateId, page, + size, sortBy, sortOrder, searchString); + + JSONObject responcedata = new JSONObject(); + responcedata.put("total_rows", userManagementService.getCountCoursesByParentCourseAndTypeAndState(parentOrgId, + typeId, stateId, searchString)); + + JSONArray rows = new JSONArray(); + for (Organisation organisation : organisations) { + + JSONObject responseRow = new JSONObject(); + responseRow.put("id", organisation.getOrganisationId()); + String orgName = organisation.getName() == null ? "" : organisation.getName(); + responseRow.put("name", StringEscapeUtils.escapeHtml(orgName)); + String orgCode = organisation.getCode() == null ? "" : organisation.getCode(); + responseRow.put("code", StringEscapeUtils.escapeHtml(orgCode)); + String orgDescription = organisation.getDescription() == null ? "" : organisation.getDescription(); + responseRow.put("description", StringEscapeUtils.escapeHtml(orgDescription)); + + rows.put(responseRow); + } + responcedata.put("rows", rows); + res.setContentType("application/json;charset=utf-8"); + res.getWriter().print(new String(responcedata.toString())); + return null; + } + + private void initServices() { + if (userManagementService == null) { + WebApplicationContext ctx = WebApplicationContextUtils + .getWebApplicationContext(getServlet().getServletContext()); + userManagementService = (UserManagementService) ctx.getBean("userManagementService"); + } + } +} \ No newline at end of file Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/OrgSaveAction.java =================================================================== diff -u --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/OrgSaveAction.java (revision 0) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/OrgSaveAction.java (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -0,0 +1,265 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ +package org.lamsfoundation.lams.admin.web.action; + +import java.util.Date; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.commons.beanutils.BeanUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; +import org.apache.struts.action.Action; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.struts.action.ActionMessage; +import org.apache.struts.action.ActionMessages; +import org.apache.struts.action.DynaActionForm; +import org.lamsfoundation.lams.admin.AdminConstants; +import org.lamsfoundation.lams.admin.service.AdminServiceProxy; +import org.lamsfoundation.lams.usermanagement.Organisation; +import org.lamsfoundation.lams.usermanagement.OrganisationState; +import org.lamsfoundation.lams.usermanagement.OrganisationType; +import org.lamsfoundation.lams.usermanagement.SupportedLocale; +import org.lamsfoundation.lams.usermanagement.dto.UserDTO; +import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; +import org.lamsfoundation.lams.util.MessageService; +import org.lamsfoundation.lams.util.ValidationUtil; +import org.lamsfoundation.lams.util.audit.IAuditService; +import org.lamsfoundation.lams.web.session.SessionManager; +import org.lamsfoundation.lams.web.util.AttributeNames; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.WebApplicationContextUtils; + +/** + * @version + * + *

+ * View Source + *

+ * + * @author Fei Yang + * + * Created at 16:42:53 on 2006-6-7 + */ + +/** + * struts doclets + * + * + * + * + * + * + * + * + * + * + */ + +public class OrgSaveAction extends Action { + + private static Logger log = Logger.getLogger(OrgSaveAction.class); + private static IUserManagementService service; + private MessageService messageService; + + @Override + public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + + if (service == null) { + service = AdminServiceProxy.getService(getServlet().getServletContext()); + } + if (messageService == null) { + messageService = AdminServiceProxy.getMessageService(getServlet().getServletContext()); + } + DynaActionForm orgForm = (DynaActionForm) form; + Integer orgId = (Integer) orgForm.get("orgId"); + Organisation org; + + if (isCancelled(request)) { + if (orgId != 0) { + request.setAttribute("org", orgId); + org = (Organisation) service.findById(Organisation.class, orgId); + if (org.getOrganisationType().getOrganisationTypeId().equals(OrganisationType.CLASS_TYPE)) { + return mapping.findForward("userlist"); + } + } else { + request.setAttribute("org", orgForm.get("parentId")); + } + return mapping.findForward("orglist"); + } + + ActionMessages errors = new ActionMessages(); + + //organisation name validation + String orgName = (orgForm.get("name") == null) ? null : (String) orgForm.get("name"); + if (StringUtils.isBlank(orgName)) { + errors.add("name", new ActionMessage("error.name.required")); + } else if (!ValidationUtil.isOrgNameValid(orgName)) { + errors.add("name", new ActionMessage("error.name.invalid.characters")); + } + + if (errors.isEmpty()) { + HttpSession ss = SessionManager.getSession(); + UserDTO user = (UserDTO) ss.getAttribute(AttributeNames.USER); + SupportedLocale locale = (SupportedLocale) service.findById(SupportedLocale.class, + (Integer) orgForm.get("localeId")); + OrganisationState state = (OrganisationState) service.findById(OrganisationState.class, + (Integer) orgForm.get("stateId")); + + if (orgId != 0) { + if (service.canEditGroup(user.getUserID(), orgId)) { + org = (Organisation) service.findById(Organisation.class, orgId); + // set archived date only when it first changes to become archived + if (state.getOrganisationStateId().equals(OrganisationState.ARCHIVED) && !org.getOrganisationState() + .getOrganisationStateId().equals(OrganisationState.ARCHIVED)) { + org.setArchivedDate(new Date()); + } + writeAuditLog(org, orgForm, state, locale); + BeanUtils.copyProperties(org, orgForm); + } else { + request.setAttribute("errorName", "UserAction"); + request.setAttribute("errorMessage", messageService.getMessage("error.authorisation")); + return mapping.findForward("error"); + } + } else { + org = new Organisation(); + BeanUtils.copyProperties(org, orgForm); + org.setParentOrganisation( + (Organisation) service.findById(Organisation.class, (Integer) orgForm.get("parentId"))); + org.setOrganisationType( + (OrganisationType) service.findById(OrganisationType.class, (Integer) orgForm.get("typeId"))); + writeAuditLog(org, orgForm, org.getOrganisationState(), org.getLocale()); + } + org.setLocale(locale); + org.setOrganisationState(state); + if (log.isDebugEnabled()) { + log.debug("orgId: " + org.getOrganisationId() + " create date: " + org.getCreateDate()); + } + org = service.saveOrganisation(org, user.getUserID()); + + request.setAttribute("org", orgForm.get("parentId")); + return mapping.findForward("orglist"); + } else { + saveErrors(request, errors); + return mapping.findForward("organisation"); + } + } + + private void writeAuditLog(Organisation org, DynaActionForm orgForm, OrganisationState newState, + SupportedLocale newLocale) { + + WebApplicationContext ctx = WebApplicationContextUtils + .getRequiredWebApplicationContext(getServlet().getServletContext()); + IAuditService auditService = (IAuditService) ctx.getBean("auditService"); + MessageService messageService = (MessageService) ctx.getBean("adminMessageService"); + + String message; + + // audit log entries for organisation attribute changes + if ((Integer) orgForm.get("orgId") != 0) { + final String key = "audit.organisation.change"; + String[] args = new String[4]; + args[1] = org.getName() + "(" + org.getOrganisationId() + ")"; + if (!org.getOrganisationState().getOrganisationStateId().equals(orgForm.get("stateId"))) { + args[0] = "state"; + args[2] = org.getOrganisationState().getDescription(); + args[3] = newState.getDescription(); + message = messageService.getMessage(key, args); + auditService.log(AdminConstants.MODULE_NAME, message); + } + if (!StringUtils.equals(org.getName(), (String) orgForm.get("name"))) { + args[0] = "name"; + args[2] = org.getName(); + args[3] = (String) orgForm.get("name"); + message = messageService.getMessage(key, args); + auditService.log(AdminConstants.MODULE_NAME, message); + } + if (!StringUtils.equals(org.getCode(), (String) orgForm.get("code"))) { + args[0] = "code"; + args[2] = org.getCode(); + args[3] = (String) orgForm.get("code"); + message = messageService.getMessage(key, args); + auditService.log(AdminConstants.MODULE_NAME, message); + } + if (!StringUtils.equals(org.getDescription(), orgForm.getString("description"))) { + args[0] = "description"; + args[2] = org.getDescription(); + args[3] = (String) orgForm.get("description"); + message = messageService.getMessage(key, args); + auditService.log(AdminConstants.MODULE_NAME, message); + } + if (!org.getCourseAdminCanAddNewUsers().equals(orgForm.get("courseAdminCanAddNewUsers"))) { + args[0] = "courseAdminCanAddNewUsers"; + args[2] = org.getCourseAdminCanAddNewUsers() ? "true" : "false"; + args[3] = (Boolean) orgForm.get("courseAdminCanAddNewUsers") ? "true" : "false"; + message = messageService.getMessage(key, args); + auditService.log(AdminConstants.MODULE_NAME, message); + } + if (!org.getCourseAdminCanBrowseAllUsers().equals(orgForm.get("courseAdminCanBrowseAllUsers"))) { + args[0] = "courseAdminCanBrowseAllUsers"; + args[2] = org.getCourseAdminCanBrowseAllUsers() ? "true" : "false"; + args[3] = (Boolean) orgForm.get("courseAdminCanBrowseAllUsers") ? "true" : "false"; + message = messageService.getMessage(key, args); + auditService.log(AdminConstants.MODULE_NAME, message); + } + if (!org.getCourseAdminCanChangeStatusOfCourse() + .equals(orgForm.get("courseAdminCanChangeStatusOfCourse"))) { + args[0] = "courseAdminCanChangeStatusOfCourse"; + args[2] = org.getCourseAdminCanChangeStatusOfCourse() ? "true" : "false"; + args[3] = (Boolean) orgForm.get("courseAdminCanChangeStatusOfCourse") ? "true" : "false"; + message = messageService.getMessage(key, args); + auditService.log(AdminConstants.MODULE_NAME, message); + } + /* + * this field not set yet + * if(!org.getCourseAdminCanCreateGuestAccounts().equals((Boolean)orgForm.get( + * "courseAdminCanCreateGuestAccounts"))) { + * args[0] = "courseAdminCanCreateGuestAccounts"; + * args[2] = org.getCourseAdminCanCreateGuestAccounts() ? "true" : "false"; + * args[3] = (Boolean)orgForm.get("courseAdminCanCreateGuestAccounts") ? "true" : "false"; + * message = messageService.getMessage(key, args); + * auditService.log(AdminConstants.MODULE_NAME, message); + * } + */ + if (!org.getLocale().getLocaleId().equals(orgForm.get("localeId"))) { + args[0] = "locale"; + args[2] = org.getLocale().getDescription(); + args[3] = newLocale.getDescription(); + message = messageService.getMessage(key, args); + auditService.log(AdminConstants.MODULE_NAME, message); + } + } else { + String[] args = new String[2]; + args[0] = org.getName() + "(" + org.getOrganisationId() + ")"; + args[1] = org.getOrganisationType().getName(); + message = messageService.getMessage("audit.organisation.create", args); + auditService.log(AdminConstants.MODULE_NAME, message); + } + } + +} Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/OrganisationAction.java =================================================================== diff -u --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/OrganisationAction.java (revision 0) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/OrganisationAction.java (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -0,0 +1,179 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +package org.lamsfoundation.lams.admin.web.action; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.commons.beanutils.BeanUtils; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.struts.action.DynaActionForm; +import org.lamsfoundation.lams.admin.service.AdminServiceProxy; +import org.lamsfoundation.lams.usermanagement.Organisation; +import org.lamsfoundation.lams.usermanagement.OrganisationState; +import org.lamsfoundation.lams.usermanagement.OrganisationType; +import org.lamsfoundation.lams.usermanagement.Role; +import org.lamsfoundation.lams.usermanagement.SupportedLocale; +import org.lamsfoundation.lams.usermanagement.dto.UserDTO; +import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; +import org.lamsfoundation.lams.util.MessageService; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.action.LamsDispatchAction; +import org.lamsfoundation.lams.web.session.SessionManager; +import org.lamsfoundation.lams.web.util.AttributeNames; + +/** + * @author Fei Yang + * + * + * + * + * + * + */ +public class OrganisationAction extends LamsDispatchAction { + + private static IUserManagementService service; + private static MessageService messageService; + private static List locales; + private static List status; + + public ActionForward edit(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + OrganisationAction.service = AdminServiceProxy.getService(getServlet().getServletContext()); + initLocalesAndStatus(); + DynaActionForm orgForm = (DynaActionForm) form; + Integer orgId = WebUtil.readIntParam(request, "orgId", true); + + HttpSession session = SessionManager.getSession(); + if (session != null) { + UserDTO userDto = (UserDTO) session.getAttribute(AttributeNames.USER); + if (userDto != null) { + Integer userId = userDto.getUserID(); + // sysadmin, global group admin, group manager, group admin can edit group + if (OrganisationAction.service.canEditGroup(userId, orgId)) { + // edit existing organisation + if (orgId != null) { + Organisation org = (Organisation) OrganisationAction.service.findById(Organisation.class, + orgId); + BeanUtils.copyProperties(orgForm, org); + orgForm.set("parentId", org.getParentOrganisation().getOrganisationId()); + orgForm.set("parentName", org.getParentOrganisation().getName()); + orgForm.set("typeId", org.getOrganisationType().getOrganisationTypeId()); + orgForm.set("stateId", org.getOrganisationState().getOrganisationStateId()); + SupportedLocale locale = org.getLocale(); + orgForm.set("localeId", locale != null ? locale.getLocaleId() : null); + } + request.getSession().setAttribute("locales", OrganisationAction.locales); + request.getSession().setAttribute("status", OrganisationAction.status); + if (OrganisationAction.service.isUserSysAdmin() + || OrganisationAction.service.isUserGlobalGroupAdmin()) { + return mapping.findForward("organisation"); + } else { + return mapping.findForward("organisationCourseAdmin"); + } + } + } + } + + return error(mapping, request); + } + + public ActionForward create(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + OrganisationAction.service = AdminServiceProxy.getService(getServlet().getServletContext()); + initLocalesAndStatus(); + DynaActionForm orgForm = (DynaActionForm) form; + + if (!(request.isUserInRole(Role.SYSADMIN) || OrganisationAction.service.isUserGlobalGroupAdmin())) { + // only sysadmins and global group admins can create groups + if (((orgForm.get("typeId") != null) && orgForm.get("typeId").equals(OrganisationType.COURSE_TYPE)) + || (orgForm.get("typeId") == null)) { + return error(mapping, request); + } + } + + // creating new organisation + orgForm.set("orgId", null); + Integer parentId = WebUtil.readIntParam(request, "parentId", true); + if (parentId != null) { + Organisation parentOrg = (Organisation) OrganisationAction.service.findById(Organisation.class, parentId); + orgForm.set("parentName", parentOrg.getName()); + } + request.getSession().setAttribute("locales", OrganisationAction.locales); + request.getSession().setAttribute("status", OrganisationAction.status); + return mapping.findForward("organisation"); + } + + /** + * Looks up course ID by its name. Used mainly by TestHarness. + */ + @SuppressWarnings("unchecked") + public ActionForward getOrganisationIdByName(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws IOException { + String organisationName = WebUtil.readStrParam(request, "name"); + OrganisationAction.service = AdminServiceProxy.getService(getServlet().getServletContext()); + List organisations = service.findByProperty(Organisation.class, "name", organisationName); + if (!organisations.isEmpty()) { + response.setContentType("text/plain;charset=utf-8"); + response.getWriter().print(organisations.get(0).getOrganisationId()); + } + return null; + } + + private ActionForward error(ActionMapping mapping, HttpServletRequest request) { + OrganisationAction.messageService = AdminServiceProxy.getMessageService(getServlet().getServletContext()); + request.setAttribute("errorName", "OrganisationAction"); + request.setAttribute("errorMessage", OrganisationAction.messageService.getMessage("error.authorisation")); + return mapping.findForward("error"); + } + + /* + * public ActionForward remove(ActionMapping mapping, ActionForm form,HttpServletRequest request, + * HttpServletResponse response){ + * Integer orgId = WebUtil.readIntParam(request,"orgId"); + * getService().deleteById(Organisation.class,orgId); + * Integer parentId = WebUtil.readIntParam(request,"parentId"); + * request.setAttribute("org",parentId); + * return mapping.findForward("orglist"); + * } + */ + + @SuppressWarnings("unchecked") + private void initLocalesAndStatus() { + if ((OrganisationAction.locales == null) + || ((OrganisationAction.status == null) && (OrganisationAction.service != null))) { + OrganisationAction.locales = OrganisationAction.service.findAll(SupportedLocale.class); + OrganisationAction.status = OrganisationAction.service.findAll(OrganisationState.class); + Collections.sort(OrganisationAction.locales); + } + } +} \ No newline at end of file Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/ScheduledJobListAction.java =================================================================== diff -u --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/ScheduledJobListAction.java (revision 0) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/ScheduledJobListAction.java (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -0,0 +1,112 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +package org.lamsfoundation.lams.admin.web.action; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; +import org.apache.struts.action.Action; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.lamsfoundation.lams.admin.web.dto.ScheduledJobDTO; +import org.quartz.JobDetail; +import org.quartz.JobKey; +import org.quartz.Scheduler; +import org.quartz.SchedulerException; +import org.quartz.Trigger; +import org.quartz.impl.matchers.GroupMatcher; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.WebApplicationContextUtils; + +/** + * + * @author Steve.Ni + * @version $Revision$ + * + * + * + * + */ +public class ScheduledJobListAction extends Action { + + private static final Logger log = Logger.getLogger(ScheduledJobListAction.class); + + /** + * Get all waitting queue jobs scheduled in Quartz table and display job name, job start time and description. The + * description will be in format "Lesson Name":"the lesson creator", or "The gate name":"The relatived lesson name". + * + * @param mapping + * The ActionMapping used to select this instance + * @param actionForm + * The optional ActionForm bean for this request (if any) + * @param request + * The HTTP request we are processing + * @param response + * The HTTP response we are creating + * + * @exception IOException + * if an input/output error occurs + * @exception ServletException + * if a servlet exception occurs + * + */ + @SuppressWarnings("unchecked") + @Override + public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + + WebApplicationContext ctx = WebApplicationContextUtils + .getWebApplicationContext(this.getServlet().getServletContext()); + Scheduler scheduler = (Scheduler) ctx.getBean("scheduler"); + ArrayList jobList = new ArrayList(); + try { + Set jobKeys = scheduler.getJobKeys(GroupMatcher.jobGroupEquals(Scheduler.DEFAULT_GROUP)); + for (JobKey jobKey : jobKeys) { + ScheduledJobDTO jobDto = new ScheduledJobDTO(); + JobDetail detail = scheduler.getJobDetail(jobKey); + jobDto.setName(jobKey.getName()); + jobDto.setDescription(detail.getDescription()); + List triggers = (List) scheduler.getTriggersOfJob(jobKey); + for (Trigger trigger : triggers) { + jobDto.setStartDate(trigger.getStartTime()); + jobList.add(jobDto); + } + } + } catch (SchedulerException e) { + ScheduledJobListAction.log.equals("Failed get job names:" + e.getMessage()); + } + + request.setAttribute("jobList", jobList); + return mapping.findForward("list"); + } + +} Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/ServerListAction.java =================================================================== diff -u --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/ServerListAction.java (revision 0) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/ServerListAction.java (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -0,0 +1,55 @@ +/**************************************************************** + * Copyright (C) 2006 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ +package org.lamsfoundation.lams.admin.web.action; + +import java.util.Collections; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts.action.Action; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.lamsfoundation.lams.admin.service.AdminServiceProxy; +import org.lamsfoundation.lams.integration.ExtServer; + +/** + * + * @author Fei Yang + */ +public class ServerListAction extends Action { + + @Override + @SuppressWarnings("unchecked") + public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + List extServers = AdminServiceProxy.getIntegrationService(getServlet().getServletContext()) + .getAllExtServers(); + Collections.sort(extServers); + request.setAttribute("servers", extServers); + return mapping.findForward("serverlist"); + } + +} Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/ServerMaintainAction.java =================================================================== diff -u --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/ServerMaintainAction.java (revision 0) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/ServerMaintainAction.java (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -0,0 +1,88 @@ +/**************************************************************** + * Copyright (C) 2006 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ +package org.lamsfoundation.lams.admin.web.action; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.beanutils.BeanUtils; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.struts.action.DynaActionForm; +import org.lamsfoundation.lams.admin.service.AdminServiceProxy; +import org.lamsfoundation.lams.integration.ExtServer; +import org.lamsfoundation.lams.integration.service.IIntegrationService; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.action.LamsDispatchAction; + +/** + *

+ * View Source + *

+ * + * @author Fei Yang + */ +public class ServerMaintainAction extends LamsDispatchAction { + + @SuppressWarnings("unchecked") + public ActionForward edit(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + DynaActionForm extServerForm = (DynaActionForm) form; + Integer sid = WebUtil.readIntParam(request, "sid", true); + if (sid != null) { + ExtServer map = AdminServiceProxy.getIntegrationService(getServlet().getServletContext()) + .getExtServer(sid); + BeanUtils.copyProperties(extServerForm, map); + } + return mapping.findForward("servermaintain"); + } + + public ActionForward disable(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + IIntegrationService service = AdminServiceProxy.getIntegrationService(getServlet().getServletContext()); + Integer sid = WebUtil.readIntParam(request, "sid", false); + ExtServer map = service.getExtServer(sid); + map.setDisabled(true); + service.saveExtServer(map); + return mapping.findForward("serverlist"); + } + + public ActionForward enable(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + IIntegrationService service = AdminServiceProxy.getIntegrationService(getServlet().getServletContext()); + Integer sid = WebUtil.readIntParam(request, "sid", false); + ExtServer map = service.getExtServer(sid); + map.setDisabled(false); + service.saveExtServer(map); + return mapping.findForward("serverlist"); + } + + public ActionForward delete(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + Integer sid = WebUtil.readIntParam(request, "sid", false); + AdminServiceProxy.getService(getServlet().getServletContext()).deleteById(ExtServer.class, sid); + return mapping.findForward("serverlist"); + } + +} Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/ServerSaveAction.java =================================================================== diff -u --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/ServerSaveAction.java (revision 0) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/ServerSaveAction.java (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -0,0 +1,120 @@ +/**************************************************************** + * Copyright (C) 2006 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ +package org.lamsfoundation.lams.admin.web.action; + +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.beanutils.BeanUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.struts.action.Action; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.struts.action.ActionMessage; +import org.apache.struts.action.ActionMessages; +import org.apache.struts.action.DynaActionForm; +import org.lamsfoundation.lams.admin.service.AdminServiceProxy; +import org.lamsfoundation.lams.integration.ExtServer; +import org.lamsfoundation.lams.integration.service.IIntegrationService; +import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; +import org.lamsfoundation.lams.util.MessageService; + +/** + *

+ * View Source + *

+ * + * @author Fei Yang + */ +public class ServerSaveAction extends Action { + + private static IIntegrationService service; + private static IUserManagementService userService; + private static MessageService messageService; + + @Override + @SuppressWarnings("unchecked") + public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + + if (isCancelled(request)) { + return mapping.findForward("success"); + } + + service = AdminServiceProxy.getIntegrationService(getServlet().getServletContext()); + userService = AdminServiceProxy.getService(getServlet().getServletContext()); + messageService = AdminServiceProxy.getMessageService(getServlet().getServletContext()); + + DynaActionForm extServerForm = (DynaActionForm) form; + ActionMessages errors = new ActionMessages(); + String[] requiredFields = { "serverid", "serverkey", "servername", "prefix", "userinfoUrl" }; + for (String requiredField : requiredFields) { + if (StringUtils.trimToNull(extServerForm.getString(requiredField)) == null) { + errors.add(requiredField, + new ActionMessage("error.required", messageService.getMessage("sysadmin." + requiredField))); + } + } + + Integer sid = (Integer) extServerForm.get("sid"); + if (errors.isEmpty()) {//check duplication + String[] uniqueFields = { "serverid", "prefix" }; + for (String uniqueField : uniqueFields) { + List list = userService.findByProperty(ExtServer.class, uniqueField, + extServerForm.get(uniqueField)); + if (list != null && list.size() > 0) { + if (sid.equals(-1)) {//new map + errors.add(uniqueField, new ActionMessage("error.not.unique", + messageService.getMessage("sysadmin." + uniqueField))); + } else { + ExtServer map = (ExtServer) list.get(0); + if (!map.getSid().equals(sid)) { + errors.add(uniqueField, new ActionMessage("error.not.unique", + messageService.getMessage("sysadmin." + uniqueField))); + } + } + + } + } + } + if (errors.isEmpty()) { + ExtServer map = null; + if (sid.equals(-1)) { + map = new ExtServer(); + BeanUtils.copyProperties(map, extServerForm); + map.setSid(null); + map.setServerTypeId(ExtServer.INTEGRATION_SERVER_TYPE); + } else { + map = service.getExtServer(sid); + BeanUtils.copyProperties(map, extServerForm); + } + service.saveExtServer(map); + return mapping.findForward("success"); + } else { + saveErrors(request, errors); + return mapping.getInputForward(); + } + } +} Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/ToolContentListAction.java =================================================================== diff -u --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/ToolContentListAction.java (revision 0) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/ToolContentListAction.java (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -0,0 +1,327 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + +package org.lamsfoundation.lams.admin.web.action; + +import java.io.IOException; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import javax.sql.DataSource; + +import org.apache.commons.lang.StringUtils; +import org.apache.struts.action.Action; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.tomcat.util.json.JSONArray; +import org.apache.tomcat.util.json.JSONException; +import org.apache.tomcat.util.json.JSONObject; +import org.lamsfoundation.lams.admin.service.AdminServiceProxy; +import org.lamsfoundation.lams.learningdesign.LearningLibrary; +import org.lamsfoundation.lams.learningdesign.LearningLibraryGroup; +import org.lamsfoundation.lams.learningdesign.dto.LearningLibraryDTO; +import org.lamsfoundation.lams.learningdesign.dto.LibraryActivityDTO; +import org.lamsfoundation.lams.learningdesign.service.ILearningDesignService; +import org.lamsfoundation.lams.tool.Tool; +import org.lamsfoundation.lams.usermanagement.Role; +import org.lamsfoundation.lams.usermanagement.dto.UserDTO; +import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.session.SessionManager; +import org.lamsfoundation.lams.web.util.AttributeNames; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.WebApplicationContextUtils; + +/** + * @author jliew + * + * + * + * + * + * + */ +public class ToolContentListAction extends Action { + + private static final String PARAM_ACTION = "action"; + private static final String PARAM_LIBRARY_ID = "libraryID"; + + private static final String ATTRIBUTE_ERROR_NAME = "errorName"; + private static final String ATTRIBUTE_ERROR_MESSAGE = "errorMessage"; + private static final String ATTRIBUTE_LIBRARY = "toolLibrary"; + private static final String ATTRIBUTE_VALIDITY = "learningLibraryValidity"; + private static final String ATTRIBUTE_TOOL_VERSIONS = "toolVersions"; + private static final String ATTRIBUTE_DATABASE_VERSIONS = "dbVersions"; + + private static final String FORWARD_SUCCESS = "toolcontentlist"; + private static final String FORWARD_GROUPS = "groups"; + private static final String FORWARD_ERROR = "error"; + + private static final String ACTION_ENABLE = "enable"; + private static final String ACTION_DISABLE = "disable"; + private static final String ACTION_OPEN_GROUPS = "openLearningLibraryGroups"; + private static final String ACTION_SAVE_GROUPS = "saveLearningLibraryGroups"; + + private static final String QUERY_DATABASE_VERSIONS = "select system_name, patch_level from patches"; + + private static ILearningDesignService learningDesignService; + private static IUserManagementService userManagementService; + private static DataSource dataSource; + + @SuppressWarnings("unchecked") + @Override + public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + // check permission + if (!(request.isUserInRole(Role.SYSADMIN))) { + request.setAttribute(ToolContentListAction.ATTRIBUTE_ERROR_NAME, "ToolContentListAction"); + request.setAttribute(ToolContentListAction.ATTRIBUTE_ERROR_MESSAGE, AdminServiceProxy + .getMessageService(getServlet().getServletContext()).getMessage("error.authorisation")); + return mapping.findForward(ToolContentListAction.FORWARD_ERROR); + } + + // not just display, but enable/disable a learning library + String param = request.getParameter(ToolContentListAction.PARAM_ACTION); + if (StringUtils.equals(param, ToolContentListAction.ACTION_ENABLE)) { + if (checkPriviledge(request)) { + enableLibrary(mapping, form, request, response); + } else { + return mapping.findForward(ToolContentListAction.FORWARD_ERROR); + } + } else if (StringUtils.equals(param, ToolContentListAction.ACTION_DISABLE)) { + if (checkPriviledge(request)) { + disableLibrary(mapping, form, request, response); + } else { + return mapping.findForward(ToolContentListAction.FORWARD_ERROR); + } + } else if (StringUtils.equals(param, ToolContentListAction.ACTION_OPEN_GROUPS)) { + return openLearningLibraryGroups(mapping, form, request, response); + } else if (StringUtils.equals(param, ToolContentListAction.ACTION_SAVE_GROUPS)) { + saveLearningLibraryGroups(mapping, form, request, response); + return null; + } + + // get learning library dtos and their validity + List learningLibraryDTOs = getLearningDesignService().getAllLearningLibraryDetails(false, + getUserLanguage()); + // this is filled when executing following method, for efficiency purposes + HashMap learningLibraryValidity = new HashMap(learningLibraryDTOs.size()); + ArrayList toolLibrary = filterMultipleToolEntries(learningLibraryDTOs, + learningLibraryValidity); + request.setAttribute(ToolContentListAction.ATTRIBUTE_LIBRARY, toolLibrary); + request.setAttribute(ToolContentListAction.ATTRIBUTE_VALIDITY, learningLibraryValidity); + + // get tool versions + HashMap toolVersions = new HashMap(); + List tools = getUserManagementService().findAll(Tool.class); + for (Tool tool : tools) { + toolVersions.put(tool.getToolId(), tool.getToolVersion()); + } + request.setAttribute(ToolContentListAction.ATTRIBUTE_TOOL_VERSIONS, toolVersions); + + // get tool database versions + HashMap dbVersions = new HashMap(); + Connection conn = getDataSource().getConnection(); + PreparedStatement query = conn.prepareStatement(ToolContentListAction.QUERY_DATABASE_VERSIONS); + ResultSet results = query.executeQuery(); + while (results.next()) { + dbVersions.put(results.getString("system_name"), results.getInt("patch_level")); + } + request.setAttribute(ToolContentListAction.ATTRIBUTE_DATABASE_VERSIONS, dbVersions); + + return mapping.findForward(ToolContentListAction.FORWARD_SUCCESS); + } + + // returns full list of learning libraries, valid or not + @SuppressWarnings("unchecked") + private ArrayList filterMultipleToolEntries(List learningLibraryDTOs, + HashMap learningLibraryValidity) { + ArrayList activeTools = new ArrayList(); + ArrayList activeCombinedTools = new ArrayList(); + for (LearningLibraryDTO learningLibraryDTO : learningLibraryDTOs) { + // populate information about learning libary validity + learningLibraryValidity.put(learningLibraryDTO.getLearningLibraryID(), learningLibraryDTO.getValidFlag()); + for (LibraryActivityDTO template : (List) learningLibraryDTO.getTemplateActivities()) { + // no learning library ID = a part of combined learning library, we already have it in the list + if (template.getLearningLibraryID() != null) { + // combined libraries do not have tool content ID set + if (template.getToolContentID() == null) { + if (!toolExists(template, activeCombinedTools)) { + activeCombinedTools.add(template); + } + } else { + if (!toolExists(template, activeTools)) { + activeTools.add(template); + } + } + } + } + } + // put combined libraries at the end, purely for easy of use + activeTools.addAll(activeCombinedTools); + return activeTools; + } + + private boolean toolExists(LibraryActivityDTO newItem, ArrayList list) { + for (LibraryActivityDTO libraryActivityDTO : list) { + if (newItem.getLearningLibraryID().equals(libraryActivityDTO.getLearningLibraryID())) { + return true; + } + } + return false; + } + + private String getUserLanguage() { + HttpSession ss = SessionManager.getSession(); + UserDTO user = (UserDTO) ss.getAttribute(AttributeNames.USER); + return user == null ? "" : user.getLocaleLanguage(); + } + + private boolean checkPriviledge(HttpServletRequest request) { + if (!getUserManagementService().isUserSysAdmin()) { + request.setAttribute(ToolContentListAction.ATTRIBUTE_ERROR_NAME, "ToolContentListAction"); + request.setAttribute(ToolContentListAction.ATTRIBUTE_ERROR_MESSAGE, AdminServiceProxy + .getMessageService(getServlet().getServletContext()).getMessage("error.no.sysadmin.priviledge")); + return false; + } + return true; + } + + private void disableLibrary(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) { + Long learningLibraryId = WebUtil.readLongParam(request, ToolContentListAction.PARAM_LIBRARY_ID, false); + ILearningDesignService ldService = getLearningDesignService(); + ldService.setValid(learningLibraryId, false); + } + + private void enableLibrary(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) { + Long learningLibraryId = WebUtil.readLongParam(request, ToolContentListAction.PARAM_LIBRARY_ID, false); + ILearningDesignService ldService = getLearningDesignService(); + ldService.setValid(learningLibraryId, true); + + } + + /** + * Loads groups and libraries and displays the management dialog. + */ + private ActionForward openLearningLibraryGroups(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws JSONException, IOException { + // build full list of available learning libraries + List learningLibraries = getLearningDesignService() + .getAllLearningLibraryDetails(getUserLanguage()); + JSONArray learningLibrariesJSON = new JSONArray(); + for (LearningLibraryDTO learningLibrary : learningLibraries) { + JSONObject learningLibraryJSON = new JSONObject(); + learningLibraryJSON.put("learningLibraryId", learningLibrary.getLearningLibraryID()); + learningLibraryJSON.put("title", learningLibrary.getTitle()); + learningLibrariesJSON.put(learningLibraryJSON); + } + request.setAttribute("learningLibraries", learningLibrariesJSON.toString()); + + // build list of existing groups + List groups = getLearningDesignService().getLearningLibraryGroups(); + JSONArray groupsJSON = new JSONArray(); + for (LearningLibraryGroup group : groups) { + JSONObject groupJSON = new JSONObject(); + groupJSON.put("groupId", group.getGroupId()); + groupJSON.put("name", group.getName()); + for (LearningLibrary learningLibrary : group.getLearningLibraries()) { + JSONObject learningLibraryJSON = new JSONObject(); + learningLibraryJSON.put("learningLibraryId", learningLibrary.getLearningLibraryId()); + learningLibraryJSON.put("title", learningLibrary.getTitle()); + groupJSON.append("learningLibraries", learningLibraryJSON); + } + groupsJSON.put(groupJSON); + } + request.setAttribute("groups", groupsJSON.toString()); + + return mapping.findForward(ToolContentListAction.FORWARD_GROUPS); + } + + private void saveLearningLibraryGroups(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws JSONException, IOException { + // extract groups from JSON and persist them + JSONArray groupsJSON = new JSONArray(request.getParameter("groups")); + List groups = new ArrayList(groupsJSON.length()); + + for (int groupIndex = 0; groupIndex < groupsJSON.length(); groupIndex++) { + LearningLibraryGroup group = new LearningLibraryGroup(); + groups.add(group); + + JSONObject groupJSON = groupsJSON.getJSONObject(groupIndex); + long groupId = groupJSON.optLong("groupId"); + if (groupId > 0) { + group.setGroupId(groupId); + } + group.setName(groupJSON.getString("name")); + + group.setLearningLibraries(new HashSet()); + JSONArray learningLibrariesJSON = groupJSON.getJSONArray("learningLibraries"); + for (int learningLibraryIndex = 0; learningLibraryIndex < learningLibrariesJSON + .length(); learningLibraryIndex++) { + long learningLibraryId = learningLibrariesJSON.getLong(learningLibraryIndex); + LearningLibrary learningLibrary = getLearningDesignService().getLearningLibrary(learningLibraryId); + group.getLearningLibraries().add(learningLibrary); + } + } + + getLearningDesignService().saveLearningLibraryGroups(groups); + } + + private ILearningDesignService getLearningDesignService() { + if (ToolContentListAction.learningDesignService == null) { + WebApplicationContext ctx = WebApplicationContextUtils + .getRequiredWebApplicationContext(getServlet().getServletContext()); + ToolContentListAction.learningDesignService = (ILearningDesignService) ctx.getBean("learningDesignService"); + } + return ToolContentListAction.learningDesignService; + } + + private IUserManagementService getUserManagementService() { + if (ToolContentListAction.userManagementService == null) { + WebApplicationContext ctx = WebApplicationContextUtils + .getRequiredWebApplicationContext(getServlet().getServletContext()); + ToolContentListAction.userManagementService = (IUserManagementService) ctx.getBean("userManagementService"); + } + return ToolContentListAction.userManagementService; + } + + private DataSource getDataSource() { + if (ToolContentListAction.dataSource == null) { + WebApplicationContext ctx = WebApplicationContextUtils + .getRequiredWebApplicationContext(getServlet().getServletContext()); + ToolContentListAction.dataSource = (DataSource) ctx.getBean("dataSource"); + } + return ToolContentListAction.dataSource; + } +} \ No newline at end of file Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/UserAction.java =================================================================== diff -u --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/UserAction.java (revision 0) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/UserAction.java (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -0,0 +1,388 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + +package org.lamsfoundation.lams.admin.web.action; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.TimeZone; +import java.util.TreeSet; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.beanutils.BeanUtils; +import org.apache.log4j.Logger; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.struts.action.DynaActionForm; +import org.lamsfoundation.lams.admin.AdminConstants; +import org.lamsfoundation.lams.admin.service.AdminServiceProxy; +import org.lamsfoundation.lams.admin.web.dto.UserOrgRoleDTO; +import org.lamsfoundation.lams.themes.Theme; +import org.lamsfoundation.lams.themes.service.IThemeService; +import org.lamsfoundation.lams.timezone.Timezone; +import org.lamsfoundation.lams.timezone.dto.TimezoneDTO; +import org.lamsfoundation.lams.timezone.service.ITimezoneService; +import org.lamsfoundation.lams.timezone.util.TimezoneDTOComparator; +import org.lamsfoundation.lams.usermanagement.AuthenticationMethod; +import org.lamsfoundation.lams.usermanagement.Organisation; +import org.lamsfoundation.lams.usermanagement.OrganisationState; +import org.lamsfoundation.lams.usermanagement.OrganisationType; +import org.lamsfoundation.lams.usermanagement.Role; +import org.lamsfoundation.lams.usermanagement.SupportedLocale; +import org.lamsfoundation.lams.usermanagement.User; +import org.lamsfoundation.lams.usermanagement.UserOrganisation; +import org.lamsfoundation.lams.usermanagement.UserOrganisationRole; +import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; +import org.lamsfoundation.lams.util.LanguageUtil; +import org.lamsfoundation.lams.util.MessageService; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.action.LamsDispatchAction; + +/** + * @author Jun-Dir Liew + */ +public class UserAction extends LamsDispatchAction { + + private static Logger log = Logger.getLogger(UserAction.class); + private IUserManagementService service; + private MessageService messageService; + private static IThemeService themeService; + private static ITimezoneService timezoneService; + private static List locales; + private static List authenticationMethods; + + private void initServices() { + if (service == null) { + service = AdminServiceProxy.getService(getServlet().getServletContext()); + } + if (messageService == null) { + messageService = AdminServiceProxy.getMessageService(getServlet().getServletContext()); + } + if (UserAction.themeService == null) { + UserAction.themeService = AdminServiceProxy.getThemeService(getServlet().getServletContext()); + } + if (UserAction.timezoneService == null) { + UserAction.timezoneService = AdminServiceProxy.getTimezoneService(getServlet().getServletContext()); + } + } + + @SuppressWarnings("unchecked") + public ActionForward edit(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + + initServices(); + if (UserAction.locales == null) { + UserAction.locales = service.findAll(SupportedLocale.class); + Collections.sort(UserAction.locales); + } + if (UserAction.authenticationMethods == null) { + UserAction.authenticationMethods = service.findAll(AuthenticationMethod.class); + } + + DynaActionForm userForm = (DynaActionForm) form; + Integer orgId = WebUtil.readIntParam(request, "orgId", true); + Integer userId = WebUtil.readIntParam(request, "userId", true); + + // Get all the css themess + List themes = UserAction.themeService.getAllThemes(); + request.setAttribute("themes", themes); + + // Select the default themes by default + Theme defaultTheme = UserAction.themeService.getDefaultTheme(); + for (Theme theme : themes) { + if (theme.getThemeId().equals(defaultTheme.getThemeId())) { + userForm.set("userTheme", theme.getThemeId()); + break; + } + } + + // test requestor's permission + Organisation org = null; + Boolean canEdit = service.isUserGlobalGroupAdmin(); + if (orgId != null) { + org = (Organisation) service.findById(Organisation.class, orgId); + if (!canEdit) { + OrganisationType orgType = org.getOrganisationType(); + Integer orgIdOfCourse = orgType.getOrganisationTypeId().equals(OrganisationType.CLASS_TYPE) + ? org.getParentOrganisation().getOrganisationId() : orgId; + User requestor = service.getUserByLogin(request.getRemoteUser()); + if (service.isUserInRole(requestor.getUserId(), orgIdOfCourse, Role.GROUP_ADMIN) + || service.isUserInRole(requestor.getUserId(), orgIdOfCourse, Role.GROUP_MANAGER)) { + Organisation course = (Organisation) service.findById(Organisation.class, orgIdOfCourse); + canEdit = course.getCourseAdminCanAddNewUsers(); + } + } + } + + if (!(canEdit || request.isUserInRole(Role.SYSADMIN))) { + request.setAttribute("errorName", "UserAction"); + request.setAttribute("errorMessage", messageService.getMessage("error.authorisation")); + return mapping.findForward("error"); + } + + // editing a user + if ((userId != null) && (userId != 0)) { + User user = (User) service.findById(User.class, userId); + UserAction.log.debug("got userid to edit: " + userId); + BeanUtils.copyProperties(userForm, user); + userForm.set("password", null); + SupportedLocale locale = user.getLocale(); + userForm.set("localeId", locale.getLocaleId()); + + AuthenticationMethod authenticationMethod = user.getAuthenticationMethod(); + userForm.set("authenticationMethodId", authenticationMethod.getAuthenticationMethodId()); + // set user's organisations to display + request.setAttribute("userOrgRoles", getUserOrgRoles(user)); + request.setAttribute("globalRoles", getGlobalRoles(user)); + + // Check the user css theme is still installed + Long userSelectedTheme = null; + if (user.getTheme() != null) { + for (Theme theme : themes) { + if (theme.getThemeId() == user.getTheme().getThemeId()) { + userSelectedTheme = theme.getThemeId(); + break; + } + } + } + // if still null, use the default + if (userSelectedTheme == null) { + userSelectedTheme = UserAction.themeService.getDefaultTheme().getThemeId(); + } + userForm.set("userTheme", userSelectedTheme); + + //property available for modification only to sysadmins + userForm.set("twoFactorAuthenticationEnabled", user.isTwoFactorAuthenticationEnabled()); + } else { // create a user + try { + SupportedLocale locale = LanguageUtil.getDefaultLocale(); + userForm.set("localeId", locale.getLocaleId()); + } catch (Exception e) { + UserAction.log.debug(e); + } + } + userForm.set("orgId", (org == null ? null : org.getOrganisationId())); + + // sysadmins can mark users as required to use two-factor authentication + if (request.isUserInRole(Role.SYSADMIN)) { + request.setAttribute("isSysadmin", true); + } + + // Get all available time zones + List availableTimeZones = UserAction.timezoneService.getDefaultTimezones(); + TreeSet timezoneDtos = new TreeSet(new TimezoneDTOComparator()); + for (Timezone availableTimeZone : availableTimeZones) { + String timezoneId = availableTimeZone.getTimezoneId(); + TimezoneDTO timezoneDto = new TimezoneDTO(); + timezoneDto.setTimeZoneId(timezoneId); + timezoneDto.setDisplayName(TimeZone.getTimeZone(timezoneId).getDisplayName()); + timezoneDtos.add(timezoneDto); + } + request.setAttribute("timezoneDtos", timezoneDtos); + + // for breadcrumb links + if (org != null) { + request.setAttribute("orgName", org.getName()); + Organisation parentOrg = org.getParentOrganisation(); + if ((parentOrg != null) && !parentOrg.equals(service.getRootOrganisation())) { + request.setAttribute("pOrgId", parentOrg.getOrganisationId()); + request.setAttribute("parentName", parentOrg.getName()); + } + } + + request.setAttribute("locales", UserAction.locales); + request.setAttribute("authenticationMethods", UserAction.authenticationMethods); + + return mapping.findForward("user"); + } + + // display user's global roles, if any + private UserOrgRoleDTO getGlobalRoles(User user) { + initServices(); + UserOrganisation uo = service.getUserOrganisation(user.getUserId(), + service.getRootOrganisation().getOrganisationId()); + if (uo == null) { + return null; + } + UserOrgRoleDTO uorDTO = new UserOrgRoleDTO(); + List roles = new ArrayList(); + for (Object uor : uo.getUserOrganisationRoles()) { + roles.add(((UserOrganisationRole) uor).getRole().getName()); + } + Collections.sort(roles); + uorDTO.setOrgName(uo.getOrganisation().getName()); + uorDTO.setRoles(roles); + return uorDTO; + } + + // display user's organisations and roles in them + @SuppressWarnings("unchecked") + private List getUserOrgRoles(User user) { + + initServices(); + List uorDTOs = new ArrayList(); + List uos = service.getUserOrganisationsForUserByTypeAndStatus(user.getLogin(), + OrganisationType.COURSE_TYPE, OrganisationState.ACTIVE); + for (UserOrganisation uo : uos) { + UserOrgRoleDTO uorDTO = new UserOrgRoleDTO(); + List roles = new ArrayList(); + for (Object uor : uo.getUserOrganisationRoles()) { + roles.add(((UserOrganisationRole) uor).getRole().getName()); + } + Collections.sort(roles); + uorDTO.setOrgName(uo.getOrganisation().getName()); + uorDTO.setRoles(roles); + List childDTOs = new ArrayList(); + List childuos = service.getUserOrganisationsForUserByTypeAndStatusAndParent( + user.getLogin(), OrganisationType.CLASS_TYPE, OrganisationState.ACTIVE, + uo.getOrganisation().getOrganisationId()); + for (UserOrganisation childuo : childuos) { + UserOrgRoleDTO childDTO = new UserOrgRoleDTO(); + List childroles = new ArrayList(); + for (Object uor : childuo.getUserOrganisationRoles()) { + childroles.add(((UserOrganisationRole) uor).getRole().getName()); + } + Collections.sort(childroles); + childDTO.setOrgName(childuo.getOrganisation().getName()); + childDTO.setRoles(childroles); + childDTOs.add(childDTO); + } + uorDTO.setChildDTOs(childDTOs); + uorDTOs.add(uorDTO); + } + + return uorDTOs; + } + + // determine whether to disable or delete user based on their lams data + public ActionForward remove(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + + initServices(); + + if (!(request.isUserInRole(Role.SYSADMIN) || service.isUserGlobalGroupAdmin())) { + request.setAttribute("errorName", "UserAction"); + request.setAttribute("errorMessage", messageService.getMessage("error.authorisation")); + return mapping.findForward("error"); + } + + Integer orgId = WebUtil.readIntParam(request, "orgId", true); + Integer userId = WebUtil.readIntParam(request, "userId"); + User user = (User) service.findById(User.class, userId); + + Boolean hasData = service.userHasData(user); + + request.setAttribute("method", (hasData ? "disable" : "delete")); + request.setAttribute("orgId", orgId); + request.setAttribute("userId", userId); + return mapping.findForward("remove"); + } + + public ActionForward disable(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + + initServices(); + + if (!(request.isUserInRole(Role.SYSADMIN) || service.isUserGlobalGroupAdmin())) { + request.setAttribute("errorName", "UserAction"); + request.setAttribute("errorMessage", messageService.getMessage("error.authorisation")); + return mapping.findForward("error"); + } + + Integer orgId = WebUtil.readIntParam(request, "orgId", true); + Integer userId = WebUtil.readIntParam(request, "userId"); + service.disableUser(userId); + String[] args = new String[1]; + args[0] = userId.toString(); + String message = messageService.getMessage("audit.user.disable", args); + AdminServiceProxy.getAuditService(getServlet().getServletContext()).log(AdminConstants.MODULE_NAME, message); + + if ((orgId == null) || (orgId == 0)) { + return mapping.findForward("usersearch"); + } else { + request.setAttribute("org", orgId); + return mapping.findForward("userlist"); + } + } + + public ActionForward delete(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + + initServices(); + + if (!(request.isUserInRole(Role.SYSADMIN) || service.isUserGlobalGroupAdmin())) { + request.setAttribute("errorName", "UserAction"); + request.setAttribute("errorMessage", messageService.getMessage("error.authorisation")); + return mapping.findForward("error"); + } + + Integer orgId = WebUtil.readIntParam(request, "orgId", true); + Integer userId = WebUtil.readIntParam(request, "userId"); + try { + service.removeUser(userId); + } catch (Exception e) { + request.setAttribute("errorName", "UserAction"); + request.setAttribute("errorMessage", e.getMessage()); + return mapping.findForward("error"); + } + String[] args = new String[1]; + args[0] = userId.toString(); + String message = messageService.getMessage("audit.user.delete", args); + AdminServiceProxy.getAuditService(getServlet().getServletContext()).log(AdminConstants.MODULE_NAME, message); + + if ((orgId == null) || (orgId == 0)) { + return mapping.findForward("usersearch"); + } else { + request.setAttribute("org", orgId); + return mapping.findForward("userlist"); + } + } + + // called from disabled users screen + public ActionForward enable(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + + initServices(); + + if (!(request.isUserInRole(Role.SYSADMIN) || service.isUserGlobalGroupAdmin())) { + request.setAttribute("errorName", "UserAction"); + request.setAttribute("errorMessage", messageService.getMessage("error.authorisation")); + return mapping.findForward("error"); + } + + Integer userId = WebUtil.readIntParam(request, "userId", true); + User user = (User) service.findById(User.class, userId); + + UserAction.log.debug("enabling user: " + userId); + user.setDisabledFlag(false); + service.saveUser(user); + + return mapping.findForward("disabledlist"); + } + +} \ No newline at end of file Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/UserManageAction.java =================================================================== diff -u --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/UserManageAction.java (revision 0) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/UserManageAction.java (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -0,0 +1,169 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + +package org.lamsfoundation.lams.admin.web.action; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; +import org.apache.struts.action.Action; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.lamsfoundation.lams.admin.service.AdminServiceProxy; +import org.lamsfoundation.lams.admin.web.dto.UserListDTO; +import org.lamsfoundation.lams.usermanagement.Organisation; +import org.lamsfoundation.lams.usermanagement.OrganisationType; +import org.lamsfoundation.lams.usermanagement.Role; +import org.lamsfoundation.lams.usermanagement.dto.UserDTO; +import org.lamsfoundation.lams.usermanagement.dto.UserManageBean; +import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; +import org.lamsfoundation.lams.util.MessageService; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.session.SessionManager; +import org.lamsfoundation.lams.web.util.AttributeNames; + +/** + * @author Jun-Dir Liew + * + * Created at 13:51:51 on 9/06/2006 + */ + +/** + * struts doclets + * + * + * + * + */ +public class UserManageAction extends Action { + + private static final Logger log = Logger.getLogger(UserManageAction.class); + private static IUserManagementService service; + private static MessageService messageService; + + @Override + @SuppressWarnings("unchecked") + public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + + service = AdminServiceProxy.getService(getServlet().getServletContext()); + messageService = AdminServiceProxy.getMessageService(getServlet().getServletContext()); + + // get id of org to list users for + Integer orgId = WebUtil.readIntParam(request, "org", true); + if (orgId == null) { + orgId = (Integer) request.getAttribute("org"); + } + if ((orgId == null) || (orgId <= 0)) { + return forwardError(mapping, request, "error.org.invalid"); + } + log.debug("orgId: " + orgId); + + // get org name + Organisation organisation = (Organisation) service.findById(Organisation.class, orgId); + if (organisation == null) { + return forwardError(mapping, request, "error.org.invalid"); + } + String orgName = organisation.getName(); + log.debug("orgName: " + orgName); + + Organisation pOrg = organisation.getParentOrganisation(); + if (pOrg != null) { + request.setAttribute("pOrgId", pOrg.getOrganisationId()); + request.setAttribute("pOrgName", pOrg.getName()); + } + OrganisationType orgType = organisation.getOrganisationType(); + request.setAttribute("orgType", orgType.getOrganisationTypeId()); + + // create form object + UserListDTO userManageForm = new UserListDTO(); + + Integer userId = ((UserDTO) SessionManager.getSession().getAttribute(AttributeNames.USER)).getUserID(); + Organisation orgOfCourseAdmin = (orgType.getOrganisationTypeId().equals(OrganisationType.CLASS_TYPE)) ? pOrg + : organisation; + // check permission + Integer rootOrgId = service.getRootOrganisation().getOrganisationId(); + if (request.isUserInRole(Role.SYSADMIN) || (service.isUserGlobalGroupAdmin() && !orgId.equals(rootOrgId))) { + userManageForm.setCourseAdminCanAddNewUsers(true); + userManageForm.setCourseAdminCanBrowseAllUsers(true); + request.setAttribute("canDeleteUser", true); + } else if ((service.isUserInRole(userId, orgOfCourseAdmin.getOrganisationId(), Role.GROUP_ADMIN) + || service.isUserInRole(userId, orgOfCourseAdmin.getOrganisationId(), Role.GROUP_MANAGER)) + && !orgId.equals(rootOrgId)) { + userManageForm.setCourseAdminCanAddNewUsers(orgOfCourseAdmin.getCourseAdminCanAddNewUsers()); + userManageForm.setCourseAdminCanBrowseAllUsers(orgOfCourseAdmin.getCourseAdminCanBrowseAllUsers()); + } else { + return forwardError(mapping, request, "error.authorisation"); + } + + userManageForm.setOrgId(orgId); + userManageForm.setOrgName(orgName); + List userManageBeans = service.getUserManageBeans(orgId); + Collections.sort(userManageBeans); + userManageForm.setUserManageBeans(userManageBeans); + request.setAttribute("UserManageForm", userManageForm); + + // heading + String[] args = { orgName }; + request.setAttribute("heading", messageService.getMessage("heading.manage.group.users", args)); + + // count roles in the org + HashMap roleCount = new HashMap(); + if (orgId.equals(rootOrgId)) { + roleCount.put(Role.SYSADMIN, Role.ROLE_SYSADMIN); + roleCount.put(Role.GROUP_ADMIN, Role.ROLE_GROUP_ADMIN); + } else { + roleCount.put(Role.LEARNER, Role.ROLE_LEARNER); + roleCount.put(Role.MONITOR, Role.ROLE_MONITOR); + roleCount.put(Role.AUTHOR, Role.ROLE_AUTHOR); + roleCount.put(Role.GROUP_MANAGER, Role.ROLE_GROUP_MANAGER); + roleCount.put(Role.GROUP_ADMIN, Role.ROLE_GROUP_ADMIN); + } + for (String role : roleCount.keySet()) { + Integer count = service.getCountRoleForOrg(orgId, roleCount.get(role), null); + request.setAttribute(role.replace(' ', '_'), count); + } + + // count users in the org + // TODO use hql that does a count instead of getting whole objects + Integer numUsers = Integer.valueOf(service.getUsersFromOrganisation(orgId).size()); + args[0] = numUsers.toString(); + request.setAttribute("numUsers", messageService.getMessage("label.users.in.group", args)); + + return mapping.findForward("userlist"); + } + + private ActionForward forwardError(ActionMapping mapping, HttpServletRequest request, String key) { + request.setAttribute("errorName", "UserManageAction"); + request.setAttribute("errorMessage", messageService.getMessage(key)); + return mapping.findForward("error"); + } + +} Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/UserOrgAction.java =================================================================== diff -u --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/UserOrgAction.java (revision 0) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/UserOrgAction.java (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -0,0 +1,104 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + +package org.lamsfoundation.lams.admin.web.action; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; +import org.apache.struts.action.Action; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.struts.action.DynaActionForm; +import org.lamsfoundation.lams.admin.service.AdminServiceProxy; +import org.lamsfoundation.lams.usermanagement.Organisation; +import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; +import org.lamsfoundation.lams.util.MessageService; +import org.lamsfoundation.lams.util.WebUtil; + +/** + * @author Jun-Dir Liew + * + */ + +/** + * struts doclets + * + * + * + * + * + * + * + * + */ +public class UserOrgAction extends Action { + + private static final Logger log = Logger.getLogger(UserOrgAction.class); + private static IUserManagementService service; + private static MessageService messageService; + + @Override + public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + + service = AdminServiceProxy.getService(getServlet().getServletContext()); + messageService = AdminServiceProxy.getMessageService(getServlet().getServletContext()); + + //ActionMessages errors = new ActionMessages(); + Integer orgId = WebUtil.readIntParam(request, "orgId", true); + log.debug("orgId: " + orgId); + // get org name + Organisation organisation = (Organisation) service.findById(Organisation.class, orgId); + + if ((orgId == null) || (orgId <= 0) || organisation == null) { + request.setAttribute("errorName", "UserOrgAction"); + request.setAttribute("errorMessage", messageService.getMessage("error.org.invalid")); + return mapping.findForward("error"); + } + + String orgName = organisation.getName(); + log.debug("orgName: " + orgName); + Organisation parentOrg = organisation.getParentOrganisation(); + if (parentOrg != null && !parentOrg.equals(service.getRootOrganisation())) { + request.setAttribute("pOrgId", parentOrg.getOrganisationId()); + request.setAttribute("pOrgName", parentOrg.getName()); + } + Integer orgType = organisation.getOrganisationType().getOrganisationTypeId(); + request.setAttribute("orgType", orgType); + + // create form object + DynaActionForm userOrgForm = (DynaActionForm) form; + userOrgForm.set("orgId", orgId); + userOrgForm.set("orgName", orgName); + + String[] args = { "0" }; + request.setAttribute("numExistUsers", messageService.getMessage("label.number.of.users", args)); + request.setAttribute("numPotentialUsers", messageService.getMessage("label.number.of.potential.users", args)); + + return mapping.findForward("userorg"); + } +} Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/UserOrgRoleAction.java =================================================================== diff -u --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/UserOrgRoleAction.java (revision 0) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/UserOrgRoleAction.java (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -0,0 +1,123 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + +package org.lamsfoundation.lams.admin.web.action; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.beanutils.BeanUtils; +import org.apache.log4j.Logger; +import org.apache.struts.action.Action; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.lamsfoundation.lams.admin.service.AdminServiceProxy; +import org.lamsfoundation.lams.admin.web.dto.UserBean; +import org.lamsfoundation.lams.admin.web.form.UserOrgRoleForm; +import org.lamsfoundation.lams.usermanagement.Organisation; +import org.lamsfoundation.lams.usermanagement.OrganisationType; +import org.lamsfoundation.lams.usermanagement.User; +import org.lamsfoundation.lams.usermanagement.UserOrganisation; +import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; + +/** + * @author jliew + * + * Called when a user has added users to an organisation. + * + */ + +/** + * struts doclets + * + * + * + * + * + * + * + * + */ +public class UserOrgRoleAction extends Action { + + private static Logger log = Logger.getLogger(UserOrgRoleAction.class); + private static IUserManagementService service; + + @Override + public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + + service = AdminServiceProxy.getService(getServlet().getServletContext()); + UserOrgRoleForm userOrgRoleForm = (UserOrgRoleForm) form; + // make sure we don't have left overs from any previous attempt + userOrgRoleForm.setUserBeans(new ArrayList()); + + // set list of roles appropriate for the organisation type + List roles = (List) request.getAttribute("roles"); + request.setAttribute("numroles", roles.size()); + Collections.sort(roles); + request.setAttribute("roles", roles); + + Organisation organisation = (Organisation) service.findById(Organisation.class, + (Integer) request.getAttribute("orgId")); + userOrgRoleForm.setOrgId(organisation.getOrganisationId()); + + // display breadcrumb links + request.setAttribute("orgName", organisation.getName()); + Organisation parentOrg = organisation.getParentOrganisation(); + if (parentOrg != null && !parentOrg.equals(service.getRootOrganisation())) { + request.setAttribute("pOrgId", parentOrg.getOrganisationId()); + request.setAttribute("pOrgName", parentOrg.getName()); + } + request.setAttribute("orgType", organisation.getOrganisationType().getOrganisationTypeId()); + + // populate form with users + ArrayList userOrgs = (ArrayList) request.getAttribute("newUserOrganisations"); + for (int i = 0; i < userOrgs.size(); i++) { + UserBean userBean = new UserBean(); + User user = ((UserOrganisation) userOrgs.get(i)).getUser(); + BeanUtils.copyProperties(userBean, user); + // flag users that will be added to parent group if necessary + userBean.setMemberOfParent(true); + if (organisation.getOrganisationType().getOrganisationTypeId().equals(OrganisationType.CLASS_TYPE)) { + if (service.getUserOrganisation(user.getUserId(), + organisation.getParentOrganisation().getOrganisationId()) == null) { + userBean.setMemberOfParent(false); + } + } + userOrgRoleForm.addUserBean(userBean); + log.debug("ready to assign role for user=" + userBean.getUserId()); + } + log.debug("ready to assign roles for " + userOrgRoleForm.getUserBeans().size() + " new users in organisation " + + organisation.getName()); + + return mapping.findForward("userorgrole"); + } + +} \ No newline at end of file Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/UserOrgRoleSaveAction.java =================================================================== diff -u --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/UserOrgRoleSaveAction.java (revision 0) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/UserOrgRoleSaveAction.java (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -0,0 +1,118 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + +package org.lamsfoundation.lams.admin.web.action; + +import java.util.ArrayList; +import java.util.Arrays; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; +import org.apache.struts.action.Action; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.struts.action.ActionMessage; +import org.apache.struts.action.ActionMessages; +import org.lamsfoundation.lams.admin.service.AdminServiceProxy; +import org.lamsfoundation.lams.admin.web.dto.UserBean; +import org.lamsfoundation.lams.admin.web.form.UserOrgRoleForm; +import org.lamsfoundation.lams.usermanagement.User; +import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; + +/** + * @author jliew + * + * Saves roles for users that were just added. + * Uses session scope because using request scope doesn't copy the form data + * into UserOrgRoleForm's userBeans ArrayList (the list becomes empty). + * + */ + +/** + * struts doclets + * + * + * + * + * + * + * + * + * + */ +public class UserOrgRoleSaveAction extends Action { + + private static Logger log = Logger.getLogger(UserOrgRoleSaveAction.class); + private static IUserManagementService service; + + @Override + public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + + service = AdminServiceProxy.getService(getServlet().getServletContext()); + UserOrgRoleForm userOrgRoleForm = (UserOrgRoleForm) form; + + ArrayList userBeans = userOrgRoleForm.getUserBeans(); + log.debug("userBeans is null? " + userBeans == null); + Integer orgId = userOrgRoleForm.getOrgId(); + log.debug("orgId: " + orgId); + + request.setAttribute("org", orgId); + request.getSession().removeAttribute("UserOrgRoleForm"); + + if (isCancelled(request)) { + return mapping.findForward("userlist"); + } + + // save UserOrganisation memberships, and the associated roles; + // for subgroups, if user is not a member of the parent group then add to that as well. + for (int i = 0; i < userBeans.size(); i++) { + UserBean bean = (UserBean) userBeans.get(i); + User user = (User) service.findById(User.class, bean.getUserId()); + log.debug("userId: " + bean.getUserId()); + String[] roleIds = bean.getRoleIds(); + if (roleIds.length == 0) { + // TODO forward to userorgrole.do, not userorg.do + ActionMessages errors = new ActionMessages(); + errors.add("roles", new ActionMessage("error.roles.empty")); + saveErrors(request, errors); + request.setAttribute("orgId", orgId); + return mapping.findForward("userorg"); + } + service.setRolesForUserOrganisation(user, orgId, Arrays.asList(roleIds)); + // FMALIKOFF 5/7/7 Commented out the following code that set the roles in the course if the current org is a class, as the logic + // is done in service.setRolesForUserOrganisation() + //if (organisation.getOrganisationType().getOrganisationTypeId().equals(OrganisationType.CLASS_TYPE)) { + // if (service.getUserOrganisation(bean.getUserId(), organisation.getParentOrganisation().getOrganisationId())==null) { + // service.setRolesForUserOrganisation(user, organisation.getParentOrganisation(), (List)Arrays.asList(roleIds)); + // } + //} + } + return mapping.findForward("userlist"); + } + +} Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/UserOrgSaveAction.java =================================================================== diff -u --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/UserOrgSaveAction.java (revision 0) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/UserOrgSaveAction.java (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -0,0 +1,147 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + +package org.lamsfoundation.lams.admin.web.action; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; +import org.apache.struts.action.Action; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.struts.action.DynaActionForm; +import org.lamsfoundation.lams.admin.service.AdminServiceProxy; +import org.lamsfoundation.lams.usermanagement.Organisation; +import org.lamsfoundation.lams.usermanagement.Role; +import org.lamsfoundation.lams.usermanagement.User; +import org.lamsfoundation.lams.usermanagement.UserOrganisation; +import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; + +/** + * @author Jun-Dir Liew + * + * Created at 17:22:21 on 20/06/2006 + */ + +/** + * struts doclets + * + * + * + * + * + */ +public class UserOrgSaveAction extends Action { + + private static Logger log = Logger.getLogger(UserOrgSaveAction.class); + private static IUserManagementService service; + private List rolelist; + + @Override + @SuppressWarnings("unchecked") + public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + + DynaActionForm userOrgForm = (DynaActionForm) form; + + Integer orgId = (Integer) userOrgForm.get("orgId"); + request.setAttribute("org", orgId); + + if (isCancelled(request)) { + return mapping.findForward("userlist"); + } + + service = AdminServiceProxy.getService(getServlet().getServletContext()); + if (rolelist == null) { + rolelist = service.findAll(Role.class); + } + + Organisation organisation = (Organisation) service.findById(Organisation.class, orgId); + Set uos = organisation.getUserOrganisations(); + + String[] userIds = (String[]) userOrgForm.get("userIds"); + List userIdList = Arrays.asList(userIds); + log.debug("new user membership of orgId=" + orgId + " will be: " + userIdList); + + // remove UserOrganisations that aren't in form data + Iterator iter = uos.iterator(); + while (iter.hasNext()) { + UserOrganisation uo = (UserOrganisation) iter.next(); + Integer userId = uo.getUser().getUserId(); + if (userIdList.indexOf(userId.toString()) < 0) { + User user = (User) service.findById(User.class, userId); + Set userUos = user.getUserOrganisations(); + userUos.remove(uo); + user.setUserOrganisations(userUos); + iter.remove(); + log.debug("removed userId=" + userId + " from orgId=" + orgId); + // remove from subgroups + service.deleteChildUserOrganisations(uo.getUser(), uo.getOrganisation()); + } + } + // add UserOrganisations that are in form data + List newUserOrganisations = new ArrayList(); + for (int i = 0; i < userIdList.size(); i++) { + Integer userId = new Integer(userIdList.get(i)); + Iterator iter2 = uos.iterator(); + Boolean alreadyInOrg = false; + while (iter2.hasNext()) { + UserOrganisation uo = (UserOrganisation) iter2.next(); + if (uo.getUser().getUserId().equals(userId)) { + alreadyInOrg = true; + break; + } + } + if (!alreadyInOrg) { + User user = (User) service.findById(User.class, userId); + UserOrganisation uo = new UserOrganisation(user, organisation); + newUserOrganisations.add(uo); + } + } + + organisation.setUserOrganisations(uos); + service.save(organisation); + + // if no new users, then finish; otherwise forward to where roles can be assigned for new users. + if (newUserOrganisations.isEmpty()) { + log.debug("no new users to add to orgId=" + orgId); + return mapping.findForward("userlist"); + } else { + request.setAttribute("roles", service.filterRoles(rolelist, request.isUserInRole(Role.SYSADMIN), + organisation.getOrganisationType())); + request.setAttribute("newUserOrganisations", newUserOrganisations); + request.setAttribute("orgId", orgId); + return mapping.findForward("userorgrole"); + } + } + +} Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/UserRolesAction.java =================================================================== diff -u --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/UserRolesAction.java (revision 0) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/UserRolesAction.java (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -0,0 +1,163 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + +package org.lamsfoundation.lams.admin.web.action; + +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; +import org.apache.struts.action.Action; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.struts.action.ActionMessage; +import org.apache.struts.action.ActionMessages; +import org.apache.struts.action.DynaActionForm; +import org.lamsfoundation.lams.admin.service.AdminServiceProxy; +import org.lamsfoundation.lams.usermanagement.Organisation; +import org.lamsfoundation.lams.usermanagement.OrganisationType; +import org.lamsfoundation.lams.usermanagement.Role; +import org.lamsfoundation.lams.usermanagement.User; +import org.lamsfoundation.lams.usermanagement.UserOrganisation; +import org.lamsfoundation.lams.usermanagement.UserOrganisationRole; +import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; +import org.lamsfoundation.lams.util.MessageService; +import org.lamsfoundation.lams.util.WebUtil; + +/** + * @author jliew + * + * + * + * + * + * + * + * + * + */ +public class UserRolesAction extends Action { + + private static Logger log = Logger.getLogger(UserRolesAction.class); + private static IUserManagementService service; + private static MessageService messageService; + private static List rolelist; + + @Override + @SuppressWarnings("unchecked") + public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + + service = AdminServiceProxy.getService(getServlet().getServletContext()); + messageService = AdminServiceProxy.getMessageService(getServlet().getServletContext()); + if (rolelist == null) { + rolelist = service.findAll(Role.class); + Collections.sort(rolelist); + } + + ActionMessages errors = new ActionMessages(); + DynaActionForm userRolesForm = (DynaActionForm) form; + Integer orgId = WebUtil.readIntParam(request, "orgId", true); + Integer userId = WebUtil.readIntParam(request, "userId", true); + + // user and org ids passed as attributes by UserSaveAction + if (orgId == null) { + orgId = (Integer) request.getAttribute("orgId"); + } + if (orgId == null) { + errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("error.org.invalid")); + saveErrors(request, errors); + return mapping.findForward("userrole"); + } + if (userId == null || userId == 0) { + userId = (Integer) request.getAttribute("userId"); + } + if (userId == null) { + errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("error.userid.invalid")); + saveErrors(request, errors); + return mapping.findForward("userrole"); + } + log.debug("editing roles for userId: " + userId + " and orgId: " + orgId); + + // test requestor's permission + Organisation org = (Organisation) service.findById(Organisation.class, orgId); + User user = (User) service.findById(User.class, userId); + OrganisationType orgType = org.getOrganisationType(); + Integer orgIdOfCourse = (orgType.getOrganisationTypeId().equals(OrganisationType.CLASS_TYPE)) + ? org.getParentOrganisation().getOrganisationId() : orgId; + Boolean isSysadmin = request.isUserInRole(Role.SYSADMIN); + User requestor = service.getUserByLogin(request.getRemoteUser()); + Integer rootOrgId = service.getRootOrganisation().getOrganisationId(); + Boolean requestorHasRole = service.isUserInRole(requestor.getUserId(), orgIdOfCourse, Role.GROUP_MANAGER) + || (service.isUserInRole(requestor.getUserId(), orgIdOfCourse, Role.GROUP_ADMIN) + && !rootOrgId.equals(orgId)) + || (service.isUserGlobalGroupAdmin() && !rootOrgId.equals(orgId)); + + if (!(requestorHasRole || isSysadmin)) { + request.setAttribute("errorName", "UserRolesAction"); + request.setAttribute("errorMessage", messageService.getMessage("error.authorisation")); + return mapping.findForward("error"); + } + + userRolesForm.set("userId", userId); + userRolesForm.set("orgId", org.getOrganisationId()); + // screen display vars + request.setAttribute("rolelist", service.filterRoles(rolelist, isSysadmin, orgType)); + request.setAttribute("login", user.getLogin()); + request.setAttribute("fullName", user.getFullName()); + request.setAttribute("orgName", org.getName()); + Organisation parentOrg = org.getParentOrganisation(); + if (parentOrg != null && !parentOrg.equals(service.getRootOrganisation())) { + request.setAttribute("pOrgId", parentOrg.getOrganisationId()); + request.setAttribute("parentName", parentOrg.getName()); + } + + String[] roles = null; + UserOrganisation uo = service.getUserOrganisation(userId, orgId); + if (uo != null) { + Iterator iter2 = uo.getUserOrganisationRoles().iterator(); + roles = new String[uo.getUserOrganisationRoles().size()]; + int i = 0; + while (iter2.hasNext()) { + UserOrganisationRole uor = (UserOrganisationRole) iter2.next(); + roles[i] = uor.getRole().getRoleId().toString(); + log.debug("got roleid: " + roles[i]); + i++; + } + } else { + ActionMessages messages = new ActionMessages(); + messages.add("roles", new ActionMessage("msg.add.to.org", org.getName())); + saveMessages(request, messages); + } + userRolesForm.set("roles", roles); + + return mapping.findForward("userrole"); + } + +} Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/UserRolesSaveAction.java =================================================================== diff -u --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/UserRolesSaveAction.java (revision 0) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/UserRolesSaveAction.java (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -0,0 +1,109 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + +package org.lamsfoundation.lams.admin.web.action; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; +import org.apache.struts.action.Action; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.struts.action.ActionMessage; +import org.apache.struts.action.ActionMessages; +import org.apache.struts.action.DynaActionForm; +import org.lamsfoundation.lams.admin.service.AdminServiceProxy; +import org.lamsfoundation.lams.usermanagement.Organisation; +import org.lamsfoundation.lams.usermanagement.Role; +import org.lamsfoundation.lams.usermanagement.User; +import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; + +/** + * @author jliew + * + * + * + * + * + * + * + * + * + * + */ +public class UserRolesSaveAction extends Action { + + private static Logger log = Logger.getLogger(UserRolesSaveAction.class); + private static IUserManagementService service; + private static List rolelist; + + @Override + public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + + service = AdminServiceProxy.getService(getServlet().getServletContext()); + if (rolelist == null) { + rolelist = service.findAll(Role.class); + Collections.sort(rolelist); + } + + ActionMessages errors = new ActionMessages(); + DynaActionForm userRolesForm = (DynaActionForm) form; + Integer orgId = (Integer) userRolesForm.get("orgId"); + Integer userId = (Integer) userRolesForm.get("userId"); + String[] roles = (String[]) userRolesForm.get("roles"); + + request.setAttribute("org", orgId); + + if (isCancelled(request)) { + return mapping.findForward("userlist"); + } + + log.debug("userId: " + userId + ", orgId: " + orgId + " will have " + roles.length + " roles"); + Organisation org = (Organisation) service.findById(Organisation.class, orgId); + User user = (User) service.findById(User.class, userId); + + // user must have at least 1 role + if (roles.length < 1) { + errors.add("roles", new ActionMessage("error.roles.empty")); + saveErrors(request, errors); + request.setAttribute("rolelist", + service.filterRoles(rolelist, request.isUserInRole(Role.SYSADMIN), org.getOrganisationType())); + request.setAttribute("login", user.getLogin()); + request.setAttribute("fullName", user.getFullName()); + return mapping.findForward("userroles"); + } + + service.setRolesForUserOrganisation(user, orgId, Arrays.asList(roles)); + + return mapping.findForward("userlist"); + } + +} Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/UserSaveAction.java =================================================================== diff -u --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/UserSaveAction.java (revision 0) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/UserSaveAction.java (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -0,0 +1,287 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +package org.lamsfoundation.lams.admin.web.action; + +import java.util.Date; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.beanutils.BeanUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.struts.action.ActionMessage; +import org.apache.struts.action.ActionMessages; +import org.apache.struts.action.DynaActionForm; +import org.lamsfoundation.lams.admin.AdminConstants; +import org.lamsfoundation.lams.admin.service.AdminServiceProxy; +import org.lamsfoundation.lams.security.ISecurityService; +import org.lamsfoundation.lams.themes.Theme; +import org.lamsfoundation.lams.usermanagement.AuthenticationMethod; +import org.lamsfoundation.lams.usermanagement.SupportedLocale; +import org.lamsfoundation.lams.usermanagement.User; +import org.lamsfoundation.lams.usermanagement.dto.UserDTO; +import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; +import org.lamsfoundation.lams.util.HashUtil; +import org.lamsfoundation.lams.util.ValidationUtil; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.action.LamsDispatchAction; +import org.lamsfoundation.lams.web.session.SessionManager; +import org.lamsfoundation.lams.web.util.AttributeNames; + +/** + * @author Jun-Dir Liew + * + * Created at 12:35:38 on 14/06/2006 + */ + +/** + * struts doclets + * + * + * + * + * + * + * + */ + +public class UserSaveAction extends LamsDispatchAction { + + private static Logger log = Logger.getLogger(UserSaveAction.class); + private static IUserManagementService service; + + public ActionForward saveUserDetails(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + + UserSaveAction.service = AdminServiceProxy.getService(getServlet().getServletContext()); + // action input + ActionMessages errors = new ActionMessages(); + DynaActionForm userForm = (DynaActionForm) form; + Integer orgId = (Integer) userForm.get("orgId"); + Integer userId = (Integer) userForm.get("userId"); + ISecurityService securityService = AdminServiceProxy.getSecurityService(getServlet().getServletContext()); + Integer loggeduserId = ((UserDTO) SessionManager.getSession().getAttribute(AttributeNames.USER)).getUserID(); + + // check if logged in User is Sysadmin + if (!securityService.isSysadmin(loggeduserId, "Edit User Details " + userId, true)) { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "Only Sysadmin has edit permisions"); + return null; + } + + UserSaveAction.log.debug("orgId: " + orgId); + Boolean edit = false; + SupportedLocale locale = (SupportedLocale) UserSaveAction.service.findById(SupportedLocale.class, + (Integer) userForm.get("localeId")); + AuthenticationMethod authenticationMethod = (AuthenticationMethod) UserSaveAction.service + .findById(AuthenticationMethod.class, (Integer) userForm.get("authenticationMethodId")); + UserSaveAction.log.debug("locale: " + locale); + UserSaveAction.log.debug("authenticationMethod:" + authenticationMethod); + + if (isCancelled(request)) { + if ((orgId == null) || (orgId == 0)) { + return mapping.findForward("usersearch"); + } + request.setAttribute("org", orgId); + return mapping.findForward("userlist"); + } + + User user = null; + if (userId != 0) { + edit = true; + user = (User) UserSaveAction.service.findById(User.class, userId); + } + + // login validation + String login = (userForm.get("login") == null) ? null : userForm.getString("login").trim(); + if (StringUtils.isBlank(login)) { + errors.add("login", new ActionMessage("error.login.required")); + } else if (!ValidationUtil.isUserNameValid(login)) { + errors.add("login", new ActionMessage("error.username.invalid.characters")); + } else { + userForm.set("login", login); + User existingUser = UserSaveAction.service.getUserByLogin(login); + if (existingUser != null) { + if ((user != null) && StringUtils.equals(user.getLogin(), login)) { + // login exists - it's the user's current login + } else { + errors.add("login", new ActionMessage("error.login.unique", + "(" + login + ", ID: " + existingUser.getUserId() + ")")); + } + } + } + + //first name validation + String firstName = (userForm.get("firstName") == null) ? null : (String) userForm.get("firstName"); + if (StringUtils.isBlank(firstName)) { + errors.add("firstName", new ActionMessage("error.firstname.required")); + } else if (!ValidationUtil.isFirstLastNameValid(firstName)) { + errors.add("firstName", new ActionMessage("error.firstname.invalid.characters")); + } + + //last name validation + String lastName = (userForm.get("lastName") == null) ? null : (String) userForm.get("lastName"); + if (StringUtils.isBlank(lastName)) { + errors.add("lastName", new ActionMessage("error.lastname.required")); + } else if (!ValidationUtil.isFirstLastNameValid(lastName)) { + errors.add("lastName", new ActionMessage("error.lastname.invalid.characters")); + } + + //user email validation + String userEmail = (userForm.get("email") == null) ? null : (String) userForm.get("email"); + if (StringUtils.isBlank(userEmail)) { + errors.add("email", new ActionMessage("error.email.required")); + } else if (!ValidationUtil.isEmailValid(userEmail)) { + errors.add("email", new ActionMessage("error.valid.email.required")); + } + + if (errors.isEmpty()) { + if (edit) { // edit user + UserSaveAction.log.debug("editing userId: " + userId); + // hash the new password if necessary, and audit the fact + userForm.set("password", user.getPassword()); + BeanUtils.copyProperties(user, userForm); + user.setLocale(locale); + user.setAuthenticationMethod(authenticationMethod); + + Theme cssTheme = (Theme) UserSaveAction.service.findById(Theme.class, (Long) userForm.get("userTheme")); + user.setTheme(cssTheme); + + UserSaveAction.service.saveUser(user); + } else { // create user + + //password validation + String password2 = userForm.getString("password2"); + String password = (userForm.get("password") == null) ? null : (String) userForm.get("password"); + if (StringUtils.isBlank(password)) { + errors.add("password", new ActionMessage("error.password.required")); + } + if (!StringUtils.equals(password, ((String) userForm.get("password2")))) { + errors.add("password", new ActionMessage("error.newpassword.mismatch")); + } + if (!ValidationUtil.isPasswordValueValid(password, password2)) { + errors.add("password", new ActionMessage("error.newpassword.mismatch")); + } + + if (errors.isEmpty()) { + user = new User(); + String salt = HashUtil.salt(); + String passwordHash = HashUtil.sha256((String) userForm.get("password"), salt); + BeanUtils.copyProperties(user, userForm); + user.setSalt(salt); + user.setPassword(passwordHash); + UserSaveAction.log.debug("creating user... new login: " + user.getLogin()); + if (errors.isEmpty()) { + // TODO set theme according to user input + // instead of server default. + user.setTheme(UserSaveAction.service.getDefaultTheme()); + user.setDisabledFlag(false); + user.setCreateDate(new Date()); + user.setAuthenticationMethod((AuthenticationMethod) UserSaveAction.service + .findByProperty(AuthenticationMethod.class, "authenticationMethodName", "LAMS-Database") + .get(0)); + user.setUserId(null); + user.setLocale(locale); + + Theme theme = (Theme) UserSaveAction.service.findById(Theme.class, + (Long) userForm.get("userTheme")); + user.setTheme(theme); + + UserSaveAction.service.saveUser(user); + + // make 'create user' audit log entry + UserSaveAction.service.auditUserCreated(user, AdminConstants.MODULE_NAME); + + UserSaveAction.log.debug("user: " + user.toString()); + } + } + } + } + + if (errors.isEmpty()) { + if ((orgId == null) || (orgId == 0)) { + return mapping.findForward("usersearch"); + } + if (edit) { + request.setAttribute("org", orgId); + return mapping.findForward("userlist"); + } else { + request.setAttribute("orgId", orgId); + request.setAttribute("userId", user.getUserId()); + return mapping.findForward("userroles"); + } + } else { + saveErrors(request, errors); + request.setAttribute("orgId", orgId); + return mapping.findForward("user"); + } + } + + public ActionForward changePass(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + UserSaveAction.service = AdminServiceProxy.getService(getServlet().getServletContext()); + ActionMessages errors = new ActionMessages(); + Integer userId = WebUtil.readIntParam(request, "userId", true); + ISecurityService securityService = AdminServiceProxy.getSecurityService(getServlet().getServletContext()); + Integer loggeduserId = ((UserDTO) SessionManager.getSession().getAttribute(AttributeNames.USER)).getUserID(); + + // check if logged in User is Sysadmin + if (!securityService.isSysadmin(loggeduserId, "Change Password of User " + userId, true)) { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "Only Sysadmin has edit permisions"); + return null; + } + + String password = WebUtil.readStrParam(request, "password"); + String password2 = WebUtil.readStrParam(request, "password2"); + + //password validation + if (StringUtils.isBlank(password)) { + errors.add("password", new ActionMessage("error.password.required")); + } + + if (!StringUtils.equals(password, password2)) { + errors.add("password", new ActionMessage("error.newpassword.mismatch")); + } + if (!ValidationUtil.isPasswordValueValid(password, password2)) { + errors.add("password", new ActionMessage("label.password.restrictions")); + } + + if (errors.isEmpty()) { + User user = (User) UserSaveAction.service.findById(User.class, userId); + String salt = HashUtil.salt(); + String passwordHash = HashUtil.sha256(password, salt); + user.setSalt(salt); + user.setPassword(passwordHash); + UserSaveAction.service.saveUser(user); + return mapping.findForward("userChangePass"); + } + saveErrors(request, errors); + return mapping.findForward("errorPass"); + + } + +} Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/UserSearchAction.java =================================================================== diff -u --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/UserSearchAction.java (revision 0) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/UserSearchAction.java (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -0,0 +1,156 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + +package org.lamsfoundation.lams.admin.web.action; + +import java.io.IOException; +import java.util.List; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang.StringEscapeUtils; +import org.apache.log4j.Logger; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.tomcat.util.json.JSONArray; +import org.apache.tomcat.util.json.JSONException; +import org.apache.tomcat.util.json.JSONObject; +import org.lamsfoundation.lams.admin.service.AdminServiceProxy; +import org.lamsfoundation.lams.usermanagement.Role; +import org.lamsfoundation.lams.usermanagement.dto.UserDTO; +import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; +import org.lamsfoundation.lams.util.MessageService; +import org.lamsfoundation.lams.util.WebUtil; +import org.lamsfoundation.lams.web.action.LamsDispatchAction; + +/** + * @author jliew + * + * + * + * + */ +public class UserSearchAction extends LamsDispatchAction { + + private static Logger log = Logger.getLogger(UserSearchAction.class); + private static IUserManagementService service; + private static MessageService messageService; + + @Override + public ActionForward unspecified(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + initServices(); + + if (!(request.isUserInRole(Role.SYSADMIN) || service.isUserGlobalGroupAdmin())) { + log.debug("user not sysadmin or global group admin"); + + request.setAttribute("errorName", "UserSearchAction authorisation"); + request.setAttribute("errorMessage", messageService.getMessage("error.authorisation")); + return mapping.findForward("error"); + } + + return mapping.findForward("usersearchlist"); + } + + /** + * Returns list of paged users. + */ + public ActionForward getPagedUsers(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse res) throws IOException, ServletException, JSONException { + initServices(); + + // the organisation type of the children + String searchString = WebUtil.readStrParam(request, "fcol[1]", true); + + // paging parameters of tablesorter + int size = WebUtil.readIntParam(request, "size"); + int page = WebUtil.readIntParam(request, "page"); + Integer isSort1 = WebUtil.readIntParam(request, "column[0]", true); + Integer isSort2 = WebUtil.readIntParam(request, "column[1]", true); + Integer isSort3 = WebUtil.readIntParam(request, "column[2]", true); + Integer isSort4 = WebUtil.readIntParam(request, "column[3]", true); + Integer isSort5 = WebUtil.readIntParam(request, "column[4]", true); + + String sortBy = "userId"; + String sortOrder = "DESC"; + if (isSort1 != null) { + sortBy = "userId"; + sortOrder = isSort1.equals(0) ? "ASC" : "DESC"; + + } else if (isSort2 != null) { + sortBy = "login"; + sortOrder = isSort2.equals(0) ? "ASC" : "DESC"; + + } else if (isSort3 != null) { + sortBy = "firstName"; + sortOrder = isSort3.equals(0) ? "ASC" : "DESC"; + + } else if (isSort4 != null) { + sortBy = "lastName"; + sortOrder = isSort4.equals(0) ? "ASC" : "DESC"; + + } else if (isSort5 != null) { + sortBy = "email"; + sortOrder = isSort5.equals(0) ? "ASC" : "DESC"; + } + + List userDtos = service.getAllUsersPaged(page, size, sortBy, sortOrder, searchString); + + JSONObject responcedata = new JSONObject(); + responcedata.put("total_rows", service.getCountUsers(searchString)); + + JSONArray rows = new JSONArray(); + for (UserDTO userDto : userDtos) { + + JSONObject responseRow = new JSONObject(); + responseRow.put("userId", userDto.getUserID()); + responseRow.put("login", StringEscapeUtils.escapeHtml(userDto.getLogin())); + String firstName = userDto.getFirstName() == null ? "" : userDto.getFirstName(); + responseRow.put("firstName", StringEscapeUtils.escapeHtml(firstName)); + String lastName = userDto.getLastName() == null ? "" : userDto.getLastName(); + responseRow.put("lastName", StringEscapeUtils.escapeHtml(lastName)); + String email = userDto.getEmail() == null ? "" : userDto.getEmail(); + responseRow.put("email", StringEscapeUtils.escapeHtml(email)); + + rows.put(responseRow); + } + responcedata.put("rows", rows); + res.setContentType("application/json;charset=utf-8"); + res.getWriter().print(new String(responcedata.toString())); + return null; + } + + private void initServices() { + if (service == null) { + service = AdminServiceProxy.getService(getServlet().getServletContext()); + } + if (messageService == null) { + messageService = AdminServiceProxy.getMessageService(getServlet().getServletContext()); + } + } + +} Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/dto/OrgManageBean.java =================================================================== diff -u --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/dto/OrgManageBean.java (revision 0) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/dto/OrgManageBean.java (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -0,0 +1,130 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ +package org.lamsfoundation.lams.admin.web.dto; + +import java.util.Date; + +import org.lamsfoundation.lams.usermanagement.SupportedLocale; + +/** + * @version + * + *

+ * View Source + *

+ * + * @author Fei Yang + * + * Created at 22:55:01 on 2006-6-6 + */ +public class OrgManageBean implements Comparable { + + /** + * OrgManageBean Constructor + * + * @param + */ + public OrgManageBean() { + super(); + + } + + private Integer organisationId; + private String name; + private String code; + private String description; + private Date createDate; + private boolean editable; + private String status; + private SupportedLocale locale; + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public Date getCreateDate() { + return createDate; + } + + public void setCreateDate(Date createDate) { + this.createDate = createDate; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public SupportedLocale getLocale() { + return locale; + } + + public void setLocale(SupportedLocale locale) { + this.locale = locale; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getOrganisationId() { + return organisationId; + } + + public void setOrganisationId(Integer organisationId) { + this.organisationId = organisationId; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public boolean isEditable() { + return editable; + } + + public void setEditable(boolean editable) { + this.editable = editable; + } + + @Override + public int compareTo(Object o) { + return name.compareToIgnoreCase(((OrgManageBean) o).getName()); + } + +} Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/dto/ScheduledJobDTO.java =================================================================== diff -u --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/dto/ScheduledJobDTO.java (revision 0) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/dto/ScheduledJobDTO.java (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -0,0 +1,62 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +package org.lamsfoundation.lams.admin.web.dto; + +import java.util.Date; + +/** + * DTO class of quartz job object for displaying on screen. + * + * @author Steve.Ni + */ +public class ScheduledJobDTO { + + private String name; + private Date startDate; + private String description; + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Date getStartDate() { + return startDate; + } + + public void setStartDate(Date startDate) { + this.startDate = startDate; + } +} Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/dto/UserBean.java =================================================================== diff -u --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/dto/UserBean.java (revision 0) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/dto/UserBean.java (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -0,0 +1,72 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + +package org.lamsfoundation.lams.admin.web.dto; + +/** + * @author jliew + * + * Bean used as member of UserOrgRoleForm, representing a user's roles. + * + */ +public class UserBean { + + private Integer userId; + private String login; + private String[] roleIds = {}; + private Boolean memberOfParent; + + public Integer getUserId() { + return this.userId; + } + + public void setUserId(Integer userId) { + this.userId = userId; + } + + public String getLogin() { + return this.login; + } + + public void setLogin(String login) { + this.login = login; + } + + public String[] getRoleIds() { + return this.roleIds; + } + + public void setRoleIds(String[] roleIds) { + this.roleIds = roleIds; + } + + public Boolean getMemberOfParent() { + return this.memberOfParent; + } + + public void setMemberOfParent(Boolean memberOfParent) { + this.memberOfParent = memberOfParent; + } + +} Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/dto/UserListDTO.java =================================================================== diff -u --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/dto/UserListDTO.java (revision 0) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/dto/UserListDTO.java (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -0,0 +1,83 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + +package org.lamsfoundation.lams.admin.web.dto; + +import java.util.List; + +import org.lamsfoundation.lams.usermanagement.dto.UserManageBean; + +/** + * @author Jun-Dir Liew + * + * Created at 13:47:02 on 9/06/2006 + */ +public class UserListDTO { + + private List userManageBeans; + private Integer orgId; + private String orgName; + private Boolean courseAdminCanAddNewUsers; + private Boolean courseAdminCanBrowseAllUsers; + + public List getUserManageBeans() { + return userManageBeans; + } + + public void setUserManageBeans(List userManageBeans) { + this.userManageBeans = userManageBeans; + } + + public Integer getOrgId() { + return orgId; + } + + public void setOrgId(Integer orgId) { + this.orgId = orgId; + } + + public String getOrgName() { + return orgName; + } + + public void setOrgName(String orgName) { + this.orgName = orgName; + } + + public Boolean getCourseAdminCanAddNewUsers() { + return courseAdminCanAddNewUsers; + } + + public void setCourseAdminCanAddNewUsers(Boolean courseAdminCanAddNewUsers) { + this.courseAdminCanAddNewUsers = courseAdminCanAddNewUsers; + } + + public Boolean getCourseAdminCanBrowseAllUsers() { + return courseAdminCanBrowseAllUsers; + } + + public void setCourseAdminCanBrowseAllUsers(Boolean courseAdminCanBrowseAllUsers) { + this.courseAdminCanBrowseAllUsers = courseAdminCanBrowseAllUsers; + } +} Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/form/ImportExcelForm.java =================================================================== diff -u --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/form/ImportExcelForm.java (revision 0) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/form/ImportExcelForm.java (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -0,0 +1,55 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + +package org.lamsfoundation.lams.admin.web.form; + +import org.apache.struts.action.ActionForm; +import org.apache.struts.upload.FormFile; + +/** + * @author jliew + * + * + */ +public class ImportExcelForm extends ActionForm { + + private Integer orgId; + private FormFile file; + + public Integer getOrgId() { + return orgId; + } + + public void setOrgId(Integer orgId) { + this.orgId = orgId; + } + + public FormFile getFile() { + return file; + } + + public void setFile(FormFile file) { + this.file = file; + } + +} Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/form/OrgManageForm.java =================================================================== diff -u -rc92ea51a973dc03ece970c057dd9369eda6a8c24 -r85ef8aca5722a36582117db1e8b988e2c16b6369 --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/form/OrgManageForm.java (.../OrgManageForm.java) (revision c92ea51a973dc03ece970c057dd9369eda6a8c24) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/form/OrgManageForm.java (.../OrgManageForm.java) (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -25,7 +25,7 @@ import java.util.List; import org.apache.struts.action.ActionForm; -import org.lamsfoundation.lams.admin.web.OrgManageBean; +import org.lamsfoundation.lams.admin.web.dto.OrgManageBean; /** * @version Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/form/UserOrgRoleForm.java =================================================================== diff -u --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/form/UserOrgRoleForm.java (revision 0) +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/form/UserOrgRoleForm.java (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -0,0 +1,71 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + +package org.lamsfoundation.lams.admin.web.form; + +import java.util.ArrayList; + +import org.apache.struts.action.ActionForm; +import org.lamsfoundation.lams.admin.web.dto.UserBean; + +/** + * @author jliew + * + * This is the Action Form that is used when a user has added users + * to an organisation via UserOrgForm. Used to record roles for each + * of the added users. + * + */ + +/** + * struts doclet + * + * + */ +public class UserOrgRoleForm extends ActionForm { + + private ArrayList userBeans = new ArrayList(); + private Integer orgId; + + public ArrayList getUserBeans() { + return userBeans; + } + + public void setUserBeans(ArrayList userBeans) { + this.userBeans = userBeans; + } + + public Integer getOrgId() { + return orgId; + } + + public void setOrgId(Integer orgId) { + this.orgId = orgId; + } + + public void addUserBean(UserBean userBean) { + userBeans.add(userBean); + } + +} Index: lams_admin/web/WEB-INF/struts-config.xml =================================================================== diff -u -r953f62a7fc515e2dc5c4ad983df233070cf7a82c -r85ef8aca5722a36582117db1e8b988e2c16b6369 --- lams_admin/web/WEB-INF/struts-config.xml (.../struts-config.xml) (revision 953f62a7fc515e2dc5c4ad983df233070cf7a82c) +++ lams_admin/web/WEB-INF/struts-config.xml (.../struts-config.xml) (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -23,11 +23,11 @@ /> @@ -141,7 +141,7 @@ @@ -178,7 +178,7 @@ @@ -271,7 +271,7 @@ @@ -283,7 +283,7 @@ @@ -588,7 +588,7 @@ @@ -881,7 +881,7 @@ @@ -893,7 +893,7 @@ - + Index: lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/service/McService.java =================================================================== diff -u --- lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/service/McService.java (revision 0) +++ lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/service/McService.java (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -0,0 +1,1964 @@ +/*************************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * ***********************************************************************/ + +package org.lamsfoundation.lams.tool.mc.service; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Date; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.SortedMap; +import java.util.TreeMap; +import java.util.TreeSet; + +import javax.servlet.http.HttpSession; + +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; +import org.apache.poi.hssf.usermodel.HSSFCell; +import org.apache.poi.hssf.usermodel.HSSFCellStyle; +import org.apache.poi.hssf.usermodel.HSSFRow; +import org.apache.poi.hssf.usermodel.HSSFSheet; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.Font; +import org.apache.poi.ss.usermodel.IndexedColors; +import org.apache.tomcat.util.json.JSONArray; +import org.apache.tomcat.util.json.JSONException; +import org.apache.tomcat.util.json.JSONObject; +import org.lamsfoundation.lams.contentrepository.client.IToolContentHandler; +import org.lamsfoundation.lams.gradebook.service.IGradebookService; +import org.lamsfoundation.lams.learning.service.ILearnerService; +import org.lamsfoundation.lams.learningdesign.service.ExportToolContentException; +import org.lamsfoundation.lams.learningdesign.service.IExportToolContentService; +import org.lamsfoundation.lams.learningdesign.service.ImportToolContentException; +import org.lamsfoundation.lams.notebook.model.NotebookEntry; +import org.lamsfoundation.lams.notebook.service.CoreNotebookConstants; +import org.lamsfoundation.lams.notebook.service.ICoreNotebookService; +import org.lamsfoundation.lams.rest.RestTags; +import org.lamsfoundation.lams.rest.ToolRestManager; +import org.lamsfoundation.lams.tool.IToolVO; +import org.lamsfoundation.lams.tool.ToolCompletionStatus; +import org.lamsfoundation.lams.tool.ToolContentManager; +import org.lamsfoundation.lams.tool.ToolOutput; +import org.lamsfoundation.lams.tool.ToolOutputDefinition; +import org.lamsfoundation.lams.tool.ToolSessionExportOutputData; +import org.lamsfoundation.lams.tool.ToolSessionManager; +import org.lamsfoundation.lams.tool.exception.DataMissingException; +import org.lamsfoundation.lams.tool.exception.ToolException; +import org.lamsfoundation.lams.tool.mc.McAppConstants; +import org.lamsfoundation.lams.tool.mc.dao.IMcContentDAO; +import org.lamsfoundation.lams.tool.mc.dao.IMcOptionsContentDAO; +import org.lamsfoundation.lams.tool.mc.dao.IMcQueContentDAO; +import org.lamsfoundation.lams.tool.mc.dao.IMcSessionDAO; +import org.lamsfoundation.lams.tool.mc.dao.IMcUserDAO; +import org.lamsfoundation.lams.tool.mc.dao.IMcUsrAttemptDAO; +import org.lamsfoundation.lams.tool.mc.dto.AnswerDTO; +import org.lamsfoundation.lams.tool.mc.dto.LeaderResultsDTO; +import org.lamsfoundation.lams.tool.mc.dto.McOptionDTO; +import org.lamsfoundation.lams.tool.mc.dto.McQuestionDTO; +import org.lamsfoundation.lams.tool.mc.dto.McSessionMarkDTO; +import org.lamsfoundation.lams.tool.mc.dto.McUserMarkDTO; +import org.lamsfoundation.lams.tool.mc.dto.ReflectionDTO; +import org.lamsfoundation.lams.tool.mc.dto.SessionDTO; +import org.lamsfoundation.lams.tool.mc.dto.ToolOutputDTO; +import org.lamsfoundation.lams.tool.mc.pojos.McContent; +import org.lamsfoundation.lams.tool.mc.pojos.McOptsContent; +import org.lamsfoundation.lams.tool.mc.pojos.McQueContent; +import org.lamsfoundation.lams.tool.mc.pojos.McQueUsr; +import org.lamsfoundation.lams.tool.mc.pojos.McSession; +import org.lamsfoundation.lams.tool.mc.pojos.McUsrAttempt; +import org.lamsfoundation.lams.tool.mc.util.McSessionComparator; +import org.lamsfoundation.lams.tool.mc.util.McStringComparator; +import org.lamsfoundation.lams.tool.service.ILamsToolService; +import org.lamsfoundation.lams.usermanagement.User; +import org.lamsfoundation.lams.usermanagement.dto.UserDTO; +import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; +import org.lamsfoundation.lams.util.ExcelUtil; +import org.lamsfoundation.lams.util.JsonUtil; +import org.lamsfoundation.lams.util.MessageService; +import org.lamsfoundation.lams.util.NumberUtil; +import org.lamsfoundation.lams.util.audit.IAuditService; +import org.lamsfoundation.lams.web.session.SessionManager; +import org.lamsfoundation.lams.web.util.AttributeNames; +import org.springframework.dao.DataAccessException; + +/** + * + * The POJO implementation of Mc service. All business logics of MCQ tool are implemented in this class. It translate + * the request from presentation layer and perform appropriate database operation. + * + * @author Ozgur Demirtas + */ +public class McService implements IMcService, ToolContentManager, ToolSessionManager, ToolRestManager, McAppConstants { + private static Logger logger = Logger.getLogger(McService.class.getName()); + + private IMcContentDAO mcContentDAO; + private IMcQueContentDAO mcQueContentDAO; + private IMcOptionsContentDAO mcOptionsContentDAO; + private IMcSessionDAO mcSessionDAO; + private IMcUserDAO mcUserDAO; + private IMcUsrAttemptDAO mcUsrAttemptDAO; + private MCOutputFactory mcOutputFactory; + + private IAuditService auditService; + private IUserManagementService userManagementService; + private ILearnerService learnerService; + private ILamsToolService toolService; + private IToolContentHandler mcToolContentHandler = null; + private IExportToolContentService exportContentService; + private IGradebookService gradebookService; + + private ICoreNotebookService coreNotebookService; + + private MessageService messageService; + + public McService() { + } + + @Override + public McQueUsr checkLeaderSelectToolForSessionLeader(McQueUsr user, Long toolSessionId) { + if ((user == null) || (toolSessionId == null)) { + return null; + } + + McSession mcSession = mcSessionDAO.getMcSessionById(toolSessionId); + McQueUsr leader = mcSession.getGroupLeader(); + // check leader select tool for a leader only in case QA tool doesn't know it. As otherwise it will screw + // up previous scratches done + if (leader == null) { + + Long leaderUserId = toolService.getLeaderUserId(toolSessionId, user.getQueUsrId().intValue()); + if (leaderUserId != null) { + + leader = getMcUserBySession(leaderUserId, mcSession.getUid()); + + // create new user in a DB + if (leader == null) { + logger.debug("creating new user with userId: " + leaderUserId); + User leaderDto = (User) userManagementService.findById(User.class, leaderUserId.intValue()); + String userName = leaderDto.getLogin(); + String fullName = leaderDto.getFirstName() + " " + leaderDto.getLastName(); + leader = new McQueUsr(leaderUserId, userName, fullName, mcSession, new TreeSet()); + mcUserDAO.saveMcUser(user); + } + + // set group leader + mcSession.setGroupLeader(leader); + mcSessionDAO.updateMcSession(mcSession); + } + } + + return leader; + } + + @Override + public void copyAnswersFromLeader(McQueUsr user, McQueUsr leader) { + + if ((user == null) || (leader == null) || user.getUid().equals(leader.getUid())) { + return; + } + + List leaderAttempts = this.getFinalizedUserAttempts(leader); + for (McUsrAttempt leaderAttempt : leaderAttempts) { + + McQueContent question = leaderAttempt.getMcQueContent(); + McUsrAttempt userAttempt = mcUsrAttemptDAO.getUserAttemptByQuestion(user.getUid(), question.getUid()); + + // if response doesn't exist - created mcUsrAttempt in the db + if (userAttempt == null) { + userAttempt = new McUsrAttempt(leaderAttempt.getAttemptTime(), question, user, + leaderAttempt.getMcOptionsContent(), leaderAttempt.getMark(), leaderAttempt.isPassed(), + leaderAttempt.isAttemptCorrect()); + mcUsrAttemptDAO.saveMcUsrAttempt(userAttempt); + + // if it's been changed by the leader + } else if (leaderAttempt.getAttemptTime().compareTo(userAttempt.getAttemptTime()) != 0) { + userAttempt.setMcOptionsContent(leaderAttempt.getMcOptionsContent()); + userAttempt.setAttemptTime(leaderAttempt.getAttemptTime()); + this.updateMcUsrAttempt(userAttempt); + } + + user.setNumberOfAttempts(leader.getNumberOfAttempts()); + user.setLastAttemptTotalMark(leader.getLastAttemptTotalMark()); + this.updateMcQueUsr(user); + } + } + + @Override + public void createMc(McContent mcContent) throws McApplicationException { + try { + mcContentDAO.saveMcContent(mcContent); + } catch (DataAccessException e) { + throw new McApplicationException("Exception occured when lams is creating mc content: " + e.getMessage(), + e); + } + } + + @Override + public McContent getMcContent(Long toolContentId) throws McApplicationException { + try { + return mcContentDAO.findMcContentById(toolContentId); + } catch (DataAccessException e) { + throw new McApplicationException("Exception occured when lams is loading mc content: " + e.getMessage(), e); + } + } + + @Override + public void setDefineLater(String strToolContentID, boolean value) { + + McContent mcContent = getMcContent(new Long(strToolContentID)); + if (mcContent != null) { + mcContent.setDefineLater(value); + updateMc(mcContent); + } + } + + @Override + public void updateQuestion(McQueContent mcQueContent) throws McApplicationException { + try { + mcQueContentDAO.updateMcQueContent(mcQueContent); + } catch (DataAccessException e) { + throw new McApplicationException( + "Exception occured when lams is updating mc que content: " + e.getMessage(), e); + } + + } + + @Override + public McQueContent getQuestionByDisplayOrder(final Long displayOrder, final Long mcContentUid) + throws McApplicationException { + try { + return mcQueContentDAO.getQuestionContentByDisplayOrder(displayOrder, mcContentUid); + } catch (DataAccessException e) { + throw new McApplicationException( + "Exception occured when lams is getting mc que content by display order: " + e.getMessage(), e); + } + } + + @Override + public List getAllQuestionsSorted(final long mcContentId) throws McApplicationException { + try { + return mcQueContentDAO.getAllQuestionEntriesSorted(mcContentId); + } catch (DataAccessException e) { + throw new McApplicationException( + "Exception occured when lams is getting all question entries: " + e.getMessage(), e); + } + } + + @Override + public void saveOrUpdateMcQueContent(McQueContent mcQueContent) throws McApplicationException { + try { + mcQueContentDAO.saveOrUpdateMcQueContent(mcQueContent); + } catch (DataAccessException e) { + throw new McApplicationException( + "Exception occured when lams is updating mc que content: " + e.getMessage(), e); + } + } + + @Override + public McContent createQuestions(List questionDTOs, McContent content) { + + int displayOrder = 0; + for (McQuestionDTO questionDTO : questionDTOs) { + String currentQuestionText = questionDTO.getQuestion(); + + // skip empty questions + if (currentQuestionText.isEmpty()) { + continue; + } + + ++displayOrder; + String currentFeedback = questionDTO.getFeedback(); + String currentMark = questionDTO.getMark(); + /* set the default mark in case it is not provided */ + if (currentMark == null) { + currentMark = "1"; + } + + McQueContent question = getQuestionByUid(questionDTO.getUid()); + + // in case question doesn't exist + if (question == null) { + question = new McQueContent(currentQuestionText, new Integer(displayOrder), new Integer(currentMark), + currentFeedback, content, null, null); + + // adding a new question to content + content.getMcQueContents().add(question); + question.setMcContent(content); + + // in case question exists already + } else { + + question.setQuestion(currentQuestionText); + question.setFeedback(currentFeedback); + question.setDisplayOrder(new Integer(displayOrder)); + question.setMark(new Integer(currentMark)); + } + + // persist candidate answers + List optionDTOs = questionDTO.getOptionDtos(); + Set oldOptions = question.getMcOptionsContents(); + Set newOptions = new HashSet(); + int displayOrderOption = 1; + for (McOptionDTO optionDTO : optionDTOs) { + + Long optionUid = optionDTO.getUid(); + String optionText = optionDTO.getCandidateAnswer(); + boolean isCorrectOption = "Correct".equals(optionDTO.getCorrect()); + + //find persisted option if it exists + McOptsContent option = new McOptsContent(); + for (McOptsContent oldOption : oldOptions) { + if (oldOption.getUid().equals(optionUid)) { + option = oldOption; + } + } + + option.setDisplayOrder(displayOrderOption); + option.setCorrectOption(isCorrectOption); + option.setMcQueOptionText(optionText); + option.setMcQueContent(question); + + newOptions.add(option); + displayOrderOption++; + } + + question.setMcOptionsContents(newOptions); + + // updating the existing question content + updateQuestion(question); + + } + return content; + } + + @Override + public void releaseQuestionsFromCache(McContent content) { + for (McQueContent question : (Set) content.getMcQueContents()) { + mcQueContentDAO.releaseQuestionFromCache(question); + } + } + + @Override + public McQueUsr createMcUser(Long toolSessionID) throws McApplicationException { + try { + HttpSession ss = SessionManager.getSession(); + UserDTO toolUser = (UserDTO) ss.getAttribute(AttributeNames.USER); + Long userId = toolUser.getUserID().longValue(); + String userName = toolUser.getLogin(); + String fullName = toolUser.getFirstName() + " " + toolUser.getLastName(); + McSession mcSession = getMcSessionById(toolSessionID.longValue()); + + McQueUsr user = new McQueUsr(userId, userName, fullName, mcSession, new TreeSet()); + mcUserDAO.saveMcUser(user); + + return user; + } catch (DataAccessException e) { + throw new McApplicationException("Exception occured when lams is creating mc QueUsr: " + e.getMessage(), e); + } + } + + @Override + public void updateMcQueUsr(McQueUsr mcQueUsr) throws McApplicationException { + try { + mcUserDAO.updateMcUser(mcQueUsr); + } catch (DataAccessException e) { + throw new McApplicationException("Exception occured when lams is updating mc QueUsr: " + e.getMessage(), e); + } + } + + @Override + public McQueUsr getMcUserBySession(final Long queUsrId, final Long mcSessionUid) throws McApplicationException { + try { + return mcUserDAO.getMcUserBySession(queUsrId, mcSessionUid); + } catch (DataAccessException e) { + throw new McApplicationException("Exception occured when lams is getting mc QueUsr: " + e.getMessage(), e); + } + } + + @Override + public McQueUsr getMcUserByUID(Long uid) throws McApplicationException { + try { + return mcUserDAO.getMcUserByUID(uid); + } catch (DataAccessException e) { + throw new McApplicationException( + "Exception occured when lams is getting the mc QueUsr by uid." + e.getMessage(), e); + } + } + + @Override + public List getPagedUsersBySession(Long sessionId, int page, int size, String sortBy, + String sortOrder, String searchString) { + return mcUserDAO.getPagedUsersBySession(sessionId, page, size, sortBy, sortOrder, searchString); + } + + @Override + public int getCountPagedUsersBySession(Long sessionId, String searchString) { + return mcUserDAO.getCountPagedUsersBySession(sessionId, searchString); + } + + @Override + public String getLocalizedMessage(String key) { + return messageService.getMessage(key); + } + + @Override + public void saveUserAttempt(McQueUsr user, List answerDtos) { + + Date attemptTime = new Date(System.currentTimeMillis()); + + for (AnswerDTO answerDto : answerDtos) { + + Long questionUid = answerDto.getQuestionUid(); + McQueContent question = this.getQuestionByUid(questionUid); + if (question == null) { + throw new McApplicationException( + "Can't find question with specified question uid: " + answerDto.getQuestionUid()); + } + + McOptsContent answerOption = answerDto.getAnswerOption(); + if (answerOption != null) { + + Integer mark = answerDto.getMark(); + boolean passed = user.isMarkPassed(mark); + boolean isAttemptCorrect = answerDto.isAttemptCorrect(); + + McUsrAttempt userAttempt = this.getUserAttemptByQuestion(user.getUid(), questionUid); + if (userAttempt != null) { + + McOptsContent previosAnswer = userAttempt.getMcOptionsContent(); + // check if answer hasn't been changed since the last time + if (previosAnswer.getUid().equals(answerOption.getUid())) { + // don't save anything + continue; + + } else { + // in case answer has been changed update userttempt + userAttempt.setAttemptTime(attemptTime); + userAttempt.setMcOptionsContent(answerOption); + userAttempt.setMark(mark); + userAttempt.setPassed(passed); + userAttempt.setAttemptCorrect(isAttemptCorrect); + } + + } else { + // create new userAttempt + userAttempt = new McUsrAttempt(attemptTime, question, user, answerOption, mark, passed, + isAttemptCorrect); + } + + mcUsrAttemptDAO.saveMcUsrAttempt(userAttempt); + + } + } + } + + @Override + public void updateMcUsrAttempt(McUsrAttempt mcUsrAttempt) throws McApplicationException { + try { + mcUsrAttemptDAO.updateMcUsrAttempt(mcUsrAttempt); + } catch (DataAccessException e) { + throw new McApplicationException("Exception occured when lams is updating mc UsrAttempt: " + e.getMessage(), + e); + } + } + + @Override + public List getAnswersFromDatabase(McContent mcContent, McQueUsr user) { + List answerDtos = new LinkedList(); + List questions = this.getQuestionsByContentUid(mcContent.getUid()); + + for (McQueContent question : questions) { + AnswerDTO answerDto = new AnswerDTO(); + Set optionSet = question.getMcOptionsContents(); + List optionList = new LinkedList(optionSet); + + boolean randomize = mcContent.isRandomize(); + if (randomize) { + ArrayList shuffledList = new ArrayList(optionList); + Collections.shuffle(shuffledList); + optionList = new LinkedList(shuffledList); + } + + answerDto.setQuestion(question.getQuestion()); + answerDto.setDisplayOrder(question.getDisplayOrder().toString()); + answerDto.setQuestionUid(question.getUid()); + + answerDto.setMark(question.getMark()); + answerDto.setOptions(optionList); + + answerDtos.add(answerDto); + } + + // populate answers + if (user != null) { + + for (AnswerDTO answerDto : answerDtos) { + Long questionUid = answerDto.getQuestionUid(); + + McUsrAttempt dbAttempt = this.getUserAttemptByQuestion(user.getUid(), questionUid); + if (dbAttempt != null) { + Long selectedOptionUid = dbAttempt.getMcOptionsContent().getUid(); + + // mark selected option as selected + for (McOptsContent option : answerDto.getOptions()) { + if (selectedOptionUid.equals(option.getUid())) { + option.setSelected(true); + } + } + } + } + } + + return answerDtos; + } + + @Override + public List buildGroupsMarkData(McContent mcContent, boolean isFullAttemptDetailsRequired) { + List listMonitoredMarksContainerDTO = new LinkedList(); + Set sessions = new TreeSet(new McSessionComparator()); + sessions.addAll(mcContent.getMcSessions()); + int numQuestions = mcContent.getMcQueContents().size(); + + for (McSession session : sessions) { + + McSessionMarkDTO mcSessionMarkDTO = new McSessionMarkDTO(); + mcSessionMarkDTO.setSessionId(session.getMcSessionId().toString()); + mcSessionMarkDTO.setSessionName(session.getSession_name().toString()); + + Set sessionUsers = session.getMcQueUsers(); + Iterator usersIterator = sessionUsers.iterator(); + + Map mapSessionUsersData = new TreeMap( + new McStringComparator()); + Long mapIndex = new Long(1); + + while (usersIterator.hasNext()) { + McQueUsr user = usersIterator.next(); + + McUserMarkDTO mcUserMarkDTO = new McUserMarkDTO(); + mcUserMarkDTO.setSessionId(session.getMcSessionId().toString()); + mcUserMarkDTO.setSessionName(session.getSession_name().toString()); + mcUserMarkDTO.setFullName(user.getFullname()); + mcUserMarkDTO.setUserGroupLeader(session.isUserGroupLeader(user)); + mcUserMarkDTO.setUserName(user.getUsername()); + mcUserMarkDTO.setQueUsrId(user.getUid().toString()); + + if (isFullAttemptDetailsRequired) { + + // The marks for the user must be listed in the display order of the question. + // Other parts of the code assume that the questions will be in consecutive display + // order starting 1 (e.g. 1, 2, 3, not 1, 3, 4) so we set up an array and use + // the ( display order - 1) as the index (arrays start at 0, rather than 1 hence -1) + // The user must answer all questions, so we can assume that they will have marks + // for all questions or no questions. + // At present there can only be one answer for each question but there may be more + // than one in the future and if so, we don't want to count the mark twice hence + // we need to check if we've already processed this question in the total. + Integer[] userMarks = new Integer[numQuestions]; + String[] answeredOptions = new String[numQuestions]; + Date attemptTime = null; + List finalizedUserAttempts = this.getFinalizedUserAttempts(user); + long totalMark = 0; + for (McUsrAttempt attempt : finalizedUserAttempts) { + Integer displayOrder = attempt.getMcQueContent().getDisplayOrder(); + int arrayIndex = (displayOrder != null) && (displayOrder.intValue() > 0) + ? displayOrder.intValue() - 1 : 1; + if (userMarks[arrayIndex] == null) { + + // We get the mark for the attempt if the answer is correct and we don't allow + // retries, or if the answer is correct and the learner has met the passmark if + // we do allow retries. + boolean isRetries = session.getMcContent().isRetries(); + Integer mark = attempt.getMarkForShow(isRetries); + userMarks[arrayIndex] = mark; + totalMark += mark.intValue(); + + // find out the answered option's sequential letter - A,B,C... + String answeredOptionLetter = ""; + int optionCount = 1; + for (McOptsContent option : (Set) attempt.getMcQueContent() + .getMcOptionsContents()) { + if (attempt.getMcOptionsContent().getUid().equals(option.getUid())) { + answeredOptionLetter = String.valueOf((char) ((optionCount + 'A') - 1)); + break; + } + optionCount++; + } + answeredOptions[arrayIndex] = answeredOptionLetter; + } + // get the attempt time, (NB all questions will have the same attempt time) + // Not efficient, since we assign this value for each attempt + attemptTime = attempt.getAttemptTime(); + } + + mcUserMarkDTO.setMarks(userMarks); + mcUserMarkDTO.setAnsweredOptions(answeredOptions); + mcUserMarkDTO.setAttemptTime(attemptTime); + mcUserMarkDTO.setTotalMark(new Long(totalMark)); + + } else { + int totalMark = mcUsrAttemptDAO.getUserTotalMark(user.getUid()); + mcUserMarkDTO.setTotalMark(new Long(totalMark)); + } + + mapSessionUsersData.put(mapIndex.toString(), mcUserMarkDTO); + mapIndex = new Long(mapIndex.longValue() + 1); + } + + mcSessionMarkDTO.setUserMarks(mapSessionUsersData); + listMonitoredMarksContainerDTO.add(mcSessionMarkDTO); + } + + return listMonitoredMarksContainerDTO; + } + + @Override + public List getFinalizedUserAttempts(final McQueUsr user) throws McApplicationException { + try { + return mcUsrAttemptDAO.getFinalizedUserAttempts(user.getUid()); + } catch (DataAccessException e) { + throw new McApplicationException( + "Exception occured when lams is getting the learner's attempts by user id and que content id and attempt order: " + + e.getMessage(), + e); + } + } + + @Override + public McUsrAttempt getUserAttemptByQuestion(Long queUsrUid, Long mcQueContentId) throws McApplicationException { + try { + return mcUsrAttemptDAO.getUserAttemptByQuestion(queUsrUid, mcQueContentId); + } catch (DataAccessException e) { + throw new McApplicationException( + "Exception occured when lams is getting the learner's attempts by user id and que content id and attempt order: " + + e.getMessage(), + e); + } + } + + @Override + public List getLearnerMarksByContentId(Long toolContentId) { + return mcUsrAttemptDAO.getLearnerMarksByContentId(toolContentId); + } + + @Override + public List getQuestionsByContentUid(final Long contentUid) throws McApplicationException { + try { + return mcQueContentDAO.getQuestionsByContentUid(contentUid.longValue()); + } catch (DataAccessException e) { + throw new McApplicationException( + "Exception occured when lams is getting by uid mc question content: " + e.getMessage(), e); + } + } + + @Override + public List refreshQuestionContent(final Long mcContentId) throws McApplicationException { + try { + return mcQueContentDAO.refreshQuestionContent(mcContentId); + } catch (DataAccessException e) { + throw new McApplicationException( + "Exception occured when lams is refreshing mc question content: " + e.getMessage(), e); + } + + } + + @Override + public void removeMcQueContent(McQueContent mcQueContent) throws McApplicationException { + try { + mcQueContentDAO.removeMcQueContent(mcQueContent); + } catch (DataAccessException e) { + throw new McApplicationException( + "Exception occured when lams is removing mc question content: " + e.getMessage(), e); + } + } + + @Override + public List getOptionDtos(Long mcQueContentId) throws McApplicationException { + try { + return mcOptionsContentDAO.getOptionDtos(mcQueContentId); + } catch (DataAccessException e) { + throw new McApplicationException( + "Exception occured when lams is populating candidate answers dto" + e.getMessage(), e); + } + } + + @Override + public McSession getMcSessionById(Long mcSessionId) throws McApplicationException { + try { + return mcSessionDAO.getMcSessionById(mcSessionId); + } catch (DataAccessException e) { + throw new McApplicationException( + "Exception occured when lams is retrieving by id mc session : " + e.getMessage(), e); + } + } + + @Override + public void updateMc(McContent mc) throws McApplicationException { + try { + mcContentDAO.updateMcContent(mc); + } catch (DataAccessException e) { + throw new McApplicationException( + "Exception occured when lams is updating" + " the mc content: " + e.getMessage(), e); + } + } + + @Override + public Object[] getMarkStatistics(McSession mcSession) { + return mcUserDAO.getStatsMarksBySession(mcSession.getMcSessionId()); + } + + @Override + public List findOptionsByQuestionUid(Long mcQueContentId) throws McApplicationException { + try { + return mcOptionsContentDAO.findMcOptionsContentByQueId(mcQueContentId); + } catch (DataAccessException e) { + throw new McApplicationException( + "Exception occured when lams is finding by que id" + " the mc options: " + e.getMessage(), e); + } + } + + @Override + public McQueContent getQuestionByUid(Long uid) { + if (uid == null) { + return null; + } + + return mcQueContentDAO.findMcQuestionContentByUid(uid); + } + + @Override + public void updateMcOptionsContent(McOptsContent mcOptsContent) throws McApplicationException { + try { + mcOptionsContentDAO.updateMcOptionsContent(mcOptsContent); + } catch (DataAccessException e) { + throw new McApplicationException( + "Exception occured when lams is updating" + " the mc options content: " + e.getMessage(), e); + } + } + + @Override + public void changeUserAttemptMark(Long userAttemptUid, Integer newMark) { + if (newMark == null) { + return; + } + + McUsrAttempt userAttempt = mcUsrAttemptDAO.getUserAttemptByUid(userAttemptUid); + Integer userId = userAttempt.getMcQueUsr().getQueUsrId().intValue(); + Long userUid = userAttempt.getMcQueUsr().getUid(); + Long toolSessionId = userAttempt.getMcQueUsr().getMcSession().getMcSessionId(); + Integer oldMark = userAttempt.getMark(); + int oldTotalMark = mcUsrAttemptDAO.getUserTotalMark(userUid); + + int totalMark = (oldMark == null) ? oldTotalMark + newMark : (oldTotalMark - oldMark) + newMark; + + //update mark for one particular question + userAttempt.setMark(newMark); + mcUsrAttemptDAO.saveMcUsrAttempt(userAttempt); + + //update user's total mark + McQueUsr user = userAttempt.getMcQueUsr(); + user.setLastAttemptTotalMark(totalMark); + updateMcQueUsr(user); + + // propagade changes to Gradebook + gradebookService.updateActivityMark(new Double(totalMark), null, userId, toolSessionId, false); + + // record mark change with audit service + auditService.logMarkChange(McAppConstants.TOOL_SIGNATURE, userAttempt.getMcQueUsr().getQueUsrId(), + userAttempt.getMcQueUsr().getUsername(), "" + oldMark, "" + totalMark); + + } + + @Override + public void recalculateUserAnswers(McContent content, Set oldQuestions, + List questionDTOs, List deletedQuestions) { + + // create list of modified questions + List modifiedQuestions = new ArrayList(); + // create list of modified question marks + List modifiedQuestionsMarksOnly = new ArrayList(); + for (McQueContent oldQuestion : oldQuestions) { + for (McQuestionDTO questionDTO : questionDTOs) { + if (oldQuestion.getUid().equals(questionDTO.getUid())) { + + boolean isQuestionModified = false; + boolean isQuestionMarkModified = false; + + // question is different + if (!oldQuestion.getQuestion().equals(questionDTO.getQuestion())) { + isQuestionModified = true; + } + + // mark is different + if (oldQuestion.getMark().intValue() != (new Integer(questionDTO.getMark())).intValue()) { + isQuestionMarkModified = true; + } + + // options are different + Set oldOptions = oldQuestion.getMcOptionsContents(); + List optionDTOs = questionDTO.getOptionDtos(); + for (McOptsContent oldOption : oldOptions) { + for (McOptionDTO optionDTO : optionDTOs) { + if (oldOption.getUid().equals(optionDTO.getUid())) { + + if (!StringUtils.equals(oldOption.getMcQueOptionText(), optionDTO.getCandidateAnswer()) + || (oldOption.isCorrectOption() != "Correct".equals(optionDTO.getCorrect()))) { + isQuestionModified = true; + } + } + } + } + + if (isQuestionModified) { + modifiedQuestions.add(questionDTO); + + } else if (isQuestionMarkModified) { + modifiedQuestionsMarksOnly.add(questionDTO); + } + } + } + } + + Set sessionList = content.getMcSessions(); + for (McSession session : sessionList) { + Long toolSessionId = session.getMcSessionId(); + Set sessionUsers = session.getMcQueUsers(); + + for (McQueUsr user : sessionUsers) { + + final int oldTotalMark = mcUsrAttemptDAO.getUserTotalMark(user.getUid()); + int newTotalMark = oldTotalMark; + + // get all finished user results + List userAttempts = getFinalizedUserAttempts(user); + Iterator iter = userAttempts.iterator(); + while (iter.hasNext()) { + McUsrAttempt userAttempt = iter.next(); + + McQueContent question = userAttempt.getMcQueContent(); + + boolean isRemoveQuestionResult = false; + + // [+] if the question mark is modified + for (McQuestionDTO modifiedQuestion : modifiedQuestionsMarksOnly) { + if (question.getUid().equals(modifiedQuestion.getUid())) { + Integer newQuestionMark = new Integer(modifiedQuestion.getMark()); + Integer oldQuestionMark = question.getMark(); + Integer newActualMark = (userAttempt.getMark() * newQuestionMark) / oldQuestionMark; + + newTotalMark += newActualMark - userAttempt.getMark(); + + // update question answer's mark + userAttempt.setMark(newActualMark); + mcUsrAttemptDAO.saveMcUsrAttempt(userAttempt); + + break; + } + + } + + // [+] if the question is modified + for (McQuestionDTO modifiedQuestion : modifiedQuestions) { + if (question.getUid().equals(modifiedQuestion.getUid())) { + isRemoveQuestionResult = true; + break; + } + } + + // [+] if the question was removed + for (McQuestionDTO deletedQuestion : deletedQuestions) { + if (question.getUid().equals(deletedQuestion.getUid())) { + isRemoveQuestionResult = true; + break; + } + } + + if (isRemoveQuestionResult) { + + Integer oldMark = userAttempt.getMark(); + if (oldMark != null) { + newTotalMark -= oldMark; + } + + iter.remove(); + mcUsrAttemptDAO.removeAttempt(userAttempt); + } + + // [+] doing nothing if the new question was added + + } + + // propagade new total mark to Gradebook if it was changed + if (newTotalMark != oldTotalMark) { + gradebookService.updateActivityMark(new Double(newTotalMark), null, user.getQueUsrId().intValue(), + toolSessionId, false); + } + + } + } + + } + + @Override + public byte[] prepareSessionDataSpreadsheet(McContent mcContent) throws IOException { + + Set questions = mcContent.getMcQueContents(); + int maxOptionsInQuestion = 0; + for (McQueContent question : questions) { + if (question.getMcOptionsContents().size() > maxOptionsInQuestion) { + maxOptionsInQuestion = question.getMcOptionsContents().size(); + } + } + + int totalNumberOfUsers = 0; + for (McSession session : (Set) mcContent.getMcSessions()) { + totalNumberOfUsers += session.getMcQueUsers().size(); + } + + List sessionMarkDTOs = this.buildGroupsMarkData(mcContent, true); + + // create an empty excel file + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFCellStyle greenColor = wb.createCellStyle(); + greenColor.setFillForegroundColor(IndexedColors.LIME.getIndex()); + greenColor.setFillPattern(CellStyle.SOLID_FOREGROUND); + Font whiteFont = wb.createFont(); + whiteFont.setColor(IndexedColors.WHITE.getIndex()); + whiteFont.setFontName(ExcelUtil.DEFAULT_FONT_NAME); + greenColor.setFont(whiteFont); + + // ======================================================= Report by question IRA page + // ======================================= + + HSSFSheet sheet = wb.createSheet(messageService.getMessage("label.report.by.question")); + + HSSFRow row; + HSSFCell cell; + int rowCount = 0; + + row = sheet.createRow(rowCount++); + int count = 0; + cell = row.createCell(count++); + cell.setCellValue(messageService.getMessage("label.question")); + for (int optionCount = 0; optionCount < maxOptionsInQuestion; optionCount++) { + cell = row.createCell(count++); + cell.setCellValue(String.valueOf((char) (optionCount + 'A'))); + } + cell = row.createCell(count++); + cell.setCellValue(messageService.getMessage("label.not.available")); + + for (McQueContent question : questions) { + + row = sheet.createRow(rowCount); + count = 0; + + cell = row.createCell(count++); + cell.setCellValue(rowCount); + rowCount++; + + int totalPercentage = 0; + for (McOptsContent option : (Set) question.getMcOptionsContents()) { + int optionAttemptCount = mcUsrAttemptDAO.getAttemptsCountPerOption(option.getUid()); + cell = row.createCell(count++); + int percentage = (optionAttemptCount * 100) / totalNumberOfUsers; + cell.setCellValue(percentage + "%"); + totalPercentage += percentage; + if (option.isCorrectOption()) { + cell.setCellStyle(greenColor); + } + } + cell = row.createCell(maxOptionsInQuestion + 1); + cell.setCellValue((100 - totalPercentage) + "%"); + } + + rowCount++; + row = sheet.createRow(rowCount++); + cell = row.createCell(0); + cell.setCellValue(messageService.getMessage("label.legend")); + row = sheet.createRow(rowCount++); + cell = row.createCell(0); + cell.setCellValue(messageService.getMessage("label.denotes.correct.answer")); + cell.setCellStyle(greenColor); + cell = row.createCell(1); + cell.setCellStyle(greenColor); + cell = row.createCell(2); + cell.setCellStyle(greenColor); + + // ======================================================= Report by student IRA page + // ======================================= + + sheet = wb.createSheet(messageService.getMessage("label.report.by.student")); + rowCount = 0; + + row = sheet.createRow(rowCount++); + count = 2; + for (int questionCount = 1; questionCount <= questions.size(); questionCount++) { + cell = row.createCell(count++); + cell.setCellValue(messageService.getMessage("label.question") + questionCount); + } + cell = row.createCell(count++); + cell.setCellValue(messageService.getMessage("label.total")); + cell = row.createCell(count++); + cell.setCellValue(messageService.getMessage("label.total") + " %"); + + row = sheet.createRow(rowCount++); + count = 1; + ArrayList correctAnswers = new ArrayList(); + cell = row.createCell(count++); + cell.setCellValue(messageService.getMessage("label.correct.answer")); + for (McQueContent question : questions) { + + // find out the correct answer's sequential letter - A,B,C... + String correctAnswerLetter = ""; + int answerCount = 1; + for (McOptsContent option : (Set) question.getMcOptionsContents()) { + if (option.isCorrectOption()) { + correctAnswerLetter = String.valueOf((char) ((answerCount + 'A') - 1)); + break; + } + answerCount++; + } + cell = row.createCell(count++); + cell.setCellValue(correctAnswerLetter); + correctAnswers.add(correctAnswerLetter); + } + + row = sheet.createRow(rowCount++); + count = 0; + cell = row.createCell(count++); + cell.setCellValue(messageService.getMessage("group.label")); + cell = row.createCell(count++); + cell.setCellValue(messageService.getMessage("label.learner")); + + ArrayList totalPercentList = new ArrayList(); + int[] numberOfCorrectAnswersPerQuestion = new int[questions.size()]; + for (McSessionMarkDTO sessionMarkDTO : sessionMarkDTOs) { + Map usersMarksMap = sessionMarkDTO.getUserMarks(); + + for (McUserMarkDTO userMark : usersMarksMap.values()) { + row = sheet.createRow(rowCount++); + count = 0; + cell = row.createCell(count++); + cell.setCellValue(sessionMarkDTO.getSessionName()); + + cell = row.createCell(count++); + cell.setCellValue(userMark.getFullName()); + + String[] answeredOptions = userMark.getAnsweredOptions(); + int numberOfCorrectlyAnsweredByUser = 0; + for (int i = 0; i < answeredOptions.length; i++) { + String answeredOption = answeredOptions[i]; + cell = row.createCell(count++); + cell.setCellValue(answeredOption); + if (StringUtils.equals(answeredOption, correctAnswers.get(i))) { + cell.setCellStyle(greenColor); + numberOfCorrectlyAnsweredByUser++; + numberOfCorrectAnswersPerQuestion[count - 3]++; + } + } + + cell = row.createCell(count++); + cell.setCellValue(new Long(userMark.getTotalMark())); + + int totalPercents = (numberOfCorrectlyAnsweredByUser * 100) / questions.size(); + totalPercentList.add(totalPercents); + cell = row.createCell(count++); + cell.setCellValue(totalPercents + "%"); + } + + rowCount++; + } + + // ave + row = sheet.createRow(rowCount++); + count = 1; + cell = row.createCell(count++); + cell.setCellValue(messageService.getMessage("label.ave")); + for (int numberOfCorrectAnswers : numberOfCorrectAnswersPerQuestion) { + cell = row.createCell(count++); + cell.setCellValue(((numberOfCorrectAnswers * 100) / totalPercentList.size()) + "%"); + } + + // class mean + Integer[] totalPercents = totalPercentList.toArray(new Integer[0]); + Arrays.sort(totalPercents); + int sum = 0; + for (int i = 0; i < totalPercents.length; i++) { + sum += totalPercents[i]; + } + row = sheet.createRow(rowCount++); + cell = row.createCell(1); + cell.setCellValue(messageService.getMessage("label.class.mean")); + if (totalPercents.length != 0) { + int classMean = sum / totalPercents.length; + cell = row.createCell(questions.size() + 3); + cell.setCellValue(classMean + "%"); + } + + // median + row = sheet.createRow(rowCount++); + cell = row.createCell(1); + cell.setCellValue(messageService.getMessage("label.median")); + if (totalPercents.length != 0) { + int median; + int middle = totalPercents.length / 2; + if ((totalPercents.length % 2) == 1) { + median = totalPercents[middle]; + } else { + median = (int) ((totalPercents[middle - 1] + totalPercents[middle]) / 2.0); + } + cell = row.createCell(questions.size() + 3); + cell.setCellValue(median + "%"); + } + + row = sheet.createRow(rowCount++); + cell = row.createCell(0); + cell.setCellValue(messageService.getMessage("label.legend")); + + row = sheet.createRow(rowCount++); + cell = row.createCell(0); + cell.setCellValue(messageService.getMessage("label.denotes.correct.answer")); + cell.setCellStyle(greenColor); + cell = row.createCell(1); + cell.setCellStyle(greenColor); + cell = row.createCell(2); + cell.setCellStyle(greenColor); + + // ======================================================= Marks page + // ======================================= + + sheet = wb.createSheet("Marks"); + + rowCount = 0; + count = 0; + + row = sheet.createRow(rowCount++); + for (McQueContent question : questions) { + cell = row.createCell(2 + count++); + cell.setCellValue(messageService.getMessage("label.monitoring.downloadMarks.question.mark", + new Object[] { count, question.getMark() })); + } + + for (McSessionMarkDTO sessionMarkDTO : sessionMarkDTOs) { + Map usersMarksMap = sessionMarkDTO.getUserMarks(); + + String currentSessionName = sessionMarkDTO.getSessionName(); + + row = sheet.createRow(rowCount++); + + cell = row.createCell(0); + cell.setCellValue(messageService.getMessage("group.label")); + + cell = row.createCell(1); + cell.setCellValue(currentSessionName); + cell.setCellStyle(greenColor); + + rowCount++; + count = 0; + + row = sheet.createRow(rowCount++); + + cell = row.createCell(count++); + cell.setCellValue(messageService.getMessage("label.learner")); + + cell = row.createCell(count++); + cell.setCellValue(messageService.getMessage("label.monitoring.downloadMarks.username")); + + cell = row.createCell(questions.size() + 2); + cell.setCellValue(messageService.getMessage("label.total")); + + for (McUserMarkDTO userMark : usersMarksMap.values()) { + row = sheet.createRow(rowCount++); + count = 0; + + cell = row.createCell(count++); + cell.setCellValue(userMark.getFullName()); + + cell = row.createCell(count++); + cell.setCellValue(userMark.getUserName()); + + Integer[] marks = userMark.getMarks(); + for (int i = 0; i < marks.length; i++) { + cell = row.createCell(count++); + Integer mark = (marks[i] == null) ? 0 : marks[i]; + cell.setCellValue(mark); + } + + cell = row.createCell(count++); + cell.setCellValue(userMark.getTotalMark()); + } + + rowCount++; + + } + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + wb.write(bos); + + byte[] data = bos.toByteArray(); + + return data; + } + + @Override + public void copyToolContent(Long fromContentId, Long toContentId) { + + if (fromContentId == null) { + logger.warn("fromContentId is null."); + long defaultContentId = getToolDefaultContentIdBySignature(McAppConstants.TOOL_SIGNATURE); + fromContentId = new Long(defaultContentId); + } + + if (toContentId == null) { + logger.error("throwing ToolException: toContentId is null"); + throw new ToolException("toContentId is missing"); + } + + McContent fromContent = mcContentDAO.findMcContentById(fromContentId); + + if (fromContent == null) { + logger.warn("fromContent is null."); + long defaultContentId = getToolDefaultContentIdBySignature(McAppConstants.TOOL_SIGNATURE); + fromContent = mcContentDAO.findMcContentById(defaultContentId); + } + + McContent toContent = McContent.newInstance(fromContent, toContentId); + if (toContent == null) { + logger.error("throwing ToolException: WARNING!, retrieved toContent is null."); + throw new ToolException("WARNING! Fail to create toContent. Can't continue!"); + } else { + mcContentDAO.saveMcContent(toContent); + } + } + + @SuppressWarnings("unchecked") + @Override + public void removeToolContent(Long toolContentId) throws ToolException { + McContent mcContent = mcContentDAO.findMcContentById(toolContentId); + if (mcContent == null) { + logger.warn("Can not remove the tool content as it does not exist, ID: " + toolContentId); + return; + } + + for (McSession session : (Set) mcContent.getMcSessions()) { + List entries = coreNotebookService.getEntry(session.getMcSessionId(), + CoreNotebookConstants.NOTEBOOK_TOOL, McAppConstants.TOOL_SIGNATURE); + for (NotebookEntry entry : entries) { + coreNotebookService.deleteEntry(entry); + } + } + + mcContentDAO.delete(mcContent); + } + + @Override + public void resetDefineLater(Long toolContentId) throws DataMissingException, ToolException { + McContent mcContent = getMcContent(toolContentId); + if (mcContent == null) { + throw new DataMissingException("mcContent is missing"); + } + mcContent.setDefineLater(false); + mcContentDAO.saveMcContent(mcContent); + } + + @Override + @SuppressWarnings("unchecked") + public void removeLearnerContent(Long toolContentId, Integer userId) throws ToolException { + if (logger.isDebugEnabled()) { + logger.debug( + "Removing Multiple Choice attempts for user ID " + userId + " and toolContentId " + toolContentId); + } + + McContent content = mcContentDAO.findMcContentById(toolContentId); + if (content != null) { + for (McSession session : (Set) content.getMcSessions()) { + McQueUsr user = mcUserDAO.getMcUserBySession(userId.longValue(), session.getUid()); + if (user != null) { + mcUsrAttemptDAO.removeAllUserAttempts(user.getUid()); + + NotebookEntry entry = getEntry(session.getMcSessionId(), CoreNotebookConstants.NOTEBOOK_TOOL, + McAppConstants.TOOL_SIGNATURE, userId); + if (entry != null) { + mcContentDAO.delete(entry); + } + + if ((session.getGroupLeader() != null) && session.getGroupLeader().getUid().equals(user.getUid())) { + session.setGroupLeader(null); + } + + mcUserDAO.removeMcUser(user); + + gradebookService.updateActivityMark(null, null, userId, session.getMcSessionId(), false); + } + } + } + } + + @Override + public void exportToolContent(Long toolContentId, String rootPath) throws DataMissingException, ToolException { + McContent toolContentObj = mcContentDAO.findMcContentById(toolContentId); + if (toolContentObj == null) { + long defaultContentId = getToolDefaultContentIdBySignature(McAppConstants.TOOL_SIGNATURE); + toolContentObj = mcContentDAO.findMcContentById(defaultContentId); + } + if (toolContentObj == null) { + throw new DataMissingException("Unable to find default content for the multiple choice tool"); + } + + try { + // set ToolContentHandler as null to avoid copy file node in repository again. + toolContentObj = McContent.newInstance(toolContentObj, toolContentId); + toolContentObj.setMcSessions(null); + exportContentService.exportToolContent(toolContentId, toolContentObj, mcToolContentHandler, rootPath); + } catch (ExportToolContentException e) { + throw new ToolException(e); + } + } + + @Override + public void importToolContent(Long toolContentId, Integer newUserUid, String toolContentPath, String fromVersion, + String toVersion) throws ToolException { + try { + // register version filter class + exportContentService.registerImportVersionFilterClass(McImportContentVersionFilter.class); + + Object toolPOJO = exportContentService.importToolContent(toolContentPath, mcToolContentHandler, fromVersion, + toVersion); + if (!(toolPOJO instanceof McContent)) { + throw new ImportToolContentException( + "Import MC tool content failed. Deserialized object is " + toolPOJO); + } + McContent toolContentObj = (McContent) toolPOJO; + + // reset it to new toolContentId + toolContentObj.setMcContentId(toolContentId); + toolContentObj.setCreatedBy(newUserUid); + mcContentDAO.saveMcContent(toolContentObj); + } catch (ImportToolContentException e) { + throw new ToolException(e); + } + } + + @Override + public SortedMap getToolOutputDefinitions(Long toolContentId, int definitionType) + throws ToolException { + McContent content = getMcContent(toolContentId); + if (content == null) { + long defaultToolContentId = getToolDefaultContentIdBySignature(McAppConstants.TOOL_SIGNATURE); + content = getMcContent(defaultToolContentId); + } + return mcOutputFactory.getToolOutputDefinitions(content, definitionType); + } + + @Override + public String getToolContentTitle(Long toolContentId) { + return mcContentDAO.findMcContentById(toolContentId).getTitle(); + } + + @Override + public boolean isContentEdited(Long toolContentId) { + return mcContentDAO.findMcContentById(toolContentId).isDefineLater(); + } + + @Override + public boolean isReadOnly(Long toolContentId) { + McContent content = mcContentDAO.findMcContentById(toolContentId); + for (McSession session : (Set) content.getMcSessions()) { + if (!session.getMcQueUsers().isEmpty()) { + return true; + } + } + + return false; + } + + /** + * it is possible that the tool session id already exists in the tool sessions table as the users from the same + * session are involved. existsSession(long toolSessionId) + * + * @param toolSessionId + * @return boolean + */ + @Override + public boolean existsSession(Long toolSessionId) { + McSession mcSession = getMcSessionById(toolSessionId); + return mcSession != null; + } + + @Override + public void createToolSession(Long toolSessionId, String toolSessionName, Long toolContentId) throws ToolException { + + if (toolSessionId == null) { + logger.error("toolSessionId is null"); + throw new ToolException("toolSessionId is missing"); + } + + McContent mcContent = mcContentDAO.findMcContentById(toolContentId); + + // create a new a new tool session if it does not already exist in the tool session table + if (!existsSession(toolSessionId)) { + try { + McSession mcSession = new McSession(toolSessionId, new Date(System.currentTimeMillis()), + McSession.INCOMPLETE, toolSessionName, mcContent, new TreeSet()); + + mcSessionDAO.saveMcSession(mcSession); + + } catch (Exception e) { + logger.error("Error creating new toolsession in the db"); + throw new ToolException("Error creating new toolsession in the db: " + e); + } + } + } + + @Override + public void removeToolSession(Long toolSessionId) throws DataMissingException, ToolException { + if (toolSessionId == null) { + logger.error("toolSessionId is null"); + throw new DataMissingException("toolSessionId is missing"); + } + + McSession mcSession = null; + try { + mcSession = getMcSessionById(toolSessionId); + } catch (McApplicationException e) { + throw new DataMissingException("error retrieving mcSession: " + e); + } catch (Exception e) { + throw new ToolException("error retrieving mcSession: " + e); + } + + if (mcSession == null) { + logger.error("mcSession is null"); + throw new DataMissingException("mcSession is missing"); + } + + try { + mcSessionDAO.removeMcSession(mcSession); + logger.debug("mcSession " + mcSession + " has been deleted successfully."); + } catch (McApplicationException e) { + throw new ToolException("error deleting mcSession:" + e); + } + } + + @Override + public String leaveToolSession(Long toolSessionId, Long learnerId) throws DataMissingException, ToolException { + + if (learnerService == null) { + return "dummyNextUrl"; + } + + if (learnerId == null) { + logger.error("learnerId is null"); + throw new DataMissingException("learnerId is missing"); + } + + if (toolSessionId == null) { + logger.error("toolSessionId is null"); + throw new DataMissingException("toolSessionId is missing"); + } + + McSession mcSession = null; + try { + mcSession = getMcSessionById(toolSessionId); + } catch (McApplicationException e) { + throw new DataMissingException("error retrieving mcSession: " + e); + } catch (Exception e) { + throw new ToolException("error retrieving mcSession: " + e); + } + mcSession.setSessionStatus(McAppConstants.COMPLETED); + mcSessionDAO.updateMcSession(mcSession); + + String nextUrl = learnerService.completeToolSession(toolSessionId, learnerId); + if (nextUrl == null) { + logger.error("nextUrl is null"); + throw new ToolException("nextUrl is null"); + } + return nextUrl; + } + + @Override + public ToolSessionExportOutputData exportToolSession(Long toolSessionId) + throws DataMissingException, ToolException { + throw new ToolException("not yet implemented"); + } + + @Override + public ToolSessionExportOutputData exportToolSession(List toolSessionIds) + throws DataMissingException, ToolException { + throw new ToolException("not yet implemented"); + + } + + @Override + public SortedMap getToolOutput(List names, Long toolSessionId, Long learnerId) { + return mcOutputFactory.getToolOutput(names, this, toolSessionId, learnerId); + } + + @Override + public ToolOutput getToolOutput(String name, Long toolSessionId, Long learnerId) { + return mcOutputFactory.getToolOutput(name, this, toolSessionId, learnerId); + } + + @Override + public List getToolOutputs(String name, Long toolContentId) { + return mcOutputFactory.getToolOutputs(name, this, toolContentId); + } + + @Override + public void forceCompleteUser(Long toolSessionId, User user) { + Long userId = user.getUserId().longValue(); + + McSession session = getMcSessionById(toolSessionId); + if ((session == null) || (session.getMcContent() == null)) { + return; + } + McContent content = session.getMcContent(); + + // copy answers only in case leader aware feature is ON + if (content.isUseSelectLeaderToolOuput()) { + + McQueUsr mcUser = getMcUserBySession(userId, session.getUid()); + // create user if he hasn't accessed this activity yet + if (mcUser == null) { + + String userName = user.getLogin(); + String fullName = user.getFirstName() + " " + user.getLastName(); + mcUser = new McQueUsr(userId, userName, fullName, session, new TreeSet()); + mcUserDAO.saveMcUser(mcUser); + } + + McQueUsr groupLeader = session.getGroupLeader(); + + // check if leader has submitted answers + if ((groupLeader != null) && groupLeader.isResponseFinalised()) { + + // we need to make sure specified user has the same scratches as a leader + copyAnswersFromLeader(mcUser, groupLeader); + } + + } + + } + + @Override + public IToolVO getToolBySignature(String toolSignature) throws McApplicationException { + IToolVO tool = toolService.getToolBySignature(toolSignature); + return tool; + } + + @Override + public long getToolDefaultContentIdBySignature(String toolSignature) { + long contentId = 0; + contentId = toolService.getToolDefaultContentIdBySignature(toolSignature); + return contentId; + } + + @Override + public boolean isGroupedActivity(long toolContentID) { + return toolService.isGroupedActivity(toolContentID); + } + + @Override + public void auditLogStartEditingActivityInMonitor(long toolContentID) { + toolService.auditLogStartEditingActivityInMonitor(toolContentID); + } + + @Override + public String getActivityEvaluation(Long toolContentId) { + return toolService.getActivityEvaluation(toolContentId); + } + + @Override + public void setActivityEvaluation(Long toolContentId, String toolOutputDefinition) { + toolService.setActivityEvaluation(toolContentId, toolOutputDefinition); + } + + /** + * @param mcContentDAO + * The mcContentDAO to set. + */ + public void setMcContentDAO(IMcContentDAO mcContentDAO) { + this.mcContentDAO = mcContentDAO; + } + + /** + * @param mcOptionsContentDAO + * The mcOptionsContentDAO to set. + */ + public void setMcOptionsContentDAO(IMcOptionsContentDAO mcOptionsContentDAO) { + this.mcOptionsContentDAO = mcOptionsContentDAO; + } + + /** + * @param mcQueContentDAO + * The mcQueContentDAO to set. + */ + public void setMcQueContentDAO(IMcQueContentDAO mcQueContentDAO) { + this.mcQueContentDAO = mcQueContentDAO; + } + + /** + * @param mcSessionDAO + * The mcSessionDAO to set. + */ + public void setMcSessionDAO(IMcSessionDAO mcSessionDAO) { + this.mcSessionDAO = mcSessionDAO; + } + + /** + * @param mcUserDAO + * The mcUserDAO to set. + */ + public void setMcUserDAO(IMcUserDAO mcUserDAO) { + this.mcUserDAO = mcUserDAO; + } + + /** + * @param mcUsrAttemptDAO + * The mcUsrAttemptDAO to set. + */ + public void setMcUsrAttemptDAO(IMcUsrAttemptDAO mcUsrAttemptDAO) { + this.mcUsrAttemptDAO = mcUsrAttemptDAO; + } + + public void setUserManagementService(IUserManagementService userManagementService) { + this.userManagementService = userManagementService; + } + + public void setToolService(ILamsToolService toolService) { + this.toolService = toolService; + } + + /** + * @param mcToolContentHandler + * The mcToolContentHandler to set. + */ + public void setMcToolContentHandler(IToolContentHandler mcToolContentHandler) { + this.mcToolContentHandler = mcToolContentHandler; + } + + /** + * @param learnerService + * The learnerService to set. + */ + public void setLearnerService(ILearnerService learnerService) { + this.learnerService = learnerService; + } + + public void setExportContentService(IExportToolContentService exportContentService) { + this.exportContentService = exportContentService; + } + + public void setGradebookService(IGradebookService gradebookService) { + this.gradebookService = gradebookService; + } + + public void setMcOutputFactory(MCOutputFactory mcOutputFactory) { + this.mcOutputFactory = mcOutputFactory; + } + + @Override + public List getReflectionList(McContent mcContent, Long userID) { + List reflectionsContainerDTO = new LinkedList(); + if (userID == null) { + // all users mode + for (McSession mcSession : (Set) mcContent.getMcSessions()) { + + for (McQueUsr user : (Set) mcSession.getMcQueUsers()) { + + NotebookEntry notebookEntry = this.getEntry(mcSession.getMcSessionId(), + CoreNotebookConstants.NOTEBOOK_TOOL, McAppConstants.TOOL_SIGNATURE, + new Integer(user.getQueUsrId().toString())); + + if (notebookEntry != null) { + ReflectionDTO reflectionDTO = new ReflectionDTO(); + reflectionDTO.setUserId(user.getQueUsrId().toString()); + reflectionDTO.setSessionId(mcSession.getMcSessionId().toString()); + reflectionDTO.setUserName(user.getFullname()); + reflectionDTO.setReflectionUid(notebookEntry.getUid().toString()); + // String notebookEntryPresentable = McUtils.replaceNewLines(notebookEntry.getEntry()); + reflectionDTO.setEntry(notebookEntry.getEntry()); + reflectionsContainerDTO.add(reflectionDTO); + } + } + } + } else { + // single user mode + for (Iterator sessionIter = mcContent.getMcSessions().iterator(); sessionIter.hasNext();) { + McSession mcSession = (McSession) sessionIter.next(); + for (Iterator userIter = mcSession.getMcQueUsers().iterator(); userIter.hasNext();) { + McQueUsr user = (McQueUsr) userIter.next(); + if (user.getQueUsrId().equals(userID)) { + NotebookEntry notebookEntry = this.getEntry(mcSession.getMcSessionId(), + CoreNotebookConstants.NOTEBOOK_TOOL, McAppConstants.TOOL_SIGNATURE, + new Integer(user.getQueUsrId().toString())); + + if (notebookEntry != null) { + ReflectionDTO reflectionDTO = new ReflectionDTO(); + reflectionDTO.setUserId(user.getQueUsrId().toString()); + reflectionDTO.setSessionId(mcSession.getMcSessionId().toString()); + reflectionDTO.setUserName(user.getFullname()); + reflectionDTO.setReflectionUid(notebookEntry.getUid().toString()); + // String notebookEntryPresentable = McUtils.replaceNewLines(notebookEntry.getEntry()); + reflectionDTO.setEntry(notebookEntry.getEntry()); + reflectionsContainerDTO.add(reflectionDTO); + } + } + } + } + } + + return reflectionsContainerDTO; + } + + @Override + public Long createNotebookEntry(Long id, Integer idType, String signature, Integer userID, String entry) { + return coreNotebookService.createNotebookEntry(id, idType, signature, userID, "", entry); + } + + @Override + public NotebookEntry getEntry(Long id, Integer idType, String signature, Integer userID) { + + List list = coreNotebookService.getEntry(id, idType, signature, userID); + if ((list == null) || list.isEmpty()) { + return null; + } else { + return list.get(0); + } + } + + @Override + public void updateEntry(NotebookEntry notebookEntry) { + coreNotebookService.updateEntry(notebookEntry); + } + + /** + * @return Returns the coreNotebookService. + */ + public ICoreNotebookService getCoreNotebookService() { + return coreNotebookService; + } + + /** + * @param coreNotebookService + * The coreNotebookService to set. + */ + public void setCoreNotebookService(ICoreNotebookService coreNotebookService) { + this.coreNotebookService = coreNotebookService; + } + + /** + * @return Returns the auditService. + */ + public IAuditService getAuditService() { + return auditService; + } + + /** + * @param auditService + * The auditService to set. + */ + public void setAuditService(IAuditService auditService) { + this.auditService = auditService; + } + + /** + * @return Returns the MessageService. + */ + public MessageService getMessageService() { + return messageService; + } + + /** + * @param messageService + * The MessageService to set. + */ + public void setMessageService(MessageService messageService) { + this.messageService = messageService; + } + + @Override + public Class[] getSupportedToolOutputDefinitionClasses(int definitionType) { + return mcOutputFactory.getSupportedDefinitionClasses(definitionType); + } + + @Override + public ToolCompletionStatus getCompletionStatus(Long learnerId, Long toolSessionId) { + McSession session = getMcSessionById(toolSessionId); + McQueUsr learner = mcUserDAO.getMcUserBySession(learnerId, session.getUid()); + if (learner == null) { + return new ToolCompletionStatus(ToolCompletionStatus.ACTIVITY_NOT_ATTEMPTED, null, null); + } + + Date startDate = null; + Date endDate = null; + List attempts = getFinalizedUserAttempts(learner); + for (McUsrAttempt item : attempts) { + Date newDate = item.getAttemptTime(); + if (newDate != null) { + if (startDate == null || newDate.before(startDate)) + startDate = newDate; + if (endDate == null || newDate.after(endDate)) + endDate = newDate; + } + } + + if (learner.isResponseFinalised()) + return new ToolCompletionStatus(ToolCompletionStatus.ACTIVITY_COMPLETED, startDate, endDate); + else + return new ToolCompletionStatus(ToolCompletionStatus.ACTIVITY_ATTEMPTED, startDate, null); + } + + @Override + public LeaderResultsDTO getLeaderResultsDTOForLeaders(Long contentId) { + LeaderResultsDTO newDto = new LeaderResultsDTO(contentId); + Object[] markStats = mcUserDAO.getStatsMarksForLeaders(contentId); + if ( markStats != null ) { + newDto.setMinMark(markStats[0] != null ? NumberUtil.formatLocalisedNumber((Float)markStats[0], (Locale)null, 2) : "0.00"); + newDto.setAvgMark(markStats[1] != null ? NumberUtil.formatLocalisedNumber((Float)markStats[1], (Locale)null, 2) : "0.00"); + newDto.setMaxMark(markStats[2] != null ? NumberUtil.formatLocalisedNumber((Float)markStats[2], (Locale)null, 2) : "0.00"); + newDto.setNumberGroupsLeaderFinished((Integer)markStats[3]); + } + return newDto; + } + + @SuppressWarnings("unchecked") + @Override + public List getSessionDtos(Long contentId, boolean includeStatistics) { + List sessionDtos = new ArrayList(); + + McContent mcContent = getMcContent(contentId); + if (mcContent != null) { + Set sessions = new TreeSet(new McSessionComparator()); + sessions.addAll(mcContent.getMcSessions()); + for (McSession session : sessions) { + SessionDTO sessionDto = new SessionDTO(); + sessionDto.setSessionId(session.getMcSessionId()); + sessionDto.setSessionName(session.getSession_name()); + //for statistics tab + if (includeStatistics) { + int countUsers = mcUserDAO.getCountPagedUsersBySession(session.getMcSessionId(), ""); + sessionDto.setNumberLearners(countUsers); + Object[] markStats = mcUserDAO.getStatsMarksBySession(session.getMcSessionId()); + if (markStats != null) { + sessionDto.setMinMark(markStats[0] != null + ? NumberUtil.formatLocalisedNumber((Float) markStats[0], (Locale) null, 2) : "0.00"); + sessionDto.setAvgMark(markStats[1] != null + ? NumberUtil.formatLocalisedNumber((Float) markStats[1], (Locale) null, 2) : "0.00"); + sessionDto.setMaxMark(markStats[2] != null + ? NumberUtil.formatLocalisedNumber((Float) markStats[2], (Locale) null, 2) : "0.00"); + } + } + + sessionDtos.add(sessionDto); + } + } + return sessionDtos; + } + + @Override + public List getMarksArray(Long sessionId) { + return mcUserDAO.getRawUserMarksBySession(sessionId); + } + + @Override + public List getMarksArrayForLeaders(Long toolContentId) { + return mcUserDAO.getRawLeaderMarksByToolContentId(toolContentId); + } + + + + // ****************** REST methods ************************* + + /** + * Rest call to create a new Multiple Choice content. Required fields in toolContentJSON: "title", "instructions", + * "questions". The questions entry should be JSONArray containing JSON objects, which in turn must contain + * "questionText", "displayOrder" (Integer) and a JSONArray "answers". The answers entry should be JSONArray + * containing JSON objects, which in turn must contain "answerText", "displayOrder" (Integer), "correct" (Boolean). + * + * Retries are controlled by lockWhenFinished, which defaults to true (no retries). + */ + @SuppressWarnings("unchecked") + @Override + public void createRestToolContent(Integer userID, Long toolContentID, JSONObject toolContentJSON) + throws JSONException { + + McContent mcq = new McContent(); + Date updateDate = new Date(); + + mcq.setCreationDate(updateDate); + mcq.setUpdateDate(updateDate); + mcq.setCreatedBy(userID.longValue()); + mcq.setDefineLater(false); + + mcq.setMcContentId(toolContentID); + mcq.setTitle(toolContentJSON.getString(RestTags.TITLE)); + mcq.setInstructions(toolContentJSON.getString(RestTags.INSTRUCTIONS)); + + mcq.setRetries(JsonUtil.opt(toolContentJSON, "allowRetries", Boolean.FALSE)); + mcq.setUseSelectLeaderToolOuput( + JsonUtil.opt(toolContentJSON, RestTags.USE_SELECT_LEADER_TOOL_OUTPUT, Boolean.FALSE)); + mcq.setReflect(JsonUtil.opt(toolContentJSON, RestTags.REFLECT_ON_ACTIVITY, Boolean.FALSE)); + mcq.setReflectionSubject(JsonUtil.opt(toolContentJSON, RestTags.REFLECT_INSTRUCTIONS, "")); + mcq.setQuestionsSequenced(JsonUtil.opt(toolContentJSON, "questionsSequenced", Boolean.FALSE)); + mcq.setRandomize(JsonUtil.opt(toolContentJSON, "randomize", Boolean.FALSE)); + mcq.setShowReport(JsonUtil.opt(toolContentJSON, "showReport", Boolean.FALSE)); + mcq.setDisplayAnswers(JsonUtil.opt(toolContentJSON, "displayAnswers", Boolean.FALSE)); + mcq.setShowMarks(JsonUtil.opt(toolContentJSON, "showMarks", Boolean.FALSE)); + mcq.setPrefixAnswersWithLetters(JsonUtil.opt(toolContentJSON, "prefixAnswersWithLetters", Boolean.TRUE)); + mcq.setPassMark(JsonUtil.opt(toolContentJSON, "passMark", 0)); + // submissionDeadline is set in monitoring + + createMc(mcq); + + // Questions + JSONArray questions = toolContentJSON.getJSONArray(RestTags.QUESTIONS); + for (int i = 0; i < questions.length(); i++) { + JSONObject questionData = (JSONObject) questions.get(i); + McQueContent question = new McQueContent(questionData.getString(RestTags.QUESTION_TEXT), + questionData.getInt(RestTags.DISPLAY_ORDER), 1, "", mcq, null, new HashSet()); + + JSONArray optionsData = questionData.getJSONArray(RestTags.ANSWERS); + for (int j = 0; j < optionsData.length(); j++) { + JSONObject optionData = (JSONObject) optionsData.get(j); + question.getMcOptionsContents().add(new McOptsContent(optionData.getInt(RestTags.DISPLAY_ORDER), + optionData.getBoolean(RestTags.CORRECT), optionData.getString(RestTags.ANSWER_TEXT), question)); + } + saveOrUpdateMcQueContent(question); + } + + // TODO + // mcq.setContent(content) - can't find in database + // mcq.setConditions(conditions); + + } +} Fisheye: Tag 85ef8aca5722a36582117db1e8b988e2c16b6369 refers to a dead (removed) revision in file `lams_tool_lamc/src/java/org/lamsfoundation/lams/tool/mc/service/McServicePOJO.java'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/qaApplicationContext.xml =================================================================== diff -u -ra6641bf9262a01d07740a517643f8fe187ec5b1f -r85ef8aca5722a36582117db1e8b988e2c16b6369 --- lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/qaApplicationContext.xml (.../qaApplicationContext.xml) (revision a6641bf9262a01d07740a517643f8fe187ec5b1f) +++ lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/qaApplicationContext.xml (.../qaApplicationContext.xml) (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -70,7 +70,7 @@ - + Index: lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/service/QaOutputFactory.java =================================================================== diff -u -r7af0a437b323d3d479c87d6a8884125213dc4411 -r85ef8aca5722a36582117db1e8b988e2c16b6369 --- lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/service/QaOutputFactory.java (.../QaOutputFactory.java) (revision 7af0a437b323d3d479c87d6a8884125213dc4411) +++ lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/service/QaOutputFactory.java (.../QaOutputFactory.java) (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -93,7 +93,7 @@ } /** - * Follows {@link QaServicePOJO#getToolOutput(List, Long, Long)}. + * Follows {@link QaService#getToolOutput(List, Long, Long)}. * */ public SortedMap getToolOutput(List names, IQaService qaService, Long toolSessionId, Index: lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/service/QaService.java =================================================================== diff -u --- lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/service/QaService.java (revision 0) +++ lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/service/QaService.java (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -0,0 +1,1288 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + +package org.lamsfoundation.lams.tool.qa.service; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.Iterator; +import java.util.List; +import java.util.Random; +import java.util.Set; +import java.util.SortedMap; +import java.util.SortedSet; +import java.util.TreeSet; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +import org.apache.log4j.Logger; +import org.apache.tomcat.util.json.JSONArray; +import org.apache.tomcat.util.json.JSONException; +import org.apache.tomcat.util.json.JSONObject; +import org.lamsfoundation.lams.contentrepository.client.IToolContentHandler; +import org.lamsfoundation.lams.events.IEventNotificationService; +import org.lamsfoundation.lams.learning.service.ILearnerService; +import org.lamsfoundation.lams.learningdesign.service.ExportToolContentException; +import org.lamsfoundation.lams.learningdesign.service.IExportToolContentService; +import org.lamsfoundation.lams.learningdesign.service.ImportToolContentException; +import org.lamsfoundation.lams.notebook.model.NotebookEntry; +import org.lamsfoundation.lams.notebook.service.CoreNotebookConstants; +import org.lamsfoundation.lams.notebook.service.ICoreNotebookService; +import org.lamsfoundation.lams.rating.dto.ItemRatingDTO; +import org.lamsfoundation.lams.rating.model.LearnerItemRatingCriteria; +import org.lamsfoundation.lams.rating.model.RatingCriteria; +import org.lamsfoundation.lams.rating.service.IRatingService; +import org.lamsfoundation.lams.rest.RestTags; +import org.lamsfoundation.lams.rest.ToolRestManager; +import org.lamsfoundation.lams.tool.IToolVO; +import org.lamsfoundation.lams.tool.ToolCompletionStatus; +import org.lamsfoundation.lams.tool.ToolContentManager; +import org.lamsfoundation.lams.tool.ToolOutput; +import org.lamsfoundation.lams.tool.ToolOutputDefinition; +import org.lamsfoundation.lams.tool.ToolSessionExportOutputData; +import org.lamsfoundation.lams.tool.ToolSessionManager; +import org.lamsfoundation.lams.tool.exception.DataMissingException; +import org.lamsfoundation.lams.tool.exception.ToolException; +import org.lamsfoundation.lams.tool.qa.QaAppConstants; +import org.lamsfoundation.lams.tool.qa.QaCondition; +import org.lamsfoundation.lams.tool.qa.QaConfigItem; +import org.lamsfoundation.lams.tool.qa.QaContent; +import org.lamsfoundation.lams.tool.qa.QaQueContent; +import org.lamsfoundation.lams.tool.qa.QaQueUsr; +import org.lamsfoundation.lams.tool.qa.QaSession; +import org.lamsfoundation.lams.tool.qa.QaUsrResp; +import org.lamsfoundation.lams.tool.qa.QaWizardCategory; +import org.lamsfoundation.lams.tool.qa.dao.IQaConfigItemDAO; +import org.lamsfoundation.lams.tool.qa.dao.IQaContentDAO; +import org.lamsfoundation.lams.tool.qa.dao.IQaQueUsrDAO; +import org.lamsfoundation.lams.tool.qa.dao.IQaQuestionDAO; +import org.lamsfoundation.lams.tool.qa.dao.IQaSessionDAO; +import org.lamsfoundation.lams.tool.qa.dao.IQaUsrRespDAO; +import org.lamsfoundation.lams.tool.qa.dao.IQaWizardDAO; +import org.lamsfoundation.lams.tool.qa.dto.QaQuestionDTO; +import org.lamsfoundation.lams.tool.qa.util.QaApplicationException; +import org.lamsfoundation.lams.tool.service.ILamsToolService; +import org.lamsfoundation.lams.usermanagement.User; +import org.lamsfoundation.lams.usermanagement.dto.UserDTO; +import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; +import org.lamsfoundation.lams.util.JsonUtil; +import org.lamsfoundation.lams.util.MessageService; +import org.lamsfoundation.lams.util.audit.IAuditService; +import org.lamsfoundation.lams.web.session.SessionManager; +import org.lamsfoundation.lams.web.util.AttributeNames; +import org.springframework.dao.DataAccessException; + +/** + * The POJO implementation of Qa service. All business logics of Qa tool are implemented in this class. It translate the + * request from presentation layer and perform approporiate database operation. + * + * @author Ozgur Demirtas + */ +public class QaService implements IQaService, ToolContentManager, ToolSessionManager, ToolRestManager, QaAppConstants { + private static Logger logger = Logger.getLogger(QaService.class.getName()); + + private IQaContentDAO qaDAO; + private IQaQuestionDAO qaQuestionDAO; + + private IQaSessionDAO qaSessionDAO; + private IQaQueUsrDAO qaQueUsrDAO; + private IQaUsrRespDAO qaUsrRespDAO; + + private IToolContentHandler qaToolContentHandler = null; + private IUserManagementService userManagementService; + private ILamsToolService toolService; + private ILearnerService learnerService; + private IAuditService auditService; + private IExportToolContentService exportContentService; + private QaOutputFactory qaOutputFactory; + private IQaConfigItemDAO qaConfigItemDAO; + private IQaWizardDAO qaWizardDAO; + + private ICoreNotebookService coreNotebookService; + private IRatingService ratingService; + private IEventNotificationService eventNotificationService; + private MessageService messageService; + + private Random generator = new Random(); + + @Override + public boolean isUserGroupLeader(QaQueUsr user, Long toolSessionId) { + + QaSession session = this.getSessionById(toolSessionId); + QaQueUsr groupLeader = session.getGroupLeader(); + + boolean isUserLeader = (groupLeader != null) && user.getUid().equals(groupLeader.getUid()); + return isUserLeader; + } + + @Override + public QaQueUsr checkLeaderSelectToolForSessionLeader(QaQueUsr user, Long toolSessionId) { + if ((user == null) || (toolSessionId == null)) { + return null; + } + + QaSession qaSession = this.getSessionById(toolSessionId); + QaQueUsr leader = qaSession.getGroupLeader(); + // check leader select tool for a leader only in case QA tool doesn't know it. As otherwise it will screw + // up previous scratches done + if (leader == null) { + + Long leaderUserId = toolService.getLeaderUserId(toolSessionId, user.getQueUsrId().intValue()); + if (leaderUserId != null) { + leader = getUserByIdAndSession(leaderUserId, toolSessionId); + + // create new user in a DB + if (leader == null) { + User leaderDto = (User) getUserManagementService().findById(User.class, leaderUserId.intValue()); + String userName = leaderDto.getLogin(); + String fullName = leaderDto.getFirstName() + " " + leaderDto.getLastName(); + leader = new QaQueUsr(leaderUserId, userName, fullName, qaSession, new TreeSet()); + qaQueUsrDAO.createUsr(user); + } + + // set group leader + qaSession.setGroupLeader(leader); + this.updateSession(qaSession); + } + } + + return leader; + } + + @Override + public void copyAnswersFromLeader(QaQueUsr user, QaQueUsr leader) { + + if ((user == null) || (leader == null) || user.getUid().equals(leader.getUid())) { + return; + } + + for (QaUsrResp leaderResponse : (Set) leader.getQaUsrResps()) { + QaQueContent question = leaderResponse.getQaQuestion(); + QaUsrResp response = qaUsrRespDAO.getResponseByUserAndQuestion(user.getQueUsrId(), question.getUid()); + + // if response doesn't exist + if (response == null) { + response = new QaUsrResp(leaderResponse.getAnswer(), leaderResponse.getAnswerAutosaved(), + leaderResponse.getAttemptTime(), "", question, user, true); + createUserResponse(response); + + // if it's been changed by the leader + } else if (leaderResponse.getAttemptTime().compareTo(response.getAttemptTime()) != 0) { + response.setAnswer(leaderResponse.getAnswer()); + response.setAttemptTime(leaderResponse.getAttemptTime()); + response.setTimezone(""); + updateUserResponse(response); + } + } + } + + @Override + public void setDefineLater(String strToolContentID, boolean value) { + + QaContent qaContent = getQaContent(new Long(strToolContentID).longValue()); + + if (qaContent != null) { + qaContent.setDefineLater(value); + updateQaContent(qaContent); + } + } + + @Override + public List getUsersBySessionId(Long toolSessionID) { + QaSession session = qaSessionDAO.getQaSessionById(toolSessionID); + return qaQueUsrDAO.getUserBySessionOnly(session); + } + + @Override + public void createQaContent(QaContent qaContent) { + qaDAO.saveQa(qaContent); + } + + @Override + public QaContent getQaContent(long toolContentID) { + return qaDAO.getQaByContentId(toolContentID); + } + + @Override + public void saveOrUpdateQaContent(QaContent qa) { + qaDAO.saveOrUpdateQa(qa); + } + + @Override + public QaQueContent getQuestionByContentAndDisplayOrder(Long displayOrder, Long contentUid) { + return qaQuestionDAO.getQuestionByDisplayOrder(displayOrder, contentUid); + } + + @Override + public QaQueContent getQuestionByUid(Long questionUid) { + if (questionUid == null) { + return null; + } + + return qaQuestionDAO.getQuestionByUid(questionUid); + } + + @Override + public void saveOrUpdateQuestion(QaQueContent question) { + qaQuestionDAO.saveOrUpdateQaQueContent(question); + } + + @Override + public void createQuestion(QaQueContent question) { + qaQuestionDAO.createQueContent(question); + } + + @Override + public QaQueUsr createUser(Long toolSessionID, Integer userId) { + User user = (User) userManagementService.findById(User.class, userId); + String userName = user.getLogin(); + String fullName = user.getFirstName() + " " + user.getLastName(); + QaSession qaSession = getSessionById(toolSessionID.longValue()); + + QaQueUsr qaUser = new QaQueUsr(userId.longValue(), userName, fullName, qaSession, new TreeSet()); + // make sure the user was not created in the meantime + QaQueUsr existingUser = getUserByIdAndSession(userId.longValue(), toolSessionID); + if (existingUser == null) { + qaQueUsrDAO.createUsr(qaUser); + return qaUser; + } else { + return existingUser; + } + } + + @Override + public QaQueUsr getUserByIdAndSession(final Long queUsrId, final Long qaSessionId) { + return qaQueUsrDAO.getQaUserBySession(queUsrId, qaSessionId); + } + + @Override + public List getResponsesByUserUid(final Long userUid) { + return qaUsrRespDAO.getResponsesByUserUid(userUid); + } + + @Override + public QaUsrResp getResponseByUserAndQuestion(final Long queUsrId, final Long qaQueContentId) { + return qaUsrRespDAO.getResponseByUserAndQuestion(queUsrId, qaQueContentId); + } + + @Override + public List getResponseBySessionAndQuestion(final Long qaSessionId, final Long questionId) { + return qaUsrRespDAO.getResponseBySessionAndQuestion(qaSessionId, questionId); + } + + @Override + public List getResponsesForTablesorter(final Long toolContentId, final Long qaSessionId, + final Long questionId, final Long excludeUserId, boolean isOnlyLeadersIncluded, int page, int size, + int sorting, String searchString) { + return qaUsrRespDAO.getResponsesForTablesorter(toolContentId, qaSessionId, questionId, excludeUserId, + isOnlyLeadersIncluded, page, size, sorting, searchString); + } + + @Override + public int getCountResponsesBySessionAndQuestion(final Long qaSessionId, final Long questionId, + final Long excludeUserId, boolean isOnlyLeadersIncluded, String searchString) { + return qaUsrRespDAO.getCountResponsesBySessionAndQuestion(qaSessionId, questionId, excludeUserId, + isOnlyLeadersIncluded, searchString); + } + + @Override + public void updateUserResponse(QaUsrResp resp) { + qaUsrRespDAO.updateUserResponse(resp); + } + + @Override + public void updateResponseWithNewAnswer(String newAnswer, String toolSessionID, Long questionDisplayOrder, + boolean isAutosave) { + HttpSession ss = SessionManager.getSession(); + UserDTO toolUser = (UserDTO) ss.getAttribute(AttributeNames.USER); + Long userId = new Long(toolUser.getUserID().longValue()); + QaQueUsr user = getUserByIdAndSession(userId, new Long(toolSessionID)); + + QaSession session = getSessionById(new Long(toolSessionID)); + QaContent qaContent = session.getQaContent(); + + QaQueContent question = getQuestionByContentAndDisplayOrder(new Long(questionDisplayOrder), qaContent.getUid()); + + QaUsrResp response = getResponseByUserAndQuestion(user.getQueUsrId(), question.getUid()); + // if response doesn't exist + if (response == null) { + response = isAutosave + ? new QaUsrResp(null, newAnswer, new Date(System.currentTimeMillis()), "", question, user, true) + : new QaUsrResp(newAnswer, null, new Date(System.currentTimeMillis()), "", question, user, true); + createUserResponse(response); + + // if answer has changed + } else if (!newAnswer.equals(response.getAnswer())) { + if (isAutosave) { + response.setAnswerAutosaved(newAnswer); + } else { + response.setAnswer(newAnswer); + response.setAnswerAutosaved(null); + } + + response.setAttemptTime(new Date(System.currentTimeMillis())); + response.setTimezone(""); + updateUserResponse(response); + } + } + + @Override + public void createUserResponse(QaUsrResp qaUsrResp) { + qaUsrRespDAO.createUserResponse(qaUsrResp); + } + + @Override + public void updateUser(QaQueUsr qaQueUsr) { + qaQueUsrDAO.updateUsr(qaQueUsr); + } + + @Override + public QaUsrResp getResponseById(Long responseId) { + return qaUsrRespDAO.getResponseById(responseId); + } + + @Override + public QaSession getSessionById(long qaSessionId) { + return qaSessionDAO.getQaSessionById(qaSessionId); + } + + @Override + public void updateQaContent(QaContent qa) { + qaDAO.updateQa(qa); + } + + @Override + public void updateSession(QaSession qaSession) { + qaSessionDAO.UpdateQaSession(qaSession); + } + + @Override + public void removeUserResponse(QaUsrResp resp) { + auditService.logChange(QaAppConstants.MY_SIGNATURE, resp.getQaQueUser().getQueUsrId(), + resp.getQaQueUser().getUsername(), resp.getAnswer(), null); + qaUsrRespDAO.removeUserResponse(resp); + } + + @Override + public void updateResponseVisibility(Long responseUid, boolean isHideItem) { + + QaUsrResp response = getResponseById(responseUid); + if (response != null) { + // createBy should be null for system default value. + Long userId = 0L; + String loginName = "No user"; + if (response.getQaQueUser() != null) { + userId = response.getQaQueUser().getQueUsrId(); + loginName = response.getQaQueUser().getUsername(); + } + if (isHideItem) { + auditService.logHideEntry(QaAppConstants.MY_SIGNATURE, userId, loginName, response.getAnswer()); + } else { + auditService.logShowEntry(QaAppConstants.MY_SIGNATURE, userId, loginName, response.getAnswer()); + } + response.setVisible(!isHideItem); + updateUserResponse(response); + } + } + + @Override + public List getAllQuestionEntries(final Long uid) { + return qaQuestionDAO.getAllQuestionEntries(uid.longValue()); + } + + @Override + public List getAllQuestionEntriesSorted(final long contentUid) { + return qaQuestionDAO.getAllQuestionEntriesSorted(contentUid); + } + + @Override + public void removeQuestion(QaQueContent question) { + qaQuestionDAO.removeQaQueContent(question); + } + + @Override + public boolean isStudentActivityOccurredGlobal(QaContent qaContent) { + int countResponses = 0; + if (qaContent != null) { + countResponses = qaUsrRespDAO.getCountResponsesByQaContent(qaContent.getQaContentId()); + } + return countResponses > 0; + } + + @Override + public void recalculateUserAnswers(QaContent content, Set oldQuestions, + List questionDTOs, List deletedQuestions) { + + // create list of modified questions + List modifiedQuestions = new ArrayList(); + for (QaQueContent oldQuestion : oldQuestions) { + for (QaQuestionDTO questionDTO : questionDTOs) { + if (oldQuestion.getUid().equals(questionDTO.getUid())) { + + // question is different + if (!oldQuestion.getQuestion().equals(questionDTO.getQuestion())) { + modifiedQuestions.add(questionDTO); + } + } + } + } + + Set sessionList = content.getQaSessions(); + for (QaSession session : sessionList) { + Long toolSessionId = session.getQaSessionId(); + Set sessionUsers = session.getQaQueUsers(); + + for (QaQueUsr user : sessionUsers) { + + // get all finished user results + List userAttempts = qaUsrRespDAO.getResponsesByUserUid(user.getUid()); + Iterator iter = userAttempts.iterator(); + while (iter.hasNext()) { + QaUsrResp resp = iter.next(); + + QaQueContent question = resp.getQaQuestion(); + + boolean isRemoveQuestionResult = false; + + // [+] if the question is modified + for (QaQuestionDTO modifiedQuestion : modifiedQuestions) { + if (question.getUid().equals(modifiedQuestion.getUid())) { + isRemoveQuestionResult = true; + break; + } + } + + // [+] if the question was removed + for (QaQuestionDTO deletedQuestion : deletedQuestions) { + if (question.getUid().equals(deletedQuestion.getUid())) { + isRemoveQuestionResult = true; + break; + } + } + + if (isRemoveQuestionResult) { + iter.remove(); + qaUsrRespDAO.removeUserResponse(resp); + } + + // [+] doing nothing if the new question was added + + } + + } + } + + } + + @Override + public void resetDefineLater(Long toolContentId) throws DataMissingException, ToolException { + QaContent qaContent = qaDAO.getQaByContentId(toolContentId.longValue()); + if (qaContent == null) { + logger.error("throwing DataMissingException: WARNING!: retrieved qaContent is null."); + throw new DataMissingException("qaContent is missing"); + } + qaContent.setDefineLater(false); + updateQaContent(qaContent); + } + + @Override + public void copyToolContent(Long fromContentId, Long toContentId) { + long defaultContentId = 0; + if (fromContentId == null) { + defaultContentId = getToolDefaultContentIdBySignature(QaAppConstants.MY_SIGNATURE); + fromContentId = new Long(defaultContentId); + } + + if (toContentId == null) { + logger.error("throwing ToolException: toContentId is null"); + throw new ToolException("toContentId is missing"); + } + + QaContent fromContent = qaDAO.getQaByContentId(fromContentId.longValue()); + + if (fromContent == null) { + defaultContentId = getToolDefaultContentIdBySignature(QaAppConstants.MY_SIGNATURE); + fromContentId = new Long(defaultContentId); + + fromContent = qaDAO.getQaByContentId(fromContentId.longValue()); + } + QaContent toContent = QaContent.newInstance(fromContent, toContentId); + if (toContent == null) { + logger.error("throwing ToolException: WARNING!, retrieved toContent is null."); + throw new ToolException("WARNING! Fail to create toContent. Can't continue!"); + } else { + // save questions first, because if Hibernate decides to flush Conditions first, + // there is no cascade to questions and it may trigger an error + for (QaQueContent question : toContent.getQaQueContents()) { + qaQuestionDAO.saveOrUpdateQaQueContent(question); + } + qaDAO.saveQa(toContent); + } + + } + + @SuppressWarnings("unchecked") + @Override + public void removeToolContent(Long toolContentId) throws ToolException { + QaContent qaContent = qaDAO.getQaByContentId(toolContentId.longValue()); + if (qaContent == null) { + logger.warn("Can not remove the tool content as it does not exist, ID: " + toolContentId); + return; + } + + for (QaSession session : (Set) qaContent.getQaSessions()) { + List entries = coreNotebookService.getEntry(session.getQaSessionId(), + CoreNotebookConstants.NOTEBOOK_TOOL, QaAppConstants.MY_SIGNATURE); + for (NotebookEntry entry : entries) { + coreNotebookService.deleteEntry(entry); + } + } + + qaDAO.removeQa(toolContentId); + } + + @Override + @SuppressWarnings("unchecked") + public void removeLearnerContent(Long toolContentId, Integer userId) throws ToolException { + if (logger.isDebugEnabled()) { + logger + .debug("Removing Q&A answers for user ID " + userId + " and toolContentId " + toolContentId); + } + + QaContent content = qaDAO.getQaByContentId(toolContentId); + if (content != null) { + for (QaSession session : (Set) content.getQaSessions()) { + QaQueUsr user = qaQueUsrDAO.getQaUserBySession(userId.longValue(), session.getQaSessionId()); + if (user != null) { + for (QaUsrResp response : (Set) user.getQaUsrResps()) { + qaUsrRespDAO.removeUserResponse(response); + } + + if ((session.getGroupLeader() != null) && session.getGroupLeader().getUid().equals(user.getUid())) { + session.setGroupLeader(null); + } + + qaQueUsrDAO.deleteQaQueUsr(user); + + NotebookEntry entry = getEntry(session.getQaSessionId(), CoreNotebookConstants.NOTEBOOK_TOOL, + QaAppConstants.MY_SIGNATURE, userId); + if (entry != null) { + qaDAO.delete(entry); + } + } + } + } + } + + @Override + public List getUserReflectionsForTablesorter(Long toolSessionId, int page, int size, int sorting, + String searchString) { + return qaQueUsrDAO.getUserReflectionsForTablesorter(toolSessionId, page, size, sorting, searchString, + getCoreNotebookService()); + } + + @Override + public int getCountUsersBySessionWithSearch(Long toolSessionId, String searchString) { + return qaQueUsrDAO.getCountUsersBySessionWithSearch(toolSessionId, searchString); + } + + @Override + public void notifyTeachersOnResponseSubmit(Long sessionId) { + final String NEW_LINE_CHARACTER = "
"; + + HttpSession ss = SessionManager.getSession(); + UserDTO userDto = (UserDTO) ss.getAttribute(AttributeNames.USER); + Long userId = new Long(userDto.getUserID().longValue()); + QaQueUsr user = getUserByIdAndSession(userId, new Long(sessionId)); + String fullName = user.getFullname(); + + // add question-answer pairs to email message + List responses = qaUsrRespDAO.getResponsesByUserUid(user.getUid()); + Date attemptTime = new Date(); + String message = new String(); + for (QaUsrResp response : responses) { + String question = response.getQaQuestion().getQuestion(); + String answer = response.getAnswer(); + + message += NEW_LINE_CHARACTER + NEW_LINE_CHARACTER + question + " " + answer; + attemptTime = response.getAttemptTime(); + } + + message = NEW_LINE_CHARACTER + NEW_LINE_CHARACTER + + messageService.getMessage("label.user.has.answered.questions", new Object[] { fullName, attemptTime }) + + message + NEW_LINE_CHARACTER + NEW_LINE_CHARACTER; + + eventNotificationService.notifyLessonMonitors(sessionId, message, true); + } + + @Override + public void exportToolContent(Long toolContentID, String rootPath) { + QaContent toolContentObj = qaDAO.getQaByContentId(toolContentID); + if (toolContentObj == null) { + long defaultToolContentId = toolService.getToolDefaultContentIdBySignature(QaAppConstants.MY_SIGNATURE); + toolContentObj = getQaContent(defaultToolContentId); + } + if (toolContentObj == null) { + throw new DataMissingException("Unable to find default content for the question and answer tool"); + } + + try { + // set ToolContentHandler as null to avoid copy file node in + // repository again. + toolContentObj = QaContent.newInstance(toolContentObj, toolContentID); + + // don't export following fields value + toolContentObj.setQaSessions(null); + Set questions = toolContentObj.getQaQueContents(); + for (QaQueContent question : questions) { + question.setQaContent(null); + } + for (LearnerItemRatingCriteria criteria : toolContentObj.getRatingCriterias()) { + criteria.setToolContentId(null); + } + + exportContentService.exportToolContent(toolContentID, toolContentObj, qaToolContentHandler, rootPath); + } catch (ExportToolContentException e) { + throw new ToolException(e); + } + } + + @Override + public void importToolContent(Long toolContentID, Integer newUserUid, String toolContentPath, String fromVersion, + String toVersion) throws ToolException { + try { + // register version filter class + exportContentService.registerImportVersionFilterClass(QaImportContentVersionFilter.class); + + Object toolPOJO = exportContentService.importToolContent(toolContentPath, qaToolContentHandler, fromVersion, + toVersion); + if (!(toolPOJO instanceof QaContent)) { + throw new ImportToolContentException( + "Import QA tool content failed. Deserialized object is " + toolPOJO); + } + QaContent toolContentObj = (QaContent) toolPOJO; + + // reset it to new toolContentID + toolContentObj.setQaContentId(toolContentID); + toolContentObj.setCreatedBy(newUserUid); + Set criterias = toolContentObj.getRatingCriterias(); + if (criterias != null) { + for (LearnerItemRatingCriteria criteria : toolContentObj.getRatingCriterias()) { + criteria.setToolContentId(toolContentID); + if (criteria.getMaxRating() == null || criteria.getRatingStyle() == null) { + if (criteria.getOrderId() == 0) { + criteria.setMaxRating(0); + criteria.setRatingStyle(RatingCriteria.RATING_STYLE_COMMENT); + } else { + criteria.setMaxRating(RatingCriteria.RATING_STYLE_STAR_DEFAULT_MAX); + criteria.setRatingStyle(RatingCriteria.RATING_STYLE_STAR); + } + } + } + } + + // set back the tool content + Set questions = toolContentObj.getQaQueContents(); + for (QaQueContent question : questions) { + question.setQaContent(toolContentObj); + } + qaDAO.saveOrUpdateQa(toolContentObj); + } catch (ImportToolContentException e) { + throw new ToolException(e); + } + } + + @Override + public SortedMap getToolOutputDefinitions(Long toolContentId, int definitionType) + throws ToolException { + QaContent qaContent = qaDAO.getQaByContentId(toolContentId); + if (qaContent == null) { + long defaultToolContentId = toolService.getToolDefaultContentIdBySignature(QaAppConstants.MY_SIGNATURE); + qaContent = getQaContent(defaultToolContentId); + } + return getQaOutputFactory().getToolOutputDefinitions(qaContent, definitionType); + } + + @Override + public String getToolContentTitle(Long toolContentId) { + return qaDAO.getQaByContentId(toolContentId).getTitle(); + } + + @Override + public boolean isContentEdited(Long toolContentId) { + return qaDAO.getQaByContentId(toolContentId).isDefineLater(); + } + + @Override + public boolean isReadOnly(Long toolContentId) { + QaContent content = qaDAO.getQaByContentId(toolContentId); + for (QaSession session : (Set) content.getQaSessions()) { + if (!session.getQaQueUsers().isEmpty()) { + return true; + } + } + + return false; + } + + @Override + public void createToolSession(Long toolSessionId, String toolSessionName, Long toolContentID) throws ToolException { + + if (toolSessionId == null) { + logger.error("toolSessionId is null"); + throw new ToolException("toolSessionId is missing"); + } + + QaContent qaContent = qaDAO.getQaByContentId(toolContentID.longValue()); + + /* + * create a new a new tool session if it does not already exist in the tool session table + */ + QaSession qaSession = getSessionById(toolSessionId); + if (qaSession == null) { + try { + qaSession = new QaSession(toolSessionId, new Date(System.currentTimeMillis()), QaSession.INCOMPLETE, + toolSessionName, qaContent, new TreeSet()); + qaSessionDAO.createSession(qaSession); + } catch (Exception e) { + logger.error("Error creating new toolsession in the db"); + throw new ToolException("Error creating new toolsession in the db: " + e); + } + } + } + + @Override + public void removeToolSession(Long toolSessionId) throws DataMissingException, ToolException { + if (toolSessionId == null) { + logger.error("toolSessionId is null"); + throw new DataMissingException("toolSessionId is missing"); + } + + QaSession qaSession = null; + try { + qaSession = getSessionById(toolSessionId.longValue()); + } catch (QaApplicationException e) { + throw new DataMissingException("error retrieving qaSession: " + e); + } catch (Exception e) { + throw new ToolException("error retrieving qaSession: " + e); + } + + if (qaSession == null) { + logger.error("qaSession is null"); + throw new DataMissingException("qaSession is missing"); + } + + try { + qaSessionDAO.deleteQaSession(qaSession); + } catch (QaApplicationException e) { + throw new ToolException("error deleting qaSession:" + e); + } + } + + @Override + public String leaveToolSession(Long toolSessionId, Long learnerId) throws DataMissingException, ToolException { + + if (toolSessionId == null) { + logger.error("toolSessionId is null"); + throw new DataMissingException("toolSessionId is missing"); + } + + if (learnerId == null) { + logger.error("learnerId is null"); + throw new DataMissingException("learnerId is missing"); + } + + QaSession qaSession = getSessionById(toolSessionId.longValue()); + qaSession.setSession_end_date(new Date(System.currentTimeMillis())); + qaSession.setSession_status(QaAppConstants.COMPLETED); + updateSession(qaSession); + + try { + String nextUrl = learnerService.completeToolSession(toolSessionId, learnerId); + return nextUrl; + } catch (DataAccessException e) { + throw new ToolException("Exception occured when user is leaving tool session: " + e); + } + + } + + @Override + public List getRatingCriterias(Long toolContentId) { + return ratingService.getCriteriasByToolContentId(toolContentId); + } + + @Override + public void saveRatingCriterias(HttpServletRequest request, Collection oldCriterias, + Long toolContentId) { + ratingService.saveRatingCriterias(request, oldCriterias, toolContentId); + } + + @Override + public boolean isCommentsEnabled(Long toolContentId) { + return ratingService.isCommentsEnabled(toolContentId); + } + + @Override + public boolean isRatingsEnabled(QaContent qaContent) { + //check if allow rate answers is ON and also that there is at least one non-comments rating criteria available + boolean allowRateAnswers = false; + if (qaContent.isAllowRateAnswers()) { + List ratingCriterias = getRatingCriterias(qaContent.getQaContentId()); + for (RatingCriteria ratingCriteria : ratingCriterias) { + if (!ratingCriteria.isCommentsEnabled()) { + allowRateAnswers = true; + break; + } + } + } + return allowRateAnswers; + } + + @Override + public List getRatingCriteriaDtos(Long contentId, Long toolSessionId, Collection itemIds, + boolean isCommentsByOtherUsersRequired, Long userId) { + return ratingService.getRatingCriteriaDtos(contentId, toolSessionId, itemIds, isCommentsByOtherUsersRequired, userId); + } + + @Override + public int getCountItemsRatedByUser(Long toolContentId, Integer userId) { + return ratingService.getCountItemsRatedByUser(toolContentId, userId); + } + + /** + * ToolSessionManager CONTRACT + */ + @Override + public ToolSessionExportOutputData exportToolSession(Long toolSessionId) + throws DataMissingException, ToolException { + throw new ToolException("not yet implemented"); + } + + /** + * ToolSessionManager CONTRACT + */ + @Override + public ToolSessionExportOutputData exportToolSession(List toolSessionIds) + throws DataMissingException, ToolException { + throw new ToolException("not yet implemented"); + } + + @Override + public SortedMap getToolOutput(List names, Long toolSessionId, Long learnerId) { + return getQaOutputFactory().getToolOutput(names, this, toolSessionId, learnerId); + } + + @Override + public ToolOutput getToolOutput(String name, Long toolSessionId, Long learnerId) { + return getQaOutputFactory().getToolOutput(name, this, toolSessionId, learnerId); + } + + @Override + public List getToolOutputs(String name, Long toolContentId) { + return new ArrayList(); + } + + @Override + public void forceCompleteUser(Long toolSessionId, User user) { + Long userId = user.getUserId().longValue(); + + QaSession session = getSessionById(toolSessionId); + if ((session == null) || (session.getQaContent() == null)) { + return; + } + QaContent content = session.getQaContent(); + + // copy answers only in case leader aware feature is ON + if (content.isUseSelectLeaderToolOuput()) { + + QaQueUsr qaUser = getUserByIdAndSession(userId, toolSessionId); + // create user if he hasn't accessed this activity yet + if (qaUser == null) { + + String userName = user.getLogin(); + String fullName = user.getFirstName() + " " + user.getLastName(); + qaUser = new QaQueUsr(userId, userName, fullName, session, new TreeSet()); + qaQueUsrDAO.createUsr(qaUser); + } + + QaQueUsr groupLeader = session.getGroupLeader(); + + // check if leader has submitted answers + if ((groupLeader != null) && groupLeader.isResponseFinalized()) { + + // we need to make sure specified user has the same scratches as a leader + copyAnswersFromLeader(qaUser, groupLeader); + } + + } + + } + + @Override + public IToolVO getToolBySignature(String toolSignature) { + IToolVO tool = toolService.getToolBySignature(toolSignature); + return tool; + } + + @Override + public long getToolDefaultContentIdBySignature(String toolSignature) { + long contentId = 0; + contentId = toolService.getToolDefaultContentIdBySignature(toolSignature); + return contentId; + } + + @Override + public Long createNotebookEntry(Long id, Integer idType, String signature, Integer userID, String entry) { + return coreNotebookService.createNotebookEntry(id, idType, signature, userID, "", entry); + } + + @Override + public NotebookEntry getEntry(Long id, Integer idType, String signature, Integer userID) { + + List list = coreNotebookService.getEntry(id, idType, signature, userID); + if ((list == null) || list.isEmpty()) { + return null; + } else { + return list.get(0); + } + } + + @Override + public boolean isGroupedActivity(long toolContentID) { + return toolService.isGroupedActivity(toolContentID); + } + + @Override + public void auditLogStartEditingActivityInMonitor(long toolContentID) { + toolService.auditLogStartEditingActivityInMonitor(toolContentID); + } + + @Override + public String getLearnerContentFolder(Long toolSessionId, Long userId) { + return toolService.getLearnerContentFolder(toolSessionId, userId); + } + + /** + * @return Returns the userManagementService. + */ + public IUserManagementService getUserManagementService() { + return userManagementService; + } + + public void setLearnerService(ILearnerService learnerService) { + this.learnerService = learnerService; + } + + public void setQaDAO(IQaContentDAO qaDAO) { + this.qaDAO = qaDAO; + } + + public void setQaQuestionDAO(IQaQuestionDAO qaQuestionDAO) { + this.qaQuestionDAO = qaQuestionDAO; + } + + public void setQaSessionDAO(IQaSessionDAO qaSessionDAO) { + this.qaSessionDAO = qaSessionDAO; + } + + public void setQaQueUsrDAO(IQaQueUsrDAO qaQueUsrDAO) { + this.qaQueUsrDAO = qaQueUsrDAO; + } + + public void setQaUsrRespDAO(IQaUsrRespDAO qaUsrRespDAO) { + this.qaUsrRespDAO = qaUsrRespDAO; + } + + /** + * @return Returns the qaDAO. + */ + public IQaContentDAO getQaDAO() { + return qaDAO; + } + + public void setUserManagementService(IUserManagementService userManagementService) { + this.userManagementService = userManagementService; + } + + public void setToolService(ILamsToolService toolService) { + this.toolService = toolService; + } + + /** + * @param qaToolContentHandler + * The qaToolContentHandler to set. + */ + public void setQaToolContentHandler(IToolContentHandler qaToolContentHandler) { + this.qaToolContentHandler = qaToolContentHandler; + } + + @Override + public IAuditService getAuditService() { + return auditService; + } + + public void setAuditService(IAuditService auditService) { + this.auditService = auditService; + } + + public IExportToolContentService getExportContentService() { + return exportContentService; + } + + public void setExportContentService(IExportToolContentService exportContentService) { + this.exportContentService = exportContentService; + } + + // ========================================================================================= + /** + * @return Returns the coreNotebookService. + */ + public ICoreNotebookService getCoreNotebookService() { + return coreNotebookService; + } + + /** + * @param coreNotebookService + * The coreNotebookService to set. + */ + public void setCoreNotebookService(ICoreNotebookService coreNotebookService) { + this.coreNotebookService = coreNotebookService; + } + + public void setRatingService(IRatingService ratingService) { + this.ratingService = ratingService; + } + + public void setEventNotificationService(IEventNotificationService eventNotificationService) { + this.eventNotificationService = eventNotificationService; + } + + public void setMessageService(MessageService messageService) { + this.messageService = messageService; + } + + @Override + public void updateEntry(NotebookEntry notebookEntry) { + coreNotebookService.updateEntry(notebookEntry); + } + + public QaOutputFactory getQaOutputFactory() { + return qaOutputFactory; + } + + public void setQaOutputFactory(QaOutputFactory qaOutputFactory) { + this.qaOutputFactory = qaOutputFactory; + } + + public IQaConfigItemDAO getQaConfigItemDAO() { + return qaConfigItemDAO; + } + + public void setQaConfigItemDAO(IQaConfigItemDAO qaConfigItemDAO) { + this.qaConfigItemDAO = qaConfigItemDAO; + } + + public IQaWizardDAO getQaWizardDAO() { + return qaWizardDAO; + } + + public void setQaWizardDAO(IQaWizardDAO qaWizardDAO) { + this.qaWizardDAO = qaWizardDAO; + } + + @Override + public QaContent getQaContentBySessionId(Long sessionId) { + QaSession session = qaSessionDAO.getQaSessionById(sessionId); + // to skip CGLib problem + Long contentId = session.getQaContent().getQaContentId(); + QaContent qaContent = qaDAO.getQaByContentId(contentId); + return qaContent; + } + + @Override + public String createConditionName(Collection existingConditions) { + String uniqueNumber = null; + do { + uniqueNumber = String.valueOf(Math.abs(generator.nextInt())); + for (QaCondition condition : existingConditions) { + String[] splitedName = getQaOutputFactory().splitConditionName(condition.getName()); + if (uniqueNumber.equals(splitedName[1])) { + uniqueNumber = null; + } + } + } while (uniqueNumber == null); + return getQaOutputFactory().buildUserAnswersConditionName(uniqueNumber); + } + + @Override + public void deleteCondition(QaCondition condition) { + if ((condition != null) && (condition.getConditionId() != null)) { + qaDAO.deleteCondition(condition); + } + } + + @Override + public QaConfigItem getConfigItem(String configKey) { + return qaConfigItemDAO.getConfigItemByKey(configKey); + } + + @Override + public void saveOrUpdateConfigItem(QaConfigItem configItem) { + qaConfigItemDAO.saveOrUpdate(configItem); + } + + @Override + public SortedSet getWizardCategories() { + return qaWizardDAO.getWizardCategories(); + } + + @Override + public void saveOrUpdateQaWizardCategories(SortedSet categories) { + qaWizardDAO.saveOrUpdateCategories(categories); + } + + @Override + public void deleteWizardCategoryByUID(Long uid) { + qaWizardDAO.deleteWizardCategoryByUID(uid); + } + + @Override + public void deleteWizardSkillByUID(Long uid) { + qaWizardDAO.deleteWizardSkillByUID(uid); + } + + @Override + public void deleteWizardQuestionByUID(Long uid) { + qaWizardDAO.deleteWizardQuestionByUID(uid); + } + + @Override + public void deleteAllWizardCategories() { + qaWizardDAO.deleteAllWizardCategories(); + } + + @Override + public void removeQuestionsFromCache(QaContent qaContent) { + qaDAO.removeQuestionsFromCache(qaContent); + } + + @Override + public void removeQaContentFromCache(QaContent qaContent) { + qaDAO.removeQaContentFromCache(qaContent); + } + + @Override + public Class[] getSupportedToolOutputDefinitionClasses(int definitionType) { + return getQaOutputFactory().getSupportedDefinitionClasses(definitionType); + } + + @Override + public ToolCompletionStatus getCompletionStatus(Long learnerId, Long toolSessionId) { + QaQueUsr learner = qaQueUsrDAO.getQaUserBySession(learnerId, toolSessionId); + if (learner == null) { + return new ToolCompletionStatus(ToolCompletionStatus.ACTIVITY_NOT_ATTEMPTED, null, null); + } + + Date startDate = null; + Date endDate = null; + Set attempts = learner.getQaUsrResps(); + for (QaUsrResp item : attempts) { + Date newDate = item.getAttemptTime(); + if (newDate != null) { + if (startDate == null || newDate.before(startDate)) + startDate = newDate; + if (endDate == null || newDate.after(endDate)) + endDate = newDate; + } + } + + if (learner.isLearnerFinished()) + return new ToolCompletionStatus(ToolCompletionStatus.ACTIVITY_COMPLETED, startDate, endDate); + else + return new ToolCompletionStatus(ToolCompletionStatus.ACTIVITY_ATTEMPTED, startDate, null); + } + // ****************** REST methods ************************* + + /** + * Rest call to create a new Q&A content. Required fields in toolContentJSON: title, instructions, questions. The + * questions entry should be JSONArray containing JSON objects, which in turn must contain "questionText", + * "displayOrder" and may also contain feedback and required (boolean) + */ + @Override + public void createRestToolContent(Integer userID, Long toolContentID, JSONObject toolContentJSON) + throws JSONException { + + QaContent qa = new QaContent(); + Date updateDate = new Date(); + + qa.setCreationDate(updateDate); + qa.setUpdateDate(updateDate); + qa.setCreatedBy(userID.longValue()); + + qa.setQaContentId(toolContentID); + qa.setTitle(toolContentJSON.getString(RestTags.TITLE)); + qa.setInstructions(toolContentJSON.getString(RestTags.INSTRUCTIONS)); + + qa.setDefineLater(false); + + qa.setLockWhenFinished(JsonUtil.opt(toolContentJSON, RestTags.LOCK_WHEN_FINISHED, Boolean.FALSE)); + qa.setNoReeditAllowed(JsonUtil.opt(toolContentJSON, "noReeditAllowed", Boolean.FALSE)); + qa.setAllowRichEditor(JsonUtil.opt(toolContentJSON, RestTags.ALLOW_RICH_TEXT_EDITOR, Boolean.FALSE)); + qa.setUseSelectLeaderToolOuput( + JsonUtil.opt(toolContentJSON, RestTags.USE_SELECT_LEADER_TOOL_OUTPUT, Boolean.FALSE)); + qa.setMinimumRates(JsonUtil.opt(toolContentJSON, RestTags.MINIMUM_RATES, 0)); + qa.setMaximumRates(JsonUtil.opt(toolContentJSON, RestTags.MAXIMUM_RATES, 0)); + qa.setShowOtherAnswers(JsonUtil.opt(toolContentJSON, "showOtherAnswers", Boolean.TRUE)); + qa.setUsernameVisible(JsonUtil.opt(toolContentJSON, "usernameVisible", Boolean.FALSE)); + qa.setAllowRateAnswers(JsonUtil.opt(toolContentJSON, "allowRateAnswers", Boolean.FALSE)); + qa.setNotifyTeachersOnResponseSubmit( + JsonUtil.opt(toolContentJSON, "notifyTeachersOnResponseSubmit", Boolean.FALSE)); + qa.setReflect(JsonUtil.opt(toolContentJSON, RestTags.REFLECT_ON_ACTIVITY, Boolean.FALSE)); + qa.setReflectionSubject(JsonUtil.opt(toolContentJSON, RestTags.REFLECT_INSTRUCTIONS, (String) null)); + qa.setQuestionsSequenced(JsonUtil.opt(toolContentJSON, "questionsSequenced", Boolean.FALSE)); + + // submissionDeadline is set in monitoring + // qa.setMonitoringReportTitle(); Can't find this field in the database - assuming unused. + // qa.setReportTitle(); Can't find this field in the database - assuming unused. + // qa.setContent(content); Can't find this field in the database - assuming unused. + + saveOrUpdateQaContent(qa); + // Questions + JSONArray questions = toolContentJSON.getJSONArray(RestTags.QUESTIONS); + for (int i = 0; i < questions.length(); i++) { + JSONObject questionData = (JSONObject) questions.get(i); + QaQueContent question = new QaQueContent(questionData.getString(RestTags.QUESTION_TEXT), + questionData.getInt(RestTags.DISPLAY_ORDER), JsonUtil.opt(questionData, "feedback", (String) null), + JsonUtil.opt(questionData, "required", Boolean.FALSE), + JsonUtil.opt(questionData, "minWordsLimit", 0), qa); + saveOrUpdateQuestion(question); + } + + // TODO + // qa.setConditions(conditions); + + } +} Fisheye: Tag 85ef8aca5722a36582117db1e8b988e2c16b6369 refers to a dead (removed) revision in file `lams_tool_laqa/src/java/org/lamsfoundation/lams/tool/qa/service/QaServicePOJO.java'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_tool_nb/src/java/org/lamsfoundation/lams/tool/noticeboard/nbApplicationContext.xml =================================================================== diff -u -ra6641bf9262a01d07740a517643f8fe187ec5b1f -r85ef8aca5722a36582117db1e8b988e2c16b6369 --- lams_tool_nb/src/java/org/lamsfoundation/lams/tool/noticeboard/nbApplicationContext.xml (.../nbApplicationContext.xml) (revision a6641bf9262a01d07740a517643f8fe187ec5b1f) +++ lams_tool_nb/src/java/org/lamsfoundation/lams/tool/noticeboard/nbApplicationContext.xml (.../nbApplicationContext.xml) (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -21,7 +21,7 @@
- + Index: lams_tool_nb/src/java/org/lamsfoundation/lams/tool/noticeboard/service/NoticeboardService.java =================================================================== diff -u --- lams_tool_nb/src/java/org/lamsfoundation/lams/tool/noticeboard/service/NoticeboardService.java (revision 0) +++ lams_tool_nb/src/java/org/lamsfoundation/lams/tool/noticeboard/service/NoticeboardService.java (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -0,0 +1,657 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + + +package org.lamsfoundation.lams.tool.noticeboard.service; + +import java.util.ArrayList; +import java.util.Date; +import java.util.Iterator; +import java.util.List; +import java.util.SortedMap; +import java.util.TreeMap; + +import org.apache.log4j.Logger; +import org.apache.tomcat.util.json.JSONException; +import org.apache.tomcat.util.json.JSONObject; +import org.lamsfoundation.lams.contentrepository.ItemNotFoundException; +import org.lamsfoundation.lams.contentrepository.RepositoryCheckedException; +import org.lamsfoundation.lams.contentrepository.client.IToolContentHandler; +import org.lamsfoundation.lams.learning.service.ILearnerService; +import org.lamsfoundation.lams.learningdesign.service.ExportToolContentException; +import org.lamsfoundation.lams.learningdesign.service.IExportToolContentService; +import org.lamsfoundation.lams.learningdesign.service.ImportToolContentException; +import org.lamsfoundation.lams.notebook.model.NotebookEntry; +import org.lamsfoundation.lams.notebook.service.CoreNotebookConstants; +import org.lamsfoundation.lams.notebook.service.ICoreNotebookService; +import org.lamsfoundation.lams.rest.RestTags; +import org.lamsfoundation.lams.rest.ToolRestManager; +import org.lamsfoundation.lams.tool.ToolCompletionStatus; +import org.lamsfoundation.lams.tool.ToolContentManager; +import org.lamsfoundation.lams.tool.ToolOutput; +import org.lamsfoundation.lams.tool.ToolOutputDefinition; +import org.lamsfoundation.lams.tool.ToolSessionExportOutputData; +import org.lamsfoundation.lams.tool.ToolSessionManager; +import org.lamsfoundation.lams.tool.exception.DataMissingException; +import org.lamsfoundation.lams.tool.exception.ToolException; +import org.lamsfoundation.lams.tool.noticeboard.NoticeboardConstants; +import org.lamsfoundation.lams.tool.noticeboard.NoticeboardContent; +import org.lamsfoundation.lams.tool.noticeboard.NoticeboardSession; +import org.lamsfoundation.lams.tool.noticeboard.NoticeboardUser; +import org.lamsfoundation.lams.tool.noticeboard.dao.INoticeboardContentDAO; +import org.lamsfoundation.lams.tool.noticeboard.dao.INoticeboardSessionDAO; +import org.lamsfoundation.lams.tool.noticeboard.dao.INoticeboardUserDAO; +import org.lamsfoundation.lams.tool.noticeboard.util.NbApplicationException; +import org.lamsfoundation.lams.tool.service.ILamsToolService; +import org.lamsfoundation.lams.usermanagement.User; +import org.lamsfoundation.lams.util.JsonUtil; + +/** + * An implementation of the NoticeboardService interface. + * + * As a requirement, all LAMS tool's service bean must implement ToolContentManager and ToolSessionManager. + * + * @author mtruong + */ +public class NoticeboardService + implements INoticeboardService, ToolContentManager, ToolSessionManager, ToolRestManager { + private static Logger log = Logger.getLogger(NoticeboardService.class); + + private ILearnerService learnerService; + private ILamsToolService toolService; + private IExportToolContentService exportContentService; + private IToolContentHandler nbToolContentHandler; + private ICoreNotebookService coreNotebookService; + + private INoticeboardContentDAO nbContentDAO; + private INoticeboardSessionDAO nbSessionDAO; + private INoticeboardUserDAO nbUserDAO; + + @Override + public NoticeboardContent retrieveNoticeboard(Long nbContentId) throws NbApplicationException { + if (nbContentId == null) { + throw new NbApplicationException("Tool content ID is missing"); + } + + return nbContentDAO.findNbContentById(nbContentId); + } + + @Override + public NoticeboardContent retrieveNoticeboardBySessionID(Long nbSessionId) { + if (nbSessionId == null) { + throw new NbApplicationException("Tool session ID is missing"); + } + + return nbContentDAO.getNbContentBySession(nbSessionId); + } + + @Override + public void saveNoticeboard(NoticeboardContent nbContent) { + if (nbContent.getUid() == null) { + nbContentDAO.saveNbContent(nbContent); + } else { + nbContentDAO.updateNbContent(nbContent); + } + } + + @Override + public void removeNoticeboardSessionsFromContent(NoticeboardContent nbContent) { + nbContent.getNbSessions().clear(); + nbContentDAO.removeNbSessions(nbContent); + } + + @Override + public void removeNoticeboard(Long nbContentId) { + if (nbContentId == null) { + throw new NbApplicationException("Tool content ID is missing"); + } + nbContentDAO.removeNoticeboard(nbContentId); + } + + @Override + public void removeNoticeboard(NoticeboardContent nbContent) { + nbContentDAO.removeNoticeboard(nbContent); + } + + @Override + public NoticeboardSession retrieveNoticeboardSession(Long nbSessionId) { + if (nbSessionId == null) { + throw new NbApplicationException("Tool session ID is missing"); + } + + return nbSessionDAO.findNbSessionById(nbSessionId); + } + + @Override + public void saveNoticeboardSession(NoticeboardSession nbSession) { + NoticeboardContent content = nbSession.getNbContent(); + nbSessionDAO.saveNbSession(nbSession); + } + + @Override + public void updateNoticeboardSession(NoticeboardSession nbSession) { + nbSessionDAO.updateNbSession(nbSession); + } + + @Override + public void removeSession(Long nbSessionId) { + if (nbSessionId == null) { + throw new NbApplicationException("Tool session id is missing"); + } + + NoticeboardSession sessionToDelete = retrieveNoticeboardSession(nbSessionId); + NoticeboardContent contentReferredBySession = sessionToDelete.getNbContent(); + // un-associate the session from content + contentReferredBySession.getNbSessions().remove(sessionToDelete); + nbSessionDAO.removeNbSession(nbSessionId); + } + + @Override + public void removeSession(NoticeboardSession nbSession) { + NoticeboardContent contentReferredBySession = nbSession.getNbContent(); + // un-associate the session from content + contentReferredBySession.getNbSessions().remove(nbSession); + nbSessionDAO.removeNbSession(nbSession); + } + + @Override + public void removeNoticeboardUsersFromSession(NoticeboardSession nbSession) { + nbSession.getNbUsers().clear(); + nbSessionDAO.removeNbUsers(nbSession); + } + + @Override + public NoticeboardSession retrieveNbSessionByUserID(Long userId) { + if (userId == null) { + throw new NbApplicationException("Tool session ID is missing"); + } + return nbSessionDAO.getNbSessionByUser(userId); + } + + @Override + public NoticeboardUser retrieveNoticeboardUser(Long nbUserId, Long nbSessionId) { + if (nbUserId == null) { + throw new NbApplicationException("User ID is missing"); + } + + return nbUserDAO.getNbUser(nbUserId, nbSessionId); + } + + @Override + public void saveNoticeboardUser(NoticeboardUser nbUser) { + NoticeboardSession session = nbUser.getNbSession(); + session.getNbUsers().add(nbUser); + nbUserDAO.saveNbUser(nbUser); + } + + @Override + public NoticeboardUser retrieveNbUserBySession(Long userId, Long sessionId) { + return nbUserDAO.getNbUserBySession(userId, sessionId); + } + + @Override + public void updateNoticeboardUser(NoticeboardUser nbUser) { + nbUserDAO.updateNbUser(nbUser); + } + + @Override + public void removeUser(NoticeboardUser nbUser) { + nbUserDAO.delete(nbUser); + } + + @Override + public void removeUser(Long nbUserId, Long toolSessionId) { + NoticeboardUser user = retrieveNoticeboardUser(nbUserId, toolSessionId); + nbUserDAO.delete(user); + } + + @Override + public void addSession(Long nbContentId, NoticeboardSession session) { + if ((nbContentId == null) || (session == null)) { + throw new NbApplicationException("Tool content ID or session is missing"); + } + + nbContentDAO.addNbSession(nbContentId, session); + } + + @Override + public void addUser(Long nbSessionId, NoticeboardUser user) { + if (nbSessionId == null) { + throw new NbApplicationException("Tool session ID is missing"); + } + nbSessionDAO.addNbUsers(nbSessionId, user); + } + + @Override + public int getNumberOfUsersInSession(NoticeboardSession session) { + return nbUserDAO.getNumberOfUsers(session); + } + + @Override + public int calculateTotalNumberOfUsers(Long toolContentId) { + if (toolContentId == null) { + throw new NbApplicationException("Tool content id is missing"); + } + + int totalNumberOfUsers = 0; + NoticeboardContent nbContent = retrieveNoticeboard(toolContentId); + for (NoticeboardSession session : nbContent.getNbSessions()) { + totalNumberOfUsers += getNumberOfUsersInSession(session); + } + + return totalNumberOfUsers; + } + + @SuppressWarnings("unchecked") + @Override + public List getUsersBySession(Long sessionId) { + if (sessionId == null) { + throw new NbApplicationException("Session ID is missing"); + } + return nbUserDAO.getNbUsersBySession(sessionId); + } + + @Override + public boolean isGroupedActivity(long toolContentID) { + return toolService.isGroupedActivity(toolContentID); + } + + @Override + public void auditLogStartEditingActivityInMonitor(long toolContentID) { + toolService.auditLogStartEditingActivityInMonitor(toolContentID); + } + + @Override + public void copyToolContent(Long fromContentId, Long toContentId) throws ToolException { + if (toContentId == null) { + throw new ToolException("Failed to copy Noticeboard tool content. Missing parameter: toContentId"); + } + if (fromContentId == null) { + // use the default content Id + fromContentId = getToolDefaultContentIdBySignature(NoticeboardConstants.TOOL_SIGNATURE); + } + + // fromContentId might not have any content, in this case use default content + // default content id might not have any contnet, throw exception + NoticeboardContent originalNb = null; + + try { + if ((originalNb = retrieveNoticeboard(fromContentId)) == null) // the id given does not have content, use + // default content + { + // use default content id to grab contents + NoticeboardContent defaultContent = retrieveNoticeboard( + getToolDefaultContentIdBySignature(NoticeboardConstants.TOOL_SIGNATURE)); + + if (defaultContent != null) { + NoticeboardContent newContent = NoticeboardContent.newInstance(defaultContent, toContentId); + saveNoticeboard(newContent); + } else { + throw new ToolException("Default content is missing. Unable to copy tool content"); + } + } else { + NoticeboardContent newNbContent = NoticeboardContent.newInstance(originalNb, toContentId); + saveNoticeboard(newNbContent); + } + } catch (RepositoryCheckedException e) { + log.error("Unable to copy the tool content due to a content repository error. fromContentId " + + fromContentId + " toContentId " + toContentId); + throw new ToolException(e); + } + + } + + @Override + public void resetDefineLater(Long toolContentId) throws DataMissingException, ToolException { + NoticeboardContent nbContent = getAndCheckIDandObject(toolContentId); + nbContent.setDefineLater(false); + saveNoticeboard(nbContent); + } + + @Override + public void removeToolContent(Long toolContentId) throws ToolException { + NoticeboardContent nbContent = retrieveNoticeboard(toolContentId); + if (nbContent == null) { + log.warn("Can not remove the tool content as it does not exist, ID: " + toolContentId); + return; + } + + for (NoticeboardSession session : nbContent.getNbSessions()) { + List entries = coreNotebookService.getEntry(session.getNbSessionId(), + CoreNotebookConstants.NOTEBOOK_TOOL, NoticeboardConstants.TOOL_SIGNATURE); + for (NotebookEntry entry : entries) { + coreNotebookService.deleteEntry(entry); + } + } + + removeNoticeboard(toolContentId); + } + + @Override + public void removeLearnerContent(Long toolContentId, Integer userId) throws ToolException { + if (log.isDebugEnabled()) { + log.debug("Removing Noticeboard user for user ID " + userId + " and toolContentId " + toolContentId); + } + + NoticeboardContent nbContent = nbContentDAO.findNbContentById(toolContentId); + if (nbContent == null) { + log.warn("Did not find activity with toolContentId: " + toolContentId + " to remove learner content"); + return; + } + + for (NoticeboardSession session : nbContent.getNbSessions()) { + NoticeboardUser user = nbUserDAO.getNbUser(userId.longValue(), session.getNbSessionId()); + if (user != null) { + NotebookEntry entry = getEntry(session.getNbSessionId(), CoreNotebookConstants.NOTEBOOK_TOOL, + NoticeboardConstants.TOOL_SIGNATURE, userId); + if (entry != null) { + nbContentDAO.delete(entry); + } + + nbUserDAO.delete(user); + } + } + } + + private NoticeboardContent getAndCheckIDandObject(Long toolContentId) throws ToolException, DataMissingException { + if (toolContentId == null) { + throw new ToolException("Tool content ID is missing. Unable to continue"); + } + + NoticeboardContent nbContent = retrieveNoticeboard(toolContentId); + if (nbContent == null) { + throw new DataMissingException("No tool content matches this tool content id"); + } + + return nbContent; + } + + private NoticeboardSession getAndCheckSessionIDandObject(Long toolSessionId) + throws ToolException, DataMissingException { + if (toolSessionId == null) { + throw new ToolException("Tool session ID is missing."); + } + + NoticeboardSession nbSession = retrieveNoticeboardSession(toolSessionId); + if (nbSession == null) { + throw new DataMissingException("No tool session matches this tool session id"); + } + + return nbSession; + } + + @Override + public void exportToolContent(Long toolContentId, String rootPath) throws DataMissingException, ToolException { + NoticeboardContent toolContentObj = nbContentDAO.findNbContentById(toolContentId); + if (toolContentObj == null) { + Long defaultContentId = getToolDefaultContentIdBySignature(NoticeboardConstants.TOOL_SIGNATURE); + toolContentObj = retrieveNoticeboard(defaultContentId); + } + if (toolContentObj == null) { + throw new DataMissingException("Unable to find default content for the noticeboard tool"); + } + + try { + // set ResourceToolContentHandler as null to avoid copy file node in repository again. + toolContentObj = NoticeboardContent.newInstance(toolContentObj, toolContentId); + toolContentObj.setNbSessions(null); + exportContentService.exportToolContent(toolContentId, toolContentObj, nbToolContentHandler, rootPath); + } catch (ExportToolContentException e) { + throw new ToolException(e); + } catch (ItemNotFoundException e) { + throw new ToolException(e); + } catch (RepositoryCheckedException e) { + throw new ToolException(e); + } + } + + @Override + public void importToolContent(Long toolContentId, Integer newUserUid, String toolContentPath, String fromVersion, + String toVersion) throws ToolException { + try { + // register version filter class + exportContentService.registerImportVersionFilterClass(NoticeboardImportContentVersionFilter.class); + + Object toolPOJO = exportContentService.importToolContent(toolContentPath, nbToolContentHandler, fromVersion, + toVersion); + if (!(toolPOJO instanceof NoticeboardContent)) { + throw new ImportToolContentException( + "Import Noteice board tool content failed. Deserialized object is " + toolPOJO); + } + NoticeboardContent toolContentObj = (NoticeboardContent) toolPOJO; + + // reset it to new toolContentId + toolContentObj.setNbContentId(toolContentId); + nbContentDAO.saveNbContent(toolContentObj); + } catch (ImportToolContentException e) { + throw new ToolException(e); + } + } + + @Override + public SortedMap getToolOutputDefinitions(Long toolContentId, int definitionType) + throws ToolException { + return new TreeMap(); + } + + @Override + public String getToolContentTitle(Long toolContentId) { + return retrieveNoticeboard(toolContentId).getTitle(); + } + + @Override + public boolean isContentEdited(Long toolContentId) { + return retrieveNoticeboard(toolContentId).isDefineLater(); + } + + @Override + public boolean isReadOnly(Long toolContentId) { + NoticeboardContent nbContent = nbContentDAO.findNbContentById(toolContentId); + for (NoticeboardSession session : nbContent.getNbSessions()) { + if (!session.getNbUsers().isEmpty()) { + return true; + } + } + + return false; + } + + @Override + public void createToolSession(Long toolSessionId, String toolSessionName, Long toolContentId) throws ToolException { + if ((toolSessionId == null) || (toolContentId == null)) { + String error = "Failed to create tool session. The tool session id or tool content id is invalid"; + throw new ToolException(error); + } + + NoticeboardContent nbContent = retrieveNoticeboard(toolContentId); + NoticeboardSession nbSession = new NoticeboardSession(toolSessionId, toolSessionName, nbContent, + new Date(System.currentTimeMillis()), NoticeboardSession.NOT_ATTEMPTED); + + nbContent.getNbSessions().add(nbSession); + saveNoticeboard(nbContent); + } + + @Override + public String leaveToolSession(Long toolSessionId, Long learnerId) throws DataMissingException, ToolException { + getAndCheckSessionIDandObject(toolSessionId); + + return learnerService.completeToolSession(toolSessionId, learnerId); + } + + @Override + public ToolSessionExportOutputData exportToolSession(Long toolSessionId) + throws ToolException, DataMissingException { + getAndCheckSessionIDandObject(toolSessionId); + throw new UnsupportedOperationException("not yet implemented"); + } + + @SuppressWarnings("unchecked") + @Override + public ToolSessionExportOutputData exportToolSession(List toolSessionIds) + throws ToolException, DataMissingException { + Iterator i = toolSessionIds.iterator(); + if (i.hasNext()) { + Long id = i.next(); + getAndCheckSessionIDandObject(id); + } + + throw new UnsupportedOperationException("not yet implemented"); + } + + @Override + public void removeToolSession(Long toolSessionId) throws DataMissingException, ToolException { + NoticeboardSession session = getAndCheckSessionIDandObject(toolSessionId); + removeSession(session); + } + + @Override + public SortedMap getToolOutput(List names, Long toolSessionId, Long learnerId) { + return new TreeMap(); + } + + @Override + public ToolOutput getToolOutput(String name, Long toolSessionId, Long learnerId) { + return null; + } + + @Override + public List getToolOutputs(String name, Long toolContentId) { + return new ArrayList(); + } + + @Override + public void forceCompleteUser(Long toolSessionId, User user) { + //no actions required + } + + @Override + public Long getToolDefaultContentIdBySignature(String toolSignature) { + return toolService.getToolDefaultContentIdBySignature(toolSignature); + } + + public void setNbContentDAO(INoticeboardContentDAO nbContentDAO) { + this.nbContentDAO = nbContentDAO; + } + + public void setNbSessionDAO(INoticeboardSessionDAO nbSessionDAO) { + this.nbSessionDAO = nbSessionDAO; + } + + public void setNbUserDAO(INoticeboardUserDAO nbUserDAO) { + this.nbUserDAO = nbUserDAO; + } + + public void setLearnerService(ILearnerService learnerService) { + this.learnerService = learnerService; + } + + public void setToolService(ILamsToolService toolService) { + this.toolService = toolService; + } + + public IToolContentHandler getNbToolContentHandler() { + return nbToolContentHandler; + } + + public void setNbToolContentHandler(IToolContentHandler nbToolContentHandler) { + this.nbToolContentHandler = nbToolContentHandler; + } + + public IExportToolContentService getExportContentService() { + return exportContentService; + } + + public void setExportContentService(IExportToolContentService exportContentService) { + this.exportContentService = exportContentService; + } + + public ICoreNotebookService getCoreNotebookService() { + return coreNotebookService; + } + + public void setCoreNotebookService(ICoreNotebookService coreNotebookService) { + this.coreNotebookService = coreNotebookService; + } + + /* =============== Wrappers Methods for Notebook Service (Reflective Option) =============== */ + + @Override + public Long createNotebookEntry(Long id, Integer idType, String signature, Integer userID, String entry) { + return coreNotebookService.createNotebookEntry(id, idType, signature, userID, "", entry); + } + + @Override + public NotebookEntry getEntry(Long id, Integer idType, String signature, Integer userID) { + List list = coreNotebookService.getEntry(id, idType, signature, userID); + if ((list == null) || list.isEmpty()) { + return null; + } else { + return list.get(0); + } + } + + @Override + public void updateEntry(NotebookEntry notebookEntry) { + coreNotebookService.updateEntry(notebookEntry); + } + + @Override + public Class[] getSupportedToolOutputDefinitionClasses(int definitionType) { + return null; + } + + @Override + public ToolCompletionStatus getCompletionStatus(Long learnerId, Long toolSessionId) { + // db doesn't have a start/finish date for learner, and session start/finish is null + NoticeboardUser learner = retrieveNoticeboardUser(learnerId, toolSessionId); + if (learner == null) { + return new ToolCompletionStatus(ToolCompletionStatus.ACTIVITY_NOT_ATTEMPTED, null, null); + } + + return new ToolCompletionStatus( + NoticeboardUser.COMPLETED.equals(learner.getUserStatus()) ? ToolCompletionStatus.ACTIVITY_COMPLETED + : ToolCompletionStatus.ACTIVITY_ATTEMPTED, null, null); + } + + // ****************** REST methods ************************* + + @Override + public void createRestToolContent(Integer userID, Long toolContentID, JSONObject toolContentJSON) + throws JSONException { + Date updateDate = new Date(); + + NoticeboardContent noticeboard = new NoticeboardContent(); + noticeboard.setNbContentId(toolContentID); + noticeboard.setTitle(toolContentJSON.getString(RestTags.TITLE)); + noticeboard.setContent(toolContentJSON.getString("content")); + noticeboard.setReflectOnActivity(JsonUtil.opt(toolContentJSON, RestTags.REFLECT_ON_ACTIVITY, Boolean.FALSE)); + noticeboard.setReflectInstructions((String) JsonUtil.opt(toolContentJSON, RestTags.REFLECT_INSTRUCTIONS, null)); + + noticeboard.setCreatorUserId(userID.longValue()); + noticeboard.setDateCreated(updateDate); + noticeboard.setDateUpdated(updateDate); + noticeboard.setContentInUse(false); + + saveNoticeboard(noticeboard); + } +} \ No newline at end of file Fisheye: Tag 85ef8aca5722a36582117db1e8b988e2c16b6369 refers to a dead (removed) revision in file `lams_tool_nb/src/java/org/lamsfoundation/lams/tool/noticeboard/service/NoticeboardServicePOJO.java'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_tool_survey/src/java/org/lamsfoundation/lams/tool/survey/service/SurveyOutputFactory.java =================================================================== diff -u -rb036e6dd6d2afe9c0e0b9143c9be3af1d53a1e0e -r85ef8aca5722a36582117db1e8b988e2c16b6369 --- lams_tool_survey/src/java/org/lamsfoundation/lams/tool/survey/service/SurveyOutputFactory.java (.../SurveyOutputFactory.java) (revision b036e6dd6d2afe9c0e0b9143c9be3af1d53a1e0e) +++ lams_tool_survey/src/java/org/lamsfoundation/lams/tool/survey/service/SurveyOutputFactory.java (.../SurveyOutputFactory.java) (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -79,7 +79,7 @@ } /** - * Follows {@link QaServicePOJO#getToolOutput(List, Long, Long)}. + * Follows {@link SurveyService#getToolOutput(List, Long, Long)}. * */ public SortedMap getToolOutput(List names, ISurveyService surveyService, Index: lams_tool_vote/src/java/org/lamsfoundation/lams/tool/vote/service/VoteService.java =================================================================== diff -u --- lams_tool_vote/src/java/org/lamsfoundation/lams/tool/vote/service/VoteService.java (revision 0) +++ lams_tool_vote/src/java/org/lamsfoundation/lams/tool/vote/service/VoteService.java (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -0,0 +1,2042 @@ +/*************************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * ***********************************************************************/ + +package org.lamsfoundation.lams.tool.vote.service; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedMap; +import java.util.SortedSet; +import java.util.TimeZone; +import java.util.TreeMap; +import java.util.TreeSet; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; +import org.apache.tomcat.util.json.JSONArray; +import org.apache.tomcat.util.json.JSONException; +import org.apache.tomcat.util.json.JSONObject; +import org.lamsfoundation.lams.contentrepository.client.IToolContentHandler; +import org.lamsfoundation.lams.learning.service.ILearnerService; +import org.lamsfoundation.lams.learningdesign.DataFlowObject; +import org.lamsfoundation.lams.learningdesign.dao.IDataFlowDAO; +import org.lamsfoundation.lams.learningdesign.service.ExportToolContentException; +import org.lamsfoundation.lams.learningdesign.service.IExportToolContentService; +import org.lamsfoundation.lams.learningdesign.service.ImportToolContentException; +import org.lamsfoundation.lams.notebook.model.NotebookEntry; +import org.lamsfoundation.lams.notebook.service.CoreNotebookConstants; +import org.lamsfoundation.lams.notebook.service.ICoreNotebookService; +import org.lamsfoundation.lams.rest.RestTags; +import org.lamsfoundation.lams.rest.ToolRestManager; +import org.lamsfoundation.lams.tool.IToolVO; +import org.lamsfoundation.lams.tool.SimpleURL; +import org.lamsfoundation.lams.tool.ToolCompletionStatus; +import org.lamsfoundation.lams.tool.ToolContentManager; +import org.lamsfoundation.lams.tool.ToolOutput; +import org.lamsfoundation.lams.tool.ToolOutputDefinition; +import org.lamsfoundation.lams.tool.ToolSessionExportOutputData; +import org.lamsfoundation.lams.tool.ToolSessionManager; +import org.lamsfoundation.lams.tool.exception.DataMissingException; +import org.lamsfoundation.lams.tool.exception.ToolException; +import org.lamsfoundation.lams.tool.service.ILamsToolService; +import org.lamsfoundation.lams.tool.vote.VoteAppConstants; +import org.lamsfoundation.lams.tool.vote.dao.IVoteContentDAO; +import org.lamsfoundation.lams.tool.vote.dao.IVoteQueContentDAO; +import org.lamsfoundation.lams.tool.vote.dao.IVoteSessionDAO; +import org.lamsfoundation.lams.tool.vote.dao.IVoteUserDAO; +import org.lamsfoundation.lams.tool.vote.dao.IVoteUsrAttemptDAO; +import org.lamsfoundation.lams.tool.vote.dto.OpenTextAnswerDTO; +import org.lamsfoundation.lams.tool.vote.dto.ReflectionDTO; +import org.lamsfoundation.lams.tool.vote.dto.SessionDTO; +import org.lamsfoundation.lams.tool.vote.dto.SessionNominationDTO; +import org.lamsfoundation.lams.tool.vote.dto.SummarySessionDTO; +import org.lamsfoundation.lams.tool.vote.dto.VoteGeneralLearnerFlowDTO; +import org.lamsfoundation.lams.tool.vote.dto.VoteMonitoredAnswersDTO; +import org.lamsfoundation.lams.tool.vote.dto.VoteMonitoredUserDTO; +import org.lamsfoundation.lams.tool.vote.dto.VoteQuestionDTO; +import org.lamsfoundation.lams.tool.vote.dto.VoteStatsDTO; +import org.lamsfoundation.lams.tool.vote.pojos.VoteContent; +import org.lamsfoundation.lams.tool.vote.pojos.VoteQueContent; +import org.lamsfoundation.lams.tool.vote.pojos.VoteQueUsr; +import org.lamsfoundation.lams.tool.vote.pojos.VoteSession; +import org.lamsfoundation.lams.tool.vote.pojos.VoteUsrAttempt; +import org.lamsfoundation.lams.tool.vote.util.VoteApplicationException; +import org.lamsfoundation.lams.tool.vote.util.VoteComparator; +import org.lamsfoundation.lams.tool.vote.util.VoteUtils; +import org.lamsfoundation.lams.tool.vote.web.action.MonitoringAction; +import org.lamsfoundation.lams.usermanagement.User; +import org.lamsfoundation.lams.usermanagement.dto.UserDTO; +import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; +import org.lamsfoundation.lams.util.JsonUtil; +import org.lamsfoundation.lams.util.MessageService; +import org.lamsfoundation.lams.util.audit.IAuditService; +import org.lamsfoundation.lams.web.session.SessionManager; +import org.lamsfoundation.lams.web.util.AttributeNames; +import org.springframework.dao.DataAccessException; + +/** + * The POJO implementation of Voting service. All business logic of Voting tool is implemented in this class. It + * translates the request from presentation layer and performs appropriate database operation. + * + * @author Ozgur Demirtas + */ +public class VoteService + implements IVoteService, ToolContentManager, ToolSessionManager, VoteAppConstants, ToolRestManager { + private static Logger logger = Logger.getLogger(VoteService.class.getName()); + + private IVoteContentDAO voteContentDAO; + private IVoteQueContentDAO voteQueContentDAO; + private IVoteSessionDAO voteSessionDAO; + private IVoteUserDAO voteUserDAO; + private IVoteUsrAttemptDAO voteUsrAttemptDAO; + + private IUserManagementService userManagementService; + private ILearnerService learnerService; + private IAuditService auditService; + private ILamsToolService toolService; + private IExportToolContentService exportContentService; + + private ICoreNotebookService coreNotebookService; + private IToolContentHandler voteToolContentHandler = null; + private VoteOutputFactory voteOutputFactory; + private IDataFlowDAO dataFlowDAO; + + private MessageService messageService; + + public VoteService() { + } + + @Override + public boolean isUserGroupLeader(VoteQueUsr user, Long toolSessionId) { + + VoteSession session = getSessionBySessionId(toolSessionId); + VoteQueUsr groupLeader = session.getGroupLeader(); + boolean isUserLeader = (groupLeader != null) && user.getUid().equals(groupLeader.getUid()); + return isUserLeader; + } + + @Override + public VoteQueUsr checkLeaderSelectToolForSessionLeader(VoteQueUsr user, Long toolSessionId) { + if ((user == null) || (toolSessionId == null)) { + logger.info("user" + user + "or" + "toolSessionId" + toolSessionId + "is null"); + return null; + } + + VoteSession session = getSessionBySessionId(toolSessionId); + VoteQueUsr leader = session.getGroupLeader(); + // check leader select tool for a leader only in case QA tool doesn't know it. As otherwise it will screw + // up previous scratches done + if (leader == null) { + if (logger.isDebugEnabled()) { + logger.debug("If QA tool does not know it checking leader select tool for leader only" + leader); + } + Long leaderUserId = toolService.getLeaderUserId(toolSessionId, user.getQueUsrId().intValue()); + if (leaderUserId != null) { + + leader = getVoteUserBySession(leaderUserId, session.getUid()); + + // create new user in a DB + if (leader == null) { + if (logger.isDebugEnabled()) { + logger.debug("creating new user with userId: " + leaderUserId); + } + User leaderDto = (User) getUserManagementService().findById(User.class, leaderUserId.intValue()); + String userName = leaderDto.getLogin(); + String fullName = leaderDto.getFirstName() + " " + leaderDto.getLastName(); + leader = new VoteQueUsr(leaderUserId, userName, fullName, session, new TreeSet()); + voteUserDAO.saveVoteUser(user); + } + + // set group leader + session.setGroupLeader(leader); + voteSessionDAO.updateVoteSession(session); + } + } + + return leader; + } + + @Override + public void copyAnswersFromLeader(VoteQueUsr user, VoteQueUsr leader) { + + if ((user == null) || (leader == null) || user.getUid().equals(leader.getUid())) { + if (logger.isDebugEnabled()) { + logger.debug("User" + user + "or" + "leader" + leader + "or Userid and Leaderid is equal"); + return; + } + } + + List leaderAttempts = this.getAttemptsForUser(leader.getUid()); + List userAttempts = this.getAttemptsForUser(user.getUid()); + + for (VoteUsrAttempt leaderAttempt : leaderAttempts) { + + VoteQueContent question = leaderAttempt.getVoteQueContent(); + Date attempTime = leaderAttempt.getAttemptTime(); + String timeZone = leaderAttempt.getTimeZone(); + String userEntry = leaderAttempt.getUserEntry(); + + VoteUsrAttempt userAttempt = null; + for (VoteUsrAttempt userAttemptDb : userAttempts) { + if (userAttemptDb.getUid().equals(leaderAttempt.getUid())) { + userAttempt = userAttemptDb; + } + } + + // if response doesn't exist - create VoteUsrAttempt in the db + if (userAttempt == null) { + logger.info("Response does not exist hence creating VoteUsrAttempt in db"); + VoteUsrAttempt voteUsrAttempt = new VoteUsrAttempt(attempTime, timeZone, question, user, userEntry, + true); + voteUsrAttemptDAO.saveVoteUsrAttempt(voteUsrAttempt); + + // if it's been changed by the leader + } else if (leaderAttempt.getAttemptTime().compareTo(userAttempt.getAttemptTime()) != 0) { + logger.info("Incase of the change done by the leader"); + userAttempt.setUserEntry(userEntry); + userAttempt.setAttemptTime(attempTime); + userAttempt.setTimeZone(timeZone); + this.updateVoteUsrAttempt(userAttempt); + + // remove userAttempt from the list so we can know which one is redundant(presumably, leader has removed + // this one) + if (logger.isDebugEnabled()) { + logger.debug("Leader has removed the userAttempt" + userAttempt); + } + userAttempts.remove(userAttempt); + } + } + + // remove redundant ones + for (VoteUsrAttempt redundantUserAttempt : userAttempts) { + voteUsrAttemptDAO.removeVoteUsrAttempt(redundantUserAttempt); + } + } + + @Override + public VoteGeneralLearnerFlowDTO prepareChartData(HttpServletRequest request, Long toolContentID, + Long toolSessionUid, VoteGeneralLearnerFlowDTO voteGeneralLearnerFlowDTO) { + + VoteContent voteContent = this.getVoteContent(toolContentID); + + int entriesCount = 0; + List userEntries = null; + if (toolSessionUid != null) { + entriesCount = voteUsrAttemptDAO.getSessionEntriesCount(toolSessionUid); + if (voteContent.isAllowText()) { + userEntries = voteUsrAttemptDAO.getSessionOpenTextUserEntries(toolSessionUid); + } else { + userEntries = new ArrayList(0); + } + } + + Long mapIndex = 1L; + int totalStandardVotesCount = 0; + + Map mapStandardUserCount = new TreeMap(new VoteComparator()); + Map mapStandardNominationsHTMLedContent = new TreeMap(new VoteComparator()); + Map mapStandardQuestionUid = new TreeMap(new VoteComparator()); + Map mapStandardToolSessionUid = new TreeMap(new VoteComparator()); + Map mapStandardNominationsContent = new TreeMap(new VoteComparator()); + Map mapVoteRates = new TreeMap(new VoteComparator()); + + for (VoteQueContent question : (Set) voteContent.getVoteQueContents()) { + + mapStandardNominationsHTMLedContent.put(mapIndex, question.getQuestion()); + String noHTMLNomination = VoteUtils.stripHTML(question.getQuestion()); + mapStandardNominationsContent.put(mapIndex, noHTMLNomination); + + int votesCount = voteUsrAttemptDAO.getStandardAttemptsForQuestionContentAndSessionUid(question.getUid(), + toolSessionUid); + totalStandardVotesCount += votesCount; + mapStandardUserCount.put(mapIndex, new Long(votesCount)); + + mapStandardQuestionUid.put(mapIndex, question.getUid()); + mapStandardToolSessionUid.put(mapIndex, toolSessionUid); + + Double voteRate = (entriesCount != 0) ? ((votesCount * 100) / entriesCount) : 0d; + mapVoteRates.put(mapIndex, voteRate); + + // mapIndex++ + mapIndex = new Long(mapIndex + 1); + } + + // open votes + if (voteContent.isAllowText()) { + int userEnteredVotesCount = entriesCount - totalStandardVotesCount; + Double voteRate = (userEnteredVotesCount != 0) ? ((userEnteredVotesCount * 100) / entriesCount) : 0d; + mapVoteRates.put(mapIndex, voteRate); + + mapStandardNominationsContent.put(mapIndex, messageService.getMessage("label.open.vote")); + mapStandardNominationsHTMLedContent.put(mapIndex, messageService.getMessage("label.open.vote")); + mapStandardUserCount.put(mapIndex, new Long(userEnteredVotesCount)); + /** following are needed just for proper iteration in the summary jsp */ + mapStandardQuestionUid.put(mapIndex, 1L); + mapStandardToolSessionUid.put(mapIndex, 1L); + } + + voteGeneralLearnerFlowDTO.setMapStandardNominationsContent(mapStandardNominationsContent); + voteGeneralLearnerFlowDTO.setMapStandardNominationsHTMLedContent(mapStandardNominationsHTMLedContent); + voteGeneralLearnerFlowDTO.setMapStandardRatesContent(mapVoteRates); + voteGeneralLearnerFlowDTO.setMapStandardUserCount(mapStandardUserCount); + voteGeneralLearnerFlowDTO.setMapStandardToolSessionUid(mapStandardToolSessionUid); + voteGeneralLearnerFlowDTO.setMapStandardQuestionUid(mapStandardQuestionUid); + request.setAttribute(VoteAppConstants.VOTE_GENERAL_LEARNER_FLOW_DTO, voteGeneralLearnerFlowDTO); + + request.setAttribute(VoteAppConstants.LIST_USER_ENTRIES_CONTENT, userEntries); + + // return value is only used in VoteChartGeneratorAction + return voteGeneralLearnerFlowDTO; + } + + @SuppressWarnings("unused") + @Override + public LinkedList getSessionDTOs(Long toolContentID) { + + LinkedList sessionDTOs = new LinkedList(); + + VoteContent voteContent = this.getVoteContent(toolContentID); + for (VoteSession session : (Set) voteContent.getVoteSessions()) { + + SessionDTO sessionDTO = new SessionDTO(); + sessionDTO.setSessionId(session.getVoteSessionId().toString()); + sessionDTO.setSessionName(session.getSession_name()); + + int entriesCount = voteUsrAttemptDAO.getSessionEntriesCount(session.getUid()); + + Long mapIndex = 1L; + int totalStandardVotesCount = 0; + + Map mapVoteRates = new TreeMap(new VoteComparator()); + Map mapStandardUserCount = new TreeMap(new VoteComparator()); + Map mapStandardNominationsHTMLedContent = new TreeMap(new VoteComparator()); + Map mapStandardQuestionUid = new TreeMap(new VoteComparator()); + Map mapStandardToolSessionUid = new TreeMap(new VoteComparator()); + + for (VoteQueContent question : (Set) voteContent.getVoteQueContents()) { + mapStandardNominationsHTMLedContent.put(mapIndex, question.getQuestion()); + + int votesCount = voteUsrAttemptDAO.getStandardAttemptsForQuestionContentAndSessionUid(question.getUid(), + session.getUid()); + totalStandardVotesCount += votesCount; + mapStandardUserCount.put(mapIndex, new Long(votesCount)); + + mapStandardQuestionUid.put(mapIndex, question.getUid()); + mapStandardToolSessionUid.put(mapIndex, session.getUid()); + + Double voteRate = (entriesCount != 0) ? ((votesCount * 100) / entriesCount) : 0d; + mapVoteRates.put(mapIndex, voteRate); + + // mapIndex++ + mapIndex = new Long(mapIndex + 1); + } + + // open votes + if (voteContent.isAllowText()) { + int userEnteredVotesCount = entriesCount - totalStandardVotesCount; + Double voteRate = (userEnteredVotesCount != 0) ? ((userEnteredVotesCount * 100) / entriesCount) : 0d; + mapVoteRates.put(mapIndex, voteRate); + + mapStandardNominationsHTMLedContent.put(mapIndex, messageService.getMessage("label.open.vote")); + mapStandardUserCount.put(mapIndex, new Long(userEnteredVotesCount)); + /** following are needed just for proper iteration in the summary jsp */ + mapStandardQuestionUid.put(mapIndex, 1L); + mapStandardToolSessionUid.put(mapIndex, 1L); + } + + sessionDTO.setMapStandardNominationsHTMLedContent(mapStandardNominationsHTMLedContent); + sessionDTO.setMapStandardUserCount(mapStandardUserCount); + sessionDTO.setMapStandardRatesContent(mapVoteRates); + sessionDTO.setMapStandardQuestionUid(mapStandardQuestionUid); + sessionDTO.setMapStandardToolSessionUid(mapStandardToolSessionUid); + + List openVotes = this.getOpenVotes(voteContent.getUid(), + session.getVoteSessionId(), null); + sessionDTO.setOpenVotes(openVotes); + boolean isExistsOpenVote = openVotes.size() > 0; + sessionDTO.setExistsOpenVote(isExistsOpenVote); + + sessionDTOs.add(sessionDTO); + } + + // All groups total + if (sessionDTOs.size() > 1) { + SessionDTO totalSessionDTO = new SessionDTO(); + totalSessionDTO.setSessionId("0"); + totalSessionDTO.setSessionName(messageService.getMessage("label.all.groups.total")); + + List totalOpenVotes = new ArrayList(); + int totalPotentialUserCount = 0; + int totalCompletedSessionUserCount = 0; + int allSessionsVotesCount = 0; + Map totalMapStandardUserCount = new TreeMap(new VoteComparator()); + for (SessionDTO sessionDTO : sessionDTOs) { + + totalPotentialUserCount += sessionDTO.getSessionUserCount(); + totalCompletedSessionUserCount += sessionDTO.getCompletedSessionUserCount(); + + Long mapIndex = 1L; + for (VoteQueContent question : (Set) voteContent.getVoteQueContents()) { + Long votesCount = sessionDTO.getMapStandardUserCount().get(mapIndex); + Long oldTotalVotesCount = (totalMapStandardUserCount.get(mapIndex) != null) + ? totalMapStandardUserCount.get(mapIndex) : 0L; + totalMapStandardUserCount.put(mapIndex, oldTotalVotesCount + votesCount); + + allSessionsVotesCount += votesCount; + + // mapIndex++ + mapIndex = new Long(mapIndex + 1); + } + + // open votes + if (voteContent.isAllowText()) { + Long votesCount = sessionDTO.getMapStandardUserCount().get(mapIndex); + Long oldTotalVotesCount = (totalMapStandardUserCount.get(mapIndex) != null) + ? totalMapStandardUserCount.get(mapIndex) : 0L; + totalMapStandardUserCount.put(mapIndex, oldTotalVotesCount + votesCount); + + allSessionsVotesCount += votesCount; + } + + totalOpenVotes.addAll(sessionDTO.getOpenVotes()); + } + totalSessionDTO.setSessionUserCount(totalPotentialUserCount); + totalSessionDTO.setCompletedSessionUserCount(totalCompletedSessionUserCount); + totalSessionDTO.setOpenVotes(totalOpenVotes); + boolean isExistsOpenVote = totalOpenVotes.size() > 0; + totalSessionDTO.setExistsOpenVote(isExistsOpenVote); + totalSessionDTO.setMapStandardNominationsHTMLedContent( + sessionDTOs.get(0).getMapStandardNominationsHTMLedContent()); + totalSessionDTO.setMapStandardQuestionUid(sessionDTOs.get(0).getMapStandardQuestionUid()); + totalSessionDTO.setMapStandardToolSessionUid(sessionDTOs.get(0).getMapStandardToolSessionUid()); + totalSessionDTO.setMapStandardUserCount(totalMapStandardUserCount); + + // All groups total -- totalMapVoteRates part + Long mapIndex = 1L; + Map totalMapVoteRates = new TreeMap(new VoteComparator()); + int totalStandardVotesCount = 0; + for (VoteQueContent question : (Set) voteContent.getVoteQueContents()) { + + Long votesCount = totalMapStandardUserCount.get(mapIndex); + + double voteRate = (allSessionsVotesCount != 0) ? ((votesCount * 100) / allSessionsVotesCount) : 0d; + totalMapVoteRates.put(mapIndex, voteRate); + + totalStandardVotesCount += votesCount; + + // mapIndex++ + mapIndex = new Long(mapIndex + 1); + } + // open votes + if (voteContent.isAllowText()) { + int userEnteredVotesCount = allSessionsVotesCount - totalStandardVotesCount; + double voteRate = (userEnteredVotesCount != 0) ? ((userEnteredVotesCount * 100) / allSessionsVotesCount) + : 0; + totalMapVoteRates.put(mapIndex, voteRate); + } + totalSessionDTO.setMapStandardRatesContent(totalMapVoteRates); + + sessionDTOs.addFirst(totalSessionDTO); + } + + return sessionDTOs; + } + + @Override + public SortedSet getMonitoringSessionDTOs(Long toolContentID) { + + SortedSet sessionDTOs = new TreeSet(); + + VoteContent voteContent = this.getVoteContent(toolContentID); + for (VoteSession session : (Set) voteContent.getVoteSessions()) { + + SummarySessionDTO sessionDTO = new SummarySessionDTO(); + sessionDTO.setSessionName(session.getSession_name()); + sessionDTO.setSessionUid(session.getUid()); + sessionDTO.setToolSessionId(session.getVoteSessionId()); + sessionDTO.setNominations(new TreeSet()); + + int entriesCount = voteUsrAttemptDAO.getSessionEntriesCount(session.getUid()); + + int totalStandardVotesCount = 0; + + for (VoteQueContent question : (Set) voteContent.getVoteQueContents()) { + + SessionNominationDTO nominationDTO = new SessionNominationDTO(); + nominationDTO.setQuestionUid(question.getUid()); + nominationDTO.setNomination(question.getQuestion()); + + int votesCount = voteUsrAttemptDAO.getStandardAttemptsForQuestionContentAndSessionUid(question.getUid(), + session.getUid()); + totalStandardVotesCount += votesCount; + + nominationDTO.setNumberOfVotes(votesCount); + nominationDTO.setPercentageOfVotes((entriesCount != 0) ? ((votesCount * 100) / entriesCount) : 0d); + sessionDTO.getNominations().add(nominationDTO); + + } + + // open votes + if (voteContent.isAllowText()) { + int userEnteredVotesCount = entriesCount - totalStandardVotesCount; + Double voteRate = (userEnteredVotesCount != 0) ? ((userEnteredVotesCount * 100) / entriesCount) : 0d; + sessionDTO.setOpenTextNumberOfVotes(userEnteredVotesCount); + sessionDTO.setOpenTextPercentageOfVotes(voteRate); + } else { + sessionDTO.setOpenTextNumberOfVotes(0); + sessionDTO.setOpenTextPercentageOfVotes(0D); + } + + sessionDTOs.add(sessionDTO); + } + + // All groups total + if (sessionDTOs.size() > 1) { + SummarySessionDTO totalSessionDTO = new SummarySessionDTO(); + totalSessionDTO.setSessionUid(0L); + totalSessionDTO.setToolSessionId(0L); + totalSessionDTO.setSessionName(messageService.getMessage("label.all.groups.total")); + totalSessionDTO.setNominations(new TreeSet()); + + HashMap nominationsTotals = new HashMap(); + int totalOpenVotes = 0; + int totalVotes = 0; + for (SummarySessionDTO sessionDTO : sessionDTOs) { + + for (SessionNominationDTO nomination : sessionDTO.getNominations()) { + Long questionUid = nomination.getQuestionUid(); + SessionNominationDTO dto = nominationsTotals.get(questionUid); + if (dto == null) { + dto = new SessionNominationDTO(); + dto.setQuestionUid(questionUid); + dto.setNomination(nomination.getNomination()); + dto.setNumberOfVotes(0); + nominationsTotals.put(questionUid, dto); + totalSessionDTO.getNominations().add(dto); + } + totalVotes += nomination.getNumberOfVotes(); + dto.setNumberOfVotes(dto.getNumberOfVotes() + nomination.getNumberOfVotes()); + } + + totalVotes += sessionDTO.getOpenTextNumberOfVotes(); + totalOpenVotes += sessionDTO.getOpenTextNumberOfVotes(); + } + for (SessionNominationDTO nomination : totalSessionDTO.getNominations()) { + nomination.setPercentageOfVotes( + (totalVotes != 0) ? ((nomination.getNumberOfVotes() * 100) / totalVotes) : 0d); + } + totalSessionDTO.setOpenTextNumberOfVotes(totalOpenVotes); + totalSessionDTO + .setOpenTextPercentageOfVotes((totalVotes != 0) ? ((totalOpenVotes * 100) / totalVotes) : 0d); + sessionDTOs.add(totalSessionDTO); + } + + return sessionDTOs; + } + + /** + * Get the count of all the potential learners for the vote session. This will include the people that have never + * logged into the lesson. Not great, but it is a better estimate of how many users there will be eventually than + * the number of people already known to the tool. + * + * @param voteSessionId + * The tool session id + */ + private int getVoteSessionPotentialLearnersCount(Long sessionUid) { + VoteSession session = voteSessionDAO.getVoteSessionByUID(sessionUid); + if (session != null) { + return toolService.getCountUsersForActivity(session.getVoteSessionId()); + } else { + logger.error("Unable to find vote session record id=" + sessionUid + ". Returning 0 users."); + return 0; + } + } + + @Override + public List getOpenVotes(Long voteContentUid, Long currentSessionId, Long userId) { + Set userEntries = voteUsrAttemptDAO.getUserEntries(voteContentUid); + + List monitoredAnswersDTOs = new LinkedList(); + for (String userEntry : userEntries) { + + if ((userEntry == null) || (userEntry.length() == 0)) { + continue; + } + + VoteMonitoredAnswersDTO voteMonitoredAnswersDTO = new VoteMonitoredAnswersDTO(); + voteMonitoredAnswersDTO.setQuestion(userEntry); + + List userAttempts = voteUsrAttemptDAO.getUserAttempts(voteContentUid, userEntry); + List monitoredUserContainerDTOs = new LinkedList(); + + for (VoteUsrAttempt voteUsrAttempt : userAttempts) { + VoteMonitoredUserDTO voteMonitoredUserDTO = new VoteMonitoredUserDTO(); + + if (currentSessionId == null) { + voteMonitoredUserDTO.setAttemptTime(voteUsrAttempt.getAttemptTime()); + voteMonitoredUserDTO.setTimeZone(voteUsrAttempt.getTimeZone()); + voteMonitoredUserDTO.setUserName(voteUsrAttempt.getVoteQueUsr().getFullname()); + voteMonitoredUserDTO.setQueUsrId(voteUsrAttempt.getVoteQueUsr().getUid().toString()); + voteMonitoredUserDTO.setUserEntry(voteUsrAttempt.getUserEntry()); + voteMonitoredUserDTO.setUid(voteUsrAttempt.getUid().toString()); + voteMonitoredUserDTO.setVisible(new Boolean(voteUsrAttempt.isVisible()).toString()); + monitoredUserContainerDTOs.add(voteMonitoredUserDTO); + + } else { + // showUserEntriesBySession is true: the case with learner export portfolio + // show user entries by same same session and same user + Long userSessionId = voteUsrAttempt.getVoteQueUsr().getVoteSession().getVoteSessionId(); + + if (userId != null) { + if (userSessionId.equals(currentSessionId)) { + Long localUserId = voteUsrAttempt.getVoteQueUsr().getQueUsrId(); + if (userId.equals(localUserId)) { + voteMonitoredUserDTO.setAttemptTime(voteUsrAttempt.getAttemptTime()); + voteMonitoredUserDTO.setTimeZone(voteUsrAttempt.getTimeZone()); + voteMonitoredUserDTO.setUserName(voteUsrAttempt.getVoteQueUsr().getFullname()); + voteMonitoredUserDTO.setQueUsrId(voteUsrAttempt.getVoteQueUsr().getUid().toString()); + voteMonitoredUserDTO.setUserEntry(voteUsrAttempt.getUserEntry()); + monitoredUserContainerDTOs.add(voteMonitoredUserDTO); + voteMonitoredUserDTO.setUid(voteUsrAttempt.getUid().toString()); + voteMonitoredUserDTO.setVisible(new Boolean(voteUsrAttempt.isVisible()).toString()); + if (voteUsrAttempt.isVisible() == false) { + voteMonitoredAnswersDTO.setQuestion("Nomination Hidden"); + } + + } + } + } else { + // showUserEntriesByUserId is false + // show user entries by same session + if (userSessionId.equals(currentSessionId)) { + voteMonitoredUserDTO.setAttemptTime(voteUsrAttempt.getAttemptTime()); + voteMonitoredUserDTO.setTimeZone(voteUsrAttempt.getTimeZone()); + voteMonitoredUserDTO.setUserName(voteUsrAttempt.getVoteQueUsr().getFullname()); + voteMonitoredUserDTO.setQueUsrId(voteUsrAttempt.getVoteQueUsr().getUid().toString()); + voteMonitoredUserDTO.setUserEntry(voteUsrAttempt.getUserEntry()); + monitoredUserContainerDTOs.add(voteMonitoredUserDTO); + voteMonitoredUserDTO.setUid(voteUsrAttempt.getUid().toString()); + voteMonitoredUserDTO.setVisible(new Boolean(voteUsrAttempt.isVisible()).toString()); + } + } + } + + } + + if (monitoredUserContainerDTOs.size() > 0) { + Map mapMonitoredUserContainerDTO = MonitoringAction + .convertToVoteMonitoredUserDTOMap(monitoredUserContainerDTOs); + + voteMonitoredAnswersDTO.setQuestionAttempts(mapMonitoredUserContainerDTO); + monitoredAnswersDTOs.add(voteMonitoredAnswersDTO); + } + } + + return monitoredAnswersDTOs; + } + + @Override + public List getReflectionData(VoteContent voteContent, Long userID) { + List reflectionsContainerDTO = new LinkedList(); + + if (userID == null) { + for (Iterator sessionIter = voteContent.getVoteSessions().iterator(); sessionIter.hasNext();) { + VoteSession voteSession = sessionIter.next(); + + for (Iterator userIter = voteSession.getVoteQueUsers().iterator(); userIter.hasNext();) { + VoteQueUsr user = userIter.next(); + + NotebookEntry notebookEntry = this.getEntry(voteSession.getVoteSessionId(), + CoreNotebookConstants.NOTEBOOK_TOOL, VoteAppConstants.MY_SIGNATURE, + new Integer(user.getQueUsrId().toString())); + + if (notebookEntry != null) { + ReflectionDTO reflectionDTO = new ReflectionDTO(); + reflectionDTO.setUserId(user.getQueUsrId().toString()); + reflectionDTO.setSessionId(voteSession.getVoteSessionId().toString()); + reflectionDTO.setUserName(user.getFullname()); + reflectionDTO.setReflectionUid(notebookEntry.getUid().toString()); + // String notebookEntryPresentable = VoteUtils.replaceNewLines(notebookEntry.getEntry()); + reflectionDTO.setEntry(notebookEntry.getEntry()); + reflectionsContainerDTO.add(reflectionDTO); + } + } + } + } else { + for (Iterator sessionIter = voteContent.getVoteSessions().iterator(); sessionIter.hasNext();) { + VoteSession voteSession = sessionIter.next(); + for (Iterator userIter = voteSession.getVoteQueUsers().iterator(); userIter.hasNext();) { + VoteQueUsr user = userIter.next(); + if (user.getQueUsrId().equals(userID)) { + NotebookEntry notebookEntry = this.getEntry(voteSession.getVoteSessionId(), + CoreNotebookConstants.NOTEBOOK_TOOL, VoteAppConstants.MY_SIGNATURE, + new Integer(user.getQueUsrId().toString())); + + if (notebookEntry != null) { + ReflectionDTO reflectionDTO = new ReflectionDTO(); + reflectionDTO.setUserId(user.getQueUsrId().toString()); + reflectionDTO.setSessionId(voteSession.getVoteSessionId().toString()); + reflectionDTO.setUserName(user.getFullname()); + reflectionDTO.setReflectionUid(notebookEntry.getUid().toString()); + // String notebookEntryPresentable = VoteUtils.replaceNewLines(notebookEntry.getEntry()); + reflectionDTO.setEntry(notebookEntry.getEntry()); + reflectionsContainerDTO.add(reflectionDTO); + } + } + } + } + } + + return reflectionsContainerDTO; + } + + @Override + public VoteContent getVoteContent(Long toolContentID) { + return voteContentDAO.getVoteContentByContentId(toolContentID); + } + + @Override + public VoteQueContent getQuestionByDisplayOrder(final Long displayOrder, final Long voteContentUid) { + return voteQueContentDAO.getQuestionByDisplayOrder(displayOrder, voteContentUid); + } + + @Override + public VoteQueUsr getUserById(long voteQueUsrId) { + VoteQueUsr voteQueUsr = voteUserDAO.getVoteQueUsrById(voteQueUsrId); + return voteQueUsr; + } + + @Override + public List getAttemptsForQuestionContentAndSessionUid(final Long questionUid, + final Long voteSessionUid) { + return voteUsrAttemptDAO.getAttemptsForQuestionContentAndSessionUid(questionUid, voteSessionUid); + } + + @Override + public Set getAttemptsForUserAndSessionUseOpenAnswer(final Long userUid, final Long sessionUid) { + List list = voteUsrAttemptDAO.getAttemptsForUserAndSessionUseOpenAnswer(userUid, sessionUid); + + //String openAnswer = ""; + Set userEntries = new HashSet(); + if ((list != null) && (list.size() > 0)) { + Iterator listIterator = list.iterator(); + while (listIterator.hasNext()) { + VoteUsrAttempt attempt = listIterator.next(); + + Long questionUid = attempt.getVoteQueContent().getUid(); + if (!questionUid.toString().equals("1")) { + userEntries.add(attempt.getVoteQueContent().getQuestion()); + } else { + // this is a user entered vote + if (attempt.getUserEntry().length() > 0) { + if (attempt.isVisible()) { + userEntries.add(attempt.getUserEntry()); + } else { + userEntries.add(getMessageService().getMessage("label.hidden")); + } + } + + } + } + } + return userEntries; + } + + @Override + public Set getAttemptsForUserAndSession(final Long queUsrUid, final Long sessionUid) { + return voteUsrAttemptDAO.getAttemptsForUserAndSession(queUsrUid, sessionUid); + } + + @Override + public VoteQueContent getVoteQueContentByUID(Long uid) { + if (uid == null) { + return null; + } + + return voteQueContentDAO.getQuestionByUid(uid); + } + + @Override + public void saveOrUpdateVoteQueContent(VoteQueContent voteQueContent) { + voteQueContentDAO.saveOrUpdateQuestion(voteQueContent); + } + + @Override + public VoteContent createQuestions(List questionDTOs, VoteContent voteContent) { + + int displayOrder = 0; + for (VoteQuestionDTO questionDTO : questionDTOs) { + String currentQuestionText = questionDTO.getQuestion(); + + // skip empty questions + if (currentQuestionText.isEmpty()) { + continue; + } + + ++displayOrder; + + VoteQueContent question = getVoteQueContentByUID(questionDTO.getUid()); + + // in case question doesn't exist + if (question == null) { + question = new VoteQueContent(currentQuestionText, displayOrder, voteContent); + // adding a new question to content + if (logger.isDebugEnabled()) { + logger.debug("Adding a new question to content" + question); + } + voteContent.getVoteQueContents().add(question); + question.setVoteContent(voteContent); + + // in case question exists already + } else { + + question.setQuestion(currentQuestionText); + question.setDisplayOrder(displayOrder); + } + + saveOrUpdateVoteQueContent(question); + } + + return voteContent; + } + + @Override + public Map buildQuestionMap(VoteContent voteContent, Collection checkedOptions) { + Map mapQuestionsContent = new TreeMap(new VoteComparator()); + Set questions = voteContent.getVoteQueContents(); + + // should we add questions from data flow from other activities? + if (Boolean.TRUE.equals(voteContent.getAssignedDataFlowObject()) + && ((voteContent.getMaxExternalInputs() == null) || (voteContent.getExternalInputsAdded() == null) + || (voteContent.getExternalInputsAdded() < voteContent.getMaxExternalInputs()))) { + // If we are using tool input, we need to get it now and + // create questions. Once they are created, they will be not altered, no matter if another learner gets to + // this point and the tool input changed + HttpSession ss = SessionManager.getSession(); + UserDTO toolUser = (UserDTO) ss.getAttribute(AttributeNames.USER); + long userId = toolUser.getUserID().longValue(); + + // We get whatever the source tool provides us with and try to create questions out of it + ToolOutput toolInput = getToolInput(voteContent.getVoteContentId(), new Long(userId).intValue()); + + Object value = toolInput.getValue().getComplex(); + short inputsAdded = voteContent.getExternalInputsAdded() == null ? 0 : voteContent.getExternalInputsAdded(); + Short maxInputs = voteContent.getMaxExternalInputs(); + Set existingNominations = voteContent.getVoteQueContents(); + // The input is an array (users) of arrays of strings (their answers) + if (value instanceof String[][]) { + if (value != null) { + String[][] usersAndAnswers = (String[][]) value; + int nominationIndex = voteContent.getVoteQueContents().size() + 1; + for (String[] userAnswers : usersAndAnswers) { + if (userAnswers != null) { + if ((maxInputs != null) && (inputsAdded >= maxInputs)) { + // if we reached the maximum number of inputs, i.e. number of students that will be + // taken + // into account + logger.info( + "We have reached max no of inputs,i.e number of students will be taken into account"); + break; + } + boolean anyAnswersAdded = false; + for (String questionText : userAnswers) { + if (!StringUtils.isBlank(questionText)) { + VoteQueContent nomination = new VoteQueContent(); + nomination.setDisplayOrder(nominationIndex); + nomination.setMcContent(voteContent); + nomination.setQuestion(questionText); + if (!VoteService.isNominationExists(nomination, existingNominations)) { + saveOrUpdateVoteQueContent(nomination); + voteContent.getVoteQueContents().add(nomination); + nominationIndex++; + anyAnswersAdded = true; + } + } + } + if (anyAnswersAdded) { + inputsAdded++; + } + } + } + } + } else if (value instanceof String[]) { + // the input is a list of strings (questions, for example) + int nominationIndex = voteContent.getVoteQueContents().size() + 1; + String[] userAnswers = (String[]) value; + for (String questionText : userAnswers) { + if ((maxInputs != null) && (inputsAdded >= maxInputs)) { + logger.info( + "We have reached max no of inputs,i.e number of students will be taken into account"); + // if we reached the maximum number of inputs, i.e. number of students that will be taken + // into account + break; + } + + if (!StringUtils.isBlank(questionText)) { + VoteQueContent nomination = new VoteQueContent(); + nomination.setDisplayOrder(nominationIndex); + nomination.setMcContent(voteContent); + nomination.setQuestion(questionText); + if (!VoteService.isNominationExists(nomination, existingNominations)) { + saveOrUpdateVoteQueContent(nomination); + voteContent.getVoteQueContents().add(nomination); + nominationIndex++; + inputsAdded++; + } + } + } + } else if ((value instanceof String) && !StringUtils.isBlank((String) value)) { + int nominationIndex = voteContent.getVoteQueContents().size() + 1; + VoteQueContent nomination = new VoteQueContent(); + nomination.setDisplayOrder(nominationIndex); + nomination.setMcContent(voteContent); + nomination.setQuestion((String) value); + if (!VoteService.isNominationExists(nomination, existingNominations)) { + saveOrUpdateVoteQueContent(nomination); + voteContent.getVoteQueContents().add(nomination); + } + } + if (value instanceof SimpleURL[][]) { + if (value != null) { + SimpleURL[][] usersAndUrls = (SimpleURL[][]) value; + int nominationIndex = voteContent.getVoteQueContents().size() + 1; + for (SimpleURL[] userUrls : usersAndUrls) { + if (userUrls != null) { + if ((maxInputs != null) && (inputsAdded >= maxInputs)) { + logger.info( + "We have reached max no of inputs,i.e number of students will be taken into account"); + // if we reached the maximum number of inputs, i.e. number of students that will be + // taken + // into account + break; + } + boolean anyAnswersAdded = false; + for (SimpleURL url : userUrls) { + if (url != null) { + VoteQueContent nomination = new VoteQueContent(); + nomination.setDisplayOrder(nominationIndex); + nomination.setMcContent(voteContent); + + String link = "" + url.getNameToDisplay() + ""; + nomination.setQuestion(link); + if (!VoteService.isNominationExists(nomination, existingNominations)) { + saveOrUpdateVoteQueContent(nomination); + voteContent.getVoteQueContents().add(nomination); + nominationIndex++; + anyAnswersAdded = true; + } + } + } + if (anyAnswersAdded) { + inputsAdded++; + } + } + } + } + } + + else if (value instanceof SimpleURL[]) { + // the input is a list of strings (questions, for example) + int nominationIndex = voteContent.getVoteQueContents().size() + 1; + SimpleURL[] userUrls = (SimpleURL[]) value; + for (SimpleURL url : userUrls) { + if ((maxInputs != null) && (inputsAdded >= maxInputs)) { + // if we reached the maximum number of inputs, i.e. number of students that will be taken + // into account + break; + } + if (url != null) { + VoteQueContent nomination = new VoteQueContent(); + nomination.setDisplayOrder(nominationIndex); + nomination.setMcContent(voteContent); + + String link = "" + url.getNameToDisplay() + ""; + nomination.setQuestion(link); + if (!VoteService.isNominationExists(nomination, existingNominations)) { + saveOrUpdateVoteQueContent(nomination); + voteContent.getVoteQueContents().add(nomination); + nominationIndex++; + inputsAdded++; + } + } + } + } else if (value instanceof SimpleURL) { + int nominationIndex = voteContent.getVoteQueContents().size() + 1; + VoteQueContent nomination = new VoteQueContent(); + nomination.setDisplayOrder(nominationIndex); + + SimpleURL url = (SimpleURL) value; + String link = "" + url.getNameToDisplay() + ""; + nomination.setQuestion(link); + if (!VoteService.isNominationExists(nomination, existingNominations)) { + nomination.setMcContent(voteContent); + saveOrUpdateVoteQueContent(nomination); + voteContent.getVoteQueContents().add(nomination); + } + } + + voteContent.setExternalInputsAdded(inputsAdded); + saveVoteContent(voteContent); + questions = voteContent.getVoteQueContents(); + } + + for (VoteQueContent question : questions) { + String displayOrder = "" + question.getDisplayOrder(); + if (((checkedOptions == null) || checkedOptions.contains(displayOrder)) && !displayOrder.equals("0")) { + /* add the question to the questions Map in the displayOrder */ + mapQuestionsContent.put(displayOrder.toString(), question.getQuestion()); + } + } + + return mapQuestionsContent; + } + + private static boolean isNominationExists(VoteQueContent nomination, Set existingNominations) { + if ((existingNominations != null) && (nomination != null)) { + for (VoteQueContent existingNomination : existingNominations) { + if ((existingNomination.getQuestion() != null) + && existingNomination.getQuestion().equals(nomination.getQuestion())) { + return true; + } + } + } + return false; + } + + @Override + public List getUserBySessionOnly(final VoteSession voteSession) { + return voteUserDAO.getUserBySessionOnly(voteSession); + } + + @Override + public VoteSession getVoteSessionByUID(Long uid) { + return voteSessionDAO.getVoteSessionByUID(uid); + } + + @Override + public void createVoteQueUsr(VoteQueUsr voteQueUsr) { + voteUserDAO.saveVoteUser(voteQueUsr); + } + + @Override + public VoteQueUsr getVoteUserBySession(final Long queUsrId, final Long sessionUid) { + return voteUserDAO.getVoteUserBySession(queUsrId, sessionUid); + } + + @Override + public void updateVoteUser(VoteQueUsr voteUser) { + voteUserDAO.updateVoteUser(voteUser); + } + + @Override + public VoteQueUsr getUserByUserId(Long userID) { + VoteQueUsr voteQueUsr = voteUserDAO.getUserByUserId(userID); + return voteQueUsr; + } + + @Override + public VoteUsrAttempt getAttemptByUID(Long uid) { + return voteUsrAttemptDAO.getAttemptByUID(uid); + } + + @Override + public void updateVoteUsrAttempt(VoteUsrAttempt voteUsrAttempt) { + voteUsrAttemptDAO.updateVoteUsrAttempt(voteUsrAttempt); + } + + @Override + public void removeAttemptsForUserandSession(final Long queUsrId, final Long sessionUid) { + voteUsrAttemptDAO.removeAttemptsForUserandSession(queUsrId, sessionUid); + } + + @Override + public List getAttemptsForUser(final Long userUid) { + return voteUsrAttemptDAO.getAttemptsForUser(userUid); + } + + @Override + public void createAttempt(VoteQueUsr voteQueUsr, Map mapGeneralCheckedOptionsContent, + String userEntry, VoteSession voteSession, Long voteContentUid) { + + Date attempTime = new Date(System.currentTimeMillis()); + String timeZone = TimeZone.getDefault().getDisplayName(); + + //in case of free entry + if (mapGeneralCheckedOptionsContent.size() == 0) { + logger.info("In case of free entry"); + VoteQueContent defaultContentFirstQuestion = voteQueContentDAO.getDefaultVoteContentFirstQuestion(); + createAttempt(defaultContentFirstQuestion, voteQueUsr, attempTime, timeZone, userEntry, voteSession); + + //if the question is selected + } else if (voteContentUid != null) { + logger.info("In case of question is selected"); + + for (String key : mapGeneralCheckedOptionsContent.keySet()) { + Long questionDisplayOrder = new Long(key); + + VoteQueContent question = getQuestionByDisplayOrder(questionDisplayOrder, voteContentUid); + createAttempt(question, voteQueUsr, attempTime, timeZone, userEntry, voteSession); + } + } + + } + + private void createAttempt(VoteQueContent question, VoteQueUsr user, Date attempTime, String timeZone, + String userEntry, VoteSession session) { + + if (question != null) { + VoteUsrAttempt existingAttempt = voteUsrAttemptDAO.getAttemptForUserAndQuestionContentAndSession( + user.getQueUsrId(), question.getVoteContentId(), session.getUid()); + + if (existingAttempt != null) { + existingAttempt.setUserEntry(userEntry); + existingAttempt.setAttemptTime(attempTime); + existingAttempt.setTimeZone(timeZone); + updateVoteUsrAttempt(existingAttempt); + } else { + VoteUsrAttempt voteUsrAttempt = new VoteUsrAttempt(attempTime, timeZone, question, user, userEntry, + true); + voteUsrAttemptDAO.saveVoteUsrAttempt(voteUsrAttempt); + } + } + } + + @Override + public VoteQueContent getQuestionByUid(Long uid) { + return voteQueContentDAO.getQuestionByUid(uid); + } + + @Override + public void removeVoteQueContent(VoteQueContent voteQueContent) { + voteQueContentDAO.removeQuestion(voteQueContent); + } + + @Override + public VoteSession getSessionBySessionId(Long voteSessionId) { + return voteSessionDAO.getSessionBySessionId(voteSessionId); + } + + @Override + public void updateVote(VoteContent vote) { + voteContentDAO.updateVoteContent(vote); + } + + @Override + public int countSessionComplete() { + return voteSessionDAO.countSessionComplete(); + } + + /** + * logs hiding of a user entered vote + */ + @Override + public void hideOpenVote(VoteUsrAttempt voteUsrAttempt) { + auditService.logHideEntry(VoteAppConstants.MY_SIGNATURE, voteUsrAttempt.getQueUsrId(), + voteUsrAttempt.getVoteQueUsr().getUsername(), voteUsrAttempt.getUserEntry()); + } + + /** + * logs showing of a user entered vote + */ + @Override + public void showOpenVote(VoteUsrAttempt voteUsrAttempt) { + auditService.logShowEntry(VoteAppConstants.MY_SIGNATURE, voteUsrAttempt.getQueUsrId(), + voteUsrAttempt.getVoteQueUsr().getUsername(), voteUsrAttempt.getUserEntry()); + } + + @Override + public void saveVoteContent(VoteContent vote) { + voteContentDAO.saveVoteContent(vote); + } + + @Override + public List getSessionsFromContent(VoteContent voteContent) { + return voteSessionDAO.getSessionsFromContent(voteContent); + } + + @Override + public int getTotalNumberOfUsers() { + return voteUserDAO.getTotalNumberOfUsers(); + } + + @Override + public List getAttemptsForUserAndQuestionContent(final Long userUid, final Long questionUid) { + try { + return voteUsrAttemptDAO.getAttemptsForUserAndQuestionContent(userUid, questionUid); + } catch (DataAccessException e) { + throw new VoteApplicationException( + "Exception occured when lams is getting vote voteUsrRespDAO by user id and que content id: " + + e.getMessage(), + e); + } + } + + @Override + public boolean studentActivityOccurredGlobal(VoteContent voteContent) { + return !voteContent.getVoteSessions().isEmpty(); + } + + @Override + public void recalculateUserAnswers(VoteContent content, Set oldQuestions, + List questionDTOs, List deletedQuestions) { + + // create list of modified questions + List modifiedQuestions = new ArrayList(); + for (VoteQueContent oldQuestion : oldQuestions) { + for (VoteQuestionDTO questionDTO : questionDTOs) { + if (oldQuestion.getUid().equals(questionDTO.getUid())) { + + // question is different + if (!oldQuestion.getQuestion().equals(questionDTO.getQuestion())) { + modifiedQuestions.add(questionDTO); + } + } + } + } + + Set sessionList = content.getVoteSessions(); + for (VoteSession session : sessionList) { + Set sessionUsers = session.getVoteQueUsers(); + + for (VoteQueUsr user : sessionUsers) { + + // get all finished user results + List userAttempts = this.getAttemptsForUser(user.getUid()); + Iterator iter = userAttempts.iterator(); + while (iter.hasNext()) { + VoteUsrAttempt userAttempt = iter.next(); + + VoteQueContent question = userAttempt.getVoteQueContent(); + + boolean isRemoveQuestionResult = false; + + // [+] if the question is modified + for (VoteQuestionDTO modifiedQuestion : modifiedQuestions) { + if (question.getUid().equals(modifiedQuestion.getUid())) { + isRemoveQuestionResult = true; + break; + } + } + + // [+] if the question was removed + for (VoteQuestionDTO deletedQuestion : deletedQuestions) { + if (question.getUid().equals(deletedQuestion.getUid())) { + isRemoveQuestionResult = true; + break; + } + } + + if (isRemoveQuestionResult) { + iter.remove(); + voteUsrAttemptDAO.removeVoteUsrAttempt(userAttempt); + } + + // [+] doing nothing if the new question was added + + } + + } + } + + } + + @Override + public void copyToolContent(Long fromContentId, Long toContentId) throws ToolException { + if (logger.isDebugEnabled()) { + logger.debug("Copy tool content fromContentId" + fromContentId + " and toContentId " + toContentId); + } + if (fromContentId == null) { + // attempt retrieving tool's default content id with signatute VoteAppConstants.MY_SIGNATURE + long defaultContentId = getToolDefaultContentIdBySignature(VoteAppConstants.MY_SIGNATURE); + fromContentId = new Long(defaultContentId); + } + + if (toContentId == null) { + logger.error("throwing ToolException: toContentId is null"); + throw new ToolException("toContentId is missing"); + } + + VoteContent fromContent = voteContentDAO.getVoteContentByContentId(fromContentId); + + if (fromContent == null) { + // attempt retrieving tool's default content id with signatute VoteAppConstants.MY_SIGNATURE + long defaultContentId = getToolDefaultContentIdBySignature(VoteAppConstants.MY_SIGNATURE); + fromContentId = new Long(defaultContentId); + + fromContent = voteContentDAO.getVoteContentByContentId(fromContentId); + } + + VoteContent toContent = VoteContent.newInstance(fromContent, toContentId); + if (toContent == null) { + logger.error("throwing ToolException: WARNING!, retrieved toContent is null."); + throw new ToolException("WARNING! Fail to create toContent. Can't continue!"); + } else { + voteContentDAO.saveVoteContent(toContent); + } + } + + // @SuppressWarnings("unchecked") + @Override + public void removeToolContent(Long toolContentId) throws ToolException { + VoteContent voteContent = voteContentDAO.getVoteContentByContentId(toolContentId); + if (voteContent == null) { + logger.warn("Can not remove the tool content as it does not exist, ID: " + toolContentId); + return; + } + + for (VoteSession session : (Set) voteContent.getVoteSessions()) { + List entries = coreNotebookService.getEntry(session.getVoteSessionId(), + CoreNotebookConstants.NOTEBOOK_TOOL, VoteAppConstants.MY_SIGNATURE); + for (NotebookEntry entry : entries) { + coreNotebookService.deleteEntry(entry); + } + } + + voteContentDAO.delete(voteContent); + } + + // @SuppressWarnings("unchecked") + @Override + public void removeLearnerContent(Long toolContentId, Integer userId) throws ToolException { + if (logger.isDebugEnabled()) { + logger.debug("Removing Vote attempts for user ID " + userId + " and toolContentId " + toolContentId); + } + + VoteContent voteContent = voteContentDAO.getVoteContentByContentId(toolContentId); + if (voteContent == null) { + logger.warn("Did not find activity with toolContentId: " + toolContentId + " to remove learner content"); + return; + } + + for (VoteSession session : (Set) voteContent.getVoteSessions()) { + VoteQueUsr user = voteUserDAO.getVoteUserBySession(userId.longValue(), session.getUid()); + if (user != null) { + voteUsrAttemptDAO.removeAttemptsForUserandSession(user.getUid(), session.getUid()); + + NotebookEntry entry = getEntry(session.getVoteSessionId(), CoreNotebookConstants.NOTEBOOK_TOOL, + VoteAppConstants.MY_SIGNATURE, userId); + if (entry != null) { + voteContentDAO.delete(entry); + } + + voteUserDAO.removeVoteUser(user); + } + } + } + + @Override + public void exportToolContent(Long toolContentID, String rootPath) throws DataMissingException, ToolException { + VoteContent toolContentObj = voteContentDAO.getVoteContentByContentId(toolContentID); + if (toolContentObj == null) { + long defaultContentId = getToolDefaultContentIdBySignature(VoteAppConstants.MY_SIGNATURE); + toolContentObj = voteContentDAO.getVoteContentByContentId(defaultContentId); + } + + if (toolContentObj == null) { + logger.error("Unable to find default content for the voting tool"); + throw new DataMissingException("Unable to find default content for the voting tool"); + } + + try { + // set ToolContentHandler as null to avoid copy file node in repository again. + toolContentObj = VoteContent.newInstance(toolContentObj, toolContentID); + + // clear unnecessary information attach + toolContentObj.setVoteSessions(null); + exportContentService.exportToolContent(toolContentID, toolContentObj, voteToolContentHandler, rootPath); + } catch (ExportToolContentException e) { + throw new ToolException(e); + } + } + + @Override + public void importToolContent(Long toolContentID, Integer newUserUid, String toolContentPath, String fromVersion, + String toVersion) throws ToolException { + try { + if (logger.isDebugEnabled()) { + logger.debug("Import tool Content : newUserUid" + newUserUid + " and toolContentID " + toolContentID + + "and toolContentPath" + toolContentPath + "and fromVersion" + fromVersion + "and toVersion" + + toVersion); + } + + // register version filter class + exportContentService.registerImportVersionFilterClass(VoteImportContentVersionFilter.class); + + Object toolPOJO = exportContentService.importToolContent(toolContentPath, voteToolContentHandler, + fromVersion, toVersion); + if (!(toolPOJO instanceof VoteContent)) { + logger.error("Import Vote tool content failed. Deserialized object is " + toolPOJO); + throw new ImportToolContentException( + "Import Vote tool content failed. Deserialized object is " + toolPOJO); + } + VoteContent toolContentObj = (VoteContent) toolPOJO; + + // reset it to new toolContentID + toolContentObj.setVoteContentId(toolContentID); + toolContentObj.setCreatedBy(newUserUid); + + voteContentDAO.saveVoteContent(toolContentObj); + } catch (ImportToolContentException e) { + logger.error("Error importing the tool content", e); + throw new ToolException(e); + } + } + + @Override + public void resetDefineLater(Long toolContentId) throws DataMissingException, ToolException { + VoteContent voteContent = getVoteContent(toolContentId); + if (voteContent == null) { + logger.error("throwing DataMissingException: WARNING!: retrieved voteContent is null."); + throw new DataMissingException("voteContent is missing"); + } + voteContent.setDefineLater(false); + saveVoteContent(voteContent); + } + + @Override + public void createToolSession(Long toolSessionID, String toolSessionName, Long toolContentID) throws ToolException { + + if (toolSessionID == null) { + logger.error("toolSessionID is null"); + throw new ToolException("toolSessionID is missing"); + } + + VoteContent voteContent = voteContentDAO.getVoteContentByContentId(toolContentID); + + /* + * create a new a new tool session if it does not already exist in the tool session table + */ + VoteSession voteSession = getSessionBySessionId(toolSessionID); + if (voteSession == null) { + try { + voteSession = new VoteSession(toolSessionID, new Date(System.currentTimeMillis()), + VoteSession.INCOMPLETE, toolSessionName, voteContent, new TreeSet()); + + voteSessionDAO.saveVoteSession(voteSession); + + } catch (Exception e) { + logger.error("Error creating new toolsession in the db"); + throw new ToolException("Error creating new toolsession in the db: " + e); + } + } + } + + @Override + public void removeToolSession(Long toolSessionID) throws DataMissingException, ToolException { + if (toolSessionID == null) { + logger.error("toolSessionID is null"); + throw new DataMissingException("toolSessionID is missing"); + } + + VoteSession voteSession = null; + try { + voteSession = getSessionBySessionId(toolSessionID); + } catch (VoteApplicationException e) { + logger.error("error retrieving voteSession:"); + throw new DataMissingException("error retrieving voteSession: " + e); + } catch (Exception e) { + logger.error("error retrieving voteSession:"); + throw new ToolException("error retrieving voteSession: " + e); + } + + if (voteSession == null) { + logger.error("voteSession is null"); + throw new DataMissingException("voteSession is missing"); + } + + try { + voteSessionDAO.removeVoteSession(voteSession); + } catch (VoteApplicationException e) { + throw new ToolException("error deleting voteSession:" + e); + } + } + + @Override + public String leaveToolSession(Long toolSessionID, Long learnerId) throws DataMissingException, ToolException { + + if (learnerService == null) { + return "dummyNextUrl"; + } + + if (learnerId == null) { + logger.error("learnerId is null"); + throw new DataMissingException("learnerId is missing"); + } + + if (toolSessionID == null) { + logger.error("toolSessionID is null"); + throw new DataMissingException("toolSessionID is missing"); + } + + VoteSession voteSession = null; + try { + voteSession = getSessionBySessionId(toolSessionID); + } catch (VoteApplicationException e) { + logger.error("error retrieving voteSession"); + throw new DataMissingException("error retrieving voteSession: " + e); + } catch (Exception e) { + throw new ToolException("error retrieving voteSession: " + e); + } + voteSession.setSessionStatus(VoteAppConstants.COMPLETED); + voteSessionDAO.updateVoteSession(voteSession); + + String nextUrl = learnerService.completeToolSession(toolSessionID, learnerId); + if (nextUrl == null) { + logger.error("nextUrl is null"); + throw new ToolException("nextUrl is null"); + } + return nextUrl; + } + + @Override + public ToolSessionExportOutputData exportToolSession(Long toolSessionID) + throws DataMissingException, ToolException { + throw new ToolException("not yet implemented"); + } + + @Override + public ToolSessionExportOutputData exportToolSession(List toolSessionIDs) + throws DataMissingException, ToolException { + throw new ToolException("not yet implemented"); + + } + + @Override + public IToolVO getToolBySignature(String toolSignature) { + IToolVO tool = toolService.getToolBySignature(toolSignature); + return tool; + } + + @Override + public long getToolDefaultContentIdBySignature(String toolSignature) { + long contentId = 0; + contentId = toolService.getToolDefaultContentIdBySignature(toolSignature); + return contentId; + } + + @Override + public List getToolSessionsForContent(VoteContent vote) { + List listToolSessionIds = voteSessionDAO.getSessionsFromContent(vote); + return listToolSessionIds; + } + + @Override + public boolean isGroupedActivity(long toolContentID) { + return toolService.isGroupedActivity(toolContentID); + } + + @Override + public void auditLogStartEditingActivityInMonitor(long toolContentID) { + toolService.auditLogStartEditingActivityInMonitor(toolContentID); + } + + @Override + public SortedMap getToolOutputDefinitions(Long toolContentId, int definitionType) + throws ToolException { + VoteContent content = getVoteContent(toolContentId); + if (content == null) { + long defaultToolContentId = getToolDefaultContentIdBySignature(VoteAppConstants.MY_SIGNATURE); + content = getVoteContent(defaultToolContentId); + } + return getVoteOutputFactory().getToolOutputDefinitions(content, definitionType); + } + + @Override + public String getToolContentTitle(Long toolContentId) { + return getVoteContent(toolContentId).getTitle(); + } + + @Override + public boolean isContentEdited(Long toolContentId) { + return getVoteContent(toolContentId).isDefineLater(); + } + + @Override + public boolean isReadOnly(Long toolContentId) { + VoteContent voteContent = voteContentDAO.getVoteContentByContentId(toolContentId); + for (VoteSession session : (Set) voteContent.getVoteSessions()) { + if (!session.getVoteQueUsers().isEmpty()) { + return true; + } + } + + return false; + } + + @Override + public SortedMap getToolOutput(List names, Long toolSessionId, Long learnerId) { + return voteOutputFactory.getToolOutput(names, this, toolSessionId, learnerId); + } + + @Override + public ToolOutput getToolOutput(String name, Long toolSessionId, Long learnerId) { + return voteOutputFactory.getToolOutput(name, this, toolSessionId, learnerId); + } + + @Override + public List getToolOutputs(String name, Long toolContentId) { + return new ArrayList(); + } + + @Override + public void forceCompleteUser(Long toolSessionId, User user) { + Long userId = user.getUserId().longValue(); + + VoteSession session = getSessionBySessionId(toolSessionId); + if ((session == null) || (session.getVoteContent() == null)) { + return; + } + VoteContent content = session.getVoteContent(); + + // copy answers only in case leader aware feature is ON + if (content.isUseSelectLeaderToolOuput()) { + + VoteQueUsr voteUser = voteUserDAO.getVoteUserBySession(userId, toolSessionId); + // create user if he hasn't accessed this activity yet + if (voteUser == null) { + String userName = user.getLogin(); + String fullName = user.getFirstName() + " " + user.getLastName(); + + voteUser = new VoteQueUsr(userId, userName, fullName, session, new TreeSet()); + createVoteQueUsr(voteUser); + } + + VoteQueUsr groupLeader = session.getGroupLeader(); + + // check if leader has submitted answers + if ((groupLeader != null) && groupLeader.isResponseFinalised()) { + + // we need to make sure specified user has the same scratches as a leader + copyAnswersFromLeader(voteUser, groupLeader); + } + + } + + } + + @Override + public Long createNotebookEntry(Long id, Integer idType, String signature, Integer userID, String entry) { + return coreNotebookService.createNotebookEntry(id, idType, signature, userID, "", entry); + } + + @Override + public NotebookEntry getEntry(Long id, Integer idType, String signature, Integer userID) { + + List list = coreNotebookService.getEntry(id, idType, signature, userID); + if ((list == null) || list.isEmpty()) { + return null; + } else { + return list.get(0); + } + } + + @Override + public List getAllQuestionsSorted(final long voteContentId) { + return voteQueContentDAO.getAllQuestionsSorted(voteContentId); + } + + /******** Tablesorter methods ************/ + /** + * Gets the basic details about an attempt for a nomination. questionUid must not be null, sessionUid may be NULL. + * This is + * unusual for these methods - usually sessionId may not be null. In this case if sessionUid is null then you get + * the values for the whole class, not just the group. + * + * Will return List<[login (String), fullname(String), attemptTime(Timestamp]> + */ + @Override + public List getUserAttemptsForTablesorter(Long sessionUid, Long questionUid, int page, int size, + int sorting, String searchString) { + return voteUsrAttemptDAO.getUserAttemptsForTablesorter(sessionUid, questionUid, page, size, sorting, + searchString); + } + + @Override + public int getCountUsersBySession(Long sessionUid, Long questionUid, String searchString) { + return voteUsrAttemptDAO.getCountUsersBySession(sessionUid, questionUid, searchString); + } + + @Override + public List getUserReflectionsForTablesorter(Long sessionUid, int page, int size, int sorting, + String searchString) { + return voteUsrAttemptDAO.getUserReflectionsForTablesorter(sessionUid, page, size, sorting, searchString, + getCoreNotebookService()); + } + + @Override + public List getStatisticsBySession(Long toolContentId) { + + List stats = voteUsrAttemptDAO.getStatisticsBySession(toolContentId); + for (VoteStatsDTO stat : stats) { + stat.setCountAllUsers(getVoteSessionPotentialLearnersCount(stat.getSessionUid())); + } + return stats; + } + + /** Gets the details for the open text nominations */ + @Override + public List getUserOpenTextAttemptsForTablesorter(Long sessionUid, Long contentUid, int page, + int size, int sorting, String searchStringVote, String searchStringUsername) { + return voteUsrAttemptDAO.getUserOpenTextAttemptsForTablesorter(sessionUid, contentUid, page, size, sorting, + searchStringVote, searchStringUsername); + } + + @Override + public int getCountUsersForOpenTextEntries(Long sessionUid, Long contentUid, String searchStringVote, + String searchStringUsername) { + return voteUsrAttemptDAO.getCountUsersForOpenTextEntries(sessionUid, contentUid, searchStringVote, + searchStringUsername); + } + + /** + * @return Returns the toolService. + */ + public ILamsToolService getToolService() { + return toolService; + } + + /** + * @return Returns the userManagementService. + */ + public IUserManagementService getUserManagementService() { + return userManagementService; + } + + public void setUserManagementService(IUserManagementService userManagementService) { + this.userManagementService = userManagementService; + } + + public void setToolService(ILamsToolService toolService) { + this.toolService = toolService; + } + + /** + * @return Returns the voteToolContentHandler. + */ + public IToolContentHandler getVoteToolContentHandler() { + return voteToolContentHandler; + } + + /** + * @param voteToolContentHandler + * The voteToolContentHandler to set. + */ + public void setVoteToolContentHandler(IToolContentHandler voteToolContentHandler) { + this.voteToolContentHandler = voteToolContentHandler; + } + + /** + * @return Returns the learnerService. + */ + public ILearnerService getLearnerService() { + return learnerService; + } + + /** + * @param learnerService + * The learnerService to set. + */ + public void setLearnerService(ILearnerService learnerService) { + this.learnerService = learnerService; + } + + /** + * @return Returns the voteContentDAO. + */ + public IVoteContentDAO getVoteContentDAO() { + return voteContentDAO; + } + + /** + * @param voteContentDAO + * The voteContentDAO to set. + */ + public void setVoteContentDAO(IVoteContentDAO voteContentDAO) { + this.voteContentDAO = voteContentDAO; + } + + /** + * @return Returns the voteQueContentDAO. + */ + public IVoteQueContentDAO getVoteQueContentDAO() { + return voteQueContentDAO; + } + + /** + * @param voteQueContentDAO + * The voteQueContentDAO to set. + */ + public void setVoteQueContentDAO(IVoteQueContentDAO voteQueContentDAO) { + this.voteQueContentDAO = voteQueContentDAO; + } + + /** + * @return Returns the voteSessionDAO. + */ + public IVoteSessionDAO getVoteSessionDAO() { + return voteSessionDAO; + } + + /** + * @param voteSessionDAO + * The voteSessionDAO to set. + */ + public void setVoteSessionDAO(IVoteSessionDAO voteSessionDAO) { + this.voteSessionDAO = voteSessionDAO; + } + + /** + * @return Returns the voteUserDAO. + */ + public IVoteUserDAO getVoteUserDAO() { + return voteUserDAO; + } + + /** + * @param voteUserDAO + * The voteUserDAO to set. + */ + public void setVoteUserDAO(IVoteUserDAO voteUserDAO) { + this.voteUserDAO = voteUserDAO; + } + + /** + * @return Returns the voteUsrAttemptDAO. + */ + public IVoteUsrAttemptDAO getVoteUsrAttemptDAO() { + return voteUsrAttemptDAO; + } + + /** + * @param voteUsrAttemptDAO + * The voteUsrAttemptDAO to set. + */ + public void setVoteUsrAttemptDAO(IVoteUsrAttemptDAO voteUsrAttemptDAO) { + this.voteUsrAttemptDAO = voteUsrAttemptDAO; + } + + /** + * @return Returns the auditService. + */ + public IAuditService getAuditService() { + return auditService; + } + + /** + * @param auditService + * The auditService to set. + */ + public void setAuditService(IAuditService auditService) { + this.auditService = auditService; + } + + public IExportToolContentService getExportContentService() { + return exportContentService; + } + + public void setExportContentService(IExportToolContentService exportContentService) { + this.exportContentService = exportContentService; + } + + /** + * @return Returns the coreNotebookService. + */ + public ICoreNotebookService getCoreNotebookService() { + return coreNotebookService; + } + + /** + * @param coreNotebookService + * The coreNotebookService to set. + */ + public void setCoreNotebookService(ICoreNotebookService coreNotebookService) { + this.coreNotebookService = coreNotebookService; + } + + public VoteOutputFactory getVoteOutputFactory() { + return voteOutputFactory; + } + + public void setVoteOutputFactory(VoteOutputFactory voteOutputFactory) { + this.voteOutputFactory = voteOutputFactory; + } + + /** + * @return Returns the MessageService. + */ + @Override + public MessageService getMessageService() { + return messageService; + } + + /** + * @param messageService + * The MessageService to set. + */ + public void setMessageService(MessageService messageService) { + this.messageService = messageService; + } + + @Override + public void removeQuestionsFromCache(VoteContent voteContent) { + voteContentDAO.removeQuestionsFromCache(voteContent); + } + + @Override + public void removeVoteContentFromCache(VoteContent voteContent) { + voteContentDAO.removeVoteContentFromCache(voteContent); + } + + public void setDataFlowDAO(IDataFlowDAO dataFlowDAO) { + this.dataFlowDAO = dataFlowDAO; + } + + @Override + public ToolOutput getToolInput(Long requestingToolContentId, Integer learnerId) { + // just forwarding to learner service + return learnerService.getToolInput(requestingToolContentId, VoteAppConstants.DATA_FLOW_OBJECT_ASSIGMENT_ID, + learnerId); + } + + @Override + public void saveDataFlowObjectAssigment(DataFlowObject assignedDataFlowObject) { + // this also should be done in learner service, but for simplicity... + if (assignedDataFlowObject != null) { + assignedDataFlowObject.setToolAssigmentId(VoteAppConstants.DATA_FLOW_OBJECT_ASSIGMENT_ID); + dataFlowDAO.update(assignedDataFlowObject); + } + } + + @Override + public DataFlowObject getAssignedDataFlowObject(Long toolContentId) { + return dataFlowDAO.getAssignedDataFlowObject(toolContentId, VoteAppConstants.DATA_FLOW_OBJECT_ASSIGMENT_ID); + } + + @Override + public List getDataFlowObjects(Long toolContentId) { + return dataFlowDAO.getDataFlowObjectsByToolContentId(toolContentId); + } + + @SuppressWarnings("rawtypes") + @Override + public Class[] getSupportedToolOutputDefinitionClasses(int definitionType) { + return getVoteOutputFactory().getSupportedDefinitionClasses(definitionType); + } + + @Override + public ToolCompletionStatus getCompletionStatus(Long learnerId, Long toolSessionId) { + VoteSession session = getSessionBySessionId(toolSessionId); + VoteQueUsr learner = getVoteUserBySession(learnerId, session.getUid()); + if (learner == null) { + return new ToolCompletionStatus(ToolCompletionStatus.ACTIVITY_NOT_ATTEMPTED, null, null); + } + + + Date startDate = null; + Date endDate = null; + Set attempts = learner.getVoteUsrAttempts(); // expect only one + for (VoteUsrAttempt item : attempts) { + Date newDate = item.getAttemptTime(); + if (newDate != null) { + if (startDate == null || newDate.before(startDate)) + startDate = newDate; + if (endDate == null || newDate.after(endDate)) + endDate = newDate; + } + } + + if (learner.isResponseFinalised()) + return new ToolCompletionStatus(ToolCompletionStatus.ACTIVITY_COMPLETED, startDate, endDate); + else + return new ToolCompletionStatus(ToolCompletionStatus.ACTIVITY_ATTEMPTED, startDate, null); + } + + // ****************** REST methods ************************* + + /** + * Rest call to create a new Vote content. Required fields in toolContentJSON: "title", "instructions", "answers". + * The "answers" entry should be a JSONArray of Strings. + */ + @Override + public void createRestToolContent(Integer userID, Long toolContentID, JSONObject toolContentJSON) + throws JSONException { + if (logger.isDebugEnabled()) { + logger.debug("Rest call to create a new Vote content for userID" + userID + " and toolContentID " + + toolContentID); + } + Date updateDate = new Date(); + + VoteContent vote = new VoteContent(); + vote.setVoteContentId(toolContentID); + vote.setTitle(toolContentJSON.getString(RestTags.TITLE)); + vote.setInstructions(toolContentJSON.getString(RestTags.INSTRUCTIONS)); + vote.setCreatedBy(userID); + vote.setCreationDate(updateDate); + vote.setUpdateDate(updateDate); + + vote.setAllowText(JsonUtil.opt(toolContentJSON, "allowText", Boolean.FALSE)); + vote.setDefineLater(false); + vote.setLockOnFinish(JsonUtil.opt(toolContentJSON, RestTags.LOCK_WHEN_FINISHED, Boolean.FALSE)); + vote.setMaxNominationCount(JsonUtil.opt(toolContentJSON, "maxNominations", "1")); + vote.setMinNominationCount(JsonUtil.opt(toolContentJSON, "minNominations", "1")); + vote.setReflect(JsonUtil.opt(toolContentJSON, RestTags.REFLECT_ON_ACTIVITY, Boolean.FALSE)); + vote.setReflectionSubject(JsonUtil.opt(toolContentJSON, RestTags.REFLECT_INSTRUCTIONS, (String) null)); + vote.setShowResults(JsonUtil.opt(toolContentJSON, "showResults", Boolean.TRUE)); + vote.setUseSelectLeaderToolOuput( + JsonUtil.opt(toolContentJSON, RestTags.USE_SELECT_LEADER_TOOL_OUTPUT, Boolean.FALSE)); + + // Is the data flow functionality actually used anywhere? + vote.setAssignedDataFlowObject((Boolean) JsonUtil.opt(toolContentJSON, "assignedDataFlowObject", null)); + vote.setExternalInputsAdded((Short) JsonUtil.opt(toolContentJSON, "externalInputsAdded", null)); + vote.setMaxExternalInputs(JsonUtil.opt(toolContentJSON, "maxInputs", Short.valueOf("0"))); + + // submissionDeadline is set in monitoring + + // **************************** Nomination entries ********************* + JSONArray answers = toolContentJSON.getJSONArray(RestTags.ANSWERS); + //Set newAnswersSet = vote.getVoteQueContents(); + for (int i = 0; i < answers.length(); i++) { + // String answerJSONData = (String) answers.get(i); + VoteQueContent answer = new VoteQueContent(); + answer.setDisplayOrder(i + 1); + answer.setMcContent(vote); + answer.setQuestion((String) answers.get(i)); + answer.setVoteContent(vote); + vote.getVoteQueContents().add(answer); + } + + saveVoteContent(vote); + + } + +} \ No newline at end of file Fisheye: Tag 85ef8aca5722a36582117db1e8b988e2c16b6369 refers to a dead (removed) revision in file `lams_tool_vote/src/java/org/lamsfoundation/lams/tool/vote/service/VoteServicePOJO.java'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_tool_vote/src/java/org/lamsfoundation/lams/tool/vote/voteApplicationContext.xml =================================================================== diff -u -r99531c32db263651828f39f4d7ad9923a6eec030 -r85ef8aca5722a36582117db1e8b988e2c16b6369 --- lams_tool_vote/src/java/org/lamsfoundation/lams/tool/vote/voteApplicationContext.xml (.../voteApplicationContext.xml) (revision 99531c32db263651828f39f4d7ad9923a6eec030) +++ lams_tool_vote/src/java/org/lamsfoundation/lams/tool/vote/voteApplicationContext.xml (.../voteApplicationContext.xml) (revision 85ef8aca5722a36582117db1e8b988e2c16b6369) @@ -60,7 +60,7 @@ - +