/* (non-Javadoc)
   * @see edu.internet2.middleware.grouper.ui.RepositoryBrowser#advancedSearch(edu.internet2.middleware.grouper.GrouperSession, java.lang.String, java.util.Map, java.util.List)
   */
  public List advancedSearch(GrouperSession s, String from, Map attr, List outTerms)
      throws Exception {
    List res = new ArrayList();
    String maxCountStr = getSingle("maxFields", attr);
    int maxCount = Integer.parseInt(maxCountStr);
    String lastQuery = null;
    String lastField = null;
    String lastAndOrNot = null;
    String field;
    String query;
    String andOrNot;
    Map fieldMaps = GrouperHelper.getFieldsAsMap();
    String lastFieldDisplayName = null;
    QueryFilter queryFilter = null;
    if (outTerms == null) outTerms = new ArrayList();

    Stem fromStem = StemFinder.findByName(s, from, true);
    for (int i = 1; i <= maxCount; i++) {
      field = getSingle("searchField." + i, attr);
      query = getSingle("searchField." + i + ".query", attr);
      if (i == 1 && (field == null || query == null)) {
        if (getSingle("searchType.1", attr) != null) break;
        throw new IllegalArgumentException(
            "The first search field and query value must be enetered");
      }
      andOrNot = getSingle("searchField." + i + ".searchAndOrNot", attr);
      if (query == null || "".equals(query)) query = lastQuery;
      if (i > 1) {
        if (queryFilter == null) {
          queryFilter = getGroupAttributeFilter(lastField, lastQuery, fromStem);
          outTerms.add(lastQuery);
          lastFieldDisplayName = (String) ((Map) fieldMaps.get(lastField)).get("displayName");
          outTerms.add(lastFieldDisplayName);
        }
        if (field == null && i == 2) {
          break;
        }
        if (field == null && i > 2) break;

        if ("and".equals(lastAndOrNot)) {
          queryFilter =
              new IntersectionFilter(queryFilter, getGroupAttributeFilter(field, query, fromStem));
        } else if ("or".equals(lastAndOrNot)) {
          queryFilter =
              new UnionFilter(queryFilter, getGroupAttributeFilter(field, query, fromStem));
        } else {
          queryFilter =
              new ComplementFilter(queryFilter, getGroupAttributeFilter(field, query, fromStem));
        }
        outTerms.add(lastAndOrNot);
        outTerms.add(query);
        outTerms.add(field);
      }
      lastQuery = query;
      lastField = field;
      lastAndOrNot = andOrNot;
    }
    // Now add GroupTYpe filter
    String groupTypeText = navBundle.getString("find.results.group-type");
    String groupType = null;
    maxCountStr = getSingle("maxTypes", attr);
    try {
      maxCount = Integer.parseInt(maxCountStr);
    } catch (NumberFormatException e) {
      maxCount = 0;
    }
    GroupType gt = null;
    for (int i = 1; i <= maxCount; i++) {
      groupType = getSingle("searchType." + i, attr);
      if (groupType == null) break;
      gt = GroupTypeFinder.find(groupType, true);

      andOrNot = getSingle("searchType." + i + ".searchAndOrNot", attr);

      if (queryFilter == null) {
        queryFilter = new GroupTypeFilter(gt, fromStem);
        outTerms.add(groupTypeText);
        outTerms.add(gt.getName());
      } else {
        if ("and".equals(andOrNot)) {
          queryFilter = new IntersectionFilter(queryFilter, new GroupTypeFilter(gt, fromStem));
        } else if ("or".equals(andOrNot)) {
          queryFilter = new UnionFilter(queryFilter, new GroupTypeFilter(gt, fromStem));
        } else {
          queryFilter = new ComplementFilter(queryFilter, new GroupTypeFilter(gt, fromStem));
        }
        outTerms.add(andOrNot);
        outTerms.add(groupTypeText);
        outTerms.add(groupType);
      }
    }

    GrouperQuery q = GrouperQuery.createQuery(s, queryFilter);
    res.addAll(q.getGroups());
    return res;
  }
  /**
   * Only accessible from Create groups, implements stem search logic
   *
   * @param s
   * @param from
   * @param attr
   * @param outTerms
   * @return list of Stems matching search criteria
   * @throws Exception
   */
  public List advancedStemSearch(GrouperSession s, String from, Map attr, List outTerms)
      throws Exception {
    List res = new ArrayList();
    String maxCountStr = getSingle("maxFields", attr);
    int maxCount = Integer.parseInt(maxCountStr);
    String lastQuery = null;
    String lastField = null;
    String lastAndOrNot = null;
    String field;
    String query;
    String andOrNot;
    Map fieldMaps = (Map) GrouperHelper.getFieldsAsMap().get("stems");
    String lastFieldDisplayName = null;
    QueryFilter queryFilter = null;
    if (outTerms == null) outTerms = new ArrayList();

    Stem fromStem = StemFinder.findByName(s, from, true);
    for (int i = 1; i <= maxCount; i++) {
      field = getSingle("searchField." + i, attr);
      query = getSingle("searchField." + i + ".query", attr);
      if (i == 1 && (field == null || query == null)) {
        if (getSingle("searchType.1", attr) != null) break;
        throw new IllegalArgumentException(
            "The first search field and query value must be enetered");
      }
      andOrNot = getSingle("searchField." + i + ".searchAndOrNot", attr);
      if (query == null || "".equals(query)) query = lastQuery;
      if (i > 1) {
        if (queryFilter == null) {
          queryFilter = getStemAttributeFilter(lastField, lastQuery, fromStem);
          outTerms.add(lastQuery);
          lastFieldDisplayName = (String) fieldMaps.get(lastField);
          outTerms.add(lastFieldDisplayName);
        }
        if (field == null && i == 2) {
          break;
        }
        if (field == null && i > 2) break;

        if ("and".equals(lastAndOrNot)) {
          queryFilter =
              new IntersectionFilter(queryFilter, getStemAttributeFilter(field, query, fromStem));
        } else if ("or".equals(lastAndOrNot)) {
          queryFilter =
              new UnionFilter(queryFilter, getStemAttributeFilter(field, query, fromStem));
        } else {
          queryFilter =
              new ComplementFilter(queryFilter, getStemAttributeFilter(field, query, fromStem));
        }
        outTerms.add(lastAndOrNot);
        outTerms.add(query);
        outTerms.add(field);
      }
      lastQuery = query;
      lastField = field;
      lastAndOrNot = andOrNot;
    }

    GrouperQuery q = GrouperQuery.createQuery(s, queryFilter);
    res.addAll(q.getStems());
    return res;
  }