org.esco.grouperui.services.grouper.internal.escoaddons.GrouperServiceApi.java Source code

Java tutorial

Introduction

Here is the source code for org.esco.grouperui.services.grouper.internal.escoaddons.GrouperServiceApi.java

Source

/**
 * Copyright (C) 2009 GIP RECIA http://www.recia.fr
 * @Author (C) 2009 GIP RECIA <contact@recia.fr>
 * @Contributor (C) 2009 SOPRA http://www.sopragroup.com/
 * @Contributor (C) 2011 Pierre Legay <pierre.legay@recia.fr>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.esco.grouperui.services.grouper.internal.escoaddons;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Date;

import javax.servlet.jsp.tagext.TryCatchFinally;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.Validate;
import org.esco.grouperui.domaine.beans.Group;
import org.esco.grouperui.domaine.beans.GroupDetail;
import org.esco.grouperui.domaine.beans.GroupPrivilegeEnum;
import org.esco.grouperui.domaine.beans.GroupType;
import org.esco.grouperui.domaine.beans.Members;
import org.esco.grouperui.domaine.beans.Person;
import org.esco.grouperui.domaine.beans.Privilege;
import org.esco.grouperui.domaine.beans.SourceTypeEnum;
import org.esco.grouperui.domaine.beans.Stem;
import org.esco.grouperui.domaine.beans.StemPrivilegeEnum;
import org.esco.grouperui.exceptions.ESCOTechnicalException;
import org.esco.grouperui.exceptions.business.ESCOAddMemberException;
import org.esco.grouperui.exceptions.business.ESCOAttributeException;
import org.esco.grouperui.exceptions.business.ESCODeleteMemberException;
import org.esco.grouperui.exceptions.business.ESCOGroupNotFoundException;
import org.esco.grouperui.exceptions.business.ESCOGroupNotMoveException;
import org.esco.grouperui.exceptions.business.ESCOGroupNotSaveException;
import org.esco.grouperui.exceptions.business.ESCOGroupNotUniqueException;
import org.esco.grouperui.exceptions.business.ESCOInsufficientPrivilegesException;
import org.esco.grouperui.exceptions.business.ESCOStemNotFoundException;
import org.esco.grouperui.exceptions.business.ESCOStemNotMoveException;
import org.esco.grouperui.exceptions.business.ESCOStemNotSaveException;
import org.esco.grouperui.exceptions.business.ESCOStemNotUniqueException;
import org.esco.grouperui.exceptions.business.ESCOSubjectNotFoundException;
import org.esco.grouperui.exceptions.business.ESCOSubjectNotUniqueException;
import org.esco.grouperui.services.ESCOConstantes;
import org.esco.grouperui.services.application.IGrouperService;
import org.esco.grouperui.services.application.filters.PrivilegeSearchEnum;
import org.esco.grouperui.services.application.filters.PrivilegeTypeEnum;
import org.esco.grouperui.services.application.filters.ScopeEnum;
import org.esco.grouperui.services.application.filters.SearchGroupEnum;
import org.esco.grouperui.services.application.filters.SearchStemEnum;
import org.esco.grouperui.services.application.filters.SearchTypeEnum;
import org.esco.grouperui.services.extension.ServiceConstants;
import org.esco.grouperui.services.grouper.internal.PrivilegeAssignUtils;
import org.esco.grouperui.services.grouper.strategy.search.IStrategyGroupSearch;
import org.esco.grouperui.services.grouper.strategy.search.IStrategySubjectSearch;
import org.esco.grouperui.services.grouper.strategy.search.locator.IStrategyGroupSearchLocator;
import org.esco.grouperui.services.grouper.strategy.search.locator.IStrategySubjectSearchLocator;
import org.esco.grouperui.tools.IWrapper;
import org.esco.grouperui.tools.log.ESCOLoggerFactory;
import org.esco.grouperui.tools.log.IESCOLogger;
import org.esco.grouperui.tools.property.PropertyManager;
import org.springframework.beans.factory.InitializingBean;

import com.google.common.collect.ArrayListMultimap;

import edu.emory.mathcs.backport.java.util.Arrays;
import edu.internet2.middleware.grouper.FieldFinder;
import edu.internet2.middleware.grouper.GroupFinder;
import edu.internet2.middleware.grouper.GroupMove;
import edu.internet2.middleware.grouper.GroupSave;
import edu.internet2.middleware.grouper.GroupTypeFinder;
import edu.internet2.middleware.grouper.GrouperSession;
import edu.internet2.middleware.grouper.Member;
import edu.internet2.middleware.grouper.MemberFinder;
import edu.internet2.middleware.grouper.Membership;
import edu.internet2.middleware.grouper.StemFinder;
import edu.internet2.middleware.grouper.StemMove;
import edu.internet2.middleware.grouper.StemSave;
import edu.internet2.middleware.grouper.SubjectFinder;
import edu.internet2.middleware.grouper.Stem.Scope;
import edu.internet2.middleware.grouper.exception.GrantPrivilegeException;
import edu.internet2.middleware.grouper.exception.GroupDeleteException;
import edu.internet2.middleware.grouper.exception.GroupModifyException;
import edu.internet2.middleware.grouper.exception.GroupNotFoundException;
import edu.internet2.middleware.grouper.exception.InsufficientPrivilegeException;
import edu.internet2.middleware.grouper.exception.MemberAddException;
import edu.internet2.middleware.grouper.exception.MemberDeleteException;
import edu.internet2.middleware.grouper.exception.QueryException;
import edu.internet2.middleware.grouper.exception.SchemaException;
import edu.internet2.middleware.grouper.exception.SessionException;
import edu.internet2.middleware.grouper.exception.StemAddException;
import edu.internet2.middleware.grouper.exception.StemDeleteException;
import edu.internet2.middleware.grouper.exception.StemModifyException;
import edu.internet2.middleware.grouper.exception.StemNotFoundException;
import edu.internet2.middleware.grouper.hibernate.GrouperTransaction;
import edu.internet2.middleware.grouper.hibernate.GrouperTransactionHandler;
import edu.internet2.middleware.grouper.internal.dao.GroupDAO;
import edu.internet2.middleware.grouper.internal.dao.GrouperDAOException;
import edu.internet2.middleware.grouper.membership.MembershipType;
import edu.internet2.middleware.grouper.misc.GrouperDAOFactory;
import edu.internet2.middleware.grouper.misc.SaveMode;
import edu.internet2.middleware.grouper.privs.AccessPrivilege;
import edu.internet2.middleware.grouper.privs.NamingPrivilege;
import edu.internet2.middleware.grouper.privs.PrivilegeHelper;
import edu.internet2.middleware.grouper.subj.LazySubject;
import edu.internet2.middleware.subject.Subject;
import edu.internet2.middleware.subject.SubjectNotFoundException;
import edu.internet2.middleware.subject.SubjectNotUniqueException;
import edu.internet2.middleware.subject.provider.GetPersonsDataDelegate;

/**
 * <b>Service API implementation.</b>
 * 
 * @author SopraGroup
 * 
 * Une modification de grouperServiceApi d'origine v2.6.06
 * pour tester une acceleration possible de l'affichage de l'arbre des groupes.
 * 
 * P.Legay
 */

public class GrouperServiceApi implements IGrouperService, InitializingBean {

    /** UID. */
    private static final long serialVersionUID = 7867717609418726754L;

    /** Wrapper : Subject to Person. */
    private IWrapper<edu.internet2.middleware.subject.Subject, Person> personWrapper;

    /** Strategy locator. **/
    private IStrategySubjectSearchLocator strategyLocator;

    /** Strategy locator. **/
    private IStrategyGroupSearchLocator strategyGroupLocator;

    /** Wrapper: GroupType API to GroupType. */
    private IWrapper<edu.internet2.middleware.grouper.GroupType, GroupType> groupTypeWrapper;

    /** Wrapper: group API to group. */
    private IWrapper<edu.internet2.middleware.grouper.Group, Group> groupAPIWrapper;

    /** Wrapper: stem API to stem. */
    private IWrapper<edu.internet2.middleware.grouper.Stem, Stem> stemAPIWrapper;

    /** un logger */
    private final IESCOLogger LOGGER = ESCOLoggerFactory.getLogger(GrouperServiceApi.class);
    /** GrouperHelperFactory */
    private GrouperHelperFactory grouperHelperFactory;

    /** Delegate optimized to retrieve the persons attributes.*/
    private GetPersonsDataDelegate personsDataDelegate = new GetPersonsDataDelegate();

    /**
     * Default constructor.
     */
    public GrouperServiceApi() {
        //
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        if (grouperHelperFactory == null) {
            throw new Exception(
                    "property grouperHelperFactory of class " + getClass().getName() + " can not be null");
        }
    }

    /**
     * {@inheritDoc}
     */
    public Person findSubjectById(final String theIdentifier)
            throws ESCOSubjectNotFoundException, ESCOSubjectNotUniqueException {
        Validate.notNull(theIdentifier, "The identifier must be defined");
        // long timeTotal = 0;
        edu.internet2.middleware.subject.Subject subject = null;
        GrouperSession session = null;
        try {
            session = GrouperSession.startRootSession();
            // long deb = System.currentTimeMillis();
            subject = SubjectFinder.findByIdOrIdentifier(theIdentifier, true);
            // timeTotal = System.currentTimeMillis() - deb;
            // Log to calculate time of service
            // this.LOGGER.error("findSubjectById;" + timeTotal);
        } catch (SubjectNotFoundException e) {
            throw new ESCOSubjectNotFoundException(ServiceConstants.SUBJECT_NOT_FOUND, e);
        } catch (SubjectNotUniqueException e) {
            throw new ESCOSubjectNotUniqueException(ServiceConstants.SUBJECT_NOT_UNIQUE, e);
        } finally {
            GrouperSession.stopQuietly(session);
        }

        return this.getPersonWrapper().wrap(subject);
    }

    /**
     * {@inheritDoc}
     */
    public List<Person> searchSubjects(final Person thePerson, final String thePath, final String theTerm) {
        Validate.notNull(thePerson, ServiceConstants.THE_PERSON_MUST_BE_DEFINED);
        Validate.notNull(thePath, ServiceConstants.THE_PATH_MUST_BE_DEFINED);
        Validate.notNull(theTerm, ServiceConstants.THE_TERM_MUST_BE_DEFINED);

        IStrategySubjectSearch strategy = this.getStrategyLocator().locate(thePerson, thePath, theTerm);
        if (strategy == null) {
            throw new ESCOTechnicalException(ServiceConstants.STRATEGY_NOT_FOUND);
        }
        return strategy.searchSubjects(thePerson, thePath, theTerm);
    }

    /**
     * {@inheritDoc}
     */
    public List<Group> findMemberships(final Person thePerson, final String theSubjectId,
            final ScopeEnum theMembershipsScope) throws ESCOGroupNotFoundException {
        Validate.notNull(thePerson, ServiceConstants.THE_PERSON_MUST_BE_DEFINED);
        Validate.notNull(theSubjectId, ServiceConstants.THE_SUBJECT_MUST_BE_DEFINED);
        Validate.notNull(theMembershipsScope, ServiceConstants.THE_SCOPE_MUST_BE_DEFINED);
        // long timeTotal = 0;
        // this list is the result and it is modified in the method
        // callbackGrouperTransaction
        final List<Group> groupsAsMemberhips = new ArrayList<Group>();

        GrouperSession session = null;
        GrouperSession rootSession = null;
        edu.internet2.middleware.subject.Subject person = null;
        try {
            // long deb = System.currentTimeMillis();
            rootSession = GrouperSession.startRootSession();
            session = GrouperSession.start(SubjectFinder.findById(thePerson.getId(), true));
            person = SubjectFinder.findById(theSubjectId, true);
            // timeTotal += System.currentTimeMillis() - deb;
        } catch (SessionException e) {
            throw new ESCOTechnicalException(ServiceConstants.SESSION_CANNOT_BE_CREATE, e);
        } catch (SubjectNotFoundException e) {
            throw new ESCOTechnicalException(ServiceConstants.SUBJECT_NOT_FOUND, e);
        } catch (SubjectNotUniqueException e) {
            throw new ESCOTechnicalException(ServiceConstants.SUBJECT_NOT_UNIQUE, e);
        }

        try {
            final GrouperSession grouperSession = session;
            final Subject subject = person;
            final IWrapper<edu.internet2.middleware.grouper.Group, Group> grouperApiWrapper = this.groupAPIWrapper;

            // start a transaction
            // long deb = System.currentTimeMillis();
            GrouperTransaction.callbackGrouperTransaction(new GrouperTransactionHandler() {
                public Object callback(final GrouperTransaction grouperTransaction) throws GrouperDAOException {
                    Member member = MemberFinder.findBySubject(grouperSession, subject, true);
                    Set<Membership> memberships = null;
                    if (ScopeEnum.IMMEDIATE.equals(theMembershipsScope)) {
                        memberships = member.getImmediateMemberships();
                    } else {
                        if (ScopeEnum.EFFECTIVE.equals(theMembershipsScope)) {
                            memberships = member.getEffectiveMemberships();
                        } else {
                            if (ScopeEnum.ALL.equals(theMembershipsScope)) {
                                memberships = member.getMemberships();
                            } else {
                                throw new ESCOTechnicalException("The scope of membership is invalid.");
                            }
                        }
                    }
                    for (Membership membership : memberships) {
                        try {
                            groupsAsMemberhips.add(grouperApiWrapper.wrap(membership.getGroup()));
                        } catch (final GroupNotFoundException e) {
                            throw new GrouperDAOException(e);
                        }
                    }
                    return groupsAsMemberhips;
                }
            });
            // timeTotal += System.currentTimeMillis() - deb;
        } catch (GrouperDAOException e) {
            GrouperSession.stopQuietly(session);
            Throwable cause = e.getCause();
            if (cause instanceof GroupNotFoundException) {
                throw new ESCOGroupNotFoundException(ServiceConstants.GROUP_NOT_FOUND, e);
            } else {
                throw new ESCOTechnicalException(ServiceConstants.API_ERROR, e);
            }
        } finally {
            GrouperSession.stopQuietly(session);
            GrouperSession.stopQuietly(rootSession);
        }
        // Log to calculate time of service
        // this.LOGGER.error("findMemberships;" + timeTotal);
        GrouperSession.stopQuietly(session);
        return groupsAsMemberhips;
    }

