/** populates a HierarchyData object given the self Org */
  protected HierarchyData getHierarchyData(
      HttpServletRequest request,
      SimpleServletSupport support,
      HasRelationships selfOrg,
      boolean recurse,
      boolean allRelationships,
      Set visitedOrgs) {
    // create a "self" org
    String selfOrgName = ((Asset) selfOrg).getClusterPG().getMessageAddress().toString();
    visitedOrgs.add(selfOrgName);
    // build list of orgs
    HierarchyData hd = new HierarchyData();
    Organization toOrg = new Organization();
    toOrg.setUID(selfOrgName);
    toOrg.setPrettyName(selfOrgName); // where is the pretty name kept?
    hd.setRootOrgID(selfOrgName); // set rootId as self

    MutableTimeSpan mts = new MutableTimeSpan();
    RelationshipSchedule schedule = selfOrg.getRelationshipSchedule();

    Collection subordinates = new HashSet();

    if (!allRelationships) {
      Collection subordinates1 =
          schedule.getMatchingRelationships(SUBORD_ROLE, mts.getStartTime(), mts.getEndTime());
      subordinates.addAll(subordinates1);

      Collection subordinates2 =
          schedule.getMatchingRelationships(
              ADMIN_SUBORD_ROLE, mts.getStartTime(), mts.getEndTime());

      subordinates.addAll(subordinates2);
    } else {
      subordinates.addAll(schedule.getMatchingRelationships(mts));
    }

    // add self org to hierarchy
    hd.addOrgData(toOrg);

    if (VERBOSE && false)
      System.out.println("getHierarchyData - " + selfOrgName + " has these subs " + subordinates);

    if (subordinates.isEmpty()) {
      // no subordinates
      return hd;
    }

    Set recurseSubOrgSet = null;
    if (recurse) {
      recurseSubOrgSet = new HashSet();
    }

    // Safe to iterate over subordinates because getSubordinates() returns
    // a new Collection.
    for (Iterator schedIter = subordinates.iterator(); schedIter.hasNext(); ) {
      Relationship relationship = (Relationship) schedIter.next();
      Asset subOrg = (Asset) schedule.getOther(relationship);
      String role = schedule.getOtherRole(relationship).getName();

      String subOrgName = subOrg.getClusterPG().getMessageAddress().toString();

      // client wants a numerical identifier for the role
      int roleId;
      if (!allRelationships) {
        if (role.equalsIgnoreCase("AdministrativeSubordinate")) {
          // admin_subord
          roleId = org.cougaar.planning.servlet.data.hierarchy.Organization.ADMIN_SUBORDINATE;
        } else {
          // some other subord type
          //   ** add more String.equals cases here **
          roleId = org.cougaar.planning.servlet.data.hierarchy.Organization.SUBORDINATE;
        }
        toOrg.addRelation(subOrgName, roleId);
      } else if (!role.endsWith("Self")) {
        toOrg.addRelation(subOrgName, role);
      }
      if (recurse
          && (!(selfOrgName.equals(subOrgName)))
          && // don't recurse on yourself
          validRole(role)
          && // only on customers, subordinates, etc.
          !visitedOrgs.contains(subOrgName)) { // only ones we haven't visited before
        if (VERBOSE) // so we don't have circular paths
        System.out.println(
              "self "
                  + selfOrgName
                  + " sub "
                  + subOrgName
                  + " role "
                  + role
                  + (validRole(role) ? " VALID " : " invalid"));
        recurseSubOrgSet.add(subOrgName);
      }
    }

    // if we are recursing, recurse on subordinates
    if (recurse) {
      visitedOrgs.addAll(recurseSubOrgSet);
      recurseOnSubords(recurseSubOrgSet, request, support, allRelationships, visitedOrgs, hd);
    }

    // return list
    return hd;
  }