1 /*******************************************************************************
2 * Copyright � Igor Barma, Alexandre Desoubeaux, Christian Martel, Eric Brun, Mathieu Amblard, Gwenael Gevet, Pierre Guillot, 2012
3 * Copyright Alexandre Desoubeaux, Christian Martel, Cedric Lecarpentier, Alexandre Lefevre, Marc Salvat 2014-2016
4 * Copyright Alexandre Desoubeaux, Christian Martel, Cedric Lecarpentier, Marc Salvat, Marc Suarez, Harifetra Ramamonjy 2017
6 * This file is part of the work and learning management system Pentila Nero.
8 * Pentila Nero is free software. You can redistribute it and/or modify since
9 * you respect the terms of either (at least one of the both license) :
10 * - under the terms of the GNU Affero General Public License as
11 * published by the Free Software Foundation, either version 3 of the
12 * License, or (at your option) any later version.
13 * - the CeCILL-C as published by CeCILL-C; either version 1 of the
14 * License, or any later version
15 * - the GNU Lesser General Public License as published by the
16 * Free Software Foundation, either version 3 of the license,
17 * or (at your option) any later version.
19 * There are special exceptions to the terms and conditions of the
20 * licenses as they are applied to this software. View the full text of
21 * the exception in file LICENSE-PROJECT.txt in the directory of this software
24 * Pentila Nero is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * Licenses for more details.
29 * You should have received a copy of the GNU Affero General Public License
30 * and the CeCILL-C and the GNU Lesser General Public License along with
31 * Pentila Nero. If not, see :
32 * <http://www.gnu.org/licenses/> and
33 * <http://www.cecill.info/licences.fr.html>.
34 ******************************************************************************/
35 package com.pentila.entSavoie.synchroLdap.impl;
37 import java.util.ArrayList;
38 import java.util.HashMap;
39 import java.util.List;
42 import javax.naming.NamingException;
43 import javax.naming.directory.Attribute;
44 import javax.naming.directory.Attributes;
46 import com.liferay.contacts.util.OrganizationConstants;
47 import com.liferay.contacts.util.OrganizationFilter;
48 import com.liferay.portal.kernel.dao.orm.QueryUtil;
49 import com.liferay.portal.kernel.log.Log;
50 import com.liferay.portal.kernel.log.LogFactoryUtil;
51 import com.liferay.portal.kernel.workflow.WorkflowConstants;
52 import com.liferay.portal.model.Group;
53 import com.liferay.portal.model.Organization;
54 import com.liferay.portal.model.Role;
55 import com.liferay.portal.model.User;
56 import com.liferay.portal.model.UserGroup;
57 import com.liferay.portal.model.UserGroupRole;
58 import com.liferay.portal.security.ldap.LDAPConstants;
59 import com.liferay.portal.service.GroupLocalServiceUtil;
60 import com.liferay.portal.service.OrganizationLocalServiceUtil;
61 import com.liferay.portal.service.RoleLocalServiceUtil;
62 import com.liferay.portal.service.UserGroupLocalServiceUtil;
63 import com.liferay.portal.service.UserGroupRoleLocalServiceUtil;
64 import com.liferay.portal.service.UserLocalServiceUtil;
65 import com.pentila.entSavoie.ENTRolesConstants;
66 import com.pentila.entSavoie.cahierDeTexte.util.CDTColorUtil;
67 import com.pentila.entSavoie.cdt.model.SchoolSubject;
68 import com.pentila.entSavoie.cdt.model.Subject;
69 import com.pentila.entSavoie.cdt.service.SchoolSubjectLocalServiceUtil;
70 import com.pentila.entSavoie.cdt.service.SubjectLocalServiceUtil;
71 import com.pentila.entSavoie.gestionVieScolaire.model.SynchroConfig;
72 import com.pentila.entSavoie.gestionVieScolaire.service.SynchroConfigLocalServiceUtil;
73 import com.pentila.entSavoie.synchroLdap.exceptions.UserSynchronizationException;
74 import com.pentila.entSavoie.userProperties.model.UserRelationship;
75 import com.pentila.entSavoie.userProperties.service.UserRelationshipLocalServiceUtil;
76 import com.pentila.entSavoie.userRelationship.UserRelationshipConstants;
77 import com.pentila.entSavoie.utils.ENTMainUtilsLocalServiceUtil;
78 import com.pentila.entSavoie.utils.ENTOrganizationsUtil;
81 * Class used to manage memberships during the synchronization process
82 * @author Cedric Lecarpentier
85 public class MembershipManager {
87 private static Log _log = LogFactoryUtil.getLog(MembershipManager.class);
90 private static long companyId;
92 // This map indicates, for a given student userId, if there was a membership modification or not => fasten its parent's synchronization
93 private static Map<Long, Boolean> childModificationsMap;
95 // The list of school org ids that do use AAF for membership management
96 private static List<Long> schoolsUsingAAFMode;
98 // The list of all ENT users (used to determine all users except stdents, parents and teachers)
99 private static List<Long> allENTUserIds;
101 // The root organization
102 private static Organization rootOrg;
105 * Entry point for managing memberships during the synchronization process
107 * @throws NamingException
110 public static void manageMemberships(long _companyId) throws NamingException, Exception {
112 _log.info("Start manageMemberships");
113 companyId = _companyId;
115 initMembership(companyId);
117 // Get all users in DB
118 List<User> allENTUsers = UserLocalServiceUtil.getUsers(QueryUtil.ALL_POS, QueryUtil.ALL_POS);
119 allENTUserIds = new ArrayList<Long>();
120 for (User user : allENTUsers) {
121 allENTUserIds.add(user.getUserId());
124 manageAllStudentsMembership();
125 manageAllParentsMemberships();
126 manageAllTeachersMemberships();
127 manageAllOtherProfilesMemberships();
132 * Manage memberships for all students
134 private static void manageAllStudentsMembership() {
137 Role studentRole = RoleLocalServiceUtil.getRole(companyId, ENTRolesConstants.NATIONAL_1);
138 List<User> students = UserLocalServiceUtil.getRoleUsers(studentRole.getRoleId());
139 _log.info("Manage student memberships : fetched "+students.size()+" students ...");
141 // Loop over students
142 long studentAll0 = System.currentTimeMillis();
144 for (User student : students) {
145 if (SynchronizationManager.getUserAttributesMap().containsKey(student.getScreenName())) {
147 // Skip inactive students
148 if (student.getStatus() == WorkflowConstants.STATUS_INACTIVE) {
152 long studentTime0 = System.currentTimeMillis();
153 Attributes studentAttributes = SynchronizationManager.getUserAttributesMap().get(student.getScreenName());
154 manageStudentMembership(student, studentAttributes);
156 long studentTime1 = System.currentTimeMillis();
157 _log.info("Student membership took "+(studentTime1 - studentTime0)+" ms : "+studentIdx + "/" + students.size());
160 allENTUserIds.remove(student.getUserId());
162 long studentAll1 = System.currentTimeMillis();
163 int studentMembershipTime = (int)((studentAll1 - studentAll0)/60000);
164 SynchronizationReport.setStudentMembershipTime(studentMembershipTime);
165 _log.info("Whole student membership took "+studentMembershipTime+" minutes");
166 } catch (Exception e) {
167 _log.error("Error when managing student memberships ", e);
172 * Manage membership for a given student
174 * @param userAttributes
176 private static void manageStudentMembership(User student, Attributes userAttributes) {
179 // Get existing orgs in which the student is member
180 List<Organization> existingOrgsList = OrganizationLocalServiceUtil.getUserOrganizations(student.getUserId());
181 _log.info("Manage membership for student "+student.getFullName()+" : "+existingOrgsList.size()+" existing classes and groups");
183 // This is the list of organization ids that need to be kept attached to the current user
184 List<Long> organizationIdsToKeep = new ArrayList<Long>();
186 Organization rattachSchool = SynchronizationManager.getRattachSchool(student);
187 if (rattachSchool == null) {
188 _log.error("No rattach school found for user "+student.getFullName());
191 organizationIdsToKeep.add(rattachSchool.getOrganizationId());
193 // Skip user if its rattach school does not use 'AAF' datasource (but 'EDT' or 'UDT')
194 if (!isSchoolImportTypeAAF(rattachSchool.getOrganizationId())) {
195 _log.info("This school does not use AAF for membership synchronization => skipping user ...");
196 removeStudentOtherOrgs(student, rattachSchool, existingOrgsList);
201 organizationIdsToKeep.add(rootOrg.getOrganizationId());
203 // Keep manually added organizations
204 List<Long> manuallyAddedOrgIds = getManuallyAddedOrganizations(student);
205 organizationIdsToKeep.addAll(manuallyAddedOrgIds);
207 // Maps used for further new membership addition
208 List<Organization> newStudentOrgs = new ArrayList<Organization>();
209 Map<Long, UserGroup> newStudentUserGroupsMap = new HashMap<Long, UserGroup>();
211 // Get 'ENTEleveClasses' and 'ENTEleveGroupes' attributes
212 List<String> userClassesAndGroups = SynchronizationUtils.getUserClassesAndGroups(student, userAttributes);
213 _log.info("Manage membership for student "+student.getFullName()+" : "+userClassesAndGroups.size()+" new classes and groups");
215 // Add student membership to these groups and classes
216 for (String className : userClassesAndGroups) {
218 //_log.info("Manage membership for student "+student.getFullName()+" : new class/group is "+className);
220 UserGroup userGroup = UserGroupLocalServiceUtil.getUserGroup(companyId, className);
221 Map<String, Organization> map = SynchronizationUtils.checkAndGetOrganizationCreation(userGroup);
222 if (map.keySet().size() > 0) {
223 Organization studentOrg = map.get("classe");
224 newStudentOrgs.add(studentOrg);
225 newStudentUserGroupsMap.put(studentOrg.getOrganizationId(), userGroup);
229 List<Organization> newStudentOrgsCopy = new ArrayList<Organization>(newStudentOrgs);
231 // Will be used to determine if there are any changes in the student's membership
232 // and then if there will be changes for the parent
233 int nbRemovedOrg = 0;
234 int nbSkippedNewOrg = 0;
236 // Loop over the existing child organizations
237 for (Organization studentOrg : existingOrgsList) {
239 //_log.info("Testing membership for student "+student.getFullName()+" : testing for removal class/group "+studentOrg.getName());
241 // Skip archived organizations
242 if (!studentOrg.getPreferences().getValue("migrate", "none").equals("none")) {
243 //_log.info(" Skipping archived org "+studentOrg.getName());
247 // Skip organizations that we want to keep
248 boolean isToKeep = false;
249 for (Long orgIdToKeep : organizationIdsToKeep) {
250 if (studentOrg.getOrganizationId() == orgIdToKeep) {
255 //_log.info(" Skipping org to keep : "+studentOrg.getName());
259 // Skip if organization was just added
261 for (Organization newStudentOrg : newStudentOrgs) {
262 if (studentOrg.getOrganizationId() == newStudentOrg.getOrganizationId()) {
264 newStudentOrgsCopy.remove(newStudentOrg);
268 //_log.info(" Skipping new school org "+studentOrg.getName());
273 _log.info("Remove student "+student.getUserId()+" from organization "+studentOrg.getName());
275 UserLocalServiceUtil.unsetOrganizationUsers(studentOrg.getOrganizationId(), new long[]{student.getUserId()});
277 SynchronizationReport.notifyStudentMembershipRemoval(student, studentOrg);
280 // Store if there was modifications (for parents)
281 if (nbRemovedOrg == 0 && nbSkippedNewOrg == userClassesAndGroups.size()) {
282 _log.info("There was no modification for child "+student.getFullName());
283 childModificationsMap.put(student.getUserId(), false);
285 _log.info("There was at least 1 modification for child "+student.getFullName()+" : "+nbRemovedOrg+" removed org, "+nbSkippedNewOrg+" skipped new orgs for "+userClassesAndGroups.size()+" new orgs.");
286 childModificationsMap.put(student.getUserId(), true);
289 // Add remaining organizations (except manually added)
290 for (Organization orgToAdd : newStudentOrgsCopy) {
291 if (manuallyAddedOrgIds.contains(orgToAdd.getOrganizationId())) {
292 _log.info("Do not add org "+orgToAdd.getName()+" to user "+student.getFullName()+" because was manually added");
295 UserLocalServiceUtil.addOrganizationUsers(orgToAdd.getOrganizationId(), new long[]{student.getUserId()});
296 // UserGroup userGroup = newStudentUserGroupsMap.get(orgToAdd.getOrganizationId());
298 // UserLocalServiceUtil.addUserGroupUsers(userGroup.getUserGroupId(), new long[] { student.getUserId() });
299 // } catch (Exception e) {
300 // _log.error("Could not add student "+student.getFullName()+" into userGroup "+userGroup.getName());
302 _log.info("Add new organization "+orgToAdd.getName()+" to user "+student.getFullName());
303 SynchronizationReport.notifyStudentMembershipCreation(student, orgToAdd);
305 } catch (Exception e) {
306 _log.error("Error when managing memberships for student "+student.getFullName(), e);
314 * Removes membership for all other organizations that are not rattach school or its child orgs
315 * @param rattachSchool
318 private static void removeStudentOtherOrgs(User student, Organization rattachSchool, List<Organization> studentOrgs) {
320 List<Long> manuallyAddedOrgIds = getManuallyAddedOrganizations(student);
321 for (Organization existingOrg : studentOrgs) {
323 if (existingOrg.getOrganizationId() != rootOrg.getOrganizationId()
324 && existingOrg.getOrganizationId() != rattachSchool.getOrganizationId()
325 && existingOrg.getParentOrganizationId() != rattachSchool.getOrganizationId()) {
327 if (manuallyAddedOrgIds.contains(existingOrg.getOrganizationId())) {
328 //_log.info("+++++ KEEP manually added org "+existingOrg.getName()+" for student "+student.getFullName() + " whereas its rattach school is "+rattachSchool.getName());
329 } else if (OrganizationFilter.isArchived(existingOrg)) {
330 //_log.info("+++++ KEEP archived org "+existingOrg.getName()+" for student "+student.getFullName() + " whereas its rattach school is "+rattachSchool.getName());
332 _log.info("+++++ REMOVE Org "+existingOrg.getName()+" (id "+existingOrg.getOrganizationId()+") for student "+student.getFullName() + " whereas its rattach school is "+rattachSchool.getName());
333 childModificationsMap.put(student.getUserId(), true);
335 UserLocalServiceUtil.unsetOrganizationUsers(existingOrg.getOrganizationId(), new long[]{student.getUserId()});
336 } catch (Exception e) {
337 _log.error("Error when removing student other membership", e);
341 } catch (Exception e) {
342 _log.error("Error when removing obsolete organization " + existingOrg.getName()+" for student "+student.getFullName(), e);
349 * Manage memberships for all parents
351 private static void manageAllParentsMemberships() {
354 Role parentRole = RoleLocalServiceUtil.getRole(companyId, ENTRolesConstants.NATIONAL_2);
355 List<User> parents = UserLocalServiceUtil.getRoleUsers(parentRole.getRoleId());
356 _log.info("Manage parent memberships : fetched "+parents.size()+" parents ...");
359 long parentAll0 = System.currentTimeMillis();
361 for (User parent : parents) {
363 // Skip inactive users
364 if (parent.getStatus() == WorkflowConstants.STATUS_INACTIVE) {
368 long parentTime0 = System.currentTimeMillis();
369 manageParentMembership(parent);
370 allENTUserIds.remove(parent.getUserId());
372 long parentTime1 = System.currentTimeMillis();
373 _log.info("Parent membership took "+(parentTime1 - parentTime0)+" ms : "+parentIdx + "/" + parents.size());
375 long parentAll1 = System.currentTimeMillis();
376 int parentMembershipTime = (int)((parentAll1 - parentAll0)/60000);
377 SynchronizationReport.setParentMembershipTime(parentMembershipTime);
378 _log.info("Whole parent membership took "+parentMembershipTime+" minutes");
379 } catch (Exception e) {
380 _log.error("Error when managing memberships for all parents ", e);
386 * Manage parent memberships:
387 * - loop over children orgs
388 * - add parent into parent-related organizations
389 * - get 'obsolete' organizations and remove them
392 private static void manageParentMembership(User parent) {
394 _log.debug("Manage membership for parent "+parent.getUserId());
396 // This is the list of organization ids that need to be kept attached to the current user
397 List<Long> organizationIdsToKeep = new ArrayList<Long>();
400 organizationIdsToKeep.add(rootOrg.getOrganizationId());
402 // Keep manually added organizations
403 List<Long> manuallyAddedOrgIds = getManuallyAddedOrganizations(parent);
404 organizationIdsToKeep.addAll(manuallyAddedOrgIds);
409 List<UserRelationship> relations = UserRelationshipLocalServiceUtil.getUserRelationshipByToUserIdRelationType(parent.getUserId(), UserRelationshipConstants.PARENT_RELATION);
410 if (relations != null) {
412 // If no update was performed on children => skip parent
413 boolean modifDoneOnChildren = false;
414 for (UserRelationship relation : relations) {
415 if (childModificationsMap.containsKey(relation.getFromUserId()) && childModificationsMap.get(relation.getFromUserId())) {
416 modifDoneOnChildren = true;
419 if (!modifDoneOnChildren && !ENTMainUtilsLocalServiceUtil.isForceParentMembership(companyId)) {
420 _log.info("No need to continue with this parent because no update was done for its children : "+parent.getFullName());
424 // Loop over child relationships to ADD all relationships
425 for (UserRelationship relation : relations) {
426 User child = UserLocalServiceUtil.getUser(relation.getFromUserId());
427 _log.info("Parent "+parent.getFullName()+"(id "+parent.getUserId()+") has child "+child.getFullName()+" (id "+child.getUserId()+")");
429 Organization rattachSchool = SynchronizationManager.getRattachSchool(child);
430 Organization parentRattachSchool = ENTOrganizationsUtil.getOrCreateOrganization(companyId, rattachSchool.getName() + OrganizationConstants.ORG_SUFFIX_PARENTS, rattachSchool.getOrganizationId());
432 organizationIdsToKeep.add(rattachSchool.getOrganizationId());
433 organizationIdsToKeep.add(parentRattachSchool.getOrganizationId());
435 // Save child-parent link for reporting
436 SynchronizationReport.addChildParentLink(child, parent);
438 // Add parent into its child organizations
439 List<Organization> childOrgList = OrganizationLocalServiceUtil.getUserOrganizations(relation.getFromUserId());
440 for (Organization childOrg : childOrgList) {
442 // Skip archived organizations
443 if (!childOrg.getPreferences().getValue("migrate", "none").equals("none")) {
448 if (childOrg.getOrganizationId() == rootOrg.getOrganizationId()) {
452 Organization parentOrg = ENTOrganizationsUtil.getOrCreateOrganization(companyId, childOrg.getName() + OrganizationConstants.ORG_SUFFIX_PARENTS, childOrg.getOrganizationId());
453 SynchronizationUtils.addOrRemoveUserFromOrg(parent, childOrg, true, OrganizationConstants.ORG_SUFFIX_PARENTS);
454 organizationIdsToKeep.add(parentOrg.getOrganizationId());
455 _log.info("Added parent "+parent.getFullName()+" to organization "+childOrg.getName()+OrganizationConstants.ORG_SUFFIX_PARENTS+" (id "+parentOrg.getOrganizationId()+")");
462 // Now loop over existing organizations in order to REMOVE obsolete organizations
464 List<Organization> parentOrgs = OrganizationLocalServiceUtil.getUserOrganizations(parent.getUserId());
465 for (Organization parentOrg : parentOrgs) {
467 //_log.info(" Testing for removal organization "+parentOrg.getName());
469 // Skip archived organizations
470 if (!parentOrg.getPreferences().getValue("migrate", "none").equals("none")) {
474 // Skip organizations to keep
475 if (doKeepOrg(parentOrg, organizationIdsToKeep)) {
479 _log.info("Remove parent "+parent.getUserId()+" from organization "+parentOrg.getName());
480 UserLocalServiceUtil.unsetOrganizationUsers(parentOrg.getOrganizationId(), new long[]{parent.getUserId()});
483 } catch (Exception e) {
484 _log.error("Error while managing memberships for parent "+parent.getFullName(), e);
491 * Manage memberships for all teachers
493 private static void manageAllTeachersMemberships() {
496 Role teacherRole = RoleLocalServiceUtil.getRole(companyId, ENTRolesConstants.NATIONAL_3);
497 List<User> teachers = UserLocalServiceUtil.getRoleUsers(teacherRole.getRoleId());
498 _log.info("Manage teachers memberships : fetched "+teachers.size()+" teachers ...");
500 // Loop over teachers
501 long teacherAll0 = System.currentTimeMillis();
503 for (User teacher : teachers) {
504 if (SynchronizationManager.getUserAttributesMap().containsKey(teacher.getScreenName())) {
506 // Skip inactive teachers
507 if (teacher.getStatus() == WorkflowConstants.STATUS_INACTIVE) {
511 long teacherTime0 = System.currentTimeMillis();
512 Attributes teacherAttributes = SynchronizationManager.getUserAttributesMap().get(teacher.getScreenName());
513 manageTeacherMembership(teacher, teacherAttributes);
514 long teacherTime1 = System.currentTimeMillis();
516 _log.info("Teacher membership took "+(teacherTime1 - teacherTime0)+" ms : " + teacherIdx+"/"+teachers.size());
518 allENTUserIds.remove(teacher.getUserId());
520 long teacherAll1 = System.currentTimeMillis();
521 int teacherMembershipTime = (int)((teacherAll1 - teacherAll0)/60000);
522 SynchronizationReport.setTeacherMembershipTime(teacherMembershipTime);
523 _log.info("Whole teacher membership took "+teacherMembershipTime+" minutes");
524 } catch (Exception e) {
525 _log.error("Error when managing memberships for all teachers ", e);
531 * Manage memberships for a given teacher
532 * - get the required memberships, grouped by school
533 * - loop over all existing organizations, and remove the ones no longer needed
534 * - add the remaining organizations
536 * @param teacherAttributes
538 private static void manageTeacherMembership(User teacher, Attributes teacherAttributes) {
541 // Get existing orgs in which the teacher is member
542 List<Organization> existingOrgsList = OrganizationLocalServiceUtil.getUserOrganizations(teacher.getUserId());
543 _log.info("Manage membership for teacher "+teacher.getFullName()+" : "+existingOrgsList.size()+" existing classes and groups");
545 // This is the list of organization ids that need to be kept attached to the current user
546 List<Long> organizationIdsToKeep = new ArrayList<Long>();
548 // Map used for further new membership addition
549 List<Organization> newTeacherOrgs = new ArrayList<Organization>();
551 // Get the teacher groups and classes defined in the LDAP
552 // Key is the school orgId, value is the list of classes and groups in this school
553 Map<Organization, List<String>> teacherSchoolClassesMap = SynchronizationUtils.getTeacherSchoolClassesMap(teacher, teacherAttributes);
555 // List of org id for this user which as other type of import
556 List<Long> schoolIdIsNotAAFImport = new ArrayList<Long>();
558 for (Organization schoolOrg : teacherSchoolClassesMap.keySet()) {
560 _log.info(" Parsing school for teacher "+teacher.getFullName()+" : school is "+schoolOrg.getName());
562 // Skip this school if the school does not use 'AAF' datasource (but 'EDT' or 'UDT')
563 if (!isSchoolImportTypeAAF(schoolOrg.getOrganizationId())) {
564 schoolIdIsNotAAFImport.add(schoolOrg.getOrganizationId());
565 _log.info(" This school "+schoolOrg.getName()+" does not use AAF for membership synchronization => add teacher to school-level organizations only");
566 addUserToSchoolLevelOrgs(teacher, schoolOrg);
570 // Synchronize subjects
571 synchronizeSubjects(teacher, teacherAttributes, schoolOrg.getOrganizationId());
573 // Get the school-related orgs of the school org
574 List<Organization> schoolLevelOrgList = getSchoolLevelOrganizations(teacher, schoolOrg);
575 for (Organization orgaToKeep : schoolLevelOrgList) {
576 // Store for further addition
577 organizationIdsToKeep.add(orgaToKeep.getOrganizationId());
578 newTeacherOrgs.add(orgaToKeep);
581 if (teacherSchoolClassesMap.get(schoolOrg) == null) {
582 _log.info(" Manage membership for teacher "+teacher.getFullName()+" : has no class or group in school "+schoolOrg.getName());
585 _log.info(" Manage membership for teacher "+teacher.getFullName()+" : has "+teacherSchoolClassesMap.get(schoolOrg).size()+" classes/groups in school "+schoolOrg.getName());
588 // Loop over classes/groups of this organization
589 // This list may be empty => add teacher only into school-level orgs
590 for (String className : teacherSchoolClassesMap.get(schoolOrg)) {
592 UserGroup userGroup = UserGroupLocalServiceUtil.getUserGroup(companyId, className);
593 Map<String, Organization> map = SynchronizationUtils.checkAndGetOrganizationCreation(userGroup);
594 if (map.keySet().size() > 0) {
596 Organization teacherOrg = map.get("classe");
597 _log.info(" Manage membership for teacher "+teacher.getFullName()+" : new class/group is "+teacherOrg.getName());
598 // Store for further addition
599 newTeacherOrgs.add(teacherOrg);
601 // Get associated '- Parents' organization
602 if (isStudentClass(teacherOrg)) {
603 Organization newTeacherParentOrg = OrganizationLocalServiceUtil.getOrganization(companyId, teacherOrg.getName() + OrganizationConstants.ORG_SUFFIX_PARENTS);
604 _log.info(" Manage membership for teacher "+teacher.getFullName()+" : new class/group is "+newTeacherParentOrg.getName() + " (parent level)");
605 // Store for further addition
606 newTeacherOrgs.add(newTeacherParentOrg);
612 // Manage technical people (recorder as Nat_3 by default, but without classes nor groups)
613 if (teacherSchoolClassesMap.keySet().size() == 0) {
614 Organization rattachSchool = SynchronizationManager.getRattachSchool(teacher);
615 if (rattachSchool != null) {
616 List<Organization> schoolLevelOrgs = getSchoolLevelOrganizations(teacher, rattachSchool);
617 for (Organization schoolLevelOrg : schoolLevelOrgs) {
618 organizationIdsToKeep.add(schoolLevelOrg.getOrganizationId());
619 _log.info("This teacher has no class/group attached yet, adding org to the list of to-keep orgs: "+schoolLevelOrg.getName());
625 // Keep root organization
626 organizationIdsToKeep.add(rootOrg.getOrganizationId());
628 // Keep manually added organizations
629 List<Long> manuallyAddedOrgIds = getManuallyAddedOrganizations(teacher);
630 organizationIdsToKeep.addAll(manuallyAddedOrgIds);
632 // Synchronize main teacher role if needed and add this org list to the list of org ids to keep
633 List<Long> ppOrgIdList = synchronizeMainTeachersRole(teacher, teacherAttributes);
634 organizationIdsToKeep.addAll(ppOrgIdList);
636 List<Organization> newTeacherOrgsCopy = new ArrayList<Organization>(newTeacherOrgs);
638 // Loop over the existing teacher organizations
639 for (Organization teacherOrg : existingOrgsList) {
641 //verify if the org is in school which doesn't use AAF import
642 if(schoolIdIsNotAAFImport.contains(teacherOrg.getOrganizationId())
643 || schoolIdIsNotAAFImport.contains(teacherOrg.getParentOrganizationId())){
648 //_log.info(" Testing membership for teacher "+teacher.getFullName()+" : testing for removal class/group "+teacherOrg.getName());
650 // Skip if organization is in the membership list (let this test first)
651 boolean isToKeep = false;
652 for (Organization newTeacherOrg : newTeacherOrgs) {
653 if (teacherOrg.getOrganizationId() == newTeacherOrg.getOrganizationId()) {
655 newTeacherOrgsCopy.remove(newTeacherOrg);
662 // Skip archived organizations
663 if (!teacherOrg.getPreferences().getValue("migrate", "none").equals("none")) {
667 // Skip organizations to keep
668 if (doKeepOrg(teacherOrg, organizationIdsToKeep)) {
672 _log.info(" Remove teacher "+teacher.getFullName()+" from organization "+teacherOrg.getName());
673 UserLocalServiceUtil.unsetOrganizationUsers(teacherOrg.getOrganizationId(), new long[]{teacher.getUserId()});
674 SynchronizationReport.notifyTeacherMembershipRemoval(teacher, teacherOrg);
676 // Also remove teacher from associated parent org
678 if (isStudentClass(teacherOrg)) {
679 Organization teacherParentOrg = OrganizationLocalServiceUtil.getOrganization(companyId, teacherOrg.getName() + OrganizationConstants.ORG_SUFFIX_PARENTS);
680 UserLocalServiceUtil.unsetOrganizationUsers(teacherParentOrg.getOrganizationId(), new long[]{teacher.getUserId()});
681 _log.info(" Remove teacher "+teacher.getFullName()+" from organization "+teacherParentOrg.getName());
683 } catch (Exception e) {
684 _log.error("Error when removing teacher "+teacher.getFullName()+" from parent-related organization of org "+teacherOrg.getName());
688 // Add remaining organizations
689 for (Organization orgToAdd : newTeacherOrgsCopy) {
691 //verify if the org is in school which doesn't use AAF import
692 if(schoolIdIsNotAAFImport.contains(orgToAdd.getOrganizationId())
693 || schoolIdIsNotAAFImport.contains(orgToAdd.getParentOrganizationId())){
697 UserLocalServiceUtil.addOrganizationUsers(orgToAdd.getOrganizationId(), new long[]{teacher.getUserId()});
698 _log.info(" Add teacher "+teacher.getUserId()+" to organization "+orgToAdd.getName());
699 SynchronizationReport.notifyTeacherMembershipCreation(teacher, orgToAdd);
701 // Also add teacher into associated parent org
703 if (isStudentClass(orgToAdd)) {
704 Organization teacherParentOrgToAdd = OrganizationLocalServiceUtil.getOrganization(companyId, orgToAdd.getName() + OrganizationConstants.ORG_SUFFIX_PARENTS);
705 UserLocalServiceUtil.addOrganizationUsers(teacherParentOrgToAdd.getOrganizationId(), new long[]{teacher.getUserId()});
706 _log.info(" Add teacher "+teacher.getUserId()+" to organization "+teacherParentOrgToAdd.getName());
708 } catch (Exception e) {
709 _log.error("Error when adding teacher "+teacher.getFullName()+" into parent-related organization of org "+orgToAdd.getName());
714 } catch (Exception e) {
715 _log.error("Error when managing memberships for teacher "+teacher.getFullName(), e);
721 * Fetch groups and classes where the teacher is main teacher
722 * return the list of orgs he is main teacher
726 private static List<Long> synchronizeMainTeachersRole (final User teacher, final Attributes attrs) {
728 _log.info("Start synchronizing main teacher role ...");
729 // The list of oraganizations in which the teacher is PP
730 List<Long> ppOrgIdList = new ArrayList<Long>();
733 // Manage principal teachers
734 Role ppRole = RoleLocalServiceUtil.getRole(teacher.getCompanyId(), ENTRolesConstants.PROF_PRINCIPAL);
735 Role orgPPRole = RoleLocalServiceUtil.getRole(teacher.getCompanyId(), ENTRolesConstants.ORGANIZATION_PROF_PRINCIPAL);
737 // Build the list of existing groupIds where the teacher is PP
738 // From this list we will remove the new groupIds where the teacher is PP
739 // At the end, we will remove all remaining obsolete groupIds
740 List<UserGroupRole> existingUserGrpR = UserGroupRoleLocalServiceUtil.getUserGroupRoles(teacher.getUserId());
741 List<Long> ppGrpList = new ArrayList<Long>();
742 for (UserGroupRole ugr: existingUserGrpR){
743 if (ugr.getRoleId() == orgPPRole.getRoleId()) {
744 ppGrpList.add(ugr.getGroupId());
745 _log.info("Teacher "+teacher.getFullName()+" is currently PP for groupId "+ugr.getGroupId());
749 boolean needGlobalPPRole = false;
751 if (attrs.get(LDAPConstants.LDAP_ATTRIBUTE_ENTAUXENSCLASSESPRINCIPAL) != null){
753 for (int i=0; i < attrs.get(LDAPConstants.LDAP_ATTRIBUTE_ENTAUXENSCLASSESPRINCIPAL).size(); i++) {
755 String profPrincClasse = attrs.get(LDAPConstants.LDAP_ATTRIBUTE_ENTAUXENSCLASSESPRINCIPAL).get(i).toString();
757 // Get class name from attribute
758 profPrincClasse = profPrincClasse.substring(3, profPrincClasse.indexOf(","));
759 if (profPrincClasse.equals("fakeDn")) {
762 UserGroup ppClasseUserGroup = UserGroupLocalServiceUtil.getUserGroup(teacher.getCompanyId(), profPrincClasse);
763 Map<String, Organization> ppClasseOrg = SynchronizationUtils.checkAndGetOrganizationCreation(ppClasseUserGroup);
764 if (ppClasseOrg.keySet().size() > 0) {
766 Organization ppClasse = ppClasseOrg.get("classe");
767 Long ppUGId = ppClasse.getGroup().getGroupId();
768 _log.info("Teacher "+teacher.getFullName()+" is main teacher of class "+ppClasse.getName());
770 // Skip this org if the school org does not use 'AAF' datasource (but 'EDT' or 'UDT')
771 if(!isSchoolImportTypeAAF(ppClasse.getParentOrganizationId())){
772 _log.info("School is not AAF mode => skipping PP role for this teacher");
775 needGlobalPPRole = true;
778 ppOrgIdList.add(ppClasse.getOrganizationId());
780 if (ppGrpList.contains(ppUGId)) {
781 ppGrpList.remove(ppUGId);
783 // Add teacher to org if needed
784 if (!OrganizationLocalServiceUtil.hasUserOrganization(teacher.getUserId(), ppClasse.getOrganizationId())) {
785 UserLocalServiceUtil.addOrganizationUsers(ppClasse.getOrganizationId(), new long[]{teacher.getUserId()});
786 SynchronizationReport.notifyTeacherMembershipCreation(teacher, ppClasse);
788 // Add role to the user group
789 UserGroupRoleLocalServiceUtil.addUserGroupRoles(teacher.getUserId(), ppUGId, new long[] {orgPPRole.getRoleId()});
790 _log.info(" Adding teacher "+teacher.getFullName()+" main teacher of class "+ppClasse.getName());
794 catch (Exception exc) {
795 _log.error("Error when adding role to user "+teacher.getFullName(), exc);
800 // Remove PP role in obsolete groupIds
801 for (Long grpIdLoc: ppGrpList) {
803 _log.info("Delete PP role for teacher "+teacher.getFullName()+" in groupId "+grpIdLoc);
804 UserGroupRoleLocalServiceUtil.deleteUserGroupRoles(teacher.getUserId(), grpIdLoc, new long[] {orgPPRole.getRoleId()});
811 // Manage global PP role
812 Boolean isPPGlobal = RoleLocalServiceUtil.hasUserRole(teacher.getUserId(), ppRole.getRoleId());
813 if (needGlobalPPRole && !isPPGlobal) {
814 RoleLocalServiceUtil.addUserRoles(teacher.getUserId(), new long[] {ppRole.getRoleId()});
815 _log.info("Adding global PP role to teacher "+teacher.getFullName());
816 } else if (!needGlobalPPRole && isPPGlobal){
817 RoleLocalServiceUtil.unsetUserRoles(teacher.getUserId(), new long[] {ppRole.getRoleId()});
818 _log.info("Removing global PP role to teacher "+teacher.getFullName());
820 } catch (Exception e) {
821 _log.error("Error when managing principal teacher role for teacher "+teacher.getFullName(), e);
823 _log.info("Teacher "+teacher.getFullName()+ " is main teacher for "+ppOrgIdList.size()+ " classes");
830 * Manage memberships for all other users (non-student, non-parent and non-teachers)
832 private static void manageAllOtherProfilesMemberships () {
835 long otherAll0 = System.currentTimeMillis();
836 _log.info("At this point, remains "+allENTUserIds.size()+" users to manage membership ...");
837 for (Long userId: allENTUserIds) {
839 User user = UserLocalServiceUtil.getUser(userId);
841 // Skip inactive users
842 if (user.getStatus() == WorkflowConstants.STATUS_INACTIVE) {
846 Attributes userAttributes = SynchronizationManager.getUserAttributesMap().get(user.getScreenName());
848 manageOtherProfilesMembership(user, userAttributes);
850 long otherAll1 = System.currentTimeMillis();
851 int otherMembershipTime = (int)((otherAll1 - otherAll0)/1000);
852 SynchronizationReport.setOtherMembershipTime(otherMembershipTime);
853 _log.info("Whole other membership took "+otherMembershipTime+" seconds");
854 } catch (Exception e) {
855 _log.error("Error when managing memberships for all other profiles ", e);
861 * Manage memberships for a given user
863 * @param userAttributes
865 private static void manageOtherProfilesMembership(User user, Attributes userAttributes) {
867 _log.info("Managing memberships for user "+user.getFullName()+" (id "+user.getUserId()+")");
870 List<Organization> newUserOrgs = new ArrayList<Organization>();
872 List<Long> organizationIdsToKeep = new ArrayList<Long>();
873 organizationIdsToKeep.add(rootOrg.getOrganizationId());
875 // Get all ENTPersonFonction attributes, get associated schools and school-level organizations
876 // And add them to the keep list
877 List<Organization> entPersonFonctionOrgs = SynchronizationUtils.getEntPersonFonctionsSchools(user, userAttributes);
878 for (Organization entPersonFonctionOrg : entPersonFonctionOrgs) {
879 List<Organization> schoolLevelOrgs = getSchoolLevelOrganizations(user, entPersonFonctionOrg);
880 for (Organization schoolLevelOrg : schoolLevelOrgs) {
881 newUserOrgs.add(schoolLevelOrg);
885 if (newUserOrgs.isEmpty()) {
886 Organization etabRattachement = SynchronizationManager.getRattachSchool(user);
887 if (etabRattachement == null) {
888 _log.error("No attached etab in LDAP for user " + user.getFullName() + " (login " + user.getLogin()+")");
892 List<Organization> schoolLevelOrgs = getSchoolLevelOrganizations(user, etabRattachement);
893 for (Organization schoolLevelOrg : schoolLevelOrgs) {
894 if (!organizationIdsToKeep.contains(schoolLevelOrg.getOrganizationId())) {
895 organizationIdsToKeep.add(schoolLevelOrg.getOrganizationId());
900 // Keep manually added organizations
901 List<Long> manuallyAddedOrgIds = getManuallyAddedOrganizations(user);
902 organizationIdsToKeep.addAll(manuallyAddedOrgIds);
904 List<Organization> newUserOrgsCopy = new ArrayList<Organization>(newUserOrgs);
906 // Get current user organizations
907 List<Organization> userOrgs = OrganizationLocalServiceUtil.getUserOrganizations(user.getUserId());
909 // Loop over user's classes and groups
910 for (Organization userOrg: userOrgs) {
912 // Skip archived organizations
913 if (!userOrg.getPreferences().getValue("migrate", "none").equals("none")) {
914 //_log.info(" Skipping archived org "+teacherOrg.getName());
918 // Skip if organization is in the membership list
919 boolean isToKeep = false;
920 for (Organization newUserOrg : newUserOrgs) {
921 if (newUserOrg.getOrganizationId() == userOrg.getOrganizationId()) {
923 newUserOrgsCopy.remove(userOrg);
927 //_log.info(" Skipping org to keep : "+userOrg.getName());
931 if (doKeepOrg(userOrg, organizationIdsToKeep)) {
932 //_log.info(" Skipping org id to keep : "+userOrg.getName());
936 _log.info("Remove user "+user.getUserId()+" from organization "+userOrg.getName());
938 UserLocalServiceUtil.unsetOrganizationUsers(userOrg.getOrganizationId(), new long[]{user.getUserId()});
941 SynchronizationReport.notifyOtherMembershipRemoval(user, userOrg);
944 // Now loop over the etabs which the user should not belong anymore
945 for (Organization orgToAdd: newUserOrgsCopy) {
947 UserLocalServiceUtil.addOrganizationUsers(orgToAdd.getOrganizationId(), new long[]{user.getUserId()});
948 _log.info("Add new organization "+orgToAdd.getName()+" to user "+user.getFullName());
951 SynchronizationReport.notifyOtherMembershipCreation(user, orgToAdd);
954 } catch (Exception e) {
955 _log.error("Error when managing other profile membership for user "+user.getFullName(), e);
961 * Method called during manual user creation, that allows to synchronize its memberships
963 public static boolean manageUserMembership(long _companyId, Attributes userAttributes) {
965 companyId = _companyId;
968 // Get screenName (ENTPersonLogin)
969 if (userAttributes.get(LDAPConstants.LDAP_ATTRIBUTE_ENTPERSONLOGIN) != null) {
970 String login = userAttributes.get(LDAPConstants.LDAP_ATTRIBUTE_ENTPERSONLOGIN).get().toString();
971 _log.info("manageUserMembership : login="+login);
972 User user = UserLocalServiceUtil.getUserByScreenName(companyId, login);
974 if (userAttributes.get(LDAPConstants.LDAP_ATTRIBUTE_ENTPERSONLOGIN) == null || userAttributes.get(LDAPConstants.LDAP_ATTRIBUTE_ENTPERSONSTRUCTRATTACH).get().toString() == null) {
975 _log.error("Manual user creation : membership sync impossible because user does not have ENTPersonLogin or ENTPersonStructRattach attribute");
978 initMembership(companyId);
979 SynchronizationManager.initUserRattachSchoolMap();
980 SynchronizationManager.getUserRattachSchoolMap().put(userAttributes.get(LDAPConstants.LDAP_ATTRIBUTE_ENTPERSONLOGIN).get().toString(), userAttributes.get(LDAPConstants.LDAP_ATTRIBUTE_ENTPERSONSTRUCTRATTACH).get().toString());
982 List<Role> roleList = RoleLocalServiceUtil.getUserRoles(user.getUserId());
983 for (Role role : roleList) {
984 _log.info("User "+user.getFullName()+" has role "+role.getName());
987 if (RoleLocalServiceUtil.hasUserRole(user.getUserId(), RoleLocalServiceUtil.getRole(_companyId, ENTRolesConstants.NATIONAL_1).getRoleId())) {
988 //if (RoleLocalServiceUtil.hasUserRole(user.getUserId(), companyId, ENTRolesConstants.NATIONAL_1, false)) {
989 manageStudentMembership(user, userAttributes);
990 } else if (RoleLocalServiceUtil.hasUserRole(user.getUserId(), RoleLocalServiceUtil.getRole(_companyId, ENTRolesConstants.NATIONAL_3).getRoleId())) {
991 manageTeacherMembership(user, userAttributes);
993 manageOtherProfilesMembership(user, userAttributes);
996 } catch (Exception e) {
997 _log.error("Error when synchronizing manually created user ", e);
1005 * Returns the list of school-level organizations for given user and school
1006 * School-level orgs are the '-Parent' or '- Personnels' or '- Enseignants' sub-orgs
1010 private static List<Organization> getSchoolLevelOrganizations (User user, Organization school) {
1012 Boolean hasTeacherGrp = false;
1013 Boolean hasPersonnelGrp = false;
1014 Boolean hasParentGrp = false;
1015 Boolean analyzeSchoolComplex = false;
1017 long userId = user.getUserId();
1019 List<Organization> resultOrgList = new ArrayList<Organization>();
1020 resultOrgList.add(school);
1026 List<Role> userRolesList = RoleLocalServiceUtil.getUserRoles(userId);
1028 // Loop over the user's roles to detect school-level orgs
1029 for (Role userRole : userRolesList) {
1030 // Student and parents => quit
1031 if (userRole.getName().equals(ENTRolesConstants.NATIONAL_1)) {
1032 return resultOrgList;
1036 if (userRole.getName().equals(ENTRolesConstants.NATIONAL_2)
1037 || userRole.getName().equals(ENTRolesConstants.NATIONAL_4)
1038 || userRole.getName().equals(ENTRolesConstants.NATIONAL_25)) {
1039 hasParentGrp = true;
1043 if (userRole.getName().equals(ENTRolesConstants.NATIONAL_3)
1044 || userRole.getName().equals(ENTRolesConstants.NATIONAL_24)
1045 || userRole.getName().equals(ENTRolesConstants.NATIONAL_25)) {
1046 hasTeacherGrp = true;
1050 if (userRole.getName().equals(ENTRolesConstants.NATIONAL_3)
1051 || userRole.getName().equals(ENTRolesConstants.NATIONAL_4)
1052 || userRole.getName().equals(ENTRolesConstants.NATIONAL_5)
1053 || userRole.getName().equals(ENTRolesConstants.NATIONAL_6)
1054 || userRole.getName().equals(ENTRolesConstants.NATIONAL_7)
1055 || userRole.getName().equals(ENTRolesConstants.NATIONAL_25)) {
1056 hasPersonnelGrp = true;
1060 if (userRole.getName().equals(ENTRolesConstants.NATIONAL_4)
1061 || userRole.getName().equals(ENTRolesConstants.NATIONAL_5)
1062 || userRole.getName().equals(ENTRolesConstants.NATIONAL_6)
1063 || userRole.getName().equals(ENTRolesConstants.NATIONAL_7)) {
1064 analyzeSchoolComplex = true;
1069 // Parent school org
1070 Organization parentOrg = ENTOrganizationsUtil.getOrCreateOrganization(user.getCompanyId(), school.getName() + OrganizationConstants.ORG_SUFFIX_PARENTS, school.getOrganizationId());
1072 resultOrgList.add(parentOrg);
1075 // Teacher school org
1076 Organization teacherOrg = ENTOrganizationsUtil.getOrCreateOrganization(user.getCompanyId(), school.getName() + OrganizationConstants.ORG_SUFFIX_TEACHERS, school.getOrganizationId());
1077 if (hasTeacherGrp) {
1078 resultOrgList.add(teacherOrg);
1081 // Personnel school org
1082 Organization personnelOrg = ENTOrganizationsUtil.getOrCreateOrganization(user.getCompanyId(), school.getName() + OrganizationConstants.ORG_SUFFIX_PERSONNELS, school.getOrganizationId());
1083 if (hasPersonnelGrp) {
1084 resultOrgList.add(personnelOrg);
1088 // If school complex and profile is National_4,5,6,7 => add user into other etabs from the school complex
1089 if (analyzeSchoolComplex) {
1091 List<Long> etabIdList = SynchronizationManager.getSchoolComplexAttachedEtabs(school.getOrganizationId());
1092 for (Long etabIdToAttach : etabIdList) {
1093 _log.info("Adding user "+user.getFullName()+" to cite scolaire etab "+etabIdToAttach);
1094 Organization schoolComplexOrg = OrganizationLocalServiceUtil.getOrganization(etabIdToAttach);
1095 resultOrgList.add(schoolComplexOrg);
1100 } catch (Exception e) {
1101 _log.error("Error when synchronizing school-level organizations for user "+user.getFullName()+ "(id "+user.getUserId()+")", e);
1103 return resultOrgList;
1107 * Adds a given user to all school-level organization for given school, depending on its role
1111 private static void addUserToSchoolLevelOrgs(User user, Organization school) {
1113 List<Organization> schoolLevelOrgs = getSchoolLevelOrganizations(user, school);
1114 for (Organization schoolLevelOrg : schoolLevelOrgs) {
1116 if (!UserLocalServiceUtil.hasOrganizationUser(schoolLevelOrg.getOrganizationId(), user.getUserId()) ) {
1117 UserLocalServiceUtil.addOrganizationUsers(schoolLevelOrg.getOrganizationId(), new long[]{user.getUserId()});
1118 _log.info(" Add user "+user.getUserId()+" to school-level organization "+schoolLevelOrg.getName());
1119 SynchronizationReport.notifyTeacherMembershipCreation(user, schoolLevelOrg);
1121 } catch (Exception e) {
1122 _log.error("Error when adding user toschool-level organization for school "+school.getName(), e);
1128 * Returns true if the given organization is a student-level class or group
1132 private static boolean isStudentClass (Organization org) {
1133 return (!org.getName().endsWith(OrganizationConstants.ORG_SUFFIX_PARENTS)
1134 && !org.getName().endsWith(OrganizationConstants.ORG_SUFFIX_TEACHERS)
1135 && !org.getName().endsWith(OrganizationConstants.ORG_SUFFIX_PERSONNELS));
1139 * Returns true if the organization is a school
1143 private static boolean isSchool(Organization org) {
1145 Organization parentOrg = org.getParentOrganization();
1146 if (parentOrg != null && parentOrg.getParentOrganizationId() == 0) {
1149 } catch (Exception e) {
1150 _log.error("Error when getting parent organization for org "+org.getName());
1156 * Returns the list of organizations ids manually added to the user userId
1158 * @return the list of org ids
1160 private static List<Long> getManuallyAddedOrganizations(User user) {
1162 List<Long> manuallyAddedOrgIds = new ArrayList<Long>();
1164 Role orgUserRole = RoleLocalServiceUtil.getRole(companyId, ENTRolesConstants.ORGANIZATION_USER);
1166 List<UserGroupRole> userGroupRoleList = UserGroupRoleLocalServiceUtil.getUserGroupRoles(user.getUserId());
1167 for (UserGroupRole userGroupRole : userGroupRoleList) {
1168 if (userGroupRole.getRoleId() == orgUserRole.getRoleId()) {
1169 Group group = GroupLocalServiceUtil.getGroup(userGroupRole.getGroupId());
1170 Organization manualOrg = OrganizationLocalServiceUtil.getOrganization(group.getClassPK());
1172 // Skip archived organizations
1173 if (!manualOrg.getPreferences().getValue("migrate", "none").equals("none")) {
1177 _log.info(" Found manually added organization is "+manualOrg.getName());
1178 manuallyAddedOrgIds.add(manualOrg.getOrganizationId());
1180 // Add school-level organizations (for schools only)
1181 if (isSchool(manualOrg)) {
1182 List<Organization> schoolLevelOrgList = getSchoolLevelOrganizations(user, manualOrg);
1183 for (Organization schoolLevelOrg : schoolLevelOrgList) {
1184 _log.info(" Found manually added organization is "+schoolLevelOrg.getName());
1185 manuallyAddedOrgIds.add(schoolLevelOrg.getOrganizationId());
1190 } catch (Exception e) {
1191 _log.error("Error when fetching manually added organizations for user "+user.getFullName());
1193 return manuallyAddedOrgIds;
1197 * Synchronizes subjects. Based on attribute ENTAuxEnsMatiereEnseignEtab
1202 private static void synchronizeSubjects(User user, Attributes atts, long schoolId)
1203 throws UserSynchronizationException {
1206 // Get attributes ENTAuxEnsMatiereEnseignEtab
1207 if (atts.get(LDAPConstants.LDAP_ATTRIBUTE_ENTAUXENSMATIEREENSEIGNETAB) != null) {
1209 Attribute entAuxEnsMatiereEnseignEtab = atts.get(LDAPConstants.LDAP_ATTRIBUTE_ENTAUXENSMATIEREENSEIGNETAB);
1212 for (int i=0; i<entAuxEnsMatiereEnseignEtab.size(); i++) {
1214 final String fullSubject = entAuxEnsMatiereEnseignEtab.get(i).toString();
1215 if (fullSubject.startsWith("cn=fakeDn")) {
1218 System.out.println("synchronize subject : teacher "+user.getFullName()+" has subject "+fullSubject);
1219 final String[] spl = fullSubject.split("\\$");
1220 String subjectDn = spl[1];
1221 String[] subjectTab = subjectDn.split(",");
1222 String subjectLongLabel = subjectTab[0];
1224 // Check if subject exists, if not, create it
1225 Subject subject = SubjectLocalServiceUtil.getSubjectByLongLabel(subjectLongLabel);
1226 if (subject == null) {
1227 _log.error("Subject with long label "+subjectLongLabel+" does not exist in database");
1231 // Check if subject already exists for this school
1232 // If not, create it
1233 List<SchoolSubject> schoolSubjectList = SchoolSubjectLocalServiceUtil.getSubjectsForSchoolSubject(schoolId, subject.getSubjectId());
1234 if (schoolSubjectList == null || schoolSubjectList.size() == 0) {
1235 SchoolSubjectLocalServiceUtil.createSchoolSubject(subject.getSubjectId(), schoolId, CDTColorUtil.getRandomColor());
1241 } catch (Exception e) {
1242 _log.error("Error when synchronizing subjects for teacher "+user.getFullName());
1243 e.printStackTrace();
1244 throw new UserSynchronizationException(user);
1251 * Is this school configured to use 'AAF' for data source membership ?
1252 * @param schoolOrgId
1253 * @return true if AAF mode for this school
1255 public static boolean isSchoolImportTypeAAF(long schoolOrgId) {
1256 // Default mode is currently AAF, because no EDT is available for 2015-2016 schoolyear
1257 return (schoolsUsingAAFMode.contains(schoolOrgId));
1261 * Init all variables for membership
1263 private static void initMembership(long companyId) {
1267 childModificationsMap = new HashMap<Long, Boolean>();
1269 rootOrg = ENTOrganizationsUtil.getOrCreateRootOrg(companyId);
1270 } catch (Exception e) {
1271 _log.error("Error while retrieving root org", e);
1277 * Init the list of schools using AAF mode for membership management
1279 private static void initAAFMode() {
1281 schoolsUsingAAFMode = new ArrayList<Long>();
1283 List<SynchroConfig> synchroConfigList = SynchroConfigLocalServiceUtil.getSynchroConfigs(QueryUtil.ALL_POS, QueryUtil.ALL_POS);
1284 for (SynchroConfig schoolConfig : synchroConfigList) {
1285 if (schoolConfig.getDataSource().equals("AAF") && schoolConfig.getConfigDone()) {
1286 _log.info("Adding school org "+schoolConfig.getEtabName()+" to AAF mode");
1287 schoolsUsingAAFMode.add(schoolConfig.getEtabId());
1290 } catch (Exception e) {
1291 _log.error("Error when checking the list of schools that use AAF as datasource for membership.", e);
1297 * Does the given org belong to the orgId list ?
1302 private static boolean doKeepOrg(Organization org, List<Long> orgIdsToKeep) {
1304 for (Long orgIdToKeep : orgIdsToKeep) {
1305 if (org.getOrganizationId() == orgIdToKeep) {