    /**
     * {@inheritDoc}
     */
    public List<GroupType> findListTypes(final String[] theNames) {
        Validate.notNull(theNames, "The names must be defined");

        List<GroupType> groupTypes = new ArrayList<GroupType>();

        GroupType groupType = null;
        for (String name : theNames) {
            try {
                groupType = this.getGroupTypeWrapper().wrap(GroupTypeFinder.find(name, true));
            } catch (SchemaException e) {
                throw new ESCOTechnicalException("Invalid group type.", e);
            }
            groupTypes.add(groupType);
        }

        return groupTypes;
    }

    /**
     * {@inheritDoc}
     */
    public Map<String, GroupType> findGroupTypes(final String[] theNames) {
        Validate.notNull(theNames, "The names must be defined");

        Map<String, GroupType> groupTypes = new HashMap<String, GroupType>();

        GroupType groupType = null;
        for (String name : theNames) {
            try {
                groupType = this.getGroupTypeWrapper().wrap(GroupTypeFinder.find(name, true));
            } catch (SchemaException e) {
                throw new ESCOTechnicalException("Invalid group type.", e);
            }
            groupTypes.put(groupType.getName(), groupType);
        }

        return groupTypes;
    }

    /**
     * {@inheritDoc}
     */
    public List<Group> findGroupsMemberOptinOptout(final Person thePerson)
            throws ESCOSubjectNotFoundException, ESCOSubjectNotUniqueException {
        Validate.notNull(thePerson, ServiceConstants.THE_PERSON_MUST_BE_DEFINED);

        // this list is the result and it is modified in the method
        // callbackGrouperTransaction
        //final List < Group > groups = new ArrayList < Group >();

        final JustIterableListGroupWrapper groups = new JustIterableListGroupWrapper();

        // long timeTotal = 0;
        GrouperSession session = null;
        GrouperSession rootSession = null;
        Subject person = null;
        try {
            // long deb = System.currentTimeMillis();
            rootSession = GrouperSession.startRootSession();
            person = SubjectFinder.findById(thePerson.getId(), true);
            // timeTotal += System.currentTimeMillis() - deb;
            if (person == null) {
                throw new ESCOSubjectNotFoundException(ServiceConstants.SUBJECT_NOT_FOUND);
            }
            session = GrouperSession.start(person);
        } catch (SessionException e) {
            throw new ESCOTechnicalException(ServiceConstants.SESSION_CANNOT_BE_CREATE, e);
        } catch (SubjectNotFoundException e) {
            throw new ESCOSubjectNotFoundException(ServiceConstants.SUBJECT_NOT_FOUND, e);
        } catch (SubjectNotUniqueException e) {
            throw new ESCOSubjectNotUniqueException(ServiceConstants.SUBJECT_NOT_UNIQUE, e);
        }

        try {
            final GrouperSession grouperSession = session;
            final Subject subject = person;
            final IWrapper<edu.internet2.middleware.grouper.Group, Group> grouperApiWrapper = this.groupAPIWrapper;

            // start a transaction
            // long deb = System.currentTimeMillis();
            GrouperTransaction.callbackGrouperTransaction(new GrouperTransactionHandler() {
                public Object callback(final GrouperTransaction grouperTransaction) throws GrouperDAOException {
                    Member member = MemberFinder.findBySubject(grouperSession, subject, false);

                    GrouperHelper gh = grouperHelperFactory.get(grouperSession);

                    try {
                        gh.setMember(member);
                    } catch (GrouperHelperException e) {
                        LOGGER.error(e, "set member error");
                        return groups;
                    }

                    Set<edu.internet2.middleware.grouper.Group> groupOptin = gh
                            .findGroupsWhereMemberHasPrivCached(Privs.OPTIN, ScopeEnum.ALL);

                    Set<edu.internet2.middleware.grouper.Group> groupOptout = gh
                            .findGroupsWhereMemberHasPrivCached(Privs.OPTOUT, ScopeEnum.ALL);

                    if (groupOptin.isEmpty() && groupOptout.isEmpty())
                        return groups;

                    Set<edu.internet2.middleware.grouper.Group> groupMembers = member.getGroups();

                    groups.setGroupAPIWrapper(grouperApiWrapper);
                    groups.setGroupSet(Privs.OPTIN, ScopeEnum.IMMEDIATE, groupOptin);
                    groups.setGroupSet(Privs.OPTOUT, ScopeEnum.IMMEDIATE, groupOptout);
                    groups.setMembers(groupMembers);

                    return groups;
                }
            });
            // timeTotal += System.currentTimeMillis() - deb;
        } catch (GrouperDAOException e) {
            GrouperSession.stopQuietly(session);
            throw new ESCOTechnicalException(ServiceConstants.API_ERROR, e);
        } finally {
            GrouperSession.stopQuietly(session);
            GrouperSession.stopQuietly(rootSession);
        }
        // Log to calculate time of service
        // this.LOGGER.error("findGroupsMemberOptinOptout;" + timeTotal);

        return groups;
    }

    /**
     * {@inheritDoc}
     */
    public List<Privilege> findGroupPrivileges(final Person thePerson, final List<String> theAttributes,
            final Map<String, SourceTypeEnum> theSources, final String theGroupName,
            final ScopeEnum thePrivilegesScope) {
        return this.findStemOrGroupPrivileges(thePerson, theAttributes, theSources, theGroupName,
                thePrivilegesScope, PrivilegeSearchEnum.GROUP);
    }

    /**
     * {@inheritDoc}
     */
    public List<Group> findSubjectPrivilegesGroup(final Person thePerson, final String theSubjectId,
            final ScopeEnum theScope) {
        // long timeTotal = 0;
        Validate.notNull(thePerson, ServiceConstants.THE_PERSON_MUST_BE_DEFINED);
        Validate.notNull(theSubjectId, ServiceConstants.THE_SUBJECT_MUST_BE_DEFINED);
        Validate.notNull(theScope, ServiceConstants.THE_SCOPE_MUST_BE_DEFINED);

        // this list is the result and it is modified in the method
        // callbackGrouperTransaction
        //    final List < Group > groups = new ArrayList < Group >();

        final JustIterableListGroupWrapper groups = new JustIterableListGroupWrapper();

        GrouperSession session = null;
        Subject subject = null;
        try {
            // long deb = System.currentTimeMillis();
            session = GrouperSession.startRootSession();
            // session =
            // GrouperSession.start(SubjectFinder.findById(thePerson.getId()));
            subject = SubjectFinder.findById(theSubjectId, true);
            // timeTotal += System.currentTimeMillis() - deb;
        } catch (SessionException e) {
            throw new ESCOTechnicalException(ServiceConstants.SESSION_CANNOT_BE_CREATE, e);
        } catch (SubjectNotFoundException e) {//
        } catch (SubjectNotUniqueException e) {//
        }

        LOGGER.debug("findSubjectPrivilegesGroup ");

        try {
            final GrouperSession grouperSession = session;
            final Subject subject2 = subject;

            // start a transaction
            // long deb = System.currentTimeMillis();
            GrouperTransaction.callbackGrouperTransaction(new GrouperTransactionHandler() {
                public Object callback(final GrouperTransaction grouperTransaction) throws GrouperDAOException {

                    Member member = MemberFinder.findBySubject(grouperSession, subject2, false);

                    GrouperHelper gh = grouperHelperFactory.get(grouperSession);
                    // le sujet de la session n'est pas celui pour les calculs
                    // on change donc le suject (et le member) du grouperHelper
                    gh.setSubject(subject2);
                    try {
                        gh.setMember(member);
                    } catch (GrouperHelperException e) {
                        throw new GrouperDAOException(e);
                    }

                    //
                    ScopeEnum scopes[] = { ScopeEnum.IMMEDIATE, ScopeEnum.EFFECTIVE };

                    for (ScopeEnum scope : scopes) {
                        if (scope == theScope || theScope == ScopeEnum.ALL) {
                            for (Privs priv : Privs.values()) {
                                if (priv.isGroup()) {
                                    groups.setGroupSet(priv, scope,
                                            gh.findGroupsWhereMemberHasPrivCached(priv, scope));
                                }
                            }
                        }
                    }

                    groups.setGroupAPIWrapper(getGroupAPIWrapper());

                    return groups;
                }
            });
            // timeTotal += System.currentTimeMillis() - deb;
        } catch (GrouperDAOException e) {
            GrouperSession.stopQuietly(session);
            throw new ESCOTechnicalException(ServiceConstants.API_ERROR, e);
        } finally {
            GrouperSession.stopQuietly(session);
        }
        // Log to calculate time of service
        // this.LOGGER.error("findSubjectPrivilegesGroup;" + timeTotal);
        return groups;
    }

    /**
     * {@inheritDoc}
     */
    public List<Stem> findSubjectPrivilegesStem(final Person thePerson, final String theSubjectId,
            final ScopeEnum thePrivilegesScope) {
        // long timeTotal = 0;
        Validate.notNull(thePerson, ServiceConstants.THE_PERSON_MUST_BE_DEFINED);
        Validate.notNull(theSubjectId, ServiceConstants.THE_SUBJECT_MUST_BE_DEFINED);
        Validate.notNull(thePrivilegesScope, ServiceConstants.THE_SCOPE_MUST_BE_DEFINED);

        // this list is the result and it is modified in the method
        // callbackGrouperTransaction

        final JustIterableListStemWrapper stems = new JustIterableListStemWrapper();

        GrouperSession session = null;
        edu.internet2.middleware.subject.Subject subject = null;
        try {
            // long deb = System.currentTimeMillis();
            session = GrouperSession.startRootSession();
            // session =
            // GrouperSession.start(SubjectFinder.findById(thePerson.getId()));
            subject = SubjectFinder.findById(theSubjectId, true);
            // timeTotal += System.currentTimeMillis() - deb;
        } catch (SessionException e) {
            throw new ESCOTechnicalException(ServiceConstants.SESSION_CANNOT_BE_CREATE, e);
        } catch (SubjectNotFoundException e) {
        } catch (SubjectNotUniqueException e) {
        }

        try {
            final GrouperSession grouperSession = session;
            final Subject subject2 = subject;

            // start a transaction
            // long deb = System.currentTimeMillis();
            LOGGER.debug("grouperTransaction.callbackGrouperTransaction(:");
            GrouperTransaction.callbackGrouperTransaction(new GrouperTransactionHandler() {
                public Object callback(final GrouperTransaction grouperTransaction) throws GrouperDAOException {

                    List<String> uuidAlreadyUse = new ArrayList<String>();
                    Member member = MemberFinder.findBySubject(grouperSession, subject2, false);

                    GrouperHelper gh = grouperHelperFactory.get(grouperSession);
                    // le sujet de la session n'est pas celui pour les calculs
                    // on change donc le suject (et le member) du grouperHelper
                    gh.setSubject(subject2);
                    try {
                        gh.setMember(member);
                    } catch (GrouperHelperException e) {
                        throw new GrouperDAOException(e);
                    }

                    stems.setStemRight(gh.findStemWhereMemberHasPriv(Privs.STEM, thePrivilegesScope));
                    stems.setCreateRight(gh.findStemWhereMemberHasPriv(Privs.CREATE, thePrivilegesScope));
                    stems.setStemApiWrapper(getStemAPIWrapper());

                    return stems;
                }
            });
            // timeTotal += System.currentTimeMillis() - deb;
        } catch (GrouperDAOException e) {
            GrouperSession.stopQuietly(session);
            throw new ESCOTechnicalException(ServiceConstants.API_ERROR, e);
        } finally {
            GrouperSession.stopQuietly(session);
        }
        // Log to calculate time of service
        // this.LOGGER.error("findSubjectPrivilegesStem;" + timeTotal);
        return stems;
    }

