gt:       members = new HashSet<ProgramElementDoc>();
context: /*
   * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.  Oracle designates this
   * particular file as subject to the "Classpath" exception as provided
   * by Oracle in the LICENSE file that accompanied this code.
   *
   * This code is distributed in the hope that it will be useful, but WITHOUT
   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   * version 2 for more details (a copy is included in the LICENSE file that
   * accompanied this code).
   *
   * You should have received a copy of the GNU General Public License version
   * 2 along with this work; if not, write to the Free Software Foundation,
   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   *
   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   * or visit www.oracle.com if you need additional information or have any
   * questions.
   */
  
  package com.sun.tools.doclets.internal.toolkit.util;
  
  import com.sun.javadoc.*;
  import com.sun.tools.doclets.internal.toolkit.*;
  import java.util.*;
  
  /**
   * A data structure that encapsulates the visible members of a particular type
   * for a given class tree. To use this data structor, you must specify the type
   * of member you are interested in (nested class, field, constructor or method)
   * and the leaf of the class tree. The data structure will map all visible
   * members in the leaf and classes above the leaf in the tree.
   * 
   * This code is not part of an API. It is implementation that is subject to
   * change. Do not use it as an API
   * 
   * @author Atul M Dambalkar
   * @author Jamie Ho (rewrite)
   */
  public class VisibleMemberMap {
  
    private boolean noVisibleMembers = true;
  
    public static final int INNERCLASSES = 0;
    public static final int ENUM_CONSTANTS = 1;
    public static final int FIELDS = 2;
    public static final int CONSTRUCTORS = 3;
    public static final int METHODS = 4;
    public static final int ANNOTATION_TYPE_MEMBER_OPTIONAL = 5;
    public static final int ANNOTATION_TYPE_MEMBER_REQUIRED = 6;
  
    /**
     * The total number of member types is {@value} .
     */
    public static final int NUM_MEMBER_TYPES = 7;
  
    public static final String STARTLEVEL = "start";
  
    /**
     * List of ClassDoc objects for which ClassMembers objects are built.
     */
    private final List<ClassDoc> visibleClasses = new ArrayList<ClassDoc>();
  
    /**
     * Map for each member name on to a map which contains members with same
     * name-signature. The mapped map will contain mapping for each MemberDoc onto
     * it's respecive level string.
     */
    private final Map<Object, Map<ProgramElementDoc, String>> memberNameMap = new HashMap<Object, Map<ProgramElementDoc, String>>();
  
    /**
     * Map of class and it's ClassMembers object.
     */
    private final Map<ClassDoc, ClassMembers> classMap = new HashMap<ClassDoc, ClassMembers>();
  
    /**
     * Type whose visible members are requested. This is the leaf of the class
     * tree being mapped.
     */
    private final ClassDoc classdoc;
  
    /**
     * Member kind: InnerClasses/Fields/Methods?
     */
    private final int kind;
  
    /**
     * Deprected members should be excluded or not?
     */
    private final boolean nodepr;
  
    /**
     * Construct a VisibleMemberMap of the given type for the given class. If
     * nodepr is true, exclude the deprecated members from the map.
     * 
     * @param classdoc
     *          the class whose members are being mapped.
     * @param kind
     *          the kind of member that is being mapped.
     * @param nodepr
     *          if true, exclude the deprecated members from the map.
     */
    public VisibleMemberMap(ClassDoc classdoc, int kind, boolean nodepr) {
      this.classdoc = classdoc;
      this.nodepr = nodepr;
      this.kind = kind;
      new ClassMembers(classdoc, STARTLEVEL).build();
    }
  
    /**
     * Return the list of visible classes in this map.
     * 
     * @return the list of visible classes in this map.
     */
    public List<ClassDoc> getVisibleClassesList() {
      sort(visibleClasses);
      return visibleClasses;
    }
  
    /**
     * Return the package private members inherited by the class. Only return if
     * parent is package private and not documented.
     * 
     * @param configuation
     *          the current configuration of the doclet.
     * @return the package private members inherited by the class.
     */
    private List<ProgramElementDoc> getInheritedPackagePrivateMethods(
        Configuration configuration) {
      List<ProgramElementDoc> results = new ArrayList<ProgramElementDoc>();
      for (Iterator<ClassDoc> iter = visibleClasses.iterator(); iter.hasNext();) {
        ClassDoc currentClass = iter.next();
        if (currentClass != classdoc && currentClass.isPackagePrivate()
            && !Util.isLinkable(currentClass, configuration)) {
          // Document these members in the child class because
          // the parent is inaccessible.
          results.addAll(getMembersFor(currentClass));
        }
      }
      return results;
    }
  
    /**
     * Return the visible members of the class being mapped. Also append at the
     * end of the list members that are inherited by inaccessible parents. We
     * document these members in the child because the parent is not documented.
     * 
     * @param configuation
     *          the current configuration of the doclet.
     */
    public List<ProgramElementDoc> getLeafClassMembers(Configuration configuration) {
      List<ProgramElementDoc> result = getMembersFor(classdoc);
      result.addAll(getInheritedPackagePrivateMethods(configuration));
      return result;
    }
  
    /**
     * Retrn the list of members for the given class.
     * 
     * @param cd
     *          the class to retrieve the list of visible members for.
     * 
     * @return the list of members for the given class.
     */
    public List<ProgramElementDoc> getMembersFor(ClassDoc cd) {
      ClassMembers clmembers = classMap.get(cd);
      if (clmembers == null) {
        return new ArrayList<ProgramElementDoc>();
      }
      return clmembers.getMembers();
    }
  
    /**
     * Sort the given mixed list of classes and interfaces to a list of classes
     * followed by interfaces traversed. Don't sort alphabetically.
     */
    private void sort(List<ClassDoc> list) {
      List<ClassDoc> classes = new ArrayList<ClassDoc>();
      List<ClassDoc> interfaces = new ArrayList<ClassDoc>();
      for (int i = 0; i < list.size(); i++) {
        ClassDoc cd = list.get(i);
        if (cd.isClass()) {
          classes.add(cd);
        } else {
          interfaces.add(cd);
        }
      }
      list.clear();
      list.addAll(classes);
      list.addAll(interfaces);
    }
  
    private void fillMemberLevelMap(List<ProgramElementDoc> list, String level) {
      for (int i = 0; i < list.size(); i++) {
        Object key = getMemberKey(list.get(i));
        Map<ProgramElementDoc, String> memberLevelMap = memberNameMap.get(key);
        if (memberLevelMap == null) {
          memberLevelMap = new HashMap<ProgramElementDoc, String>();
          memberNameMap.put(key, memberLevelMap);
        }
        memberLevelMap.put(list.get(i), level);
      }
    }
  
    private void purgeMemberLevelMap(List<ProgramElementDoc> list, String level) {
      for (int i = 0; i < list.size(); i++) {
        Object key = getMemberKey(list.get(i));
        Map<ProgramElementDoc, String> memberLevelMap = memberNameMap.get(key);
        if (level.equals(memberLevelMap.get(list.get(i))))
          memberLevelMap.remove(list.get(i));
      }
    }
  
    /**
     * Represents a class member. We should be able to just use a
     * ProgramElementDoc instead of this class, but that doesn't take type
     * variables in consideration when comparing.
     */
    private class ClassMember {
      private Set<ProgramElementDoc> members;
  
      public ClassMember(ProgramElementDoc programElementDoc) {
  