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.ArrayList;
22import java.util.List;
23
24public class NavTree {
25
26  public static void writeNavTree(String dir) {
27    List<Node> children = new ArrayList<Node>();
28    for (PackageInfo pkg : Doclava.choosePackages()) {
29      children.add(makePackageNode(pkg));
30    }
31    Node node = new Node("Reference", dir + "packages.html", children, null);
32
33    StringBuilder buf = new StringBuilder();
34    if (false) {
35      // if you want a root node
36      buf.append("[");
37      node.render(buf);
38      buf.append("]");
39    } else {
40      // if you don't want a root node
41      node.renderChildren(buf);
42    }
43
44    Data data = Doclava.makeHDF();
45    data.setValue("reference_tree", buf.toString());
46    ClearPage.write(data, "navtree_data.cs", "navtree_data.js");
47  }
48
49  private static Node makePackageNode(PackageInfo pkg) {
50    List<Node> children = new ArrayList<Node>();
51
52    addClassNodes(children, "Interfaces", pkg.interfaces());
53    addClassNodes(children, "Classes", pkg.ordinaryClasses());
54    addClassNodes(children, "Enums", pkg.enums());
55    addClassNodes(children, "Exceptions", pkg.exceptions());
56    addClassNodes(children, "Errors", pkg.errors());
57
58    return new Node(pkg.name(), pkg.htmlPage(), children, pkg.getSince());
59  }
60
61  private static void addClassNodes(List<Node> parent, String label, ClassInfo[] classes) {
62    List<Node> children = new ArrayList<Node>();
63
64    for (ClassInfo cl : classes) {
65      if (cl.checkLevel()) {
66        children.add(new Node(cl.name(), cl.htmlPage(), null, cl.getSince()));
67      }
68    }
69
70    if (children.size() > 0) {
71      parent.add(new Node(label, null, children, null));
72    }
73  }
74
75  private static class Node {
76    private String mLabel;
77    private String mLink;
78    List<Node> mChildren;
79    private String mSince;
80
81    Node(String label, String link, List<Node> children, String since) {
82      mLabel = label;
83      mLink = link;
84      mChildren = children;
85      mSince = since;
86    }
87
88    static void renderString(StringBuilder buf, String s) {
89      if (s == null) {
90        buf.append("null");
91      } else {
92        buf.append('"');
93        final int N = s.length();
94        for (int i = 0; i < N; i++) {
95          char c = s.charAt(i);
96          if (c >= ' ' && c <= '~' && c != '"' && c != '\\') {
97            buf.append(c);
98          } else {
99            buf.append("\\u");
100            for (int j = 0; i < 4; i++) {
101              char x = (char) (c & 0x000f);
102              if (x > 10) {
103                x = (char) (x - 10 + 'a');
104              } else {
105                x = (char) (x + '0');
106              }
107              buf.append(x);
108              c >>= 4;
109            }
110          }
111        }
112        buf.append('"');
113      }
114    }
115
116    void renderChildren(StringBuilder buf) {
117      List<Node> list = mChildren;
118      if (list == null || list.size() == 0) {
119        // We output null for no children. That way empty lists here can just
120        // be a byproduct of how we generate the lists.
121        buf.append("null");
122      } else {
123        buf.append("[ ");
124        final int N = list.size();
125        for (int i = 0; i < N; i++) {
126          list.get(i).render(buf);
127          if (i != N - 1) {
128            buf.append(", ");
129          }
130        }
131        buf.append(" ]\n");
132      }
133    }
134
135    void render(StringBuilder buf) {
136      buf.append("[ ");
137      renderString(buf, mLabel);
138      buf.append(", ");
139      renderString(buf, mLink);
140      buf.append(", ");
141      renderChildren(buf);
142      buf.append(", ");
143      renderString(buf, mSince);
144      buf.append(" ]");
145    }
146  }
147}
148