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; 23import java.util.SortedMap; 24import java.util.TreeMap; 25 26public class NavTree { 27 28 public static void writeNavTree(String dir) { 29 List<Node> children = new ArrayList<Node>(); 30 for (PackageInfo pkg : Doclava.choosePackages()) { 31 children.add(makePackageNode(pkg)); 32 } 33 Node node = new Node("Reference", dir + "packages.html", children, null); 34 35 StringBuilder buf = new StringBuilder(); 36 if (false) { 37 // if you want a root node 38 buf.append("["); 39 node.render(buf); 40 buf.append("]"); 41 } else { 42 // if you don't want a root node 43 node.renderChildren(buf); 44 } 45 46 Data data = Doclava.makeHDF(); 47 data.setValue("reference_tree", buf.toString()); 48 ClearPage.write(data, "navtree_data.cs", "navtree_data.js"); 49 } 50 51 /** 52 * Write the YAML formatted navigation tree. 53 * @see "http://yaml.org/" 54 */ 55 public static void writeYamlTree(String dir, String fileName){ 56 Data data = Doclava.makeHDF(); 57 ClassInfo[] classes = Converter.rootClasses(); 58 59 SortedMap<String, Object> sorted = new TreeMap<String, Object>(); 60 for (ClassInfo cl : classes) { 61 if (cl.isHidden()) { 62 continue; 63 } 64 sorted.put(cl.qualifiedName(), cl); 65 66 PackageInfo pkg = cl.containingPackage(); 67 String name; 68 if (pkg == null) { 69 name = ""; 70 } else { 71 name = pkg.name(); 72 } 73 sorted.put(name, pkg); 74 } 75 76 data = makeYamlHDF(sorted, "docs.pages", data); 77 ClearPage.write(data, "yaml_navtree.cs", Doclava.ensureSlash(dir) + fileName); 78 } 79 80 public static Data makeYamlHDF(SortedMap<String, Object> sorted, String base, Data data) { 81 82 String key = "docs.pages."; 83 int i = 0; 84 for (String s : sorted.keySet()) { 85 Object o = sorted.get(s); 86 87 if (o instanceof PackageInfo) { 88 PackageInfo pkg = (PackageInfo) o; 89 90 data.setValue("docs.pages." + i + ".id", "" + i); 91 data.setValue("docs.pages." + i + ".label", pkg.name()); 92 data.setValue("docs.pages." + i + ".shortname", "API"); 93 data.setValue("docs.pages." + i + ".link", pkg.htmlPage()); 94 data.setValue("docs.pages." + i + ".type", "package"); 95 } else if (o instanceof ClassInfo) { 96 ClassInfo cl = (ClassInfo) o; 97 98 // skip classes that are the child of another class, recursion will handle those. 99 if (cl.containingClass() == null){ 100 101 data.setValue("docs.pages." + i + ".id", "" + i); 102 data = makeYamlHDF(cl, "docs.pages."+i, data); 103 } 104 } 105 106 i++; 107 } 108 return data; 109 } 110 111 public static Data makeYamlHDF(ClassInfo cl, String base, Data data) { 112 data.setValue(base + ".label", cl.name()); 113 data.setValue(base + ".shortname", cl.name().substring(cl.name().lastIndexOf(".")+1)); 114 data.setValue(base + ".link", cl.htmlPage()); 115 data.setValue(base + ".type", cl.kind()); 116 117 if (cl.innerClasses().size() > 0){ 118 int j = 0; 119 for (ClassInfo cl2 : cl.innerClasses()){ 120 data = makeYamlHDF(cl2, base + ".children." + j, data); 121 j++; 122 } 123 } 124 125 return data; 126 } 127 private static Node makePackageNode(PackageInfo pkg) { 128 List<Node> children = new ArrayList<Node>(); 129 130 addClassNodes(children, "Interfaces", pkg.interfaces()); 131 addClassNodes(children, "Classes", pkg.ordinaryClasses()); 132 addClassNodes(children, "Enums", pkg.enums()); 133 addClassNodes(children, "Exceptions", pkg.exceptions()); 134 addClassNodes(children, "Errors", pkg.errors()); 135 136 return new Node(pkg.name(), pkg.htmlPage(), children, pkg.getSince()); 137 } 138 139 private static void addClassNodes(List<Node> parent, String label, ClassInfo[] classes) { 140 List<Node> children = new ArrayList<Node>(); 141 142 for (ClassInfo cl : classes) { 143 if (cl.checkLevel()) { 144 children.add(new Node(cl.name(), cl.htmlPage(), null, cl.getSince())); 145 } 146 } 147 148 if (children.size() > 0) { 149 parent.add(new Node(label, null, children, null)); 150 } 151 } 152 153 private static class Node { 154 private String mLabel; 155 private String mLink; 156 List<Node> mChildren; 157 private String mSince; 158 159 Node(String label, String link, List<Node> children, String since) { 160 mLabel = label; 161 mLink = link; 162 mChildren = children; 163 mSince = since; 164 } 165 166 static void renderString(StringBuilder buf, String s) { 167 if (s == null) { 168 buf.append("null"); 169 } else { 170 buf.append('"'); 171 final int N = s.length(); 172 for (int i = 0; i < N; i++) { 173 char c = s.charAt(i); 174 if (c >= ' ' && c <= '~' && c != '"' && c != '\\') { 175 buf.append(c); 176 } else { 177 buf.append("\\u"); 178 for (int j = 0; i < 4; i++) { 179 char x = (char) (c & 0x000f); 180 if (x > 10) { 181 x = (char) (x - 10 + 'a'); 182 } else { 183 x = (char) (x + '0'); 184 } 185 buf.append(x); 186 c >>= 4; 187 } 188 } 189 } 190 buf.append('"'); 191 } 192 } 193 194 void renderChildren(StringBuilder buf) { 195 List<Node> list = mChildren; 196 if (list == null || list.size() == 0) { 197 // We output null for no children. That way empty lists here can just 198 // be a byproduct of how we generate the lists. 199 buf.append("null"); 200 } else { 201 buf.append("[ "); 202 final int N = list.size(); 203 for (int i = 0; i < N; i++) { 204 list.get(i).render(buf); 205 if (i != N - 1) { 206 buf.append(", "); 207 } 208 } 209 buf.append(" ]\n"); 210 } 211 } 212 213 void render(StringBuilder buf) { 214 buf.append("[ "); 215 renderString(buf, mLabel); 216 buf.append(", "); 217 renderString(buf, mLink); 218 buf.append(", "); 219 renderChildren(buf); 220 buf.append(", "); 221 renderString(buf, mSince); 222 buf.append(" ]"); 223 } 224 } 225} 226