    /**
     * {@inheritDoc}
     */
    public Boolean moveGroup(final Person thePerson, final String theOriginalGroupId, final Stem theTargetStem)
            throws ESCOGroupNotMoveException, ESCOGroupNotFoundException, ESCOStemNotFoundException {

        GrouperSession session = null;
        GrouperSession rootSession = null;
        edu.internet2.middleware.subject.Subject subject = null;
        try {
            rootSession = GrouperSession.startRootSession();
            subject = SubjectFinder.findById(thePerson.getId(), true);
            session = GrouperSession.start(subject);
        } catch (SessionException e) {
            throw new ESCOTechnicalException(ServiceConstants.SESSION_CANNOT_BE_CREATE, e);
        } catch (SubjectNotFoundException e) {
        } catch (SubjectNotUniqueException e) {
        }

        edu.internet2.middleware.grouper.Group theInitGroup = null;
        edu.internet2.middleware.grouper.Stem theTargetedStem = null;

        try {
            theInitGroup = GroupFinder.findByUuid(session, theOriginalGroupId, true);
        } catch (GroupNotFoundException e) {
            throw new ESCOGroupNotFoundException(ServiceConstants.GROUP_NOT_FOUND, e);
        }
        try {
            theTargetedStem = StemFinder.findByName(session, theTargetStem.getName(), true);

        } catch (StemNotFoundException e) {
            throw new ESCOStemNotFoundException(ServiceConstants.STEM_NOT_FOUND, e);
        }

        GroupMove gMove = new GroupMove(theInitGroup, theTargetedStem);
        gMove.assignAlternateName(false);
        try {
            gMove.save();
            grouperHelperFactory.get(session).clearCache();

        } catch (GroupModifyException e) {
            GrouperSession.stopQuietly(session);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOGroupNotMoveException(ServiceConstants.GROUP_CANNOT_BE_MOVED, e);
        } catch (InsufficientPrivilegeException e) {
            GrouperSession.stopQuietly(session);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOGroupNotMoveException(ServiceConstants.GROUP_CANNOT_BE_MOVED, e);
        } finally {
            GrouperSession.stopQuietly(session);
            GrouperSession.stopQuietly(rootSession);
        }

        return Boolean.TRUE;

    }

    /**
     * Converts a Lazy subject into a Privilege.
     * 
     * @param theSubject
     *            The subject to convert.
     * @param theScope
     *            The privilege scope.
     * @param thePrivilegeName
     *            The privilege name.
     * @return The privilege from the subject.
     */
    private Privilege convertToPrivilege(final LazySubject theSubject, final Person person,
            final ScopeEnum theScope, final String thePrivilegeName) {

        if (theSubject == null || theSubject.getType() == null || theSubject.getType().getName() == null
                || ServiceConstants.GROUPER_ALL.equals(theSubject.getId())
                || ServiceConstants.GROUPER_SYSTEM.equals(theSubject.getId())) {
            return null;
        }

        Privilege privilege = new Privilege();
        privilege.setPrivilegeName(thePrivilegeName);
        privilege.setType(theScope);

        if (SourceTypeEnum.PERSON.equals(SourceTypeEnum.valueOf(theSubject.getType().getName().toUpperCase()))) {
            if (person == null) {
                Person aPerson = new Person();
                aPerson.setId(theSubject.getId());
                aPerson.setAttributes(theSubject.getAttributes());
                privilege.setPersonTarget(aPerson);
            } else {
                privilege.setPersonTarget(person);

            }
        } else {
            Group oneGroup = new Group();
            oneGroup.setIdGroup(theSubject.getId());
            oneGroup.setAttributes(theSubject.getAttributes());
            privilege.setGroupTarget(oneGroup);
        }
        return privilege;
    }

    /**
     * Get if the parent group has the optin or optout rigth.
     * 
     * @param theGroup
     *            The group to test.
     * @param theParentId
     *            The parent group.
     * @param isOptin
     *            True if we test optin else false for optout.
     * @return the result of the request.
     */
    private boolean getOptinOrOptoutPrivilege(final edu.internet2.middleware.grouper.Group theGroup,
            final String theParentId, final boolean isOptin) {

        boolean result = false;
        Set<Subject> aux;
        if (isOptin) {
            aux = theGroup.getOptins();
        } else {
            aux = theGroup.getOptouts();
        }
        for (Subject subject : aux) {
            if (subject != null && subject.getId().equals(theParentId)) {
                result = true;
                break;
            }
        }
        return result;
    }

    /**
     * {@inheritDoc}
     */
    public Boolean moveStem(final Person thePerson, final String theOriginalStemName, final Stem theTargetStem)
            throws ESCOStemNotMoveException, ESCOStemNotFoundException {
        Validate.notNull(thePerson, "The thePerson canot be null.");
        Validate.notNull(theOriginalStemName, "The theOriginalStemName canot be null.");
        Validate.notNull(theTargetStem, "The theTargetStem canot be null.");

        GrouperSession grouperSession = null;
        GrouperSession rootSession = null;
        Subject subject = null;

        try {
            rootSession = GrouperSession.startRootSession();
            subject = SubjectFinder.findById(thePerson.getId(), true);
            grouperSession = GrouperSession.start(subject);
        } catch (SessionException e) {
            throw new ESCOTechnicalException(ServiceConstants.SESSION_CANNOT_BE_CREATE, e);
        } catch (SubjectNotFoundException e) {//
        } catch (SubjectNotUniqueException e) {//
        }

        try {
            StemMove stemMove = new StemMove(StemFinder.findByName(grouperSession, theOriginalStemName, true),
                    StemFinder.findByName(grouperSession, theTargetStem.getName(), true));
            stemMove.assignAlternateName(false);
            stemMove.save();
            // pl
            GrouperHelper egh = grouperHelperFactory.get(grouperSession);
            egh.clearCache();

        } catch (StemModifyException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOStemNotMoveException(e.getMessage());
        } catch (InsufficientPrivilegeException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOStemNotMoveException(e.getMessage());
        } catch (StemNotFoundException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOStemNotFoundException(e.getMessage());
        } finally {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
        }
        GrouperSession.stopQuietly(grouperSession);
        return Boolean.TRUE;
    }

    /**
     * Getter for attribute <b>personWrapper</b>.
     * 
     * @return the personWrapper
     */
    public IWrapper<edu.internet2.middleware.subject.Subject, Person> getPersonWrapper() {
        return this.personWrapper;
    }

    /**
     * Setter for attribute <b>personWrapper</b>.
     * 
     * @param thePersonWrapper
     *            the personWrapper to set
     */
    public void setPersonWrapper(
            final IWrapper<edu.internet2.middleware.subject.Subject, Person> thePersonWrapper) {
        this.personWrapper = thePersonWrapper;
    }

    /**
     * Getter for attribute <b>strategyLocator</b>.
     * 
     * @return the strategyLocator
     */
    public IStrategySubjectSearchLocator getStrategyLocator() {
        return this.strategyLocator;
    }

    /**
     * @return
     */
    public IStrategyGroupSearchLocator getStrategyGroupLocator() {
        return this.strategyGroupLocator;
    }

    /**
     * @param theStrategyGroupLocator
     */
    public void setStrategyGroupLocator(final IStrategyGroupSearchLocator theStrategyGroupLocator) {
        this.strategyGroupLocator = theStrategyGroupLocator;
    }

    /**
     * Setter for attribute <b>strategyLocator</b>.
     * 
     * @param theStrategyLocator
     *            : the strategyLocator to set
     */
    public void setStrategyLocator(final IStrategySubjectSearchLocator theStrategyLocator) {
        this.strategyLocator = theStrategyLocator;
    }

    /**
     * Getter for attribute <b>groupTypeWrapper</b>.
     * 
     * @return the groupTypeWrapper
     */
    public IWrapper<edu.internet2.middleware.grouper.GroupType, GroupType> getGroupTypeWrapper() {
        return this.groupTypeWrapper;
    }

    /**
     * Setter for attribute <b>groupTypeWrapper</b>.
     * 
     * @param theGroupTypeWrapper
     *            the groupTypeWrapper to set
     */
    public void setGroupTypeWrapper(
            final IWrapper<edu.internet2.middleware.grouper.GroupType, GroupType> theGroupTypeWrapper) {
        this.groupTypeWrapper = theGroupTypeWrapper;
    }

    /**
     * Getter for attribute <b>groupAPIWrapper</b>.
     * 
     * @return the groupAPIWrapper
     */
    public IWrapper<edu.internet2.middleware.grouper.Group, Group> getGroupAPIWrapper() {
        return this.groupAPIWrapper;
    }

    /**
     * Setter for attribute <b>groupAPIWrapper</b>.
     * 
     * @param theGroupAPIWrapper
     *            the groupAPIWrapper to set
     */
    public void setGroupAPIWrapper(
            final IWrapper<edu.internet2.middleware.grouper.Group, Group> theGroupAPIWrapper) {
        this.groupAPIWrapper = theGroupAPIWrapper;
    }

    /**
     * Getter for attribute <b>stemAPIWrapper</b>.
     * 
     * @return the stemAPIWrapper to get.
     */
    public final IWrapper<edu.internet2.middleware.grouper.Stem, Stem> getStemAPIWrapper() {
        return this.stemAPIWrapper;
    }

    /**
     * Setter for attribute <b>stemAPIWrapper</b>.
     * 
     * @param theStemAPIWrapper
     *            the stemAPIWrapper to set.
     */
    public final void setStemAPIWrapper(
            final IWrapper<edu.internet2.middleware.grouper.Stem, Stem> theStemAPIWrapper) {
        this.stemAPIWrapper = theStemAPIWrapper;
    }

    /**
     * {@inheritDoc}
     */
    public Members findMembers(final Person thePerson, final String theGroupName, final List<String> theAttributes,
            final Map<String, SourceTypeEnum> theSources, final ScopeEnum theMembersScope)
            throws ESCOGroupNotFoundException, ESCOInsufficientPrivilegesException {
        Validate.notNull(thePerson, ServiceConstants.THE_PERSON_MUST_BE_DEFINED);
        Validate.notNull(theGroupName, ServiceConstants.THE_GROUP_MUST_BE_DEFINED);
        Validate.notNull(theAttributes, "The attributes must be defined");
        Validate.notNull(theSources, "The sources must be defined");
        Validate.notNull(theMembersScope, ServiceConstants.THE_SCOPE_MUST_BE_DEFINED);

        GrouperSession grouperSession = null;
        GrouperSession rootSession = null;
        Subject subject = null;
        Members members = null;

        try {
            rootSession = GrouperSession.startRootSession();
            subject = SubjectFinder.findById(thePerson.getId(), true);
            grouperSession = GrouperSession.start(subject);
        } catch (SessionException e) {
            throw new ESCOTechnicalException(ServiceConstants.SESSION_CANNOT_BE_CREATE, e);
        } catch (SubjectNotFoundException e) {//
        } catch (SubjectNotUniqueException e) {//
        }

        try {
            edu.internet2.middleware.grouper.Group group = GroupFinder.findByName(grouperSession, theGroupName,
                    true);

            Set<Member> myMembers = null;
            SourceTypeEnum type = null;

            if (ScopeEnum.ALL.equals(theMembersScope)) {
                myMembers = group.getMembers();
            } else if (ScopeEnum.EFFECTIVE.equals(theMembersScope)) {
                myMembers = group.getEffectiveMembers();
            } else if (ScopeEnum.IMMEDIATE.equals(theMembersScope)) {
                myMembers = group.getImmediateMembers();
            }

            members = new Members();
            final Set<Member> toRemove = new HashSet<Member>();
            for (Member member : myMembers) {
                type = theSources.get(member.getSubjectSourceId());

                if (type != null) {

                    if (SourceTypeEnum.GROUP.equals(type)) {
                        edu.internet2.middleware.grouper.Group groupFind = null;
                        groupFind = GroupFinder.findByUuid(grouperSession, member.getSubjectId(), true);
                        toRemove.add(member);
                        if (groupFind != null) {
                            Group groupAdd = new Group();
                            groupAdd.setIdGroup(member.getSubjectId());
                            groupAdd.setAttributes(member.getSubject().getAttributes());
                            groupAdd.setTypeEnum(type);
                            members.addGroup(groupAdd);
                        }
                    } else if (!SourceTypeEnum.PERSON.equals(type)) {
                        // Must never occur.
                        GrouperSession.stopQuietly(grouperSession);
                        throw new ESCOTechnicalException("The type of source is undefined.");
                    }

                }
            }
            myMembers.removeAll(toRemove);
            members.getPersons()
                    .addAll(personsDataDelegate.getPersonsDataFromMembers(theSources, myMembers).values());

        } catch (GroupNotFoundException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOGroupNotFoundException(ServiceConstants.GROUP_NOT_FOUND, e);
        } catch (InsufficientPrivilegeException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOInsufficientPrivilegesException(ServiceConstants.INSUFFICIENT_PRIVILEGES, e);
        } finally {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
        }
        return members;
    }

    /**
     * {@inheritDoc}
     */
    public Integer countPersons(final Person thePerson, final List<String> theGroupsName,
            final Map<String, SourceTypeEnum> theSources, final ScopeEnum theMembersScope)
            throws ESCOGroupNotFoundException, ESCOInsufficientPrivilegesException {
        Validate.notNull(thePerson, ServiceConstants.THE_PERSON_MUST_BE_DEFINED);
        Validate.notNull(theGroupsName, ServiceConstants.THE_GROUP_MUST_BE_DEFINED);

        GrouperSession grouperSession = null;
        GrouperSession rootSession = null;
        Subject subject = null;
        int cpt = 0;

        try {
            rootSession = GrouperSession.startRootSession();
            subject = SubjectFinder.findById(thePerson.getId(), true);
            grouperSession = GrouperSession.start(subject);
        } catch (SessionException e) {
            throw new ESCOTechnicalException(ServiceConstants.SESSION_CANNOT_BE_CREATE, e);
        } catch (SubjectNotFoundException e) {//
        } catch (SubjectNotUniqueException e) {//
        }

        try {
            for (String groupName : theGroupsName) {
                edu.internet2.middleware.grouper.Group group = GroupFinder.findByName(grouperSession, groupName,
                        true);

                Set<Member> myMembers = null;

                if (ScopeEnum.ALL.equals(theMembersScope)) {
                    myMembers = group.getMembers();
                } else if (ScopeEnum.EFFECTIVE.equals(theMembersScope)) {
                    myMembers = group.getEffectiveMembers();
                } else if (ScopeEnum.IMMEDIATE.equals(theMembersScope)) {
                    myMembers = group.getImmediateMembers();
                }
                for (Member member : myMembers) {
                    if (SourceTypeEnum.PERSON.equals(theSources.get(member.getSubjectSourceId()))) {
                        cpt++;
                    }
                }
            }
        } catch (GroupNotFoundException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOGroupNotFoundException(ServiceConstants.GROUP_NOT_FOUND, e);
        } catch (InsufficientPrivilegeException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOInsufficientPrivilegesException(ServiceConstants.INSUFFICIENT_PRIVILEGES, e);
        } finally {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
        }
        return new Integer(cpt);
    }

