@Transactional
  private List<UserGroup> getPrivilegesAndCreateGroups(
      LDAPUser user, boolean createNonExistingLdapGroup, User toSave) {
    GroupRepository groupRepo = ApplicationContextHolder.get().getBean(GroupRepository.class);

    List<UserGroup> ug = new LinkedList<UserGroup>();
    for (Map.Entry<String, Profile> privilege : user.getPrivileges().entries()) {
      // Add group privileges for each groups

      // Retrieve group id
      String groupName = privilege.getKey();
      Profile profile = privilege.getValue();

      Group group = groupRepo.findByName(groupName);

      if (group == null && createNonExistingLdapGroup) {
        group = new Group().setName(groupName);
        group = groupRepo.save(group);

        if (Log.isDebugEnabled(Geonet.LDAP)) {
          Log.debug(Geonet.LDAP, "  - Add LDAP group " + groupName + " for user.");
        }
      }
      if (group != null) {
        if (Log.isDebugEnabled(Geonet.LDAP)) {
          Log.debug(Geonet.LDAP, "  - Add LDAP group " + groupName + " for user.");
        }
        UserGroup usergroup = new UserGroup();
        usergroup.setGroup(group);
        usergroup.setUser(toSave);
        usergroup.setProfile(profile);
        ug.add(usergroup);
      } else {
        if (Log.isDebugEnabled(Geonet.LDAP)) {
          Log.debug(
              Geonet.LDAP,
              "  - Can't create LDAP group "
                  + groupName
                  + " for user. "
                  + "Group does not exist in local database or createNonExistingLdapGroup is set to false.");
        }
      }
    }
    return ug;
  }
  @Transactional
  private User getUser(LDAPUser user, boolean importPrivilegesFromLdap, String userName) {
    UserRepository userRepo = ApplicationContextHolder.get().getBean(UserRepository.class);

    User loadedUser = userRepo.findOneByUsername(userName);
    User toSave;
    if (loadedUser != null) {
      // If we don't import privileges from LDAP
      // Set the LDAP user profile to be the one set
      // in the local database. If not, the db profile
      // would be always reset by merge.
      if (!importPrivilegesFromLdap) {
        user.getUser().setProfile(loadedUser.getProfile());
      }
      loadedUser.mergeUser(user.getUser(), false);
      if (Log.isDebugEnabled(Geonet.LDAP)) {
        Log.debug(
            Geonet.LDAP,
            "  - Update LDAP user "
                + user.getUsername()
                + " ("
                + loadedUser.getId()
                + ") in local database.");
      }
      toSave = loadedUser;

    } else {
      if (Log.isDebugEnabled(Geonet.LDAP)) {
        Log.debug(Geonet.LDAP, "  - Saving new LDAP user " + user.getUsername() + " to database.");
      }
      toSave = user.getUser();
    }
    toSave.getSecurity().setAuthType(LDAPConstants.LDAP_FLAG);
    toSave = userRepo.save(toSave);
    user.setUser(toSave);
    return toSave;
  }
  @Transactional
  private void setUserGroups(final User user, List<UserGroup> userGroups) throws Exception {
    UserGroupRepository userGroupRepo =
        ApplicationContextHolder.get().getBean(UserGroupRepository.class);
    ;

    Collection<UserGroup> all = userGroupRepo.findAll(UserGroupSpecs.hasUserId(user.getId()));

    if (Log.isTraceEnabled(Log.JEEVES)) {
      Log.trace(Log.JEEVES, "Current usergroups:" + UserGroupSpecs.hasUserId(user.getId()));
      Log.trace(Log.JEEVES, all.size());

      for (UserGroup g : all) {
        Log.trace(Log.JEEVES, g);
      }
    }
    // Have a quick reference of existing groups and profiles for this user
    Set<String> listOfAddedProfiles = new HashSet<String>();
    for (UserGroup ug : all) {
      String key = ug.getProfile().name() + ug.getGroup().getId();
      if (!listOfAddedProfiles.contains(key)) {
        listOfAddedProfiles.add(key);
      }
    }

    // We start removing all old usergroup objects. We will remove the
    // explicitly defined for this call
    Collection<UserGroup> toRemove = new ArrayList<UserGroup>();
    toRemove.addAll(all);

    // New pairs of group-profile we need to add
    Collection<UserGroup> toAdd = new ArrayList<UserGroup>();

    // For each of the parameters on the request, make sure the group is
    // updated.
    for (UserGroup element : userGroups) {
      Group group = element.getGroup();
      String profile = element.getProfile().name();
      // The user has a new group and profile

      // Combine all groups editor and reviewer groups
      if (profile.equals(Profile.Reviewer.name())) {
        final UserGroup userGroup =
            new UserGroup().setGroup(group).setProfile(Profile.Editor).setUser(user);
        String key = Profile.Editor.toString() + group.getId();
        if (!listOfAddedProfiles.contains(key)) {
          toAdd.add(userGroup);
          listOfAddedProfiles.add(key);
        }

        // If the user is already part of this group with this profile,
        // leave it alone:
        for (UserGroup g : all) {
          if (g.getGroup().getId() == group.getId() && g.getProfile().equals(Profile.Editor)) {
            toRemove.remove(g);
          }
        }
      }

      final UserGroup userGroup =
          new UserGroup()
              .setGroup(group)
              .setProfile(Profile.findProfileIgnoreCase(profile))
              .setUser(user);
      String key = profile + group.getId();
      if (!listOfAddedProfiles.contains(key)) {
        toAdd.add(userGroup);
        listOfAddedProfiles.add(key);
      }

      // If the user is already part of this group with this profile,
      // leave it alone:
      for (UserGroup g : all) {
        if (g.getGroup().getId() == group.getId()
            && g.getProfile().name().equalsIgnoreCase(profile)) {
          toRemove.remove(g);
        }
      }
    }

    // Remove deprecated usergroups (if any)
    userGroupRepo.delete(toRemove);
    entityManager.flush();
    entityManager.clear();

    // Add only new usergroups (if any)
    userGroupRepo.save(toAdd);
    entityManager.flush();
  }