Index: lams_build/lib/lams/lams-central.jar =================================================================== diff -u -rf92865513dd2beca642af28ab42096ee4849ac32 -re923dff715d473f8bb19d3593f1419662544111c Binary files differ Index: lams_build/lib/lams/lams.jar =================================================================== diff -u -rf92865513dd2beca642af28ab42096ee4849ac32 -re923dff715d473f8bb19d3593f1419662544111c Binary files differ Index: lams_central/src/java/org/lamsfoundation/lams/web/OrganisationGroupAction.java =================================================================== diff -u -rf92865513dd2beca642af28ab42096ee4849ac32 -re923dff715d473f8bb19d3593f1419662544111c --- lams_central/src/java/org/lamsfoundation/lams/web/OrganisationGroupAction.java (.../OrganisationGroupAction.java) (revision f92865513dd2beca642af28ab42096ee4849ac32) +++ lams_central/src/java/org/lamsfoundation/lams/web/OrganisationGroupAction.java (.../OrganisationGroupAction.java) (revision e923dff715d473f8bb19d3593f1419662544111c) @@ -23,9 +23,13 @@ /* $Id$ */ package org.lamsfoundation.lams.web; +import java.util.Collections; +import java.util.Comparator; import java.util.HashSet; import java.util.LinkedList; import java.util.List; +import java.util.Set; +import java.util.TreeSet; import java.util.Vector; import javax.servlet.http.HttpServletRequest; @@ -41,6 +45,7 @@ import org.apache.tomcat.util.json.JSONException; import org.apache.tomcat.util.json.JSONObject; import org.lamsfoundation.lams.usermanagement.OrganisationGroup; +import org.lamsfoundation.lams.usermanagement.OrganisationGrouping; import org.lamsfoundation.lams.usermanagement.Role; import org.lamsfoundation.lams.usermanagement.User; import org.lamsfoundation.lams.usermanagement.dto.UserDTO; @@ -51,126 +56,298 @@ import org.lamsfoundation.lams.web.util.AttributeNames; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; -import org.springframework.web.util.WebUtils; /** * @struts.action path = "/OrganisationGroup" parameter = "method" validate = "false" - * @struts.action-forward name = "view" path = "/orgGroup.jsp" + * @struts.action-forward name = "viewGroupings" path = "/orgGrouping.jsp" + * @struts.action-forward name = "viewGroups" path = "/orgGroup.jsp" */ public class OrganisationGroupAction extends DispatchAction { + /** + * Class for displaying on groupings page. + */ + public class OrganisationGroupingDTO implements Comparable { + private Long groupingId; + private String name; + private Integer groupCount; + + public OrganisationGroupingDTO(OrganisationGrouping grouping) { + this.groupingId = grouping.getGroupingId(); + this.name = grouping.getName(); + this.groupCount = grouping.getGroups().size(); + } + + public Long getGroupingId() { + return groupingId; + } + + public void setGroupingId(Long groupingId) { + this.groupingId = groupingId; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getGroupCount() { + return groupCount; + } + + public void setGroupCount(Integer groupCount) { + this.groupCount = groupCount; + } + + @Override + public int compareTo(OrganisationGroupingDTO o) { + if (o == null) { + return 1; + } + if (this.name == null) { + return o.name == null ? 0 : 1; + } + return this.name.compareTo(o.name); + } + } + + private static final Comparator GROUP_COMPARATOR = new Comparator() { + public int compare(OrganisationGroup o1, OrganisationGroup o2) { + if (o1 == null && o2 == null) { + return 0; + } + if (o1 == null) { + return -1; + } + if (o2 == null) { + return 1; + } + if (o1.getName() == null) { + return o2.getName() == null ? 0 : -1; + } + return o1.getName().compareTo(o2.getName()); + } + }; + private static Logger log = Logger.getLogger(OrganisationGroupAction.class); - + private static IUserManagementService userManagementService; - - private static final String MAPPING_VIEW = "view"; + private static final String MAPPING_VIEW_GROUPINGS = "viewGroupings"; + private static final String MAPPING_VIEW_GROUPS = "viewGroups"; + @SuppressWarnings("unchecked") - public ActionForward view(ActionMapping mapping, ActionForm form, HttpServletRequest request, + public ActionForward viewGroupings(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws JSONException { // check if user is allowed to view and edit groups Integer userId = getUserDTO().getUserID(); int organisationId = WebUtil.readIntParam(request, AttributeNames.PARAM_ORGANISATION_ID); - boolean isGroupSuperuser = getUserManagementService().isUserInRole(userId, organisationId, Role.GROUP_ADMIN) ||getUserManagementService().isUserInRole(userId, organisationId, Role.GROUP_MANAGER); - if (!isGroupSuperuser && !getUserManagementService().isUserInRole(userId, organisationId, Role.AUTHOR) && !getUserManagementService().isUserInRole(userId, organisationId, Role.MONITOR)){ - throw new UserAccessDeniedException("User " + userId + " may not view groups for course " + organisationId); + boolean isGroupSuperuser = getUserManagementService().isUserInRole(userId, organisationId, Role.GROUP_ADMIN) + || getUserManagementService().isUserInRole(userId, organisationId, Role.GROUP_MANAGER); + if (!isGroupSuperuser && !getUserManagementService().isUserInRole(userId, organisationId, Role.AUTHOR) + && !getUserManagementService().isUserInRole(userId, organisationId, Role.MONITOR)) { + throw new UserAccessDeniedException("User " + userId + " may not view groupings for course " + + organisationId); } - - if(log.isDebugEnabled()) { - log.debug("Displaying course groups for user " + userId + " and organisation " + organisationId); + + if (OrganisationGroupAction.log.isDebugEnabled()) { + OrganisationGroupAction.log.debug("Displaying course groupings for user " + userId + " and organisation " + + organisationId); } request.setAttribute(AttributeNames.PARAM_ORGANISATION_ID, organisationId); request.setAttribute("canEdit", isGroupSuperuser); - + + Set groupingDTOs = new TreeSet(); + List groupings = getUserManagementService().findByProperty(OrganisationGrouping.class, + "organisationId", organisationId); + for (OrganisationGrouping grouping : groupings) { + groupingDTOs.add(new OrganisationGroupingDTO(grouping)); + } + request.setAttribute("groupings", groupingDTOs); + + return mapping.findForward(OrganisationGroupAction.MAPPING_VIEW_GROUPINGS); + } + + @SuppressWarnings("unchecked") + public ActionForward viewGroups(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws JSONException { + // check if user is allowed to view and edit groups + Integer userId = getUserDTO().getUserID(); + int organisationId = WebUtil.readIntParam(request, AttributeNames.PARAM_ORGANISATION_ID); + boolean isGroupSuperuser = getUserManagementService().isUserInRole(userId, organisationId, Role.GROUP_ADMIN) + || getUserManagementService().isUserInRole(userId, organisationId, Role.GROUP_MANAGER); + if (!isGroupSuperuser && !getUserManagementService().isUserInRole(userId, organisationId, Role.AUTHOR) + && !getUserManagementService().isUserInRole(userId, organisationId, Role.MONITOR)) { + throw new UserAccessDeniedException("User " + userId + " may not view groups for course " + organisationId); + } + + if (OrganisationGroupAction.log.isDebugEnabled()) { + OrganisationGroupAction.log.debug("Displaying course groups for user " + userId + " and organisation " + + organisationId); + } + request.setAttribute("canEdit", isGroupSuperuser); + + JSONObject groupingJSON = new JSONObject(); + groupingJSON.put("organisationId", organisationId); + + Long groupingId = WebUtil.readLongParam(request, "groupingId", true); + OrganisationGrouping grouping = null; + // check if grouping already exists + if (groupingId != null) { + grouping = (OrganisationGrouping) getUserManagementService().findById(OrganisationGrouping.class, + groupingId); + if (grouping != null) { + groupingJSON.put("groupingId", groupingId); + groupingJSON.put("name", grouping.getName()); + } + } + // serialize database group objects into JSON Vector learners = getUserManagementService().getUsersFromOrganisationByRole(organisationId, Role.LEARNER, false, true); - List groups = getUserManagementService().findByProperty(OrganisationGroup.class, - "organisationId", organisationId); + Set groups = grouping == null ? null : grouping.getGroups(); JSONArray groupsJSON = new JSONArray(); - for (OrganisationGroup group : groups) { - JSONObject groupJSON = new JSONObject(); - groupJSON.put("name", group.getName()); - groupJSON.put("groupId", group.getGroupId()); - for (User groupUser : group.getUsers()) { - JSONObject groupUserJSON = WebUtil.userToJSON(groupUser); - groupJSON.append("users", groupUserJSON); - - // remove the user who is already assigned to a group - learners.remove(groupUser); - } + if (groups != null) { + // sort groups by their name + List groupList = new LinkedList(groups); + Collections.sort(groupList, GROUP_COMPARATOR); - groupsJSON.put(groupJSON); + for (OrganisationGroup group : groupList) { + JSONObject groupJSON = new JSONObject(); + groupJSON.put("name", group.getName()); + groupJSON.put("groupId", group.getGroupId()); + for (User groupUser : group.getUsers()) { + JSONObject groupUserJSON = WebUtil.userToJSON(groupUser); + groupJSON.append("users", groupUserJSON); + + // remove the user who is already assigned to a group + learners.remove(groupUser); + } + + groupsJSON.put(groupJSON); + } } - request.setAttribute("groups", groupsJSON); - + groupingJSON.put("groups", groupsJSON); + request.setAttribute("grouping", groupingJSON); + // all the remaining users are unassigned to any group - JSONArray unassignedUsersJSON = new JSONArray(); + JSONArray unassignedUsersJSON = new JSONArray(); for (User unassignedUser : learners) { JSONObject unassignedUserJSON = WebUtil.userToJSON(unassignedUser); unassignedUsersJSON.put(unassignedUserJSON); } request.setAttribute("unassignedUsers", unassignedUsersJSON); - - response.setContentType("application/json;charset=utf-8"); - return mapping.findForward(MAPPING_VIEW); + + return mapping.findForward(OrganisationGroupAction.MAPPING_VIEW_GROUPS); } - + public ActionForward save(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws JSONException { // check if user is allowed to edit groups Integer userId = getUserDTO().getUserID(); int organisationId = WebUtil.readIntParam(request, AttributeNames.PARAM_ORGANISATION_ID); - boolean isGroupSuperuser = getUserManagementService().isUserInRole(userId, organisationId, Role.GROUP_ADMIN) ||getUserManagementService().isUserInRole(userId, organisationId, Role.GROUP_MANAGER); - if (!isGroupSuperuser){ + boolean isGroupSuperuser = getUserManagementService().isUserInRole(userId, organisationId, Role.GROUP_ADMIN) + || getUserManagementService().isUserInRole(userId, organisationId, Role.GROUP_MANAGER); + if (!isGroupSuperuser) { throw new UserAccessDeniedException("User " + userId + " may not edit groups for course " + organisationId); } - - if(log.isDebugEnabled()) { - log.debug("Saving course groups for user " + userId + " and organisation " + organisationId); + + if (OrganisationGroupAction.log.isDebugEnabled()) { + OrganisationGroupAction.log.debug("Saving course groups for user " + userId + " and organisation " + + organisationId); } - - JSONArray newGroups = new JSONArray(request.getParameter("groups")); - List newGroupObjects = new LinkedList(); - + + // deserialize grouping + JSONObject groupingJSON = new JSONObject(request.getParameter("grouping")); + // check if already exists + Long groupingId = groupingJSON.optLong("groupingId"); + if (groupingId == 0L) { + groupingId = null; + } + // iterate over groups - for (int i = 0; i < newGroups.length(); i++) { - JSONObject newGroup = newGroups.getJSONObject(i); - OrganisationGroup newGroupObject = new OrganisationGroup(); - - Long groupId = newGroup.optLong("groupId"); - if (groupId == 0L) { - groupId = null; - } - newGroupObject.setGroupId(groupId); - newGroupObject.setOrganisationId(organisationId); - newGroupObject.setName(newGroup.optString("name", null)); - newGroupObject.setUsers(new HashSet()); - JSONArray newGroupUsers = newGroup.optJSONArray("users"); - if (newGroupUsers != null) { - // find user objects based on delivered IDs - for (int j = 0; j< newGroupUsers.length(); j++) { - Integer learnerId = newGroupUsers.getInt(j); - User user = (User)getUserManagementService().findById(User.class, learnerId); - newGroupObject.getUsers().add(user); + List groups = new LinkedList(); + JSONArray groupsJSON = groupingJSON.optJSONArray("groups"); + if (groups != null) { + for (int i = 0; i < groupsJSON.length(); i++) { + // just overwrite existing groups; they will be updated if already exist + Set users = new HashSet(); + JSONObject groupJSON = groupsJSON.getJSONObject(i); + JSONArray newGroupUsers = groupJSON.optJSONArray("users"); + if (newGroupUsers != null) { + // find user objects based on delivered IDs + for (int j = 0; j < newGroupUsers.length(); j++) { + Integer learnerId = newGroupUsers.getInt(j); + User user = (User) getUserManagementService().findById(User.class, learnerId); + users.add(user); + } } + + OrganisationGroup group = new OrganisationGroup(); + Long groupId = groupJSON.optLong("groupId"); + if (groupId > 0) { + group.setGroupId(groupId); + group.setGroupingId(groupingId); + } + group.setName(groupJSON.optString("name", null)); + group.setUsers(users); + + groups.add(group); } - newGroupObjects.add(newGroupObject); } - - getUserManagementService().saveOrganisationGroups(organisationId, newGroupObjects); - + + OrganisationGrouping grouping = null; + if (groupingId != null) { + grouping = (OrganisationGrouping) getUserManagementService().findById(OrganisationGrouping.class, + groupingId); + } + if (grouping == null) { + grouping = new OrganisationGrouping(); + grouping.setOrganisationId(organisationId); + } + grouping.setName(groupingJSON.getString("name")); + + getUserManagementService().saveOrganisationGrouping(grouping, groups); return null; } + /** + * Deletes Organisation Grouping with the given ID. + */ + public ActionForward removeGrouping(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws JSONException { + // check if user is allowed to edit groups + Integer userId = getUserDTO().getUserID(); + int organisationId = WebUtil.readIntParam(request, AttributeNames.PARAM_ORGANISATION_ID); + boolean isGroupSuperuser = getUserManagementService().isUserInRole(userId, organisationId, Role.GROUP_ADMIN) + || getUserManagementService().isUserInRole(userId, organisationId, Role.GROUP_MANAGER); + if (!isGroupSuperuser) { + throw new UserAccessDeniedException("User " + userId + " may not remove groupings for course " + + organisationId); + } + + Long groupingId = WebUtil.readLongParam(request, "groupingId"); + if (OrganisationGroupAction.log.isDebugEnabled()) { + OrganisationGroupAction.log.debug("Removing grouping " + groupingId + " for user " + userId + + " and organisation " + organisationId); + } + + getUserManagementService().deleteById(OrganisationGrouping.class, groupingId); + + return viewGroupings(mapping, form, request, response); + } + private IUserManagementService getUserManagementService() { - if (userManagementService == null) { + if (OrganisationGroupAction.userManagementService == null) { WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(getServlet() .getServletContext()); - userManagementService = (IUserManagementService) ctx.getBean("userManagementService"); + OrganisationGroupAction.userManagementService = (IUserManagementService) ctx + .getBean("userManagementService"); } - return userManagementService; + return OrganisationGroupAction.userManagementService; } - private UserDTO getUserDTO() { HttpSession ss = SessionManager.getSession(); Index: lams_central/web/css/defaultHTML.css =================================================================== diff -u -rdc7b67e7677c8cd2289130c67094a62b39177d05 -re923dff715d473f8bb19d3593f1419662544111c --- lams_central/web/css/defaultHTML.css (.../defaultHTML.css) (revision dc7b67e7677c8cd2289130c67094a62b39177d05) +++ lams_central/web/css/defaultHTML.css (.../defaultHTML.css) (revision e923dff715d473f8bb19d3593f1419662544111c) @@ -1652,4 +1652,15 @@ .split-ui-button div:first-child { margin-right: -0.4em; +} + +.customDialogButton { + position: absolute; + top: 0; + padding: 5px 20px 5px 20px; + vertical-align: center; + font-weight: bolder; + border: thin solid #2E6E9E !important; + color: #222222 !important; + background-color: #D0E5F5;" } \ No newline at end of file Index: lams_central/web/css/orgGroup.css =================================================================== diff -u -rf92865513dd2beca642af28ab42096ee4849ac32 -re923dff715d473f8bb19d3593f1419662544111c --- lams_central/web/css/orgGroup.css (.../orgGroup.css) (revision f92865513dd2beca642af28ab42096ee4849ac32) +++ lams_central/web/css/orgGroup.css (.../orgGroup.css) (revision e923dff715d473f8bb19d3593f1419662544111c) @@ -2,17 +2,36 @@ height: 100%; } +.errorMessage { + display: none; + font-weight: bold; + color: red; + margin-left: 5px; +} + div#titleDiv { font-size: small; font-weight: bold; - padding: 5px 0; - text-align: center; + padding: 5px 10px 5px 10px; border-bottom: thin dotted #2E6E9E; } -table td { +div#titleDiv input { + margin-left: 5px; + width: 290px; +} + +#titleInstructions{ + padding-top: 4px; + float: right; +} + +table#groupsTable { + height: 380px; +} + +table#groupsTable td { vertical-align: top; - height: 348px; } td#unassignedUserCell { @@ -49,13 +68,14 @@ text-align: center; } -.removeGroupButton, .sortUsersButton { +.sortUsersButton { float: right; cursor: pointer; } .removeGroupButton { - padding-right: 3px; + float: left; + cursor: pointer; width: 16px; height: 16px; } Index: lams_central/web/includes/javascript/groupDisplay.js =================================================================== diff -u -rf92865513dd2beca642af28ab42096ee4849ac32 -re923dff715d473f8bb19d3593f1419662544111c --- lams_central/web/includes/javascript/groupDisplay.js (.../groupDisplay.js) (revision f92865513dd2beca642af28ab42096ee4849ac32) +++ lams_central/web/includes/javascript/groupDisplay.js (.../groupDisplay.js) (revision e923dff715d473f8bb19d3593f1419662544111c) @@ -218,7 +218,7 @@ 'orgID' : orgID, 'autoOpen' : false, 'height' : 460, - 'width' : 880, + 'width' : 460, 'modal' : true, 'resizable' : false, 'hide' : 'fold', @@ -227,7 +227,7 @@ // load contents after opening the dialog $('#dialogFrame') .attr('src', LAMS_URL - + 'OrganisationGroup.do?method=view&organisationID=' + + 'OrganisationGroup.do?method=viewGroupings&organisationID=' + $(this).dialog('option', 'orgID')); }, 'beforeClose' : function(){ @@ -490,10 +490,35 @@ .dialog('close'); } +/** + * Loads contents to already open dialog. + */ +function loadDialogContents(title, width, height, url) { + if (title) { + $("#dialogContainer").dialog('option', 'title', title); + } + if (width && height) { + $("#dialogContainer").dialog('option', { + 'width' : width, + 'height' : height, + }).dialog('option', 'position', 'center'); + } + if (url) { + $('#dialogFrame').contents().find("body").html(''); + $('#dialogFrame').attr('src', url); + $('div.ui-dialog-titlebar .customDialogButton').remove(); + } +} + +/** + * Called from within Course Groups dialog, it saves groups and loads grouping page. + */ function saveOrgGroups() { var groupsSaved = document.getElementById('dialogFrame').contentWindow.saveGroups(); if (groupsSaved) { - $("#dialogContainer").dialog('close'); + loadDialogContents(null, 460, 460, + LAMS_URL + 'OrganisationGroup.do?method=viewGroupings&organisationID=' + + $('#dialogContainer').dialog('option', 'orgID')); } } Index: lams_central/web/includes/javascript/orgGroup.js =================================================================== diff -u -rf92865513dd2beca642af28ab42096ee4849ac32 -re923dff715d473f8bb19d3593f1419662544111c --- lams_central/web/includes/javascript/orgGroup.js (.../orgGroup.js) (revision f92865513dd2beca642af28ab42096ee4849ac32) +++ lams_central/web/includes/javascript/orgGroup.js (.../orgGroup.js) (revision e923dff715d473f8bb19d3593f1419662544111c) @@ -3,20 +3,21 @@ var lastSelectedUsers = {}; $(document).ready(function(){ + $('#groupingName').val(grouping.name); // show unassigned users on the left fillGroup(unassignedUsers, $('#unassignedUserCell')); - $.each(groups, function(){ + $.each(grouping.groups, function(){ // add existing groups addGroup(this.groupId, this.name, this.users); }); + // move Save button to the titlebar, i.e. outside of this iframe to the enveloping dialog + $('div.ui-dialog-titlebar', window.parent.document).prepend($('.customDialogButton')); if (canEdit) { // allow adding new groups $('#newGroupPlaceholder').click(function(){ addGroup(null, LABELS.GROUP_PREFIX_LABEL + $('table .groupContainer').length, null); }); - // move Save button to the titlebar, i.e. outside of this iframe to the enveloping dialog - $('div.ui-dialog-titlebar', window.parent.document).prepend($('#saveButton')); } }); @@ -210,7 +211,6 @@ } } - function removeGroup(container) { // no groupId means this group was just added and it was not persisted in DB yet var executeDelete = !$(container).attr('groupId'); @@ -228,8 +228,15 @@ if (!canEdit) { return false; } + $('.errorMessage').hide(); - // ask if removing new, empyt groups is OK + var groupingName = $('#groupingName').val(); + if (!groupingName) { + $('#groupingNameBlankError').show(); + return false; + } + + // ask if removing new, empty groups is OK var acceptEmptyGroups = true; var groupContainers = $('table .groupContainer').not('#newGroupPlaceholder'); $.each(groupContainers.not('[groupId]'), function(){ @@ -246,7 +253,11 @@ } var groupsSaved = false; - var newGroups = []; + var newGrouping = { + 'groupingId' : grouping.groupingId, + 'name' : groupingName, + 'groups' : [] + }; groupContainers.each(function(){ var groupId = $(this).attr('groupId'); var users = $('div.draggableUser', this); @@ -259,7 +270,7 @@ userIds.push($(this).attr('userId')); }); - newGroups.push({ + newGrouping.groups.push({ 'groupId' : groupId, 'name' : $('input', this).val(), 'users' : userIds @@ -272,9 +283,8 @@ url : LAMS_URL + 'OrganisationGroup.do', data : { 'method' : 'save', - 'organisationID' : orgId, - 'groups' : JSON.stringify(newGroups) - + 'organisationID' : grouping.organisationId, + 'grouping' : JSON.stringify(newGrouping) }, type : 'POST', success : function(json) { Index: lams_central/web/orgGroup.jsp =================================================================== diff -u -rf92865513dd2beca642af28ab42096ee4849ac32 -re923dff715d473f8bb19d3593f1419662544111c --- lams_central/web/orgGroup.jsp (.../orgGroup.jsp) (revision f92865513dd2beca642af28ab42096ee4849ac32) +++ lams_central/web/orgGroup.jsp (.../orgGroup.jsp) (revision e923dff715d473f8bb19d3593f1419662544111c) @@ -13,9 +13,8 @@ - + + + + + +
+ +
+ + +
+ + + + (${grouping.groupCount}) + + + +
+
+ + +
+ +
+
+ + \ No newline at end of file Index: lams_common/build.xml =================================================================== diff -u -rf92865513dd2beca642af28ab42096ee4849ac32 -re923dff715d473f8bb19d3593f1419662544111c --- lams_common/build.xml (.../build.xml) (revision f92865513dd2beca642af28ab42096ee4849ac32) +++ lams_common/build.xml (.../build.xml) (revision e923dff715d473f8bb19d3593f1419662544111c) @@ -36,6 +36,7 @@ + Index: lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch02040021.sql =================================================================== diff -u -rf92865513dd2beca642af28ab42096ee4849ac32 -re923dff715d473f8bb19d3593f1419662544111c --- lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch02040021.sql (.../patch02040021.sql) (revision f92865513dd2beca642af28ab42096ee4849ac32) +++ lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch02040021.sql (.../patch02040021.sql) (revision e923dff715d473f8bb19d3593f1419662544111c) @@ -4,13 +4,22 @@ SET FOREIGN_KEY_CHECKS=0; -- LDEV-3119 Course level groups +CREATE TABLE lams_organisation_grouping ( + grouping_id BIGINT(20) NOT NULL AUTO_INCREMENT, + organisation_id BIGINT(20) NOT NULL, + name VARCHAR(255), + PRIMARY KEY (grouping_id), + CONSTRAINT FK_lams_organisation_grouping_1 FOREIGN KEY (organisation_id) + REFERENCES lams_organisation (organisation_id) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB; + CREATE TABLE lams_organisation_group ( group_id BIGINT(20) NOT NULL AUTO_INCREMENT, - organisation_id BIGINT(20) NOT NULL, + grouping_id BIGINT(20) NOT NULL, name VARCHAR(255), PRIMARY KEY (group_id), - CONSTRAINT FK_lams_organisation_group_1 FOREIGN KEY (organisation_id) - REFERENCES lams_organisation (organisation_id) ON DELETE CASCADE ON UPDATE CASCADE + CONSTRAINT FK_lams_organisation_group_1 FOREIGN KEY (grouping_id) + REFERENCES lams_organisation_grouping (grouping_id) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB; CREATE TABLE lams_user_organisation_group ( Index: lams_common/src/java/org/lamsfoundation/lams/usermanagement/OrganisationGroup.java =================================================================== diff -u -rf92865513dd2beca642af28ab42096ee4849ac32 -re923dff715d473f8bb19d3593f1419662544111c --- lams_common/src/java/org/lamsfoundation/lams/usermanagement/OrganisationGroup.java (.../OrganisationGroup.java) (revision f92865513dd2beca642af28ab42096ee4849ac32) +++ lams_common/src/java/org/lamsfoundation/lams/usermanagement/OrganisationGroup.java (.../OrganisationGroup.java) (revision e923dff715d473f8bb19d3593f1419662544111c) @@ -39,22 +39,22 @@ private Long groupId; /** persistent field */ - private Integer organisationId; + private Long groupingId; /** nullable persistent field */ private String name; + /** persistent field */ + private Set users; + public OrganisationGroup() { } - public OrganisationGroup(Integer organisationId, String name) { - this.organisationId = organisationId; + public OrganisationGroup(Long organisationId, String name) { + this.groupingId = organisationId; this.name = name; } - /** persistent field */ - private Set users; - /** * @hibernate.id generator-class="native" type="java.lang.Long" column="group_id" */ @@ -67,14 +67,14 @@ } /** - * @hibernate.property column="organisation_id" + * @hibernate.property column="grouping_id" */ - public Integer getOrganisationId() { - return this.organisationId; + public Long getGroupingId() { + return this.groupingId; } - public void setOrganisationId(Integer organisationId) { - this.organisationId = organisationId; + public void setGroupingId(Long organisationId) { + this.groupingId = organisationId; } /** Index: lams_common/src/java/org/lamsfoundation/lams/usermanagement/OrganisationGrouping.java =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/usermanagement/OrganisationGrouping.java (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/usermanagement/OrganisationGrouping.java (revision e923dff715d473f8bb19d3593f1419662544111c) @@ -0,0 +1,129 @@ +/**************************************************************** + * 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 + * **************************************************************** + */ +/* $$Id$$ */ +package org.lamsfoundation.lams.usermanagement; + +import java.io.Serializable; +import java.util.Set; + +import org.apache.commons.lang.builder.HashCodeBuilder; + +/** + * This is a course-level group of groups of learners, i.e. a grouping. + * + * @hibernate.class table="lams_organisation_grouping" + */ +public class OrganisationGrouping implements Serializable { + + /** identifier field */ + private Long groupingId; + + /** persistent field */ + private Integer organisationId; + + /** nullable persistent field */ + private String name; + + private Set groups; + + public OrganisationGrouping() { + } + + public OrganisationGrouping(Integer organisationId, String name) { + this.organisationId = organisationId; + this.name = name; + } + + /** + * @hibernate.id generator-class="native" type="java.lang.Long" column="grouping_id" + */ + public Long getGroupingId() { + return groupingId; + } + + public void setGroupingId(Long groupId) { + this.groupingId = groupId; + } + + /** + * @hibernate.property column="organisation_id" + */ + public Integer getOrganisationId() { + return this.organisationId; + } + + public void setOrganisationId(Integer organisationId) { + this.organisationId = organisationId; + } + + /** + * @hibernate.property column="name" + */ + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + /** + * @hibernate.set cascade="all-delete-orphan" inverse="true" + * @hibernate.collection-key column="grouping_id" + * @hibernate.collection-one-to-many class="org.lamsfoundation.lams.usermanagement.OrganisationGroup" + */ + public Set getGroups() { + return groups; + } + + public void setGroups(Set groups) { + this.groups = groups; + } + + @Override + public int hashCode() { + return new HashCodeBuilder().append(groupingId).toHashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof OrganisationGroup)) { + return false; + } + OrganisationGrouping other = (OrganisationGrouping) obj; + if (groupingId == null) { + if (other.groupingId != null) { + return false; + } + } else if (!groupingId.equals(other.groupingId)) { + return false; + } + return true; + } +} \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/IUserManagementService.java =================================================================== diff -u -rf92865513dd2beca642af28ab42096ee4849ac32 -re923dff715d473f8bb19d3593f1419662544111c --- lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/IUserManagementService.java (.../IUserManagementService.java) (revision f92865513dd2beca642af28ab42096ee4849ac32) +++ lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/IUserManagementService.java (.../IUserManagementService.java) (revision e923dff715d473f8bb19d3593f1419662544111c) @@ -27,12 +27,14 @@ import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.Vector; import org.lamsfoundation.lams.themes.Theme; import org.lamsfoundation.lams.usermanagement.ForgotPasswordRequest; import org.lamsfoundation.lams.usermanagement.Organisation; import org.lamsfoundation.lams.usermanagement.OrganisationGroup; +import org.lamsfoundation.lams.usermanagement.OrganisationGrouping; import org.lamsfoundation.lams.usermanagement.OrganisationType; import org.lamsfoundation.lams.usermanagement.Role; import org.lamsfoundation.lams.usermanagement.User; @@ -532,5 +534,5 @@ /** * Stores organisation (course) groups and removes the unnecessary ones. */ - public void saveOrganisationGroups(Integer organisationId, List newGroups); + public void saveOrganisationGrouping(OrganisationGrouping grouping, Collection newGroups); } \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/UserManagementService.java =================================================================== diff -u -rf92865513dd2beca642af28ab42096ee4849ac32 -re923dff715d473f8bb19d3593f1419662544111c --- lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/UserManagementService.java (.../UserManagementService.java) (revision f92865513dd2beca642af28ab42096ee4849ac32) +++ lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/UserManagementService.java (.../UserManagementService.java) (revision e923dff715d473f8bb19d3593f1419662544111c) @@ -46,6 +46,7 @@ import org.lamsfoundation.lams.usermanagement.ForgotPasswordRequest; import org.lamsfoundation.lams.usermanagement.Organisation; import org.lamsfoundation.lams.usermanagement.OrganisationGroup; +import org.lamsfoundation.lams.usermanagement.OrganisationGrouping; import org.lamsfoundation.lams.usermanagement.OrganisationType; import org.lamsfoundation.lams.usermanagement.Role; import org.lamsfoundation.lams.usermanagement.User; @@ -185,38 +186,42 @@ } return user; } - - @SuppressWarnings("unchecked") - public void saveOrganisationGroups(Integer organisationId, List newGroups) { - List existingGroups = findByProperty(OrganisationGroup.class, - "organisationId", organisationId); - + + public void saveOrganisationGrouping(OrganisationGrouping grouping, Collection newGroups) { + if (grouping.getGroupingId() == null) { + grouping.setGroups(new HashSet()); + baseDAO.insert(grouping); + } + + Set obsoleteGroups = new HashSet(grouping.getGroups()); for (OrganisationGroup newGroup : newGroups) { OrganisationGroup existingGroup = null; // check if group already exists - for (OrganisationGroup existingGroupCandidate : existingGroups) { + for (OrganisationGroup existingGroupCandidate : grouping.getGroups()) { if (existingGroupCandidate.equals(newGroup)) { existingGroup = existingGroupCandidate; break; } } - + if (existingGroup == null) { + newGroup.setGroupingId(grouping.getGroupingId()); // it is a new group, so add it + grouping.getGroups().add(newGroup); baseDAO.insert(newGroup); } else { - // it is an existing group, update it - existingGroups.remove(existingGroup); - + obsoleteGroups.remove(existingGroup); + existingGroup.setName(newGroup.getName()); existingGroup.setUsers(newGroup.getUsers()); baseDAO.update(existingGroup); } } - - // groups which were not listed are meant to be removed - for (OrganisationGroup obsoleteExistingGroup : existingGroups) { - delete(obsoleteExistingGroup); + + // remove gropus from DB + for (OrganisationGroup obsoleteGroup : obsoleteGroups) { + grouping.getGroups().remove(obsoleteGroup); + baseDAO.delete(obsoleteGroup); } }