    /**
     * {@inheritDoc}
     */
    public void addMembers(final Person thePerson, final String theGroupName, final List<String> theMembersToAdd)
            throws ESCOGroupNotFoundException, ESCOInsufficientPrivilegesException, ESCOAddMemberException {
        Validate.notNull(thePerson, ServiceConstants.THE_PERSON_MUST_BE_DEFINED);
        Validate.notNull(theGroupName, ServiceConstants.THE_GROUP_MUST_BE_DEFINED);
        Validate.notNull(theMembersToAdd, ServiceConstants.THE_MEMBERS_MUST_BE_DEFINED);

        GrouperSession grouperSession = null;
        GrouperSession rootSession = null;
        Subject subject = null;

        try {
            rootSession = GrouperSession.startRootSession();
            subject = SubjectFinder.findById(thePerson.getId(), true);
            grouperSession = GrouperSession.start(subject);
        } catch (SessionException e) {
            throw new ESCOTechnicalException(ServiceConstants.SESSION_CANNOT_BE_CREATE, e);
        } catch (SubjectNotFoundException e) {//
        } catch (SubjectNotUniqueException e) {//
        }

        try {
            edu.internet2.middleware.grouper.Group group = GroupFinder.findByName(grouperSession, theGroupName,
                    true);

            Subject myMember = null;

            for (String subjectId : theMembersToAdd) {
                myMember = SubjectFinder.findById(subjectId, true);
                if (!group.hasImmediateMember(myMember)) {
                    group.addMember(myMember);
                }
            }
        } catch (GroupNotFoundException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOGroupNotFoundException(ServiceConstants.GROUP_NOT_FOUND, e);
        } catch (InsufficientPrivilegeException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOInsufficientPrivilegesException(ServiceConstants.INSUFFICIENT_PRIVILEGES, e);
        } catch (MemberAddException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOAddMemberException(ServiceConstants.MEMBER_CANNOT_BE_ADDED, e);
        } catch (SubjectNotFoundException e) {//
        } catch (SubjectNotUniqueException e) {//
        } finally {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
        }
    }

    /**
     * {@inheritDoc}
     */
    public void removeMembers(final Person thePerson, final String theGroupName,
            final List<String> theMembersToRemove)
            throws ESCOGroupNotFoundException, ESCOInsufficientPrivilegesException, ESCODeleteMemberException {
        this.removeMembers(thePerson, theGroupName, theMembersToRemove, true);
    }

    /**
     * {@inheritDoc}
     */
    public void removeMembers(final Person thePerson, final String theGroupName,
            final List<String> theMembersToRemove, final boolean isActAsSubject)
            throws ESCOGroupNotFoundException, ESCOInsufficientPrivilegesException, ESCODeleteMemberException {
        Validate.notNull(thePerson, ServiceConstants.THE_PERSON_MUST_BE_DEFINED);
        Validate.notNull(theGroupName, ServiceConstants.THE_GROUP_MUST_BE_DEFINED);
        Validate.notNull(theMembersToRemove, ServiceConstants.THE_MEMBERS_MUST_BE_DEFINED);

        GrouperSession grouperSession = null;
        GrouperSession rootSession = null;
        Subject subject = null;

        try {
            rootSession = GrouperSession.startRootSession();
            subject = SubjectFinder.findById(thePerson.getId(), true);

            if (isActAsSubject) {
                grouperSession = GrouperSession.start(subject);
            } else {
                grouperSession = GrouperSession.startRootSession();
            }
        } catch (SessionException e) {
            throw new ESCOTechnicalException(ServiceConstants.SESSION_CANNOT_BE_CREATE, e);
        } catch (SubjectNotFoundException e) {//
        } catch (SubjectNotUniqueException e) {//
        }

        try {
            edu.internet2.middleware.grouper.Group group = GroupFinder.findByName(grouperSession, theGroupName,
                    true);
            Subject myMember = null;
            for (String subjectId : theMembersToRemove) {
                myMember = SubjectFinder.findById(subjectId, true);
                if (group.hasMember(myMember)) {
                    group.deleteMember(myMember, false);
                }
            }

        } catch (GroupNotFoundException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOGroupNotFoundException(ServiceConstants.GROUP_NOT_FOUND, e);
        } catch (InsufficientPrivilegeException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOInsufficientPrivilegesException(ServiceConstants.INSUFFICIENT_PRIVILEGES, e);
        } catch (MemberDeleteException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCODeleteMemberException(ServiceConstants.MEMBER_CANNOT_BE_DELETED, e);
        } catch (SubjectNotFoundException e) {
        } catch (SubjectNotUniqueException e) {
        } finally {
            GrouperSession.stopQuietly(rootSession);
            GrouperSession.stopQuietly(grouperSession);
        }
    }

    /**
     * {@inheritDoc}
     */
    public void copyMembers(final Person thePerson, final String theSourceName, final String theTargetName)
            throws ESCOGroupNotFoundException, ESCOInsufficientPrivilegesException, ESCOAddMemberException {
        Validate.notNull(thePerson, ServiceConstants.THE_PERSON_MUST_BE_DEFINED);
        Validate.notNull(theSourceName, "The source name must be defined");
        Validate.notNull(theTargetName, "The target name must be defined");

        GrouperSession grouperSession = null;
        GrouperSession rootSession = null;
        Subject subject = null;

        try {
            rootSession = GrouperSession.startRootSession();
            subject = SubjectFinder.findById(thePerson.getId(), true);
            grouperSession = GrouperSession.start(subject);
        } catch (SessionException e) {
            throw new ESCOTechnicalException(ServiceConstants.SESSION_CANNOT_BE_CREATE, e);
        } catch (SubjectNotFoundException e) {//
        } catch (SubjectNotUniqueException e) {//
        }

        try {
            edu.internet2.middleware.grouper.Group group = GroupFinder.findByName(grouperSession, theSourceName,
                    true);
            edu.internet2.middleware.grouper.Group targetGroup = GroupFinder.findByName(grouperSession,
                    theTargetName, true);
            for (Member member : group.getImmediateMembers()) {
                targetGroup.addMember(member.getSubject());
            }

        } catch (GroupNotFoundException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOGroupNotFoundException(ServiceConstants.GROUP_NOT_FOUND, e);
        } catch (InsufficientPrivilegeException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOInsufficientPrivilegesException(ServiceConstants.INSUFFICIENT_PRIVILEGES, e);
        } catch (SubjectNotFoundException e) {//
        } catch (SubjectNotUniqueException e) {//
        } finally {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
        }
    }

    /**
     * {@inheritDoc}
     */
    public Stem findStemByUuid(final Person thePerson, final String theUuid)
            throws ESCOStemNotFoundException, ESCOStemNotUniqueException {
        Validate.notNull(thePerson, ServiceConstants.THE_PERSON_MUST_BE_DEFINED);
        Validate.notNull(theUuid, ServiceConstants.THE_ID_MUST_BE_DEFINED);

        GrouperSession grouperSession = null;
        GrouperSession rootSession = null;
        Subject subject = null;
        Stem stem = null;

        try {
            rootSession = GrouperSession.startRootSession();
            subject = SubjectFinder.findById(thePerson.getId(), true);
            grouperSession = GrouperSession.start(subject);
        } catch (SessionException e) {
            throw new ESCOTechnicalException(ServiceConstants.SESSION_CANNOT_BE_CREATE, e);
        } catch (SubjectNotFoundException e) {//
        } catch (SubjectNotUniqueException e) {//
        }

        try {
            edu.internet2.middleware.grouper.Stem myStem = StemFinder.findByUuid(grouperSession, theUuid, true);
            stem = this.getStemAPIWrapper().wrap(myStem);
            stem.setIsEmpty(this.isEmptyStem(stem.getName()));
        } catch (StemNotFoundException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOStemNotFoundException(ServiceConstants.STEM_NOT_FOUND, e);
        } finally {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
        }
        return stem;
    }

    /**
     * {@inheritDoc}
     */
    public Stem findStemByName(final Person thePerson, final String theName)
            throws ESCOStemNotFoundException, ESCOStemNotUniqueException {
        Validate.notNull(thePerson, ServiceConstants.THE_PERSON_MUST_BE_DEFINED);
        Validate.notNull(theName, ServiceConstants.THE_NAME_MUST_BE_DEFINED);

        GrouperSession grouperSession = null;
        GrouperSession rootSession = null;
        Subject subject = null;
        Stem stem = null;

        try {
            rootSession = GrouperSession.startRootSession();
            subject = SubjectFinder.findById(thePerson.getId(), true);
            grouperSession = GrouperSession.start(subject);
        } catch (SessionException e) {
            throw new ESCOTechnicalException(ServiceConstants.SESSION_CANNOT_BE_CREATE, e);
        } catch (SubjectNotFoundException e) {//
        } catch (SubjectNotUniqueException e) {//
        }

        try {
            edu.internet2.middleware.grouper.Stem myStem = StemFinder.findByName(grouperSession, theName, true);
            stem = this.getStemAPIWrapper().wrap(myStem);
            stem.setIsEmpty(this.isEmptyStem(stem.getName()));
        } catch (StemNotFoundException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOStemNotFoundException(ServiceConstants.STEM_NOT_FOUND, e);
        } finally {
            GrouperSession.stopQuietly(rootSession);
            GrouperSession.stopQuietly(grouperSession);
        }
        return stem;
    }

    /**
     * {@inheritDoc}
     */
    public List<Stem> searchStems(final Person thePerson, final SearchStemEnum theField, final String theTerm,
            final String thePath) throws ESCOStemNotFoundException {
        Validate.notNull(thePerson, ServiceConstants.THE_PERSON_MUST_BE_DEFINED);
        Validate.notNull(theField, ServiceConstants.THE_FIELD_MUST_BE_DEFINED);
        Validate.notNull(theTerm, ServiceConstants.THE_TERM_MUST_BE_DEFINED);
        Validate.notNull(thePath, ServiceConstants.THE_PATH_MUST_BE_DEFINED);

        GrouperSession grouperSession = null;
        GrouperSession rootSession = null;
        Subject subject = null;
        List<Stem> stems = new ArrayList<Stem>();

        try {
            rootSession = GrouperSession.startRootSession();
            subject = SubjectFinder.findById(thePerson.getId(), true);
            grouperSession = GrouperSession.start(subject);
        } catch (SessionException e) {
            throw new ESCOTechnicalException(ServiceConstants.SESSION_CANNOT_BE_CREATE, e);
        } catch (SubjectNotFoundException e) {//
        } catch (SubjectNotUniqueException e) {//
        }

        try {
            String prettyTerm = theTerm.replace(ServiceConstants.WILDCARD, ServiceConstants.GROUPER_WILDCARD);
            List<edu.internet2.middleware.grouper.Stem> stemsTmp = new ArrayList<edu.internet2.middleware.grouper.Stem>(
                    StemFinder.internal_findAllByApproximateName(grouperSession, prettyTerm));

            for (edu.internet2.middleware.grouper.Stem stem : stemsTmp) {
                stems.add(this.getStemAPIWrapper().wrap(stem));
            }
        } catch (QueryException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOStemNotFoundException(ServiceConstants.STEM_NOT_FOUND, e);
        } finally {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
        }
        return stems;
    }

    /**
     * {@inheritDoc}
     */
    public String stemCreate(final Person thePerson, final Stem theStemToCreate) throws ESCOStemNotSaveException,
            ESCOStemNotFoundException, ESCOAttributeException, ESCOInsufficientPrivilegesException {
        Validate.notNull(thePerson, ServiceConstants.THE_PERSON_MUST_BE_DEFINED);
        Validate.notNull(theStemToCreate, ServiceConstants.THE_STEM_MUST_BE_DEFINED);

        GrouperSession grouperSession = null;
        GrouperSession rootSession = null;
        Subject subject = null;
        String stemUuid = null;

        try {
            rootSession = GrouperSession.startRootSession();
            subject = SubjectFinder.findById(thePerson.getId(), true);
            grouperSession = GrouperSession.start(subject);
        } catch (SessionException e) {
            throw new ESCOTechnicalException(ServiceConstants.SESSION_CANNOT_BE_CREATE, e);
        } catch (SubjectNotFoundException e) {//
        } catch (SubjectNotUniqueException e) {//
        }

        edu.internet2.middleware.grouper.Stem alreadyExist = StemFinder.findByName(grouperSession,
                theStemToCreate.getName(), false);
        if (alreadyExist != null) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOStemNotSaveException(ServiceConstants.STEM_ALREADY_EXIST);
        }
        edu.internet2.middleware.grouper.Stem stemCreated;

        if (theStemToCreate.getDescription() != null) {
            theStemToCreate.setDescription(theStemToCreate.getDescription().trim());
        }

