/**
   * @param entity
   * @param userDn
   * @return
   * @throws org.apache.directory.fortress.core.UpdateException
   */
  Group deassign(Group entity, String userDn) throws FinderException, UpdateException {
    LdapConnection ld = null;
    String dn = getDn(entity.getName(), entity.getContextId());
    LOG.debug("deassign group property dn [{}], member dn [{}]", dn, userDn);

    try {
      List<Modification> mods = new ArrayList<Modification>();
      mods.add(
          new DefaultModification(
              ModificationOperation.REMOVE_ATTRIBUTE, SchemaConstants.MEMBER_AT, userDn));

      ld = getAdminConnection();
      modify(ld, dn, mods, entity);
    } catch (LdapException e) {
      String error =
          "deassign group name ["
              + entity.getName()
              + "] user dn ["
              + userDn
              + "] caught "
              + "LDAPException="
              + e.getMessage();
      throw new UpdateException(GlobalErrIds.GROUP_USER_DEASSIGN_FAILED, error, e);
    } finally {
      closeAdminConnection(ld);
    }

    return get(entity);
  }
  /**
   * @param group
   * @throws org.apache.directory.fortress.core.CreateException
   */
  Group create(Group group) throws CreateException {
    LdapConnection ld = null;
    String nodeDn = getDn(group.getName(), group.getContextId());

    try {
      LOG.debug("create group dn [{}]", nodeDn);
      Entry myEntry = new DefaultEntry(nodeDn);
      myEntry.add(SchemaConstants.OBJECT_CLASS_AT, GROUP_OBJ_CLASS);
      myEntry.add(SchemaConstants.CN_AT, group.getName());
      // protocol is required:
      myEntry.add(GROUP_PROTOCOL_ATTR_IMPL, group.getProtocol());
      // type is required:
      myEntry.add(GlobalIds.TYPE, group.getType().toString());

      loadAttrs(group.getMembers(), myEntry, SchemaConstants.MEMBER_AT);
      loadProperties(group.getProperties(), myEntry, GROUP_PROPERTY_ATTR_IMPL, '=');

      if (StringUtils.isNotEmpty(group.getDescription())) {
        myEntry.add(SchemaConstants.DESCRIPTION_AT, group.getDescription());
      }

      ld = getAdminConnection();
      add(ld, myEntry);
    } catch (LdapException e) {
      String error = "create group node dn [" + nodeDn + "] caught LDAPException=" + e.getMessage();
      throw new CreateException(GlobalErrIds.GROUP_ADD_FAILED, error, e);
    } finally {
      closeAdminConnection(ld);
    }

    return group;
  }
 /**
  * This method will remove group node from diretory.
  *
  * @param group
  * @throws org.apache.directory.fortress.core.RemoveException
  */
 Group remove(Group group) throws RemoveException {
   LdapConnection ld = null;
   String nodeDn = getDn(group.getName(), group.getContextId());
   LOG.debug("remove group dn [{}]", nodeDn);
   try {
     ld = getAdminConnection();
     delete(ld, nodeDn, group);
   } catch (LdapException e) {
     String error = "remove group node dn [" + nodeDn + "] caught LDAPException=" + e.getMessage();
     throw new RemoveException(GlobalErrIds.GROUP_DELETE_FAILED, error, e);
   } finally {
     closeAdminConnection(ld);
   }
   return group;
 }
  Group delete(Group group, String key, String value) throws FinderException, RemoveException {
    LdapConnection ld = null;
    String nodeDn = getDn(group.getName(), group.getContextId());

    try {
      LOG.debug("delete group property dn [{}], key [{}], value [{}]", nodeDn, key, value);
      List<Modification> mods = new ArrayList<Modification>();
      mods.add(
          new DefaultModification(
              ModificationOperation.REMOVE_ATTRIBUTE, GROUP_PROPERTY_ATTR_IMPL, key + "=" + value));
      ld = getAdminConnection();
      modify(ld, nodeDn, mods, group);
    } catch (LdapException e) {
      String error =
          "delete group property node dn [" + nodeDn + "] caught LDAPException=" + e.getMessage();
      throw new RemoveException(GlobalErrIds.GROUP_DELETE_PROPERTY_FAILED, error, e);
    } finally {
      closeAdminConnection(ld);
    }
    return get(group);
  }
  /**
   * @param group
   * @return
   * @throws org.apache.directory.fortress.core.CreateException
   */
  Group update(Group group) throws FinderException, UpdateException {
    LdapConnection ld = null;
    String nodeDn = getDn(group.getName(), group.getContextId());

    try {
      LOG.debug("update group dn [{}]", nodeDn);
      List<Modification> mods = new ArrayList<Modification>();

      if (StringUtils.isNotEmpty(group.getDescription())) {
        mods.add(
            new DefaultModification(
                ModificationOperation.REPLACE_ATTRIBUTE,
                SchemaConstants.DESCRIPTION_AT,
                group.getDescription()));
      }

      if (StringUtils.isNotEmpty(group.getProtocol())) {
        mods.add(
            new DefaultModification(
                ModificationOperation.REPLACE_ATTRIBUTE,
                GROUP_PROTOCOL_ATTR_IMPL,
                group.getProtocol()));
      }

      loadAttrs(group.getMembers(), mods, SchemaConstants.MEMBER_AT);
      loadProperties(group.getProperties(), mods, GROUP_PROPERTY_ATTR_IMPL, true, '=');

      if (mods.size() > 0) {
        ld = getAdminConnection();
        modify(ld, nodeDn, mods, group);
      }
    } catch (LdapException e) {
      String error = "update group node dn [" + nodeDn + "] caught LDAPException=" + e.getMessage();
      throw new UpdateException(GlobalErrIds.GROUP_UPDATE_FAILED, error, e);
    } finally {
      closeAdminConnection(ld);
    }
    return get(group);
  }
  /**
   * @param group
   * @return
   * @throws org.apache.directory.fortress.core.FinderException
   */
  List<Group> find(Group group) throws FinderException {
    List<Group> groupList = new ArrayList<>();
    LdapConnection ld = null;
    SearchCursor searchResults;
    String groupRoot = getRootDn(group.getContextId(), GlobalIds.GROUP_ROOT);
    String filter = null;

    try {
      String searchVal = encodeSafeText(group.getName(), GlobalIds.ROLE_LEN);
      filter =
          GlobalIds.FILTER_PREFIX
              + GROUP_OBJECT_CLASS_IMPL
              + ")("
              + SchemaConstants.CN_AT
              + "="
              + searchVal
              + "*))";
      ld = getAdminConnection();
      searchResults =
          search(
              ld, groupRoot, SearchScope.ONELEVEL, filter, GROUP_ATRS, false, GlobalIds.BATCH_SIZE);
      long sequence = 0;
      while (searchResults.next()) {
        groupList.add(unloadLdapEntry(searchResults.getEntry(), sequence++));
      }
    } catch (CursorException e) {
      String error = "find filter [" + filter + "] caught CursorException=" + e.getMessage();
      throw new FinderException(GlobalErrIds.GROUP_SEARCH_FAILED, error, e);
    } catch (LdapException e) {
      String error = "find filter [" + filter + "] caught LDAPException=" + e.getMessage();
      throw new FinderException(GlobalErrIds.GROUP_SEARCH_FAILED, error, e);
    } finally {
      closeAdminConnection(ld);
    }

    return groupList;
  }
  /**
   * @param group
   * @return
   * @throws org.apache.directory.fortress.core.FinderException
   */
  Group get(Group group) throws FinderException {
    Group entity = null;
    LdapConnection ld = null;
    String dn = getDn(group.getName(), group.getContextId());

    try {
      ld = getAdminConnection();
      Entry findEntry = read(ld, dn, GROUP_ATRS);
      if (findEntry == null) {
        String warning = "No Group entry found dn [" + dn + "]";
        throw new FinderException(GlobalErrIds.GROUP_NOT_FOUND, warning);
      }
      entity = unloadLdapEntry(findEntry, 0);
    } catch (LdapNoSuchObjectException e) {
      String warning = "read Obj COULD NOT FIND ENTRY for dn [" + dn + "]";
      throw new FinderException(GlobalErrIds.GROUP_NOT_FOUND, warning, e);
    } catch (LdapException e) {
      String error = "read dn [" + dn + "] LdapException=" + e.getMessage();
      throw new FinderException(GlobalErrIds.GROUP_READ_FAILED, error, e);
    } finally {
      closeAdminConnection(ld);
    }
    return entity;
  }