/**
   * Fetches the value of the attribute {@code ATTR_USER_OU} for the provided user account.
   *
   * @param userAccount The user account to fetch the value from.
   * @param getChildren if also children of userAccountous are to be fetched.
   * @return Returns the attribute value in an {@code EvaluationResult}.
   * @throws de.escidoc.core.common.exceptions.system.SystemException
   */
  private EvaluationResult fetchUserAccountOus(
      final UserAccount userAccount, final boolean getChildren) throws SystemException {

    final String ouAttributeName =
        EscidocConfiguration.getInstance()
            .get(EscidocConfiguration.ESCIDOC_CORE_AA_OU_ATTRIBUTE_NAME);
    if (ouAttributeName == null || ouAttributeName.length() == 0) {
      return CustomEvaluationResultBuilder.createEmptyEvaluationResult();
    }
    final List<UserAttribute> attributes =
        userAccountDao.retrieveAttributes(userAccount, ouAttributeName);
    final EvaluationResult result;
    if (attributes == null || attributes.isEmpty()) {
      result = CustomEvaluationResultBuilder.createEmptyEvaluationResult();
    } else {
      final List<StringAttribute> results = new ArrayList<StringAttribute>();
      final Collection<String> ouIds = new ArrayList<String>();
      for (final UserAttribute attribute : attributes) {
        results.add(new StringAttribute(attribute.getValue()));
        if (getChildren) {
          ouIds.add(attribute.getValue());
        }
      }
      if (getChildren) {
        final List<String> childOus =
            tripleStoreUtility.getChildrenPath(ouIds, new ArrayList<String>());
        if (childOus != null) {
          for (final String childOu : childOus) {
            results.add(new StringAttribute(childOu));
          }
        }
      }

      result = new EvaluationResult(new BagAttribute(Constants.URI_XMLSCHEMA_STRING, results));
    }
    return result;
  }
  /**
   * See Interface for functional description.
   *
   * @see UserAccountDaoInterface #retrieveUserAccounts(java.util.Map, int, int, String,
   *     ListSorting)
   */
  @Override
  public List<UserAccount> retrieveUserAccounts(
      final Map<String, Object> criterias,
      final int offset,
      final int maxResults,
      final String orderBy,
      final ListSorting sorting)
      throws SqlDatabaseSystemException {

    final DetachedCriteria detachedCriteria = DetachedCriteria.forClass(UserAccount.class, "user");

    final Map<String, Object> clonedCriterias = new HashMap<String, Object>(criterias);

    // ids
    final Set<String> userAccountIds =
        mergeSets(
            (Set<String>) clonedCriterias.remove(Constants.DC_IDENTIFIER_URI),
            (Set<String>) clonedCriterias.remove(Constants.FILTER_PATH_ID));
    if (userAccountIds != null && !userAccountIds.isEmpty()) {
      detachedCriteria.add(Restrictions.in("id", userAccountIds.toArray()));
    }

    // active flag
    final String active = (String) clonedCriterias.remove(Constants.FILTER_ACTIVE);
    final String active1 = (String) clonedCriterias.remove(Constants.FILTER_PATH_ACTIVE);
    if (active != null) {
      detachedCriteria.add(Restrictions.eq("active", Boolean.valueOf(active)));
    } else if (active1 != null) {
      detachedCriteria.add(Restrictions.eq("active", Boolean.valueOf(active1)));
    }

    for (final Entry<String, Object[]> stringEntry : criteriaMap.entrySet()) {
      if (stringEntry.getKey().equals(Constants.FILTER_ORGANIZATIONAL_UNIT)
          || stringEntry.getKey().equals(Constants.FILTER_PATH_ORGANIZATIONAL_UNIT)) {
        continue;
      }
      final Object criteriaValue = clonedCriterias.remove(stringEntry.getKey());
      if (criteriaValue != null) {
        final Object[] parts = stringEntry.getValue();
        if (parts[0].equals(COMPARE_EQ)) {
          detachedCriteria.add(Restrictions.eq((String) parts[1], criteriaValue));
        } else {
          detachedCriteria.add(Restrictions.like((String) parts[1], criteriaValue));
        }
      }
    }

    // organizational units
    final String organizationalUnit1 =
        (String) clonedCriterias.remove(Constants.FILTER_ORGANIZATIONAL_UNIT);
    final String organizationalUnit2 =
        (String) clonedCriterias.remove(Constants.FILTER_PATH_ORGANIZATIONAL_UNIT);
    final String organizationalUnit =
        organizationalUnit1 != null ? organizationalUnit1 : organizationalUnit2;
    if (organizationalUnit != null) {

      final String ouAttributeName =
          EscidocConfiguration.getInstance()
              .get(EscidocConfiguration.ESCIDOC_CORE_AA_OU_ATTRIBUTE_NAME);

      if (ouAttributeName == null || ouAttributeName.length() == 0) {
        throw new SqlDatabaseSystemException("ou-attribute-name not found in configuration");
      }
      detachedCriteria.add(
          Restrictions.sqlRestriction(
              "this_.id in ("
                  + "select ua.id from aa.user_account ua, "
                  + "aa.user_attribute atts "
                  + "where ua.id = atts.user_id "
                  + "and atts.name = '"
                  + ouAttributeName
                  + "' and atts.value = ?)",
              organizationalUnit,
              Hibernate.STRING));
      // detachedCriteria.add(Restrictions.like("ous", StringUtility
      // .concatenateToString("%", organizationalUnit, "|||%")));
    }

    if (orderBy != null) {
      if (sorting == ListSorting.ASCENDING) {
        detachedCriteria.addOrder(Order.asc(propertiesNamesMap.get(orderBy)));
      } else if (sorting == ListSorting.DESCENDING) {
        detachedCriteria.addOrder(Order.desc(propertiesNamesMap.get(orderBy)));
      }
    }

    if (clonedCriterias.isEmpty()) {
      final List<UserAccount> result;

      try {
        result = getHibernateTemplate().findByCriteria(detachedCriteria, offset, maxResults);
      } catch (final DataAccessException e) {
        throw new SqlDatabaseSystemException(e);
      }
      return result;
    } else {
      // unsupported filter criteria has been found, therefore the result
      // list must be empty.
      return new ArrayList<UserAccount>(0);
    }
  }