        try {
            StemSave myStem = new StemSave(grouperSession);
            if (StringUtils.isNotEmpty(theStemToCreate.getUuid())) {
                myStem.assignUuid(theStemToCreate.getUuid());
            }

            if (StringUtils.isNotEmpty(theStemToCreate.getDescription())) {
                myStem.assignDescription(theStemToCreate.getDescription());
            }

            if (StringUtils.isNotEmpty(theStemToCreate.getDisplayExtension())) {
                myStem.assignDisplayExtension(theStemToCreate.getDisplayExtension());
            }

            if (StringUtils.isNotEmpty(theStemToCreate.getDisplayName())) {
                myStem.assignDisplayName(theStemToCreate.getDisplayName());
            }

            if (StringUtils.isNotEmpty(theStemToCreate.getName())) {
                myStem.assignName(theStemToCreate.getName());
            }
            myStem.assignSaveMode(SaveMode.INSERT);
            stemCreated = myStem.save();

        } catch (StemNotFoundException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOStemNotFoundException(ServiceConstants.STEM_NOT_FOUND, e);
        } catch (InsufficientPrivilegeException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOInsufficientPrivilegesException(ServiceConstants.INSUFFICIENT_PRIVILEGES, e);
        } catch (StemAddException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOStemNotSaveException(ServiceConstants.STEM_CANNOT_BE_SAVED, e);
        } catch (StemModifyException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOStemNotSaveException(ServiceConstants.STEM_CANNOT_BE_SAVED, e);
        }

