Index: lams_central/src/java/org/lamsfoundation/lams/webservice/SPEnrolmentServlet.java =================================================================== diff -u -r286ef7c98baa533571da3d6af47ebc0aff0742f4 -rbbd3fae64f21997ab27690bb74f20e9b6e4af61d --- lams_central/src/java/org/lamsfoundation/lams/webservice/SPEnrolmentServlet.java (.../SPEnrolmentServlet.java) (revision 286ef7c98baa533571da3d6af47ebc0aff0742f4) +++ lams_central/src/java/org/lamsfoundation/lams/webservice/SPEnrolmentServlet.java (.../SPEnrolmentServlet.java) (revision bbd3fae64f21997ab27690bb74f20e9b6e4af61d) @@ -133,7 +133,7 @@ } // split each line into list of trimmed pieces - Map>> linesByMode = Files.readAllLines(fileInput).parallelStream().unordered() + List> allLines = Files.readAllLines(fileInput).parallelStream().unordered() .map(line -> Arrays.stream(line.split(DELIMITER)).map(elem -> elem.trim()) .collect(Collectors.toList())) // filter out malformed rows @@ -149,59 +149,69 @@ } // throw an exception when a row is malformed rather than silently discard it throw new RuntimeException("Malformed row: " + String.join(DELIMITER, row)); - }).collect(Collectors.groupingByConcurrent(row -> row.get(6))); + }).collect(Collectors.toList()); - if (linesByMode.isEmpty()) { + if (allLines.isEmpty()) { throw new ServletException("File is empty"); } + // map of course code (ID) -> course name + ConcurrentMap courses = allLines.parallelStream().unordered().collect( + Collectors.toConcurrentMap(elem -> elem.get(0), elem -> elem.get(1), (elem1, elem2) -> elem1)); + + // map of user login -> user ID + Map userIDs = new HashMap<>(); + + // find sysadmin as he/she will be the creator of organisations + Organisation rootOrganisation = userManagementService.getRootOrganisation(); + Integer creatorId = rootOrganisation.getCreatedBy().getUserId(); + + // map of user login -> email, first name + // for learner email is login, for staff it is a different ID in email format + ConcurrentMap allUsersMapped = allLines.parallelStream().unordered() + .collect(Collectors.toConcurrentMap( + elem -> elem.get(6).equals(Mode.STAFF.getRole()) + || elem.get(6).equals(Mode.MANAGER.getRole()) ? elem.get(3) : elem.get(5), + elem -> new String[] { elem.get(5), elem.get(4) }, (elem1, elem2) -> elem1)); + + Integer extServerSid = extServer.getSid(); + // load all users from DB which are present in the output file + // map of user login -> user + Map allExistingUsers = userManagementService + .findByPropertyValues(User.class, "login", allUsersMapped.keySet()).parallelStream() + .collect(Collectors.toConcurrentMap(User::getLogin, u -> u)); + // load all ext users from DB which are present in the output file + // map of user login -> extUser + Map allExistingExtUsers = userManagementService + .findByPropertyValues(ExtUserUseridMap.class, "extUsername", allExistingUsers.keySet()) + .parallelStream().filter(e -> e.getExtServer().getSid().equals(extServerSid)) + .collect(Collectors.toConcurrentMap(ExtUserUseridMap::getExtUsername, e -> e)); + // CREATE USERS and ext users + Set allUsersParsed = createUsers(extServer, creatorId, allUsersMapped, userIDs, allExistingUsers, + allExistingExtUsers); + + // map lines into corresponding roles + Map>> linesByMode = allLines.stream() + .collect(Collectors.groupingByConcurrent(row -> row.get(6))); + for (String role : Mode.getAllRoles()) { - List> lines = linesByMode.get(role); - if (lines == null) { - continue; - } - logger.info("Processing \"" + role + "\" role"); + List> lines = linesByMode.get(role); // it is easier to detect whether we process managers or staff or learners just once // than for each user - they do not come together anyway final Mode mode = role.equals(Mode.STAFF.getRole()) ? Mode.STAFF : (role.equals(Mode.MANAGER.getRole()) ? Mode.MANAGER : Mode.LEARNER); - // map of course code (ID) -> course name - ConcurrentMap courses = lines.parallelStream().unordered().collect(Collectors - .toConcurrentMap(elem -> elem.get(0), elem -> elem.get(1), (elem1, elem2) -> elem1)); + if (lines == null) { + // always process manager role, even if there are no managers + if (mode == Mode.MANAGER) { + lines = List.of(); + } else { + continue; + } + } - // map of user login -> email, first name - // for learner email is login, for staff it is a different ID in email format - ConcurrentMap users = lines.parallelStream().unordered() - .collect(Collectors.toConcurrentMap( - elem -> mode == Mode.STAFF || mode == Mode.MANAGER ? elem.get(3) : elem.get(5), - elem -> new String[] { elem.get(5), elem.get(4) }, (elem1, elem2) -> elem1)); - - // map of user login -> user ID - Map userIDs = new HashMap<>(); - - // find sysadmin as he/she will be the creator of organisations - Organisation rootOrganisation = userManagementService.getRootOrganisation(); - Integer creatorId = rootOrganisation.getCreatedBy().getUserId(); - - Integer extServerSid = extServer.getSid(); - // load all users from DB which are present in the output file - // map of user login -> user - Map allExistingUsers = userManagementService - .findByPropertyValues(User.class, "login", users.keySet()).parallelStream() - .collect(Collectors.toConcurrentMap(User::getLogin, u -> u)); - // load all ext users from DB which are present in the output file - // map of user login -> extUser - Map allExistingExtUsers = userManagementService - .findByPropertyValues(ExtUserUseridMap.class, "extUsername", allExistingUsers.keySet()) - .parallelStream().filter(e -> e.getExtServer().getSid().equals(extServerSid)) - .collect(Collectors.toConcurrentMap(ExtUserUseridMap::getExtUsername, e -> e)); - // CREATE USERS and ext users - Set allUsersParsed = createUsers(extServer, creatorId, users, userIDs, allExistingUsers, - allExistingExtUsers); - // map of user login -> course ID -> role IDs // for all users which are present in the output file Map>> allExistingRoles = userManagementService @@ -229,6 +239,7 @@ AtomicInteger mappingsProcessed = new AtomicInteger(); logger.info("Processing courses and assigments"); + for (String courseCode : courses.keySet()) { Organisation course = allExistingOrganisations.get(courseCode); @@ -607,58 +618,67 @@ Role.GROUP_MANAGER, true); // go through each user - for (String login : mappings.get(courseCode)) { - mappingsProcessed.incrementAndGet(); + List courseMappings = mappings.get(courseCode); + if (courseMappings != null) { + for (String login : courseMappings) { + mappingsProcessed.incrementAndGet(); - // check if the user is already a manager is the course - // if so, there is nothing to do - boolean userAlreadyAssigned = false; - Integer userId = userIDs.get(login); - Iterator courseUserIterator = courseUsers.iterator(); - while (courseUserIterator.hasNext()) { - if (userId.equals(courseUserIterator.next().getUserId())) { - courseUserIterator.remove(); - userAlreadyAssigned = true; - break; + // check if the user is already a manager is the course + // if so, there is nothing to do + boolean userAlreadyAssigned = false; + Integer userId = userIDs.get(login); + Iterator courseUserIterator = courseUsers.iterator(); + while (courseUserIterator.hasNext()) { + if (userId.equals(courseUserIterator.next().getUserId())) { + courseUserIterator.remove(); + userAlreadyAssigned = true; + break; + } } - } - if (userAlreadyAssigned) { - continue; - } + if (userAlreadyAssigned) { + continue; + } - // the user is not a manager yet, so assign him the role - Map> existingCoursesRoles = allExistingRoles.get(login); - Set existingCourseRoles = existingCoursesRoles == null ? null - : allExistingRoles.get(login).get(courseId); - if (existingCourseRoles == null) { - existingCourseRoles = new HashSet<>(); - } - existingCourseRoles.add(Role.ROLE_GROUP_MANAGER); + // the user is not a manager yet, so assign him the role + Map> existingCoursesRoles = allExistingRoles.get(login); + Set existingCourseRoles = existingCoursesRoles == null ? null + : allExistingRoles.get(login).get(courseId); + if (existingCourseRoles == null) { + existingCourseRoles = new HashSet<>(); + } + existingCourseRoles.add(Role.ROLE_GROUP_MANAGER); - User user = allExistingUsers.get(login); - userManagementService.setRolesForUserOrganisation(user, course, - existingCourseRoles.stream().map(String::valueOf).collect(Collectors.toList()), false); + User user = allExistingUsers.get(login); + userManagementService.setRolesForUserOrganisation(user, course, + existingCourseRoles.stream().map(String::valueOf).collect(Collectors.toList()), false); - String message = "Group manager \"" + login + "\" added to course"; - logger.info(message); - logEventService.logEvent(LogEvent.TYPE_USER_ORG_ADMIN, creatorId, null, null, null, - "SPEnrolment: " + message); + String message = "Group manager \"" + login + "\" added to course"; + logger.info(message); + logEventService.logEvent(LogEvent.TYPE_USER_ORG_ADMIN, creatorId, null, null, null, + "SPEnrolment: " + message); + } } // user is a group manager, but he should not; remove him role from course for (User user : courseUsers) { Map> existingCoursesRoles = allExistingRoles.get(user.getLogin()); - Set existingSubcourseRoles = existingCoursesRoles == null ? null - : existingCoursesRoles.get(courseId); - if (existingSubcourseRoles != null) { - existingSubcourseRoles.remove(Role.ROLE_GROUP_MANAGER); - userManagementService.setRolesForUserOrganisation(user.getUserId(), courseId, existingSubcourseRoles); - - String message = "Group manager \"" + user.getLogin() + "\" removed from course " + courseId; - logger.info(message); - logEventService.logEvent(LogEvent.TYPE_USER_ORG_ADMIN, creatorId, null, null, null, - "SPEnrolment: " + message); + Set existingSubcourseRoles = null; + if (existingCoursesRoles == null) { + existingSubcourseRoles = Set.of(); + } else { + existingSubcourseRoles = existingCoursesRoles.get(courseId); + if (existingSubcourseRoles == null) { + existingSubcourseRoles = Set.of(); + } else { + existingSubcourseRoles.remove(Role.ROLE_GROUP_MANAGER); + } } + userManagementService.setRolesForUserOrganisation(user.getUserId(), courseId, existingSubcourseRoles); + + String message = "Group manager \"" + user.getLogin() + "\" removed from course " + courseId; + logger.info(message); + logEventService.logEvent(LogEvent.TYPE_USER_ORG_ADMIN, creatorId, null, null, null, + "SPEnrolment: " + message); } } Index: lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/UserManagementService.java =================================================================== diff -u -r351f9417a32d396911387eeef3117fd40be35b7c -rbbd3fae64f21997ab27690bb74f20e9b6e4af61d --- lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/UserManagementService.java (.../UserManagementService.java) (revision 351f9417a32d396911387eeef3117fd40be35b7c) +++ lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/UserManagementService.java (.../UserManagementService.java) (revision bbd3fae64f21997ab27690bb74f20e9b6e4af61d) @@ -784,6 +784,14 @@ } } if (uors.isEmpty()) { + user.getUserOrganisations().remove(uo); + Iterator userOrganisationIterator = org.getUserOrganisations().iterator(); + while (userOrganisationIterator.hasNext()) { + if (uo.getUserOrganisationId().equals(userOrganisationIterator.next().getUserOrganisationId())) { + userOrganisationIterator.remove(); + break; + } + } delete(uo); } else { uo.setUserOrganisationRoles(uors);