/* (non-Javadoc)
   * @see edu.internet2.middleware.grouper.ui.RepositoryBrowser#getParentStems(edu.internet2.middleware.grouper.ui.GroupOrStem)
   */
  public List getParentStems(GroupOrStem groupOrStem) throws Exception {
    List path = new ArrayList();
    if (groupOrStem == null) return path;
    Map map = GrouperHelper.group2Map(s, groupOrStem);

    Stem curStem = null;
    String endPoint = GrouperHelper.NS_ROOT;

    boolean isEndPointReached = false;
    if (isHidePreRootNode()) {
      endPoint = getRootNode();
      if (map.get("name").equals(endPoint)) isEndPointReached = true;
    }

    while (!isEndPointReached
        && !"".equals(map.get("stem"))
        && !GrouperHelper.NS_ROOT.equals(map.get("stem"))) {
      curStem = StemFinder.findByName(s, (String) map.get("stem"), true);
      if (curStem != null) {
        map = GrouperHelper.stem2Map(s, curStem);
        path.add(0, map);
        if (curStem.getName().equals(endPoint)) isEndPointReached = true;
      }
    }
    if (!isEndPointReached) {
      path.add(0, GrouperHelper.stem2Map(s, StemFinder.findRootStem(s)));
    }
    return path;
  }
  /* (non-Javadoc)
   * @see edu.internet2.middleware.grouper.ui.RepositoryBrowser#search(edu.internet2.middleware.grouper.GrouperSession, java.lang.String, java.lang.String, java.util.Map)
   */
  public List search(GrouperSession s, String query, String from, Map attr, List outTerms)
      throws Exception {
    String searchInDisplayNameOrExtension = getSingle("searchInDisplayNameOrExtension", attr);
    String searchInNameOrExtension = getSingle("searchInNameOrExtension", attr);
    boolean isAdvancedSearch = "Y".equals(getSingle("advSearch", attr));
    List results = null;
    if ("stems".equals(search)) {
      if (isAdvancedSearch) {
        results = advancedStemSearch(s, from, attr, outTerms);
      } else {
        results =
            GrouperHelper.searchStems(
                s, query, from, searchInDisplayNameOrExtension, searchInNameOrExtension);
        if (outTerms != null) outTerms.add(query);
      }

    } else {
      if (isAdvancedSearch) {
        results = advancedSearch(s, from, attr, outTerms);
      } else {
        String searchInAny = getMediaProperty("search.default.any");
        if ("only".equals(searchInAny)
            || ("true".equals(searchInAny) && "any".equals(getSingle("searchIn", attr)))) {
          searchInDisplayNameOrExtension = null;
          searchInNameOrExtension = null;
        }

        results =
            GrouperHelper.searchGroups(
                s,
                query,
                from,
                searchInDisplayNameOrExtension,
                searchInNameOrExtension,
                browseMode);
        if (outTerms != null) outTerms.add(query);
      }
    }
    List filtered = new ArrayList();
    Object obj = null;
    for (int i = 0; i < results.size(); i++) {
      obj = results.get(i);
      if (isValidSearchResult(obj)) filtered.add(obj);
    }

    return filtered;
  }
 /**
  * Called from getChildren if in flat mode
  *
  * @param start
  * @param pageSize
  * @param totalCount
  * @param context
  * @param request
  * @return
  * @throws Exception
  */
 protected Set getFlatChildren(
     int start, int pageSize, StringBuffer totalCount, String context, HttpServletRequest request)
     throws Exception {
   if ("stem".equals(flatType)) {
     List l =
         GrouperHelper.stems2Maps(
             s,
             LowLevelGrouperCapableAction.sort(
                 GrouperHelper.getStemsForPrivileges(s, flatPrivs, start, pageSize, totalCount),
                 request,
                 context,
                 -1,
                 null));
     return new LinkedHashSet(l);
   }
   if (flatPrivs.length == 1 && flatPrivs[0].equals("member")) {
     /*Set tmp = GrouperHelper.getMembershipsSet(getGrouperSession(),start, pageSize, totalCount);*/
     Set tmp = GrouperHelper.getMembershipsSet(getGrouperSession());
     totalCount.append("" + tmp.size());
     List tmpList = LowLevelGrouperCapableAction.sort(tmp, request, context, -1, null);
     int end = start + pageSize;
     if (end > tmpList.size()) end = tmpList.size();
     tmpList = GrouperHelper.groups2Maps(getGrouperSession(), tmpList.subList(start, end));
     return new LinkedHashSet(tmpList);
   }
   Set groupsForPrivileges =
       GrouperHelper.getGroupsForPrivileges(s, flatPrivs, start, pageSize, totalCount);
   List l =
       GrouperHelper.groups2Maps(
           s, LowLevelGrouperCapableAction.sort(groupsForPrivileges, request, context, -1, null));
   return new LinkedHashSet(l);
 }
  /**
   * Makes HttpSession and GrouperSession available to subclasses Also handles pageSize parameter
   * and times how long is spent in an action
   */
  public ActionForward execute(
      ActionMapping mapping,
      ActionForm form,
      HttpServletRequest request,
      HttpServletResponse response)
      throws Exception {
    GrouperSession grouperSession =
        (GrouperSession)
            request.getSession().getAttribute("edu.intenet2.middleware.grouper.ui.GrouperSession");
    // if(grouperSession == null && !"/populateIndex.do".equals(request.getServletPath())) return
    // mapping.findForward("Index");

    ModuleConfig modConfig = (ModuleConfig) request.getAttribute("org.apache.struts.action.MODULE");
    String modulePrefix = modConfig.getPrefix();
    if (modulePrefix == null) modulePrefix = "";
    request.setAttribute("modulePrefix", modulePrefix);
    HttpSession session = request.getSession();
    String pageSize = request.getParameter("pageSize");
    if (pageSize != null && pageSize.length() > 0) {
      session.setAttribute("default.pagesize", pageSize);
    }

    DynaActionForm dummyForm = (DynaActionForm) form;
    if (dummyForm != null) {
      try {
        dummyForm.set("pageSize", "" + getPageSize(session));
      } catch (Exception e) {
        // Ok so form doesn't care about pageSize
        // let's just ignore it
      }
    }
    isWheelGroupMember(session);
    String wheelGroupAction = request.getParameter("wheelGroupAction");
    if (!isEmpty(wheelGroupAction)) doWheelGroupStuff(wheelGroupAction, session);
    UIThreadLocal.replace(
        "isActiveWheelGroupMember", new Boolean(isActiveWheelGroupMember(session)));

    if (grouperSession != null) {
      if (isWheelGroupMember(session)) {
        grouperSession.setConsiderIfWheelMember(isActiveWheelGroupMember(session));
      } else {
        // we'll set this back to the default
        grouperSession.setConsiderIfWheelMember(true);
      }
    }

    if (form != null) request.setAttribute("grouperForm", form);
    Object sessionMessage = session.getAttribute("sessionMessage");
    if (isEmpty(request.getAttribute("message")) && !isEmpty(sessionMessage)) {
      request.setAttribute("message", sessionMessage);
      session.removeAttribute("sessionMessage");
    }
    request.setAttribute("linkBrowseMode", getLinkBrowseMode(session));
    Date before = new Date();
    ActionForward forward = null;
    try {
      if (isEmpty(wheelGroupAction)) {

        forward =
            grouperTransactionExecute(mapping, form, request, response, session, grouperSession);

      } else
        forward =
            new ActionForward(
                GrouperUiFilter.retrieveSessionMediaResourceBundle().getString("admin.browse.path"),
                true);
    } catch (GrouperDAOException e) {
      Throwable cause = e.getCause();

      Throwable causeCause = cause == null ? null : cause.getCause();

      Throwable causeCauseCause = causeCause == null ? null : causeCause.getCause();

      HookVeto hookVeto = (cause instanceof HookVeto) ? (HookVeto) cause : null;

      hookVeto =
          ((hookVeto == null) && (causeCause instanceof HookVeto))
              ? (HookVeto) causeCause
              : hookVeto;

      hookVeto =
          ((hookVeto == null) && (causeCauseCause instanceof HookVeto))
              ? (HookVeto) causeCauseCause
              : hookVeto;

      if (hookVeto != null) {
        Message.addVetoMessageToScreen(request, hookVeto);
      } else if (!(cause instanceof UnrecoverableErrorException)) {
        LOG.error(NavExceptionHelper.toLog(cause));
        cause = new UnrecoverableErrorException(cause);
      }
      if (cause instanceof UnrecoverableErrorException) {
        NavExceptionHelper neh = getExceptionHelper(session);
        String msg = neh.getMessage((UnrecoverableErrorException) cause);
        request.setAttribute("seriousError", msg);
      }
      forward = mapping.findForward("ErrorPage");
    }
    Date after = new Date();
    long diff = after.getTime() - before.getTime();
    String url = request.getServletPath();
    Long ms = (Long) request.getAttribute("timingsMS");
    long mss = 0;
    if (ms != null) mss = ms.longValue();
    if (diff > 25) {
      request.setAttribute("timingsClass", this.getClass().getName());
      request.setAttribute("timingsMS", new Long(diff + mss));
    }
    if (forward != null && forward.getRedirect() && !isEmpty(request.getAttribute("message"))) {
      try {
        session.setAttribute("sessionMessage", request.getAttribute("message"));
      } catch (IllegalStateException e) {
      }
    }

    if (Boolean.TRUE.equals(request.getAttribute("loggedOut"))) {
      return forward;
    }
    try {
      GrouperHelper.fixSessionFields((Map) session.getAttribute("fieldList"));
    } catch (SchemaException e) {
      LOG.error(e);
    }
    String advSearch = request.getParameter("advancedSearch");
    try {
      session.getAttribute("");
    } catch (Exception e) {
      return forward;
    }
    if (!isEmpty(advSearch)) {
      setAdvancedSearchMode("true".equals(advSearch), session);
    }
    request.setAttribute("isAdvancedSearch", getAdvancedSearchMode(session));
    return forward;
  }
  /* (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;
  }
  /**
   * @see edu.internet2.middleware.grouper.ui.RepositoryBrowser#getChildren(java.lang.String, int,
   *     int, java.lang.StringBuffer, boolean, boolean)
   */
  public Set getChildren(
      String node,
      String listField,
      int start,
      int pageSize,
      StringBuffer totalCount,
      boolean isFlat,
      boolean isForAssignment,
      String omitForAssignment,
      String context,
      HttpServletRequest request)
      throws Exception {

    if (isFlat) return getFlatChildren(start, pageSize, totalCount, "flat", request);

    Set results = new LinkedHashSet();
    GroupOrStem groupOrStem = GroupOrStem.findByID(s, node);
    Group group = groupOrStem.getGroup();
    Stem stem = groupOrStem.getStem();
    if (listField == null || "".equals(listField)) listField = "members";
    Field field = FieldFinder.find(listField, true);
    List sortedChildren = null;
    int[] resultSizeArray = new int[1];
    int resultSize = 0;
    if (isForAssignment) {
      if (group != null) { // display immediate members

        Set<Membership> allChildren = new LinkedHashSet<Membership>();
        ResourceBundle resourceBundle = GrouperUiFilter.retrieveSessionMediaResourceBundle();
        String sortLimitString = resourceBundle.getString("comparator.sort.limit");
        int sortLimit = Integer.parseInt(sortLimitString);

        allChildren =
            MembershipFinder.internal_findAllImmediateByGroupAndFieldAndPage(
                group, field, start, pageSize, sortLimit, resultSizeArray);
        resultSize = resultSizeArray[0];
        sortedChildren =
            LowLevelGrouperCapableAction.sort(allChildren, request, context, resultSize, null);

        int groupList2SubjectStart = (start >= sortedChildren.size()) ? 0 : start;

        results.addAll(
            GrouperHelper.groupList2SubjectsMaps(
                s, sortedChildren, groupList2SubjectStart, pageSize));
        if (totalCount != null) {
          totalCount.setLength(0);
          totalCount.append(resultSize);
        }
        return results;
      }
    } else if (group != null) return results;
    Set<GroupAsMap> allChildren = new LinkedHashSet<GroupAsMap>();

    // must be stem
    String stemName = null;
    if (stem != null) {
      stemName = stem.getName();
    } else if (GrouperHelper.NS_ROOT.equals(node)) {
      stemName = node;
    } else {
      throw new RuntimeException(node + " is not recognised");
    }
    List<GroupAsMap> listOfMaps = getChildrenAsMaps(s, stemName, start, pageSize, resultSizeArray);

    if (this.pagedQuery()) {
      resultSize = resultSizeArray[0];
    }

    if (sortedQuery()) {
      listOfMaps = LowLevelGrouperCapableAction.sort(listOfMaps, request, context, -1, null);
    }

    allChildren.addAll(listOfMaps);
    // Map validStems  = GrouperHelper.getValidStems(s,browseMode);
    boolean addChild = false;
    int end = start + pageSize;

    Map child;
    String name;
    Iterator it = allChildren.iterator();
    int count = 0;
    while (it.hasNext()) {
      addChild = false;

      child = (Map) it.next();
      if (isForAssignment) {
        // Do not try to exclude current group - so what if someone tries to add an existing member?
        // Also becomes complicated if there are custom fields
        // if(omitForAssignment!=null && omitForAssignment.equals(child.get("id"))) {
        // addChild=false;
        // }else{
        addChild = true;
        // }
      } else {
        addChild = isValidChild(child);
      }
      if (addChild) {
        if (!this.pagedQuery()) {
          resultSize++;
        }

        if (this.pagedQuery() || (resultSize >= start && resultSize < end)) {
          results.add(child);
        }
      } else if (this.pagedQuery()) {
        resultSize--;
      }
    }
    if (totalCount != null) {
      totalCount.setLength(0);
      totalCount.append(resultSize);
    }
    return results;
  }
  public ActionForward grouperExecute(
      ActionMapping mapping,
      ActionForm form,
      HttpServletRequest request,
      HttpServletResponse response,
      HttpSession session,
      GrouperSession grouperSession)
      throws Exception {
    Class sortOverrideClass = Group.class;
    NavExceptionHelper neh = getExceptionHelper(session);
    DynaActionForm subjectForm = (DynaActionForm) form;
    if ("true".equals(request.getParameter("changeMode")))
      PopulateSearchSubjectsAction.initMode(session);
    session.setAttribute("subtitle", "subject.action.show-summary");
    if (isEmpty(subjectForm.get("callerPageId"))) {
      if (isEmpty(subjectForm.get("subjectId"))) {
        LOG.info("Restoring lastSubjectSummaryForm");
        restoreDynaFormBean(session, subjectForm, "lastSubjectSummaryForm");
      } else {
        LOG.info("Saving lastSubjectSummaryForm");
        saveDynaFormBean(session, subjectForm, "lastSubjectSummaryForm");
        saveAsCallerPage(request, subjectForm);
      }
    }
    saveAsCallerPage(request, subjectForm);

    String listField = (String) subjectForm.get("listField");
    String membershipField = "members";

    if (!isEmpty(listField)) {
      membershipField = listField;
    }
    Field mField = null;
    try {
      mField = FieldFinder.find(membershipField, true);
    } catch (SchemaException e) {
      LOG.error("Could not find Field: " + membershipField, e);
      if ("members".equals(membershipField)) {
        LOG.fatal("Built in field: members, missing");
        throw new UnrecoverableErrorException(e);
      } else {
        mField = FieldFinder.find("members", true);
        request.setAttribute(
            "message", new Message("error.subject-summary.missing-field", listField, true));
      }
    }

    subjectForm.set("contextSubject", "true");
    String subjectId = (String) subjectForm.get("subjectId");
    String subjectType = (String) subjectForm.get("subjectType");
    String subjectSource = (String) subjectForm.get("sourceId");
    if (isEmpty(subjectId) || isEmpty(subjectType) || isEmpty(subjectSource)) {
      String msg =
          neh.missingParameters(
              subjectId, "subjectId", subjectType, "subjectType", subjectSource, "sourceId");
      LOG.error(msg);
      if (doRedirectToCaller(subjectForm)) {
        session.setAttribute(
            "sessionMessage", new Message("error.subject-summary.missing-parameter", true));
        return redirectToCaller(subjectForm);
      }
      throw new UnrecoverableErrorException("error.subject-summary.missing-parameter");
    }
    Subject subject = null;
    try {
      subject = SubjectFinder.findById(subjectId, subjectType, subjectSource, true);
    } catch (Exception e) {
      LOG.error(e);
      if (e instanceof SubjectNotFoundException) {
        subject = new UnresolvableSubject(subjectId, subjectType, subjectSource);
        addMessage(
            new Message(
                "error.subject.unresolvable", new String[] {subjectId, subjectSource}, true),
            request);
      } else {

        String contextError = "error.subject-summary.subject.exception";
        session.setAttribute("sessionMessage", new Message(neh.key(e), contextError, true));
        if (doRedirectToCaller(subjectForm)) return redirectToCaller(subjectForm);
        throw new UnrecoverableErrorException(contextError, e);
      }
    }
    Map subjectMap = GrouperHelper.subject2Map(subject);
    request.setAttribute("subject", subjectMap);

    String order = null;
    try {
      order =
          GrouperUiFilter.retrieveSessionMediaResourceBundle()
              .getString("subject.attributes.order." + subject.getSource().getId());
      request.setAttribute("subjectAttributeNames", order.split(","));
    } catch (Exception e) {
      // No order specified, so go with all, in whatever order they come
      List extendedAttr = new ArrayList(GrouperUtil.nonNull(subject.getAttributes()).keySet());
      extendedAttr.add("subjectType");
      extendedAttr.add("id");
      request.setAttribute("subjectAttributeNames", extendedAttr);
    }
    String membershipListScope = (String) subjectForm.get("membershipListScope");

    if ("any-access".equals(membershipListScope)) {
      if ("false".equals(request.getParameter("advancedSearch"))) {
        membershipListScope = null;
      } else {
        request.setAttribute("fromSubjectSummary", Boolean.TRUE);

        session.setAttribute("groupSearchSubject", subject);
        session.setAttribute("groupSearchSubjectMap", subjectMap);
        return mapping.findForward(FORWARD_GroupSearch);
      }
    }
    if (":all:imm:eff:access:naming:".indexOf(":" + membershipListScope + ":") == -1) {
      membershipListScope = (String) session.getAttribute("subjectMembershipListScope");
    }
    if (membershipListScope == null) membershipListScope = "imm";
    session.setAttribute("subjectMembershipListScope", membershipListScope);
    subjectForm.set("membershipListScope", membershipListScope);

    String accessPriv = (String) subjectForm.get("accessPriv");
    if (isEmpty(accessPriv)) accessPriv = (String) session.getAttribute("subjectSummaryAccessPriv");
    if (isEmpty(accessPriv)) accessPriv = "read";
    session.setAttribute("subjectSummaryAccessPriv", accessPriv);
    subjectForm.set("accessPriv", accessPriv);

    String namingPriv = (String) subjectForm.get("namingPriv");
    if (isEmpty(namingPriv)) namingPriv = (String) session.getAttribute("subjectSummaryNamingPriv");
    if (isEmpty(namingPriv)) namingPriv = "create";
    session.setAttribute("subjectSummaryNamingPriv", namingPriv);
    subjectForm.set("namingPriv", namingPriv);
    // Retrieve the membership according to scope selected by user
    Member member = null;
    try {
      member = MemberFinder.findBySubject(grouperSession, subject, true);
      if (member == null) {
        throw new MemberNotFoundException("Unresolvable subject is also not a Member");
      }
    } catch (Exception e) {
      LOG.error(e);
      if (doRedirectToCaller(subjectForm)) {
        session.setAttribute(
            "sessionMessage", new Message("error.subject-summary.member.exception", true));
        return redirectToCaller(subjectForm);
      }
      throw new UnrecoverableErrorException("error.subject-summary.member.exception", e);
    }
    Set subjectScopes = null;
    List subjectScopeMaps = null;
    Map listViews = new HashMap();
    listViews.put("titleKey", "subject.summary.memberships");
    listViews.put("noResultsKey", "subject.list-membership.none");
    listViews.put("view", "whereSubjectsAreMembers");
    // listViews.put("itemView","whereIsMemberLink");
    listViews.put("itemView", "subjectSummary");
    listViews.put("headerView", "genericListHeader");
    listViews.put("footerView", "genericListFooter");

    if ("imm".equals(membershipListScope)) {
      subjectScopes = member.getImmediateMemberships(mField);
      listViews.put("noResultsKey", "subject.list-membership.imm.none");
    } else if ("eff".equals(membershipListScope)) {
      if (membershipField.equals("members")) {
        subjectScopes = member.getMemberships();
        subjectScopes.removeAll(member.getImmediateMemberships());

      } else {
        subjectScopes = member.getEffectiveMemberships(mField);
        listViews.put("noResultsKey", "subject.list-membership.all.none");
      }
      if ("members".equals(membershipField)) {
        listViews.put("noResultsKey", "subject.list-membership.eff.none");
      } else {
        listViews.put("noResultsKey", "subject.list-membership.custom.eff.none");
      }

    } else if ("all".equals(membershipListScope)) {
      subjectScopes = member.getMemberships(mField);
      listViews.put("noResultsKey", "subject.list-membership.all.none");
    } else if ("access".equals(membershipListScope)) {

      subjectScopes = GrouperHelper.getGroupsOrStemsWhereMemberHasPriv(member, accessPriv);

      // filter out groups where the subject can't see privs
      removeObjectsNotAllowedToSeePrivs(subjectScopes);

      subjectScopeMaps =
          GrouperHelper.subjects2SubjectPrivilegeMaps(
              grouperSession, subjectScopes, subject, accessPriv);
      listViews.put("titleKey", "subject.summary.access-privs");
      listViews.put("noResultsKey", "subject.list-access.none");
      listViews.put("view", "subjectSummaryPrivileges");
      listViews.put("itemView", "subjectSummaryPrivilege");
    } else {
      sortOverrideClass = Stem.class;
      subjectScopes = GrouperHelper.getGroupsOrStemsWhereMemberHasPriv(member, namingPriv);

      // filter out stems where the subject can't see privs
      removeObjectsNotAllowedToSeePrivs(subjectScopes);

      subjectScopeMaps =
          GrouperHelper.subjects2SubjectPrivilegeMaps(
              grouperSession, subjectScopes, subject, namingPriv);
      listViews.put("titleKey", "subject.summary.naming-privs");
      listViews.put("noResultsKey", "subject.list-naming.none");
      listViews.put("view", "subjectSummaryPrivileges");
      listViews.put("itemView", "subjectSummaryPrivilege");
    }
    request.setAttribute("scopeListData", listViews);
    if (subjectScopeMaps == null) {
      Map countMap = new HashMap();
      Map sources = new HashMap();
      List uniqueSubjectScopes =
          GrouperHelper.getOneMembershipPerSubjectOrGroup(
              subjectScopes, "subject", countMap, sources, 0);
      subjectScopeMaps = GrouperHelper.memberships2Maps(grouperSession, uniqueSubjectScopes);
      GrouperHelper.setMembershipCountPerSubjectOrGroup(subjectScopeMaps, "subject", countMap);
    }
    // This is a hack to force sorting by Group/Stem rather than Subject - which is generally what
    // happens with Memberships
    // DefaultComparatorImpl has been updated to read the TheadLocal
    UIThreadLocal.put("GrouperComparatorHelperOverrideClass", sortOverrideClass);
    subjectScopeMaps = sort(subjectScopeMaps, request, "subjectSummary", -1, null);
    UIThreadLocal.replace("GrouperComparatorHelperOverrideClass", null);
    String startStr = (String) subjectForm.get("start");
    if (startStr == null || "".equals(startStr)) startStr = "0";

    int start = Integer.parseInt(startStr);
    int pageSize = getPageSize(session);
    int end = start + pageSize;
    if (end > subjectScopeMaps.size()) end = subjectScopeMaps.size();
    CollectionPager pager =
        new CollectionPager(
            null, subjectScopeMaps, subjectScopeMaps.size(), null, start, null, pageSize);

    if (!isEmpty(listField)) pager.setParam("listField", listField);
    pager.setParam("subjectId", subjectId);
    pager.setParam("subjectType", subjectType);
    pager.setParam("sourceId", subjectSource);
    pager.setParam("returnTo", subjectForm.get("returnTo"));
    pager.setParam("returnToLinkKey", subjectForm.get("returnToLinkKey"));
    pager.setTarget(mapping.getPath());
    request.setAttribute("pager", pager);
    request.setAttribute("linkParams", pager.getParams().clone());
    request.setAttribute("listFieldParams", pager.getParams().clone());

    Map saveParams = new HashMap();
    saveParams.put("subjectId", subject.getId());
    saveParams.put("subjectType", subject.getType().getName());
    saveParams.put("sourceId", subject.getSource().getId());
    saveParams.put("callerPageId", request.getAttribute("thisPageId"));
    request.setAttribute("saveParams", saveParams);

    if (subjectType.equals("group")) {
      List lists = GrouperHelper.getReadableListFieldsForGroup(grouperSession, subjectId);
      if (!lists.isEmpty()) request.setAttribute("listFields", lists);
    }

    List memberOfListFields = GrouperHelper.getListFieldsForSubject(grouperSession, subject);
    if (memberOfListFields.size() > 0) {
      request.setAttribute("memberOfListFields", memberOfListFields);
    }

    Collection accessPrivs =
        GrouperHelper.getGroupPrivsWithLabels(GrouperUiFilter.retrieveSessionNavResourceBundle());
    Collection namingPrivs =
        GrouperHelper.getStemPrivsWithLabels(GrouperUiFilter.retrieveSessionNavResourceBundle());
    request.setAttribute("allAccessPrivs", accessPrivs);
    request.setAttribute("allNamingPrivs", namingPrivs);

    return mapping.findForward(FORWARD_SubjectSummary);
  }