        if (stemCreated != null) {
            stemUuid = stemCreated.getUuid();
            Privilege privilege = new Privilege();
            privilege.setPrivilegeType(PrivilegeTypeEnum.NAMING.getValue());
            privilege.setPrivilegeName(StemPrivilegeEnum.CREATE.getValue());
            try {
                this.assignStemPrivileges(thePerson, thePerson.getId(), stemUuid, privilege);
            } catch (ESCOStemNotUniqueException e) {
                // Nothing to do because no exception here
                // possible.
            }
        } else {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOStemNotSaveException(ServiceConstants.STEM_CANNOT_BE_SAVED);
        }
        GrouperSession.stopQuietly(grouperSession);
        GrouperSession.stopQuietly(rootSession);
        return stemUuid;
    }

    /**
     * {@inheritDoc}
     */
    public void stemUpdate(final Person thePerson, final Stem theStemToUpdate) throws ESCOStemNotSaveException,
            ESCOStemNotFoundException, ESCOAttributeException, ESCOInsufficientPrivilegesException {
        Validate.notNull(thePerson, ServiceConstants.THE_PERSON_MUST_BE_DEFINED);
        Validate.notNull(theStemToUpdate, ServiceConstants.THE_STEM_MUST_BE_DEFINED);

        GrouperSession grouperSession = null;
        GrouperSession rootSession = null;
        Subject subject = null;

        try {
            rootSession = GrouperSession.startRootSession();
            subject = SubjectFinder.findById(thePerson.getId(), true);
            grouperSession = GrouperSession.start(subject);
        } catch (SessionException e) {
            throw new ESCOTechnicalException(ServiceConstants.SESSION_CANNOT_BE_CREATE, e);
        } catch (SubjectNotFoundException e) {//
        } catch (SubjectNotUniqueException e) {//
        }

        if (theStemToUpdate.getDescription() != null) {
            theStemToUpdate.setDescription(theStemToUpdate.getDescription().trim());
        }

        try {
            StemSave myStem = new StemSave(grouperSession);
            myStem.assignStemNameToEdit(theStemToUpdate.getOriginalName());
            if (StringUtils.isNotEmpty(theStemToUpdate.getUuid())) {
                myStem.assignUuid(theStemToUpdate.getUuid());
            }

            if (StringUtils.isNotEmpty(theStemToUpdate.getDescription())) {
                myStem.assignDescription(theStemToUpdate.getDescription());
            }

            if (StringUtils.isNotEmpty(theStemToUpdate.getDisplayExtension())) {
                myStem.assignDisplayExtension(theStemToUpdate.getDisplayExtension());
            }

            if (StringUtils.isNotEmpty(theStemToUpdate.getDisplayName())) {
                myStem.assignDisplayName(theStemToUpdate.getDisplayName());
            }

            if (StringUtils.isNotEmpty(theStemToUpdate.getName())) {
                myStem.assignName(theStemToUpdate.getName());
            }

            myStem.assignSaveMode(SaveMode.UPDATE);
            myStem.save();
            // pl
            GrouperHelper egh = grouperHelperFactory.get(grouperSession);
            egh.clearCache();
        } catch (StemNotFoundException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOStemNotFoundException(ServiceConstants.STEM_NOT_FOUND, e);
        } catch (InsufficientPrivilegeException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOInsufficientPrivilegesException(ServiceConstants.INSUFFICIENT_PRIVILEGES, e);
        } catch (StemAddException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOStemNotSaveException(ServiceConstants.STEM_CANNOT_BE_SAVED, e);
        } catch (StemModifyException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOStemNotSaveException(ServiceConstants.STEM_CANNOT_BE_SAVED, e);
        } catch (Exception e) {
            throw new ESCOStemNotSaveException(ServiceConstants.STEM_CANNOT_BE_SAVED, e);
        } finally {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
        }
    }

    /**
     * {@inheritDoc}
     */
    public void stemDelete(final Person thePerson, final String theStemId)
            throws ESCOStemNotFoundException, ESCOInsufficientPrivilegesException {
        Validate.notNull(thePerson, ServiceConstants.THE_PERSON_MUST_BE_DEFINED);
        Validate.notNull(theStemId, ServiceConstants.THE_STEM_MUST_BE_DEFINED);

        GrouperSession grouperSession = null;
        GrouperSession rootSession = null;
        Subject subject = null;

        try {
            rootSession = GrouperSession.startRootSession();
            subject = SubjectFinder.findById(thePerson.getId(), true);
            grouperSession = GrouperSession.start(subject);
        } catch (SessionException e) {
            throw new ESCOTechnicalException(ServiceConstants.SESSION_CANNOT_BE_CREATE, e);
        } catch (SubjectNotFoundException e) {//
        } catch (SubjectNotUniqueException e) {//
        }

        try {
            edu.internet2.middleware.grouper.Stem stem = StemFinder.findByUuid(grouperSession, theStemId, true);
            if (stem != null) {
                stem.delete();
                // pl
                GrouperHelper egh = grouperHelperFactory.get(grouperSession);
                egh.clearCache();

            }
        } catch (StemNotFoundException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOStemNotFoundException(ServiceConstants.STEM_NOT_FOUND, e);
        } catch (InsufficientPrivilegeException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOInsufficientPrivilegesException(ServiceConstants.INSUFFICIENT_PRIVILEGES, e);
        } catch (StemDeleteException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOStemNotFoundException(ServiceConstants.STEM_CANNOT_BE_DELETED, e);
        } finally {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
        }
    }

    /**
     * {@inheritDoc}
     * 
     * @throws ESCOStemNotFoundException
     */
    public ArrayListMultimap<Integer, Group> getAllGroupsFrom(final String theParentName, final String thePersonId)
            throws ESCOStemNotFoundException {

        Validate.notNull(theParentName, "The name of the parent must be defined");
        Validate.notNull(thePersonId, ServiceConstants.THE_PERSON_MUST_BE_DEFINED);

        ArrayListMultimap<Integer, Group> result = ArrayListMultimap.create();

        int cpt = 0;

        GrouperSession session = null;
        GrouperSession rootSession = null;
        Subject person = null;
        try {
            rootSession = GrouperSession.startRootSession();
            person = SubjectFinder.findById(thePersonId, true);
            session = GrouperSession.start(person);

        } catch (SessionException e) {
            throw new ESCOTechnicalException(ServiceConstants.SESSION_CANNOT_BE_CREATE, e);
        } catch (SubjectNotFoundException e) {
            throw new ESCOTechnicalException(ServiceConstants.SUBJECT_NOT_FOUND, e);
        } catch (SubjectNotUniqueException e) {
            throw new ESCOTechnicalException(ServiceConstants.SUBJECT_NOT_UNIQUE, e);
        }

        try {
            edu.internet2.middleware.grouper.Stem parentStem = StemFinder.findByName(session, theParentName, true);

            // pl debug
            LOGGER.debug("parentStem.getChildGroups(Scope.ONE); => ");

            Set<edu.internet2.middleware.grouper.Group> groups = parentStem.getChildGroups(Scope.ONE);

            LOGGER.debug("<= parentStem.getChildGroups(Scope.ONE); ");

            // pl creation du grouperhelper qui va permetre de tester les droits
            GrouperHelper egh = grouperHelperFactory.get(session);

            for (edu.internet2.middleware.grouper.Group group : groups) {
                Group aux = this.groupAPIWrapper.wrap(group);
                aux.setCanOptin(false);
                aux.setCanOptout(false);
                aux.setUserRight(null);
                LOGGER.debug("   group.getPrivs(person); =>");
                //   Set < AccessPrivilege > privs = group.getPrivs(person);
                List<Privs> privs = egh.userPrivsList(group);

                LOGGER.debug("   <= group.getPrivs(person);", group.getName());

                if (privs == null || privs.isEmpty()) {
                    LOGGER.debug("      group sans privilege");
                } else {
                    for (Privs priv : privs) {
                        //       PrivilegeAssignUtils.assignPrivilege(aux, priv.getName());
                        PrivilegeAssignUtils.assignPrivilege(aux, priv.name());
                        LOGGER.debug("      privs=", priv);
                    }
                    result.put(cpt++, aux);
                }

            }

        } catch (StemNotFoundException stemNotFoundException) {
            GrouperSession.stopQuietly(session);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOStemNotFoundException();
        } finally {
            GrouperSession.stopQuietly(session);
            GrouperSession.stopQuietly(rootSession);
        }
        return result;

    }

    /**
     * {@inheritDoc}
     */
    public Group findGroupByUid(final Person thePerson, final String theUid)
            throws ESCOGroupNotFoundException, ESCOGroupNotUniqueException {
        Validate.notNull(thePerson, ServiceConstants.THE_PERSON_MUST_BE_DEFINED);
        Validate.notNull(theUid, ServiceConstants.THE_ID_MUST_BE_DEFINED);

        GrouperSession grouperSession = null;
        GrouperSession rootSession = null;
        Subject subject = null;
        Group myGroup = null;

        try {
            rootSession = GrouperSession.startRootSession();
            subject = SubjectFinder.findById(thePerson.getId(), true);
            grouperSession = GrouperSession.start(subject);
        } catch (SessionException e) {
            throw new ESCOTechnicalException(ServiceConstants.SESSION_CANNOT_BE_CREATE, e);
        } catch (SubjectNotFoundException e) {//
        } catch (SubjectNotUniqueException e) {//
        }

        try {
            edu.internet2.middleware.grouper.Group group = GroupFinder.findByUuid(grouperSession, theUid, true);
            myGroup = this.getGroupAPIWrapper().wrap(group);
        } catch (GroupNotFoundException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOGroupNotFoundException(ServiceConstants.STEM_NOT_FOUND, e);
        } finally {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
        }
        return myGroup;
    }

    /**
     * {@inheritDoc}
     */
    public Group findGroupByName(final Person thePerson, final String theName)
            throws ESCOGroupNotFoundException, ESCOGroupNotUniqueException {
        Validate.notNull(thePerson, ServiceConstants.THE_PERSON_MUST_BE_DEFINED);
        Validate.notNull(theName, ServiceConstants.THE_NAME_MUST_BE_DEFINED);

        GrouperSession grouperSession = null;
        GrouperSession rootSession = null;
        Subject subject = null;
        Group myGroup = null;

        try {
            rootSession = GrouperSession.startRootSession();
            subject = SubjectFinder.findById(thePerson.getId(), true);
            grouperSession = GrouperSession.start(subject);
        } catch (SessionException e) {
            throw new ESCOTechnicalException(ServiceConstants.SESSION_CANNOT_BE_CREATE, e);
        } catch (SubjectNotFoundException e) {//
        } catch (SubjectNotUniqueException e) {//
        }

        try {
            edu.internet2.middleware.grouper.Group group = GroupFinder.findByName(grouperSession, theName, true);
            myGroup = this.getGroupAPIWrapper().wrap(group);
        } catch (GroupNotFoundException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOGroupNotFoundException(ServiceConstants.STEM_NOT_FOUND, e);
        } finally {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
        }
        return myGroup;
    }

    /**
     * {@inheritDoc}
     */
    public List<Group> searchGroups(final Person thePerson, final SearchGroupEnum theField,
            final SearchTypeEnum theSearchType, final String thePath, final String theTerm)
            throws ESCOGroupNotFoundException {
        Validate.notNull(thePerson, ServiceConstants.THE_PERSON_MUST_BE_DEFINED);
        Validate.notNull(theField, ServiceConstants.THE_FIELD_MUST_BE_DEFINED);
        Validate.notNull(theSearchType, ServiceConstants.THE_SEARCH_TYPE_MUST_BE_DEFINED);
        Validate.notNull(thePath, ServiceConstants.THE_PATH_MUST_BE_DEFINED);
        Validate.notNull(theTerm, ServiceConstants.THE_TERM_MUST_BE_DEFINED);

        IStrategyGroupSearch strategy = this.getStrategyGroupLocator().locate(theField, theSearchType, thePath,
                theTerm, thePerson.getId());
        if (strategy == null) {
            throw new ESCOTechnicalException(ServiceConstants.STRATEGY_NOT_FOUND);
        }
        return strategy.searchGroups(thePerson, theField, theSearchType, thePath, theTerm);
    }

    /**
     * {@inheritDoc}
     */
    public String groupCreate(final Person thePerson, final Group theGroupToCreate)
            throws ESCOGroupNotSaveException, ESCOGroupNotFoundException, ESCOAttributeException,
            ESCOInsufficientPrivilegesException {
        Validate.notNull(thePerson, ServiceConstants.THE_PERSON_MUST_BE_DEFINED);
        Validate.notNull(theGroupToCreate, ServiceConstants.THE_GROUP_MUST_BE_DEFINED);

        GrouperSession grouperSession = null;
        GrouperSession rootSession = null;
        Subject subject = null;
        String groupUuid = null;

        try {
            rootSession = GrouperSession.startRootSession();
            subject = SubjectFinder.findById(thePerson.getId(), true);
            grouperSession = GrouperSession.start(subject);
        } catch (SessionException e) {
            throw new ESCOTechnicalException(ServiceConstants.SESSION_CANNOT_BE_CREATE, e);
        } catch (SubjectNotFoundException e) {//
        } catch (SubjectNotUniqueException e) {//
        }

        edu.internet2.middleware.grouper.Group alreadyExist = GroupFinder.findByName(grouperSession,
                theGroupToCreate.getName(), false);
        if (alreadyExist != null) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOGroupNotSaveException(ServiceConstants.GROUP_NOT_UNIQUE);
        }
        edu.internet2.middleware.grouper.Group groupCreated = null;
        try {
            GroupSave myGroup = new GroupSave(grouperSession);
            myGroup.assignUuid(theGroupToCreate.getIdGroup());
            myGroup.assignDescription(theGroupToCreate.getDescription());
            myGroup.assignDisplayExtension(theGroupToCreate.getDisplayExtension());
            myGroup.assignDisplayName(theGroupToCreate.getDisplayName());
            myGroup.assignName(theGroupToCreate.getName());
            myGroup.assignSaveMode(SaveMode.INSERT);
            groupCreated = myGroup.save();
            // pl
            GrouperHelper egh = grouperHelperFactory.get(grouperSession);
            egh.clearCache();
        } catch (GroupNotFoundException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOGroupNotFoundException(ServiceConstants.STEM_NOT_FOUND, e);
        } catch (InsufficientPrivilegeException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOInsufficientPrivilegesException(ServiceConstants.INSUFFICIENT_PRIVILEGES, e);
        } catch (GroupModifyException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOGroupNotSaveException(ServiceConstants.STEM_CANNOT_BE_SAVED, e);
        }

        if (groupCreated != null) {
            groupUuid = groupCreated.getUuid();

            // Manage of the group details.
            GroupDetail details = theGroupToCreate.getDetail();
            GroupDAO dao = GrouperDAOFactory.getFactory().getGroup();
            if (details != null) {
                if (details.getAttributeNames() != null && details.getAttributeValues() != null
                        && details.getAttributeNames().length == details.getAttributeValues().length) {
                    for (int i = 0; i < details.getAttributeNames().length; i++) {
                        groupCreated.setAttribute(details.getAttributeNames()[i], details.getAttributeValues()[i]);
                    }
                    try {
                        dao.update(groupCreated);
                    } catch (Exception e) {//
                    }
                }
                if (details.getTypeNames() != null) {
                    for (String type : details.getTypeNames()) {
                        try {
                            edu.internet2.middleware.grouper.GroupType aux = GroupTypeFinder.find(type, true);
                            if (!groupCreated.getTypes().contains(aux)) {
                                dao.addType(groupCreated, aux);
                                // types.add(GroupTypeFinder.find(type, true));
                            }
                        } catch (Exception e) {//
                        }
                    }
                    // groupCreated.setTypes(types);
                }
            }
        } else {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOGroupNotSaveException(ServiceConstants.GROUP_CANNOT_BE_SAVED);
        }
        GrouperSession.stopQuietly(grouperSession);
        GrouperSession.stopQuietly(rootSession);
        return groupUuid;
    }

    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
    public void groupUpdate(final Person thePerson, final Group theGroupToUpdate) throws ESCOGroupNotSaveException,
            ESCOGroupNotFoundException, ESCOAttributeException, ESCOInsufficientPrivilegesException {
        Validate.notNull(thePerson, ServiceConstants.THE_PERSON_MUST_BE_DEFINED);
        Validate.notNull(theGroupToUpdate, ServiceConstants.THE_GROUP_MUST_BE_DEFINED);

        GrouperSession grouperSession = null;
        GrouperSession rootSession = null;
        Subject subject = null;

        try {
            rootSession = GrouperSession.startRootSession();
            subject = SubjectFinder.findById(thePerson.getId(), true);
            grouperSession = GrouperSession.start(subject);
        } catch (SessionException e) {
            throw new ESCOTechnicalException(ServiceConstants.SESSION_CANNOT_BE_CREATE, e);
        } catch (SubjectNotFoundException e) {//
        } catch (SubjectNotUniqueException e) {//
        }
        edu.internet2.middleware.grouper.Group theGroupUpdated = null;
        try {
            theGroupUpdated = GroupFinder.findByUuid(grouperSession, theGroupToUpdate.getIdGroup(), true);
            if (theGroupUpdated == null) {
                GrouperSession.stopQuietly(grouperSession);
                GrouperSession.stopQuietly(rootSession);
                throw new ESCOGroupNotFoundException(ServiceConstants.GROUP_NOT_FOUND);
            }
        } catch (ESCOGroupNotFoundException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOGroupNotFoundException(ServiceConstants.GROUP_NOT_FOUND, e);
        }

        try {
            GroupSave myGroup = new GroupSave(grouperSession);
            myGroup.assignGroupNameToEdit(theGroupUpdated.getName());
            myGroup.assignUuid(theGroupToUpdate.getIdGroup());
            myGroup.assignDescription(theGroupToUpdate.getDescription());
            myGroup.assignDisplayExtension(theGroupToUpdate.getDisplayExtension());
            myGroup.assignDisplayName(theGroupToUpdate.getDisplayName());
            myGroup.assignName(theGroupToUpdate.getName());
            myGroup.assignSaveMode(SaveMode.UPDATE);
            theGroupUpdated = myGroup.save();
            // pl
            GrouperHelper egh = grouperHelperFactory.get(grouperSession);
            egh.clearCache();

        } catch (GroupNotFoundException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOGroupNotFoundException(ServiceConstants.GROUP_NOT_FOUND, e);
        } catch (InsufficientPrivilegeException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOInsufficientPrivilegesException(ServiceConstants.INSUFFICIENT_PRIVILEGES, e);
        } catch (GroupModifyException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOGroupNotSaveException(ServiceConstants.GROUP_CANNOT_BE_SAVED, e);
        } catch (Exception e) {
            throw new ESCOGroupNotSaveException(ServiceConstants.GROUP_CANNOT_BE_SAVED, e);
        }
        if (theGroupUpdated != null) {
            // Manage of the group details.
            GroupDetail details = theGroupToUpdate.getDetail();
            GroupDAO dao = GrouperDAOFactory.getFactory().getGroup();

            if (details != null) {

                // Manage the group attributes.
                if (details.getAttributeNames() != null && details.getAttributeValues() != null
                        && ArrayUtils.isSameLength(details.getAttributeNames(), details.getAttributeValues())) {
                    for (int i = 0; i < details.getAttributeNames().length; i++) {
                        theGroupUpdated.setAttribute(details.getAttributeNames()[i],
                                details.getAttributeValues()[i]);
                    }
                    try {
                        dao.update(theGroupUpdated);
                    } catch (Exception e) {//
                    }
                }

                if (details.getTypeNames() != null) {
                    List<String> typeNames = Arrays.asList(details.getTypeNames());
                    // Add some type.
                    for (String type : typeNames) {
                        try {
                            edu.internet2.middleware.grouper.GroupType aux = GroupTypeFinder.find(type, true);
                            if (!theGroupUpdated.getTypes().contains(aux)) {
                                dao.addType(theGroupUpdated, aux);
                            }
                        } catch (Exception e) {//
                        }
                    }
                    // Remove some type.
                    Set<edu.internet2.middleware.grouper.GroupType> originalGroupDetails = dao
                            ._findAllTypesByGroup(theGroupToUpdate.getIdGroup());

                    for (edu.internet2.middleware.grouper.GroupType type : originalGroupDetails) {
                        try {
                            if (!typeNames.contains(type.getName())
                                    && !type.getName().equals(ESCOConstantes.BASE_TYPE)) {
                                dao.deleteType(theGroupUpdated, type);
                            }
                        } catch (Exception e) {//
                        }
                    }
                }

            }
        }
        GrouperSession.stopQuietly(grouperSession);
        GrouperSession.stopQuietly(rootSession);
    }

    /**
     * {@inheritDoc}
     */
    public void groupDelete(final Person thePerson, final String theGroupId)
            throws ESCOInsufficientPrivilegesException, ESCOGroupNotFoundException {
        Validate.notNull(thePerson, ServiceConstants.THE_PERSON_MUST_BE_DEFINED);
        Validate.notNull(theGroupId, ServiceConstants.THE_GROUP_MUST_BE_DEFINED);

        GrouperSession grouperSession = null;
        GrouperSession rootSession = null;
        Subject subject = null;

        try {
            rootSession = GrouperSession.startRootSession();
            subject = SubjectFinder.findById(thePerson.getId(), true);
            grouperSession = GrouperSession.start(subject);
        } catch (SessionException e) {
            throw new ESCOTechnicalException(ServiceConstants.SESSION_CANNOT_BE_CREATE, e);
        } catch (SubjectNotFoundException e) {//
        } catch (SubjectNotUniqueException e) {//
        }

        try {
            edu.internet2.middleware.grouper.Group group = GroupFinder.findByUuid(grouperSession, theGroupId, true);
            group.delete();
            // pl
            GrouperHelper egh = grouperHelperFactory.get(grouperSession);
            egh.clearCache();

        } catch (GroupNotFoundException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOGroupNotFoundException(ServiceConstants.STEM_NOT_FOUND, e);
        } catch (InsufficientPrivilegeException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOInsufficientPrivilegesException(ServiceConstants.INSUFFICIENT_PRIVILEGES, e);
        } catch (GroupDeleteException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOGroupNotFoundException(ServiceConstants.STEM_CANNOT_BE_DELETED, e);
        }
        GrouperSession.stopQuietly(grouperSession);
        GrouperSession.stopQuietly(rootSession);
    }

    /**
     * {@inheritDoc}
     */
    public List<Privilege> findStemPrivileges(final Person thePerson, final String theStemName) {
        Validate.notNull(thePerson, ServiceConstants.THE_PERSON_MUST_BE_DEFINED);
        Validate.notNull(theStemName, ServiceConstants.THE_STEM_MUST_BE_DEFINED);

        GrouperSession grouperSession = null;
        GrouperSession rootSession = null;
        Subject subject = null;
        List<Privilege> myPrivileges = new ArrayList<Privilege>();

        try {
            rootSession = GrouperSession.startRootSession();
            subject = SubjectFinder.findById(thePerson.getId(), true);
            grouperSession = GrouperSession.start(subject);
        } catch (SessionException e) {
            throw new ESCOTechnicalException(ServiceConstants.SESSION_CANNOT_BE_CREATE, e);
        } catch (SubjectNotFoundException e) {//
        } catch (SubjectNotUniqueException e) {//
        }

        try {
            edu.internet2.middleware.grouper.Stem stem = StemFinder.findByName(grouperSession, theStemName, true);

            for (NamingPrivilege privilege : stem.getPrivs(subject)) {
                Privilege myPrivilege = new Privilege();
                myPrivilege.setPrivilegeName(privilege.getName());
                myPrivileges.add(myPrivilege);
            }
        } catch (StemNotFoundException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOTechnicalException(ServiceConstants.STEM_NOT_FOUND);
        }
        GrouperSession.stopQuietly(grouperSession);
        GrouperSession.stopQuietly(rootSession);
        return myPrivileges;
    }

    /**
     * {@inheritDoc}
     */
    public List<Privilege> findStemPrivileges(final Person thePerson, final List<String> theAttributes,
            final Map<String, SourceTypeEnum> theSources, final String theStemName,
            final ScopeEnum thePrivilegesScope) {
        return this.findStemOrGroupPrivileges(thePerson, theAttributes, theSources, theStemName, thePrivilegesScope,
                PrivilegeSearchEnum.STEM);
    }

    /**
     * Gives the list of subjects with a given direct or effective privilege granted on a group.
     * @param scope The scope of the privilege to retrieves.
     * @param group The group.
     * @param privilege The privilege.
     * @return The subjects.
     */
    private Set<Subject> findGranted(final ScopeEnum scope, final edu.internet2.middleware.grouper.Group group,
            final edu.internet2.middleware.grouper.privs.Privilege privilege) {

        Set<Membership> memberships = null;
        if (ScopeEnum.IMMEDIATE.equals(scope)) {
            memberships = group.getImmediateMemberships(FieldFinder.find(privilege.getListName(), true));
        } else if (ScopeEnum.EFFECTIVE.equals(scope)) {
            memberships = group.getNonImmediateMemberships(FieldFinder.find(privilege.getListName(), true));
        } else {
            memberships = group.getMemberships(FieldFinder.find(privilege.getListName(), true));
        }
        final Set<Subject> result = new HashSet<Subject>();

        for (final Membership membership : memberships) {
            result.add(membership.getMember().getSubject());
        }

        return result;
    }

    /**
     * Gives the list of subjects with a given direct or effective privilege granted on a stem.
     * @param scope The scope of the privilege to retrieves.
      * @param stem The folder.
      * @param privilege The privilege.
      * @return The list of subjects.
      */
    private Set<Subject> findGranted(final ScopeEnum scope, final edu.internet2.middleware.grouper.Stem stem,
            final edu.internet2.middleware.grouper.privs.Privilege privilege) {

        Set<Membership> memberships = null;

        if (ScopeEnum.ALL.equals(scope)) {
            memberships = GrouperDAOFactory.getFactory().getMembership().findAllByStemOwnerAndField(stem.getUuid(),
                    FieldFinder.find(privilege.getListName(), true), true);
        } else {
            final String immOrEff = ScopeEnum.IMMEDIATE.equals(scope) ? MembershipType.IMMEDIATE.getTypeString()
                    : MembershipType.NONIMMEDIATE.getTypeString();

            memberships = GrouperDAOFactory.getFactory().getMembership().findAllByStemOwnerAndFieldAndType(
                    stem.getUuid(), FieldFinder.find(privilege.getListName(), true), immOrEff, true);
        }

        final Set<Subject> result = new HashSet<Subject>();

        for (final Membership membership : memberships) {
            result.add(membership.getMember().getSubject());
        }

        return result;

    }

    /**
     * Finds privileges of a stem or a group.
     * 
     * @param thePerson
     *            the person performing the action (the connected user).
     * @param theAttributes
     *            the collection of attributes of the subjects which we want to
     *            retrieve.
     * @param theSources
     *            the collection of sources. These sources determine the type of
     *            object associated with the privilege (group or person).
     * @param theStemOrGroupName
     *            the name of the stem or the group.
     * @param thePrivilegesScope
     *            the scope of privileges to return (immediate, effective or
     *            both).
     * @param theTypeSearch
     *            the type of target (group or stem).
     * @return a collection of privileges.
     */
    private List<Privilege> findStemOrGroupPrivileges(final Person thePerson, final List<String> theAttributes,
            final Map<String, SourceTypeEnum> theSources, final String theStemOrGroupName,
            final ScopeEnum thePrivilegesScope, final PrivilegeSearchEnum theTypeSearch) {
        // long timeTotal = 0;
        Validate.notNull(thePerson, ServiceConstants.THE_PERSON_MUST_BE_DEFINED);
        Validate.notNull(theSources, "The sources must be defined");
        Validate.notNull(theStemOrGroupName, ServiceConstants.THE_STEM_OR_GROUP_MUST_BE_DEFINED);
        Validate.notNull(thePrivilegesScope, ServiceConstants.THE_SCOPE_MUST_BE_DEFINED);
        Validate.notNull(theTypeSearch, ServiceConstants.THE_SEARCH_TYPE_MUST_BE_DEFINED);

        GrouperSession grouperSession = null;
        GrouperSession rootSession = null;
        Subject subject = null;
        edu.internet2.middleware.grouper.Group group = null;
        edu.internet2.middleware.grouper.Stem stem = null;
        List<Privilege> result = new ArrayList<Privilege>();

        try {
            rootSession = GrouperSession.startRootSession();
            subject = SubjectFinder.findById(thePerson.getId(), true);
            grouperSession = GrouperSession.start(subject);
        } catch (SessionException e) {
            throw new ESCOTechnicalException(ServiceConstants.SESSION_CANNOT_BE_CREATE, e);
        } catch (SubjectNotFoundException e) {//
        } catch (SubjectNotUniqueException e) {//
        }

        if (PrivilegeSearchEnum.GROUP.equals(theTypeSearch)) {

            group = GroupFinder.findByName(grouperSession, theStemOrGroupName, true);

            Set<Subject> subjects = findGranted(thePrivilegesScope, group, AccessPrivilege.ADMIN);
            Map<String, Person> persons = personsDataDelegate.getPersonsDataFromSubjects(theSources, subjects);
            Map<String, Person> alreadyKnown = persons;

            for (Subject element : subjects) {
                LazySubject object = (LazySubject) element;
                Privilege priv = this.convertToPrivilege(object, persons.get(object.getId()), thePrivilegesScope,
                        "admin");
                if (priv != null) {
                    result.add(priv);
                }
            }

            subjects = findGranted(thePrivilegesScope, group, AccessPrivilege.UPDATE);
            persons = personsDataDelegate.getPersonsDataFromSubjects(theSources, subjects, alreadyKnown);
            alreadyKnown.putAll(persons);

            for (Subject element : subjects) {
                LazySubject object = (LazySubject) element;
                Privilege priv = this.convertToPrivilege(object, persons.get(object.getId()), thePrivilegesScope,
                        "update");
                if (priv != null) {
                    result.add(priv);
                }
            }

            subjects = findGranted(thePrivilegesScope, group, AccessPrivilege.READ);
            persons = personsDataDelegate.getPersonsDataFromSubjects(theSources, subjects, alreadyKnown);
            alreadyKnown.putAll(persons);

            for (Subject element : subjects) {
                LazySubject object = (LazySubject) element;
                Privilege priv = this.convertToPrivilege(object, persons.get(object.getId()), thePrivilegesScope,
                        "read");
                if (priv != null) {
                    result.add(priv);
                }
            }

            subjects = findGranted(thePrivilegesScope, group, AccessPrivilege.VIEW);
            persons = personsDataDelegate.getPersonsDataFromSubjects(theSources, subjects, alreadyKnown);
            alreadyKnown.putAll(persons);

            for (Subject element : subjects) {
                LazySubject object = (LazySubject) element;
                Privilege priv = this.convertToPrivilege(object, persons.get(object.getId()), thePrivilegesScope,
                        "view");
                if (priv != null) {
                    result.add(priv);
                }
            }

            subjects = findGranted(thePrivilegesScope, group, AccessPrivilege.OPTIN);
            persons = personsDataDelegate.getPersonsDataFromSubjects(theSources, subjects, alreadyKnown);
            alreadyKnown.putAll(persons);

            for (Subject element : subjects) {
                LazySubject object = (LazySubject) element;
                Privilege priv = this.convertToPrivilege(object, persons.get(object.getId()), thePrivilegesScope,
                        "optin");

                if (priv != null) {
                    result.add(priv);
                }
            }

            subjects = findGranted(thePrivilegesScope, group, AccessPrivilege.OPTOUT);
            persons = personsDataDelegate.getPersonsDataFromSubjects(theSources, subjects, alreadyKnown);
            alreadyKnown.putAll(persons);

            for (Subject element : subjects) {
                LazySubject object = (LazySubject) element;
                Privilege priv = this.convertToPrivilege(object, persons.get(object.getId()), thePrivilegesScope,
                        "optout");
                if (priv != null) {
                    result.add(priv);
                }
            }

        } else if (PrivilegeSearchEnum.STEM.equals(theTypeSearch)) {
            stem = StemFinder.findByName(grouperSession, theStemOrGroupName, true);

            Set<Subject> subjects = findGranted(thePrivilegesScope, stem, NamingPrivilege.STEM);
            Map<String, Person> persons = personsDataDelegate.getPersonsDataFromSubjects(theSources, subjects);
            Map<String, Person> alreadyKnown = persons;
            for (Subject element : subjects) {
                LazySubject object = (LazySubject) element;
                Privilege priv = this.convertToPrivilege(object, persons.get(object.getId()), thePrivilegesScope,
                        "stem");
                if (priv != null) {
                    result.add(priv);
                }
            }
            subjects = findGranted(thePrivilegesScope, stem, NamingPrivilege.CREATE);
            persons = personsDataDelegate.getPersonsDataFromSubjects(theSources, subjects, alreadyKnown);
            for (Subject element : subjects) {
                LazySubject object = (LazySubject) element;
                Privilege priv = this.convertToPrivilege(object, persons.get(object.getId()), thePrivilegesScope,
                        "create");
                if (priv != null) {
                    result.add(priv);
                }
            }

        } else {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            // Must never occur.
            throw new ESCOTechnicalException("The type must be group or stem.");
        }
        GrouperSession.stopQuietly(grouperSession);
        GrouperSession.stopQuietly(rootSession);
        return result;
    }

    /**
     * {@inheritDoc}
     */
    public void assignStemPrivileges(final Person thePerson, final String theSubjectIdTo, final String theStemIdOn,
            final Privilege thePrivilege)
            throws ESCOStemNotFoundException, ESCOStemNotUniqueException, ESCOInsufficientPrivilegesException {
        try {
            this.assignOrRemovePrivilegesOnStemOrGroup(thePerson, theSubjectIdTo, theStemIdOn, thePrivilege, true,
                    PrivilegeSearchEnum.STEM);
        } catch (ESCOGroupNotUniqueException e) {
            // this case doesn't happen if the type is stem
        } catch (ESCOGroupNotFoundException e) {
            // this case doesn't happen if the type is stem
        } catch (ESCOSubjectNotFoundException e) {
            // this case doesn't happen if the type is stem
        }
    }

    /**
     * Assigns or removes a privilege on a folder to a subject (group or
     * person).
     * 
     * @param thePerson
     *            the person performing the action (the connected user).
     * @param theSubjectIdTo
     *            the id of the subject (group or person) who the privileges are
     *            granted/revoked to.
     * @param theStemOrGroupUuidOn
     *            the uuid of the stem/group on which the privileges are
     *            granted/revoked.
     * @param thePrivilege
     *            the privilege to assign/remove.
     * @param isAssign
     *            is true if the privilege must be assigned and false if the
     *            privilege must be removed
     * @param theType
     *            the type of target : stem or group
     * @throws ESCOStemNotUniqueException
     *             if the stem is not unique
     * @throws ESCOStemNotFoundException
     *             if the stem is not found.
     * @throws ESCOGroupNotUniqueException
     *             if the group is not unique
     * @throws ESCOGroupNotFoundException
     *             if the group is not found.
     * @throws ESCOSubjectNotFoundException
     *             if the subject matches with theSubjectIdTo is not found.
     * @throws ESCOInsufficientPrivilegesException
     *             if the person hasn't sufficient privilege to assign/remove
     *             privileges.
     */
    private void assignOrRemovePrivilegesOnStemOrGroup(final Person thePerson, final String theSubjectIdTo,
            final String theStemOrGroupUuidOn, final Privilege thePrivilege, final boolean isAssign,
            final PrivilegeSearchEnum theType)
            throws ESCOStemNotUniqueException, ESCOStemNotFoundException, ESCOGroupNotUniqueException,
            ESCOGroupNotFoundException, ESCOInsufficientPrivilegesException, ESCOSubjectNotFoundException {
        Validate.notNull(thePerson, ServiceConstants.THE_PERSON_MUST_BE_DEFINED);
        Validate.notNull(theSubjectIdTo, "The subject id must be defined");
        Validate.notNull(theStemOrGroupUuidOn, ServiceConstants.THE_STEM_OR_GROUP_MUST_BE_DEFINED);
        Validate.notNull(thePrivilege, "The privilege must be defined");

        GrouperSession grouperSession = null;
        GrouperSession rootSession = null;
        Subject subject = null;
        Subject subjectTo = null;
        try {
            rootSession = GrouperSession.startRootSession();
            subject = SubjectFinder.findById(thePerson.getId(), true);
            subjectTo = SubjectFinder.findById(theSubjectIdTo, true);
            grouperSession = GrouperSession.start(subject);

        } catch (SessionException e) {
            throw new ESCOTechnicalException(ServiceConstants.SESSION_CANNOT_BE_CREATE, e);
        } catch (SubjectNotFoundException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOSubjectNotFoundException(ServiceConstants.SUBJECT_NOT_FOUND, e);
        } catch (SubjectNotUniqueException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOSubjectNotFoundException(ServiceConstants.SUBJECT_NOT_FOUND, e);
        }

        edu.internet2.middleware.grouper.privs.Privilege privilege = edu.internet2.middleware.grouper.privs.Privilege
                .getInstance(thePrivilege.getPrivilegeName());

        if (PrivilegeSearchEnum.STEM.equals(theType)) {
            try {
                edu.internet2.middleware.grouper.Stem stem = StemFinder.findByUuid(grouperSession,
                        theStemOrGroupUuidOn, true);
                if (isAssign) {
                    stem.grantPriv(subjectTo, privilege, false);
                } else {
                    stem.revokePriv(subjectTo, privilege, false);
                }
            } catch (StemNotFoundException e) {
                GrouperSession.stopQuietly(grouperSession);
                GrouperSession.stopQuietly(rootSession);
                throw new ESCOStemNotFoundException(ServiceConstants.STEM_NOT_FOUND, e);
            } catch (InsufficientPrivilegeException e) {
                GrouperSession.stopQuietly(grouperSession);
                GrouperSession.stopQuietly(rootSession);
                throw new ESCOInsufficientPrivilegesException(ServiceConstants.INSUFFICIENT_PRIVILEGES, e);
            } catch (GrantPrivilegeException e) {
                GrouperSession.stopQuietly(grouperSession);
                GrouperSession.stopQuietly(rootSession);
                throw new ESCOInsufficientPrivilegesException(ServiceConstants.INSUFFICIENT_PRIVILEGES, e);
            }
        } else if (PrivilegeSearchEnum.GROUP.equals(theType)) {
            try {
                edu.internet2.middleware.grouper.Group group = GroupFinder.findByUuid(grouperSession,
                        theStemOrGroupUuidOn, true);
                if (isAssign) {
                    group.grantPriv(subjectTo, privilege, false);
                } else {
                    group.revokePriv(subjectTo, privilege, false);
                }
            } catch (GroupNotFoundException e) {
                GrouperSession.stopQuietly(grouperSession);
                GrouperSession.stopQuietly(rootSession);
                throw new ESCOGroupNotFoundException(ServiceConstants.GROUP_NOT_FOUND, e);
            } catch (InsufficientPrivilegeException e) {
                GrouperSession.stopQuietly(grouperSession);
                GrouperSession.stopQuietly(rootSession);
                throw new ESCOInsufficientPrivilegesException(ServiceConstants.INSUFFICIENT_PRIVILEGES, e);
            } catch (GrantPrivilegeException e) {
                GrouperSession.stopQuietly(grouperSession);
                GrouperSession.stopQuietly(rootSession);
                throw new ESCOInsufficientPrivilegesException(ServiceConstants.INSUFFICIENT_PRIVILEGES, e);
            }
        } else {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            // This case must never occur
            throw new ESCOTechnicalException("The type is not stem or group");
        }
        // pl !!!
        grouperHelperFactory.get(grouperSession).clearCache(Privs.find(thePrivilege.getPrivilegeName()));
        GrouperSession.stopQuietly(grouperSession);
        GrouperSession.stopQuietly(rootSession);
    }

    /**
     * {@inheritDoc}
     */
    public void removeStemPrivileges(final Person thePerson, final String theSubjectIdTo, final String theStemIdOn,
            final Privilege thePrivilege)
            throws ESCOStemNotFoundException, ESCOStemNotUniqueException, ESCOInsufficientPrivilegesException {
        try {
            this.assignOrRemovePrivilegesOnStemOrGroup(thePerson, theSubjectIdTo, theStemIdOn, thePrivilege, false,
                    PrivilegeSearchEnum.STEM);
        } catch (ESCOGroupNotUniqueException e) {
            // this case doesn't happen if the type is stem
        } catch (ESCOGroupNotFoundException e) {
            // this case doesn't happen if the type is stem
        } catch (ESCOSubjectNotFoundException e) {
            // this case doesn't happen if the type is stem
        }
    }

    /**
     * {@inheritDoc}
     */
    public List<Privilege> findDefaultGroupPrivileges(final Person thePerson, final String theGroupName) {
        Validate.notNull(thePerson, ServiceConstants.THE_PERSON_MUST_BE_DEFINED);
        Validate.notNull(theGroupName, ServiceConstants.THE_GROUP_MUST_BE_DEFINED);

        GrouperSession grouperSession = null;
        GrouperSession rootSession = null;
        Subject subject = null;
        Subject subjectGrouperAll = null;
        List<Privilege> myPrivileges = new ArrayList<Privilege>();

        try {
            rootSession = GrouperSession.startRootSession();
            subject = SubjectFinder.findById(thePerson.getId(), true);
            subjectGrouperAll = SubjectFinder.findById(ServiceConstants.GROUPER_ALL, true);
            grouperSession = GrouperSession.start(subject);
        } catch (SessionException e) {
            throw new ESCOTechnicalException(ServiceConstants.SESSION_CANNOT_BE_CREATE, e);
        } catch (SubjectNotFoundException e) {//
        } catch (SubjectNotUniqueException e) {//
        }

        try {
            edu.internet2.middleware.grouper.Group group = GroupFinder.findByName(grouperSession, theGroupName,
                    true);

            for (AccessPrivilege privilege : group.getPrivs(subjectGrouperAll)) {
                Privilege myPrivilege = new Privilege();
                myPrivilege.setPrivilegeName(privilege.getName());
                myPrivilege.setPrivilegeType(privilege.getType());
                myPrivilege.setAllowed(privilege.isRevokable());
                myPrivilege.setGroup(this.getGroupAPIWrapper().wrap(group));
                myPrivilege.setType(ScopeEnum.getFromValue(privilege.getType()));
                myPrivileges.add(myPrivilege);
            }
        } catch (GroupNotFoundException e) {
        }
        GrouperSession.stopQuietly(grouperSession);
        GrouperSession.stopQuietly(rootSession);
        return myPrivileges;
    }

    /**
     * {@inheritDoc}
     */
    public void assignGroupPrivileges(final Person thePerson, final String theSubjectIdTo,
            final String theGroupIdOn, final Privilege thePrivilege)
            throws ESCOGroupNotUniqueException, ESCOGroupNotFoundException, ESCOInsufficientPrivilegesException {
        try {
            this.assignOrRemovePrivilegesOnStemOrGroup(thePerson, theSubjectIdTo, theGroupIdOn, thePrivilege, true,
                    PrivilegeSearchEnum.GROUP);
        } catch (ESCOStemNotUniqueException e) {
            // this case doesn't happen if the type is group
        } catch (ESCOStemNotFoundException e) {
            // this case doesn't happen if the type is group
        } catch (ESCOSubjectNotFoundException e) {
            // this case doesn't happen if the type is group
        }
    }

    /**
     * {@inheritDoc}
     */
    public void removeGroupPrivileges(final Person thePerson, final String theSubjectIdTo,
            final String theGroupIdOn, final Privilege thePrivilege)
            throws ESCOGroupNotUniqueException, ESCOGroupNotFoundException, ESCOInsufficientPrivilegesException {
        try {
            this.assignOrRemovePrivilegesOnStemOrGroup(thePerson, theSubjectIdTo, theGroupIdOn, thePrivilege, false,
                    PrivilegeSearchEnum.GROUP);
        } catch (ESCOStemNotUniqueException e) {
            // this case doesn't happen if the type is group
        } catch (ESCOStemNotFoundException e) {
            // this case doesn't happen if the type is group
        } catch (ESCOSubjectNotFoundException e) {
            // this case doesn't happen if the type is group
        }
    }

    /**
     * {@inheritDoc}
     * 
     * @throws ESCOStemNotFoundException
     */
    public ArrayListMultimap<Integer, Stem> getAllStemsFrom(final String theParentName, final String thePersonId,
            final Boolean theSearchIfEmpty, final String searchMode) throws ESCOStemNotFoundException {
        Validate.notNull(theParentName, "The name of the parent must be defined");
        Validate.notNull(thePersonId, ServiceConstants.THE_PERSON_MUST_BE_DEFINED);

        ArrayListMultimap<Integer, Stem> requestResult = ArrayListMultimap.create();
        int cpt = 0;
        String loadPerf = PropertyManager.find("LOAD_PERFORMANCE_PACK").deType(String.class);

        // On passe loadPerfActiv  true si on a une valeur (true ou int)
        boolean loadPerfActiv = !"false".equals(loadPerf);
        int seuilStem = -1;

        if (!"true".equals(loadPerf)) {
            try {
                // On rcupre le seul
                seuilStem = Integer.parseInt(loadPerf);
            } catch (Exception e) {
                // En cas d'erreur on passe loadPerfActiv  false
                seuilStem = -1;
                loadPerfActiv = false;
                this.LOGGER.debug("getAllStemsFrom() - Le paramtrage du seuil est incorect " + loadPerf
                        + " doit tre un entier.");
            }
        }

        GrouperSession session = null;
        GrouperSession rootSession = null;
        Subject person = null;
        try {
            rootSession = GrouperSession.startRootSession();
            person = SubjectFinder.findById(thePersonId, true);
            session = GrouperSession.start(person);

        } catch (SessionException e) {
            throw new ESCOTechnicalException(ServiceConstants.SESSION_CANNOT_BE_CREATE, e);
        } catch (SubjectNotFoundException e) {
            GrouperSession.stopQuietly(session);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOTechnicalException(ServiceConstants.SUBJECT_NOT_FOUND, e);
        } catch (SubjectNotUniqueException e) {
            GrouperSession.stopQuietly(session);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOTechnicalException(ServiceConstants.SUBJECT_NOT_UNIQUE, e);
        }

        try {
            edu.internet2.middleware.grouper.Stem parentStem = StemFinder.findByName(session, theParentName, true);

            Set<edu.internet2.middleware.grouper.Stem> childStems = parentStem.getChildStems(Scope.ONE);

            // si loadPerfActiv (recherche obtimi) : On applique le seuil 
            //     si le seuil n'est pas depass on affiche toutes les branches meme vide de droit
            //     si le seuil est depass on affihce que les branches ou on a des droits
            //   si pas de seuil (-1) on affiche que les branches avec droits
            loadPerfActiv = loadPerfActiv && (seuilStem == -1 || childStems.size() <= seuilStem);

            // pl creation du grouperhelper qui va permetre de tester les droits
            GrouperHelper egh = grouperHelperFactory.get(session);

            for (edu.internet2.middleware.grouper.Stem stem : childStems) {
                // si loadPerfActiv== false on insert tous les fils
                // si == true alors on insert que si l'utilisateur a des droits dans le stem
                if (!loadPerfActiv || egh.userHasPrivs(stem.getName())) {
                    Stem aux = this.stemAPIWrapper.wrap(stem);
                    aux.setHasCreate(false);
                    aux.setHasStem(false);

                    List<Privs> privs = egh.userPrivsList(stem);

                    for (Privs priv : privs) {
                        switch (priv) {
                        case STEM:
                            aux.setHasStem(true);
                            break;
                        case CREATE:
                            aux.setHasCreate(true);
                        default:
                            break;
                        }

                    }
                    requestResult.put(cpt++, aux);
                }
            }

        } catch (StemNotFoundException stemNotFoundException) {
            GrouperSession.stopQuietly(session);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOStemNotFoundException();
        }
        GrouperSession.stopQuietly(session);
        GrouperSession.stopQuietly(rootSession);
        return requestResult;
    }

    /**
     * {@inheritDoc}
     */
    public GroupPrivilegeEnum getPrivilegeOnGroup(final Person thePerson, final Group theGroup)
            throws ESCOGroupNotFoundException, ESCOGroupNotUniqueException, CloneNotSupportedException {
        Validate.notNull(thePerson, ServiceConstants.THE_PERSON_MUST_BE_DEFINED);
        Validate.notNull(theGroup, "The group name must be defined");

        GrouperSession grouperSession = null;
        GrouperSession rootSession = null;
        Subject subject = null;
        GroupPrivilegeEnum groupPrivilegeEnum = GroupPrivilegeEnum.NONE;

        try {
            rootSession = GrouperSession.startRootSession();
            subject = SubjectFinder.findById(thePerson.getId(), true);
            grouperSession = GrouperSession.start(subject);
        } catch (SessionException e) {
            throw new ESCOTechnicalException(ServiceConstants.SESSION_CANNOT_BE_CREATE, e);
        } catch (SubjectNotFoundException e) {//
        } catch (SubjectNotUniqueException e) {//
        }

        try {
            edu.internet2.middleware.grouper.Group group = GroupFinder.findByName(grouperSession,
                    theGroup.getName(), true);

            if (PrivilegeHelper.canAdmin(grouperSession, group, subject)) {
                groupPrivilegeEnum = GroupPrivilegeEnum.ADMIN;
            } else if (PrivilegeHelper.canUpdate(grouperSession, group, subject)) {
                groupPrivilegeEnum = GroupPrivilegeEnum.UPDATE;
            } else if (PrivilegeHelper.canRead(grouperSession, group, subject)) {
                groupPrivilegeEnum = GroupPrivilegeEnum.READ;
            } else if (PrivilegeHelper.canView(grouperSession, group, subject)) {
                groupPrivilegeEnum = GroupPrivilegeEnum.VIEW;
            } else if (PrivilegeHelper.canOptin(grouperSession, group, subject)) {
                groupPrivilegeEnum = GroupPrivilegeEnum.OPTIN;
            } else if (PrivilegeHelper.canOptout(grouperSession, group, subject)) {
                groupPrivilegeEnum = GroupPrivilegeEnum.OPTOUT;
            } else {
                groupPrivilegeEnum = GroupPrivilegeEnum.NONE;
            }

        } catch (GroupNotFoundException e) {
            GrouperSession.stopQuietly(grouperSession);
            GrouperSession.stopQuietly(rootSession);
            throw new ESCOGroupNotFoundException(ServiceConstants.GROUP_NOT_FOUND, e);
        } catch (SubjectNotFoundException e) {//
        } catch (SubjectNotUniqueException e) {//
        }
        GrouperSession.stopQuietly(grouperSession);
        GrouperSession.stopQuietly(rootSession);
        return groupPrivilegeEnum;
    }

    /**
     * Get if a stem is empty.
     * 
     * @param theParentName
     *            The stem to find the empty value.
     * @param thePersonId
     *            The connected person id.
     * @return true if the stem is empty else false otherwise.
     * @throws ESCOStemNotFoundException
     *             exception sur le stem
     */
    private Boolean isEmptyStem(final String theParentName) throws ESCOStemNotFoundException {
        Boolean isEmptyStem = Boolean.FALSE;

        GrouperSession session = null;

        try {
            session = GrouperSession.startRootSession();
        } catch (SessionException e) {
            throw new ESCOTechnicalException(ServiceConstants.SESSION_CANNOT_BE_CREATE, e);
        } catch (SubjectNotFoundException e) {//
        } catch (SubjectNotUniqueException e) {//
        }

        try {
            edu.internet2.middleware.grouper.Stem myStem = StemFinder.findByName(session, theParentName, true);
            isEmptyStem = myStem.getChildStems().isEmpty() && myStem.getChildGroups().isEmpty();
        } catch (StemNotFoundException e) {
            GrouperSession.stopQuietly(session);
            throw new ESCOStemNotFoundException(ServiceConstants.STEM_NOT_FOUND, e);
        }

        return isEmptyStem;
    }

    public GrouperHelperFactory getGrouperHelperFactory() {
        return grouperHelperFactory;
    }

    public void setGrouperHelperFactory(GrouperHelperFactory grouperHelperFactory) {
        this.grouperHelperFactory = grouperHelperFactory;
    }

}