1/*
2 * Copyright (C) 2010 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.google.doclava;
18
19import com.google.clearsilver.jsilver.data.Data;
20
21import java.util.HashMap;
22import java.util.TreeSet;
23import java.util.Set;
24
25public class Hierarchy {
26  public static void makeHierarchy(Data hdf, ClassInfo[] classes) {
27    HashMap<String, TreeSet<String>> nodes = new HashMap<String, TreeSet<String>>();
28
29    for (ClassInfo cl : classes) {
30      String name = cl.qualifiedName();
31
32      TreeSet<String> me = nodes.get(name);
33      if (me == null) {
34        me = new TreeSet<String>();
35        nodes.put(name, me);
36      }
37
38      ClassInfo superclass = cl.superclass();
39      String sname = superclass != null ? superclass.qualifiedName() : null;
40      if (sname != null) {
41        TreeSet<String> s = nodes.get(sname);
42        if (s == null) {
43          s = new TreeSet<String>();
44          nodes.put(sname, s);
45        }
46        s.add(name);
47      }
48    }
49
50    /*
51     * Set<String> keys = nodes.keySet(); for (String n: keys) { System.out.println("class: " + n);
52     *
53     * TreeSet<String> values = nodes.get(n); for (String v: values) {
54     * System.out.println("       - " + v); } }
55     */
56
57    int depth = depth(nodes, "java.lang.Object");
58
59    hdf.setValue("classes.0", "");
60    hdf.setValue("colspan", "" + depth);
61
62    recurse(nodes, "java.lang.Object", hdf.getChild("classes.0"), depth, depth);
63
64    if (false) {
65      Set<String> keys = nodes.keySet();
66      if (keys.size() > 0) {
67        System.err.println("The following classes are hidden but"
68            + " are superclasses of not-hidden classes");
69        for (String n : keys) {
70          System.err.println("  " + n);
71        }
72      }
73    }
74  }
75
76  private static int depth(HashMap<String, TreeSet<String>> nodes, String name) {
77    int d = 0;
78    TreeSet<String> derived = nodes.get(name);
79    if (derived != null && derived.size() > 0) {
80      for (String s : derived) {
81        int n = depth(nodes, s);
82        if (n > d) {
83          d = n;
84        }
85      }
86    }
87    return d + 1;
88  }
89
90  private static boolean exists(ClassInfo cl) {
91    return cl != null && !cl.isHiddenOrRemoved() && cl.isIncluded();
92  }
93
94  private static void recurse(HashMap<String, TreeSet<String>> nodes, String name, Data hdf,
95      int totalDepth, int remainingDepth) {
96    int i;
97
98    hdf.setValue("indent", "" + (totalDepth - remainingDepth - 1));
99    hdf.setValue("colspan", "" + remainingDepth);
100
101    ClassInfo cl = Converter.obtainClass(name);
102
103    hdf.setValue("class.label", cl.name());
104    hdf.setValue("class.qualified", cl.qualifiedName());
105    if (cl.checkLevel()) {
106      hdf.setValue("class.link", cl.htmlPage());
107    }
108
109    if (exists(cl)) {
110      hdf.setValue("exists", "1");
111    }
112
113    i = 0;
114    for (ClassInfo iface : cl.interfaces()) {
115      hdf.setValue("interfaces." + i + ".class.label", iface.name());
116      hdf.setValue("interfaces." + i + ".class.qualified", iface.qualifiedName());
117      if (iface.checkLevel()) {
118        hdf.setValue("interfaces." + i + ".class.link", iface.htmlPage());
119      }
120      if (exists(cl)) {
121        hdf.setValue("interfaces." + i + ".exists", "1");
122      }
123      i++;
124    }
125
126    TreeSet<String> derived = nodes.get(name);
127    if (derived != null && derived.size() > 0) {
128      hdf.setValue("derived", "");
129      Data children = hdf.getChild("derived");
130      i = 0;
131      remainingDepth--;
132      for (String s : derived) {
133        String index = "" + i;
134        children.setValue(index, "");
135        recurse(nodes, s, children.getChild(index), totalDepth, remainingDepth);
136        i++;
137      }
138    }
139
140    nodes.remove(name);
141  }
142}
143