blob: a0db8d9997add21be517ce719ce78bfb72e2d051 [file] [log] [blame]
Ben Dodson920dbbb2010-08-04 15:21:06 -07001/*
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;
Ben Dodson920dbbb2010-08-04 15:21:06 -070018import com.google.clearsilver.jsilver.data.Data;
19
20import java.util.*;
21import java.io.*;
Dirk Doughertye52f6d82013-09-04 17:27:29 -070022import java.util.regex.Pattern;
23import java.util.regex.Matcher;
Ben Dodson920dbbb2010-08-04 15:21:06 -070024
25public class SampleCode {
26 String mSource;
27 String mDest;
28 String mTitle;
Dirk Doughertyc11a4672013-08-23 19:14:10 -070029 String mProjectDir;
Dirk Dougherty25586c02013-08-30 16:21:15 -070030 String mTags;
Ben Dodson920dbbb2010-08-04 15:21:06 -070031
32 public SampleCode(String source, String dest, String title) {
33 mSource = source;
34 mTitle = title;
Dirk Dougherty25586c02013-08-30 16:21:15 -070035 mTags = null;
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -070036
Dirk Dougherty815f9342013-09-12 00:30:28 -070037 if (dest != null) {
38 int len = dest.length();
39 if (len > 1 && dest.charAt(len - 1) != '/') {
40 mDest = dest + '/';
41 } else {
42 mDest = dest;
43 }
Ben Dodson920dbbb2010-08-04 15:21:06 -070044 }
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -070045 //System.out.println("SampleCode init: source: " + mSource);
46 //System.out.println("SampleCode init: dest: " + mDest);
47 //System.out.println("SampleCode init: title: " + mTitle);
48
Ben Dodson920dbbb2010-08-04 15:21:06 -070049 }
50
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -070051 public Node write(boolean offlineMode) {
52 List<Node> filelist = new ArrayList<Node>();
Ben Dodson920dbbb2010-08-04 15:21:06 -070053 File f = new File(mSource);
Dirk Doughertyc11a4672013-08-23 19:14:10 -070054 mProjectDir = f.getName();
55 String name = mProjectDir;
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -070056 String startname = name;
57 String subdir = mDest;
58 String mOut = subdir + name;
Ben Dodson920dbbb2010-08-04 15:21:06 -070059 if (!f.isDirectory()) {
60 System.out.println("-samplecode not a directory: " + mSource);
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -070061 return null;
Ben Dodson920dbbb2010-08-04 15:21:06 -070062 }
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -070063
64 if (offlineMode)
65 writeIndexOnly(f, mDest, offlineMode);
66 else {
67 Data hdf = Doclava.makeHDF();
68 hdf.setValue("samples", "true");
Dirk Doughertyc11a4672013-08-23 19:14:10 -070069 hdf.setValue("projectDir", mProjectDir);
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -070070 writeProjectDirectory(filelist, f, mDest, false, hdf, "Files.");
Dirk Doughertyc11a4672013-08-23 19:14:10 -070071 writeProjectStructure(name, hdf);
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -070072 hdf.removeTree("parentdirs");
73 hdf.setValue("parentdirs.0.Name", name);
Dirk Doughertye52f6d82013-09-04 17:27:29 -070074 //Write root _index.jd to out and add metadata to Node.
Dirk Dougherty582c1d62013-09-13 19:45:17 -070075 Node rootNode = writeProjectIndexCs(hdf, f, null,
76 new Node.Builder().setLabel(mProjectDir).setLink("samples/"
77 + startname + "/index.html").setChildren(filelist).build());
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -070078 // return a root SC node for the sample with children appended
Dirk Doughertye52f6d82013-09-04 17:27:29 -070079 return rootNode;
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -070080 }
81 return null;
Ben Dodson920dbbb2010-08-04 15:21:06 -070082 }
83
84 public static String convertExtension(String s, String ext) {
85 return s.substring(0, s.lastIndexOf('.')) + ext;
86 }
87
88 public static String[] IMAGES = {".png", ".jpg", ".gif"};
Dirk Dougherty35427702013-11-18 15:22:01 -080089 public static String[] VIDEOS = {".mp4", ".ogv", ".webm"};
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -070090 public static String[] TEMPLATED = {".java", ".xml", ".aidl", ".rs",".txt", ".TXT"};
Ben Dodson920dbbb2010-08-04 15:21:06 -070091
92 public static boolean inList(String s, String[] list) {
93 for (String t : list) {
94 if (s.endsWith(t)) {
95 return true;
96 }
97 }
98 return false;
99 }
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -0700100
101 public static String mapTypes(String name) {
102 String type = name.substring(name.lastIndexOf('.') + 1, name.length());
103 if (type.equals("xml") || type.equals("java")) {
104 if (name.equals("AndroidManifest.xml")) type = "manifest";
105 return type;
106 } else {
107 return type = "file";
108 }
109 }
110
111 public void writeProjectDirectory(List<Node> parent, File dir, String relative, Boolean recursed, Data hdf, String newkey) {
112 TreeSet<String> dirs = new TreeSet<String>(); //dirs for project structure and breadcrumb
113 TreeSet<String> files = new TreeSet<String>(); //files for project structure and breadcrumb
114
115 String subdir = relative;
116 String name = "";
117 String label = "";
118 String link = "";
119 String type = "";
120 int i = 0;
121 String expansion = ".Sub.";
122 String key = newkey;
Dirk Dougherty35427702013-11-18 15:22:01 -0800123 double maxFileSizeBytes = 2097152; //Max size for browseable images/video
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -0700124
125 if (recursed) {
126 key = (key + expansion);
127 } else {
128 expansion = "";
129 }
130
Dirk Doughertyc11a4672013-08-23 19:14:10 -0700131 File[] dirContents = dir.listFiles();
132 Arrays.sort(dirContents, byTypeAndName);
133 for (File f: dirContents) {
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -0700134 name = f.getName();
135 // don't process certain types of files
136 if (name.startsWith(".") ||
137 name.startsWith("_") ||
138 name.equals("default.properties") ||
139 name.equals("build.properties") ||
140 name.endsWith(".ttf") ||
Dirk Doughertye52f6d82013-09-04 17:27:29 -0700141 name.endsWith(".gradle") ||
142 name.endsWith(".bat") ||
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -0700143 name.equals("Android.mk")) {
144 //System.out.println("Invalid File Type, bypassing: " + name);
145 continue;
146 }
147 if (f.isFile() && name.contains(".")){
148 String path = relative + name;
149 type = mapTypes(name);
150 link = convertExtension(path, ".html");
151 hdf.setValue("samples", "true");//dd needed?
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -0700152 if (inList(path, IMAGES)) {
153 // copy these files to output directly
154 type = "img";
Dirk Dougherty35427702013-11-18 15:22:01 -0800155 if (f.length() < maxFileSizeBytes) {
156 ClearPage.copyFile(false, f, path);
157 writeImageVideoPage(f, convertExtension(path, Doclava.htmlExtension),
158 relative, type, true);
159 } else {
160 //too large for browsing, skip copying and show generic icon
161 writeImageVideoPage(f, convertExtension(path, Doclava.htmlExtension),
162 relative, type, false);
163 }
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -0700164 files.add(name);
165 hdf.setValue(key + i + ".Type", "img");
166 hdf.setValue(key + i + ".Name", name);
167 hdf.setValue(key + i + ".Href", link);
Dirk Dougherty25586c02013-08-30 16:21:15 -0700168 hdf.setValue(key + i + ".RelPath", relative);
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -0700169 }
Dirk Dougherty35427702013-11-18 15:22:01 -0800170 if (inList(path, VIDEOS)) {
171 // copy these files to output directly
172 type = "video";
173 if (f.length() < maxFileSizeBytes) {
174 ClearPage.copyFile(false, f, path);
175 writeImageVideoPage(f, convertExtension(path, Doclava.htmlExtension),
176 relative, type, true);
177 } else {
178 //too large for browsing, skip copying and show generic icon
179 writeImageVideoPage(f, convertExtension(path, Doclava.htmlExtension),
180 relative, type, false);
181 }
182 files.add(name);
183 hdf.setValue(key + i + ".Type", "video");
184 hdf.setValue(key + i + ".Name", name);
185 hdf.setValue(key + i + ".Href", link);
186 hdf.setValue(key + i + ".RelPath", relative);
187 }
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -0700188 if (inList(path, TEMPLATED)) {
189 // copied and goes through the template
190 ClearPage.copyFile(false, f, path);
191 writePage(f, convertExtension(path, Doclava.htmlExtension), relative);
192 files.add(name);
193 hdf.setValue(key + i + ".Type", type);
194 hdf.setValue(key + i + ".Name", name);
195 hdf.setValue(key + i + ".Href", link);
Dirk Dougherty25586c02013-08-30 16:21:15 -0700196 hdf.setValue(key + i + ".RelPath", relative);
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -0700197 }
198 // add file to the navtree
Dirk Dougherty582c1d62013-09-13 19:45:17 -0700199 parent.add(new Node.Builder().setLabel(name).setLink(link).setType(type).build());
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -0700200 i++;
201 } else if (f.isDirectory()) {
202 List<Node> mchildren = new ArrayList<Node>();
203 type = "dir";
204 String dirpath = relative + name;
205 link = dirpath + "/index.html";
206 String hdfkeyName = (key + i + ".Name");
207 String hdfkeyType = (key + i + ".Type");
208 String hdfkeyHref = (key + i + ".Href");
209 hdf.setValue(hdfkeyName, name);
210 hdf.setValue(hdfkeyType, type);
211 hdf.setValue(hdfkeyHref, relative + name + "/" + "index.html");
212 //System.out.println("Found directory, recursing. Current key: " + hdfkeyName);
213 writeProjectDirectory(mchildren, f, relative + name + "/", true, hdf, (key + i));
214 if (mchildren.size() > 0) {
215 //dir is processed, now add it to the navtree
Dirk Doughertyc11a4672013-08-23 19:14:10 -0700216 //don't link sidenav subdirs at this point (but can use "link" to do so)
Dirk Dougherty582c1d62013-09-13 19:45:17 -0700217 parent.add(new Node.Builder().setLabel(name).setChildren(mchildren).setType(type).build());
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -0700218 }
Dirk Doughertyc11a4672013-08-23 19:14:10 -0700219 dirs.add(name);
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -0700220 i++;
221 }
Dirk Dougherty25586c02013-08-30 16:21:15 -0700222
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -0700223 }
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -0700224 //If this is an index for the project root (assumed root if split length is 3 (development/samples/nn)),
225 //then remove the root dir so that it won't appear in the breadcrumb. Else just pass it through to
226 //setParentDirs as usual.
227 String mpath = dir + "";
228 String sdir[] = mpath.split("/");
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -0700229 setParentDirs(hdf, relative, name, false);
Dirk Doughertye52f6d82013-09-04 17:27:29 -0700230 //Generate an index.html page for each dir being processed
231 ClearPage.write(hdf, "sampleindex.cs", relative + "/index" + Doclava.htmlExtension);
232 //concatenate dirs in the navtree. Comment out or remove to restore normal navtree
Dirk Dougherty25586c02013-08-30 16:21:15 -0700233 squashNodes(parent);
Scott Maine27c9502011-01-19 14:07:39 -0800234 }
235
Dirk Doughertyc11a4672013-08-23 19:14:10 -0700236 public void writeProjectStructure(String dir, Data hdf) {
237 //System.out.println(">>-- writing project structure for " + dir );
238 hdf.setValue("projectStructure", "true");
239 hdf.setValue("projectDir", mProjectDir);
240 hdf.setValue("page.title", mProjectDir + " Structure");
241 hdf.setValue("projectTitle", mTitle);
Dirk Doughertye52f6d82013-09-04 17:27:29 -0700242 //write the project.html file
243 ClearPage.write(hdf, "sampleindex.cs", mDest + "project" + Doclava.htmlExtension);
Dirk Doughertyc11a4672013-08-23 19:14:10 -0700244 hdf.setValue("projectStructure", "");
Ben Dodson920dbbb2010-08-04 15:21:06 -0700245 }
246
Dirk Doughertyc11a4672013-08-23 19:14:10 -0700247 /**
Dirk Doughertye52f6d82013-09-04 17:27:29 -0700248 * Processes a templated project index page from _index.jd in a project root.
249 * Each sample project must have an index, and each index locally defines it's own
250 * page.tags and sample.group cs vars. This method takes a SC node on input, reads
251 * any local vars from the _index.jd, generates an html file to out, then updates
252 * the SC node with the page vars and returns it to the caller.
253 *
Dirk Doughertyc11a4672013-08-23 19:14:10 -0700254 */
Dirk Doughertye52f6d82013-09-04 17:27:29 -0700255 public Node writeProjectIndexCs(Data hdf, File dir, String key, Node tnode) {
256 //hdf.setValue("summary", "");
257 //hdf.setValue("summaryFlag", "");
258 String filename = dir.getAbsolutePath() + "/_index.jd";
259 File f = new File(filename);
260 String rel = dir.getPath();
261 String mGroup = "";
262 hdf.setValue("samples", "true");
263 //set any default page variables for root index
264 hdf.setValue("page.title", mProjectDir);
Dirk Dougherty25586c02013-08-30 16:21:15 -0700265 hdf.setValue("projectDir", mProjectDir);
Dirk Dougherty25586c02013-08-30 16:21:15 -0700266 hdf.setValue("projectTitle", mTitle);
Dirk Dougherty35427702013-11-18 15:22:01 -0800267 //add the download/project links to the landing pages.
268 hdf.setValue("samplesProjectIndex", "true");
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -0700269
Dirk Doughertye52f6d82013-09-04 17:27:29 -0700270 if (!f.isFile()) {
271 //The sample didn't have any _index.jd, so create a stub.
272 ClearPage.write(hdf, "sampleindex.cs", mDest + "index" + Doclava.htmlExtension);
273 //Errors.error(Errors.INVALID_SAMPLE_INDEX, null, "Sample " + mProjectDir
274 // + ": Root _index.jd must be present and must define sample.group"
275 // + " tag. Please see ... for details.");
276 } else {
277 DocFile.writePage(filename, rel, mDest + "index" + Doclava.htmlExtension, hdf);
Dirk Dougherty582c1d62013-09-13 19:45:17 -0700278 PageMetadata.setPageMetadata(f, rel, mDest + "index" + Doclava.htmlExtension, hdf, Doclava.sTaglist);
Dirk Doughertye52f6d82013-09-04 17:27:29 -0700279 tnode.setTags(hdf.getValue("page.tags", ""));
280 mGroup = hdf.getValue("sample.group", "");
281 if (mGroup.equals("")) {
282 //Errors.error(Errors.INVALID_SAMPLE_INDEX, null, "Sample " + mProjectDir
283 // + ": Root _index.jd must be present and must define sample.group"
284 // + " tag. Please see ... for details.");
285 } else {
286 tnode.setGroup(hdf.getValue("sample.group", ""));
287 }
288 }
289 return tnode;
Dirk Doughertyc11a4672013-08-23 19:14:10 -0700290 }
Ben Dodson920dbbb2010-08-04 15:21:06 -0700291
Dirk Doughertyc11a4672013-08-23 19:14:10 -0700292 /**
293 * Keep track of file parents
294 */
295 Data setParentDirs(Data hdf, String subdir, String name, Boolean isFile) {
Dirk Doughertye52f6d82013-09-04 17:27:29 -0700296 //set whether to linkify the crumb dirs on each sample code page
297 hdf.setValue("pathCrumbLinks", "");
298 //isFile = false;
Dirk Doughertyc11a4672013-08-23 19:14:10 -0700299 int iter;
300 hdf.removeTree("parentdirs");
Dirk Doughertyc11a4672013-08-23 19:14:10 -0700301 String s = subdir;
302 String urlParts[] = s.split("/");
Dirk Doughertye52f6d82013-09-04 17:27:29 -0700303 //int n, l = (isFile)?1:0;
304 int n, l = 1;
305 //System.out.println("setParentDirs for " + subdir + name);
306 for (iter=1; iter < urlParts.length; iter++) {
307 n = iter-1;
Dirk Doughertyc11a4672013-08-23 19:14:10 -0700308 //System.out.println("parentdirs." + n + ".Name == " + urlParts[iter]);
309 hdf.setValue("parentdirs." + n + ".Name", urlParts[iter]);
Dirk Doughertye52f6d82013-09-04 17:27:29 -0700310 hdf.setValue("parentdirs." + n + ".Link", subdir + "index" + Doclava.htmlExtension);
Ben Dodson920dbbb2010-08-04 15:21:06 -0700311 }
Ben Dodson920dbbb2010-08-04 15:21:06 -0700312 return hdf;
313 }
314
Dirk Doughertyc11a4672013-08-23 19:14:10 -0700315 /**
316 * Write a templated source code file to out.
317 */
Ben Dodson920dbbb2010-08-04 15:21:06 -0700318 public void writePage(File f, String out, String subdir) {
319 String name = f.getName();
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -0700320 String path = f.getPath();
Ben Dodson920dbbb2010-08-04 15:21:06 -0700321 String data =
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -0700322 SampleTagInfo.readFile(new SourcePositionInfo(path, -1, -1), path, "sample code",
323 true, true, true, true);
Ben Dodson920dbbb2010-08-04 15:21:06 -0700324 data = Doclava.escape(data);
325
326 Data hdf = Doclava.makeHDF();
Dirk Dougherty25586c02013-08-30 16:21:15 -0700327
328 String relative = subdir.replaceFirst("samples/", "");
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -0700329 hdf.setValue("samples", "true");
330 setParentDirs(hdf, subdir, name, true);
331 hdf.setValue("projectTitle", mTitle);
Dirk Doughertyc11a4672013-08-23 19:14:10 -0700332 hdf.setValue("projectDir", mProjectDir);
Ben Dodson920dbbb2010-08-04 15:21:06 -0700333 hdf.setValue("page.title", name);
334 hdf.setValue("subdir", subdir);
Dirk Dougherty25586c02013-08-30 16:21:15 -0700335 hdf.setValue("relative", relative);
Ben Dodson920dbbb2010-08-04 15:21:06 -0700336 hdf.setValue("realFile", name);
337 hdf.setValue("fileContents", data);
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -0700338 hdf.setValue("resTag", "sample");
339 hdf.setValue("resType", "Sample Code");
Ben Dodson920dbbb2010-08-04 15:21:06 -0700340
341 ClearPage.write(hdf, "sample.cs", out);
342 }
343
Dirk Doughertyc11a4672013-08-23 19:14:10 -0700344 /**
Dirk Dougherty35427702013-11-18 15:22:01 -0800345 * Write a templated image or video file to out.
Dirk Doughertyc11a4672013-08-23 19:14:10 -0700346 */
Dirk Dougherty35427702013-11-18 15:22:01 -0800347 public void writeImageVideoPage(File f, String out, String subdir,
348 String resourceType, boolean browsable) {
Ben Dodson920dbbb2010-08-04 15:21:06 -0700349 Data hdf = Doclava.makeHDF();
Dirk Dougherty35427702013-11-18 15:22:01 -0800350 String name = f.getName();
351 if (!browsable) {
352 hdf.setValue("noDisplay", "true");
353 }
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -0700354 setParentDirs(hdf, subdir, name, true);
Dirk Dougherty35427702013-11-18 15:22:01 -0800355 hdf.setValue("samples", "true");
Ben Dodson920dbbb2010-08-04 15:21:06 -0700356 hdf.setValue("page.title", name);
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -0700357 hdf.setValue("projectTitle", mTitle);
Dirk Doughertyc11a4672013-08-23 19:14:10 -0700358 hdf.setValue("projectDir", mProjectDir);
Ben Dodson920dbbb2010-08-04 15:21:06 -0700359 hdf.setValue("subdir", subdir);
Dirk Dougherty35427702013-11-18 15:22:01 -0800360 hdf.setValue("resType", resourceType);
Ben Dodson920dbbb2010-08-04 15:21:06 -0700361 hdf.setValue("realFile", name);
Ben Dodson920dbbb2010-08-04 15:21:06 -0700362 ClearPage.write(hdf, "sample.cs", out);
363 }
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -0700364
365 /**
Dirk Dougherty582c1d62013-09-13 19:45:17 -0700366 * Render a SC node tree to a navtree js file.
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -0700367 */
Dirk Dougherty815f9342013-09-12 00:30:28 -0700368 public static void writeSamplesNavTree(List<Node> tnode, List<Node> groupnodes) {
369
Dirk Dougherty582c1d62013-09-13 19:45:17 -0700370 Node node = new
371 Node.Builder().setLabel("Reference").setLink("packages.html").setChildren(tnode).build();
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -0700372
Dirk Dougherty815f9342013-09-12 00:30:28 -0700373 if (groupnodes != null) {
374 for (int i = 0; i < tnode.size(); i++) {
375 groupnodes = appendNodeGroups(tnode.get(i), groupnodes);
376 }
Dirk Dougherty1d8fa8d2013-09-12 19:01:02 -0700377 for (int n = 0; n < groupnodes.size(); n++) {
378 if (groupnodes.get(n).getChildren() == null) {
379 groupnodes.remove(n);
380 n--;
381 }
382 }
Dirk Dougherty815f9342013-09-12 00:30:28 -0700383 node.setChildren(groupnodes);
384 }
385
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -0700386 StringBuilder buf = new StringBuilder();
387 if (false) {
388 // if you want a root node
389 buf.append("[");
390 node.render(buf);
391 buf.append("]");
392 } else {
393 // if you don't want a root node
394 node.renderChildren(buf);
395 }
396
397 Data data = Doclava.makeHDF();
398 data.setValue("reference_tree", buf.toString());
399 ClearPage.write(data, "samples_navtree_data.cs", "samples_navtree_data.js");
400 }
401
Dirk Dougherty25586c02013-08-30 16:21:15 -0700402 /**
Dirk Dougherty1d8fa8d2013-09-12 19:01:02 -0700403 * For a given project root node, get the group and then iterate the list of valid
404 * groups looking for a match. If found, append the project to that group node.
Dirk Dougherty582c1d62013-09-13 19:45:17 -0700405 * Samples that reference a valid sample group tag are added to a list for that
Dirk Dougherty1d8fa8d2013-09-12 19:01:02 -0700406 * group. Samples declare a sample.group tag in their _index.jd files.
Dirk Dougherty815f9342013-09-12 00:30:28 -0700407 */
408 private static List<Node> appendNodeGroups(Node gNode, List<Node> groupnodes) {
409 List<Node> mgrouplist = new ArrayList<Node>();
Dirk Dougherty1d8fa8d2013-09-12 19:01:02 -0700410 for (int i = 0; i < groupnodes.size(); i++) {
Dirk Dougherty815f9342013-09-12 00:30:28 -0700411 if (groupnodes.get(i).getLabel().equals(gNode.getGroup())) {
412 if (groupnodes.get(i).getChildren() == null) {
Dirk Dougherty1d8fa8d2013-09-12 19:01:02 -0700413 mgrouplist.add(gNode);
Dirk Dougherty815f9342013-09-12 00:30:28 -0700414 groupnodes.get(i).setChildren(mgrouplist);
Dirk Dougherty1d8fa8d2013-09-12 19:01:02 -0700415 } else {
416 groupnodes.get(i).getChildren().add(gNode);
Dirk Dougherty815f9342013-09-12 00:30:28 -0700417 }
Dirk Dougherty815f9342013-09-12 00:30:28 -0700418 break;
Dirk Dougherty1d8fa8d2013-09-12 19:01:02 -0700419 }
Dirk Dougherty815f9342013-09-12 00:30:28 -0700420 }
421 return groupnodes;
422 }
423
424 /**
Dirk Dougherty25586c02013-08-30 16:21:15 -0700425 * Sort by type and name (alpha), with manifest and src always at top.
426 */
Dirk Doughertyc11a4672013-08-23 19:14:10 -0700427 Comparator<File> byTypeAndName = new Comparator<File>() {
428 public int compare (File one, File other) {
429 if (one.isDirectory() && !other.isDirectory()) {
430 return 1;
431 } else if (!one.isDirectory() && other.isDirectory()) {
432 return -1;
Dirk Dougherty25586c02013-08-30 16:21:15 -0700433 } else if (one.getName().equals("AndroidManifest.xml")) {
434 return -1;
Dirk Doughertyc11a4672013-08-23 19:14:10 -0700435 } else {
436 return one.compareTo(other);
437 }
438 }
439 };
440
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -0700441 /**
Dirk Dougherty25586c02013-08-30 16:21:15 -0700442 * Concatenate dirs that only hold dirs to simplify nav tree
443 */
Dirk Dougherty815f9342013-09-12 00:30:28 -0700444 public static List<Node> squashNodes(List<Node> tnode) {
Dirk Dougherty25586c02013-08-30 16:21:15 -0700445 List<Node> list = tnode;
446
447 for(int i = 0; i < list.size(); ++i) {
448 //only squash dirs that contain another dir whose list size is 1 and
449 //that don't contain endpoints
450 if ((list.get(i).getType().equals("dir")) &&
451 (list.size() == 1) &&
452 (list.get(i).getChildren().get(0).getChildren() != null)) {
453 String thisLabel = list.get(i).getLabel();
454 String childLabel = list.get(i).getChildren().get(0).getLabel();
455 String newLabel = thisLabel + "/" + childLabel;
456 //Set label of parent and mChildren to those of child-child, skipping
457 //squashed dir
458 list.get(i).setLabel(newLabel);
459 list.get(i).setChildren(list.get(i).getChildren().get(0).getChildren());
460 } else {
461 continue;
462 }
463 }
464 return list;
465 }
466
467 /**
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -0700468 * SampleCode variant of NavTree node.
469 */
470 public static class Node {
471 private String mLabel;
472 private String mLink;
Dirk Doughertye52f6d82013-09-04 17:27:29 -0700473 private String mGroup; // from sample.group in _index.jd
474 private List<String> mTags; // from page.tags in _index.jd
Dirk Dougherty25586c02013-08-30 16:21:15 -0700475 private List<Node> mChildren;
476 private String mType;
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -0700477
Dirk Dougherty582c1d62013-09-13 19:45:17 -0700478 private Node(Builder builder) {
479 mLabel = builder.mLabel;
480 mLink = builder.mLink;
481 mGroup = builder.mGroup;
482 mTags = builder.mTags;
483 mChildren = builder.mChildren;
484 mType = builder.mType;
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -0700485 }
486
Dirk Dougherty582c1d62013-09-13 19:45:17 -0700487 public static class Builder {
488 private String mLabel, mLink, mGroup, mType;
489 private List<String> mTags = null;
490 private List<Node> mChildren = null;
491 public Builder setLabel(String mLabel) { this.mLabel = mLabel; return this;}
492 public Builder setLink(String mLink) { this.mLink = mLink; return this;}
493 public Builder setGroup(String mGroup) { this.mGroup = mGroup; return this;}
494 public Builder setTags(List<String> mTags) { this.mTags = mTags; return this;}
495 public Builder setChildren(List<Node> mChildren) { this.mChildren = mChildren; return this;}
496 public Builder setType(String mType) { this.mType = mType; return this;}
497 public Node build() {return new Node(this);}
498 }
499
500 public Node(String mLabel,
501 String mLink,
502 String mGroup,
503 List<String> mTags,
504 List<Node> mChildren,
505 String mType) {
506 this.mLabel = mLabel;
507 this.mLink = mLink;
508 this.mGroup = mGroup;
509 this.mTags = mTags;
510 this.mChildren = mChildren;
511 this.mType = mType; }
512
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -0700513 static void renderString(StringBuilder buf, String s) {
514 if (s == null) {
515 buf.append("null");
516 } else {
517 buf.append('"');
518 final int N = s.length();
519 for (int i = 0; i < N; i++) {
520 char c = s.charAt(i);
521 if (c >= ' ' && c <= '~' && c != '"' && c != '\\') {
522 buf.append(c);
523 } else {
524 buf.append("\\u");
525 for (int j = 0; i < 4; i++) {
526 char x = (char) (c & 0x000f);
527 if (x > 10) {
528 x = (char) (x - 10 + 'a');
529 } else {
530 x = (char) (x + '0');
531 }
532 buf.append(x);
533 c >>= 4;
534 }
535 }
536 }
537 buf.append('"');
538 }
539 }
540
541 void renderChildren(StringBuilder buf) {
542 List<Node> list = mChildren;
543 if (list == null || list.size() == 0) {
544 // We output null for no children. That way empty lists here can just
545 // be a byproduct of how we generate the lists.
546 buf.append("null");
547 } else {
548 buf.append("[ ");
549 final int N = list.size();
550 for (int i = 0; i < N; i++) {
551 list.get(i).render(buf);
552 if (i != N - 1) {
553 buf.append(", ");
554 }
555 }
556 buf.append(" ]\n");
557 }
558 }
559
Dirk Doughertye52f6d82013-09-04 17:27:29 -0700560 void renderTags(StringBuilder buf) {
561 List<String> list = mTags;
562 if (list == null || list.size() == 0) {
563 buf.append("null");
564 } else {
565 buf.append("[ ");
566 final int N = list.size();
567 for (int i = 0; i < N; i++) {
568 String tagval = list.get(i).toString();
569 buf.append('"');
570 final int L = tagval.length();
571 for (int t = 0; t < L; t++) {
572 char c = tagval.charAt(t);
573 if (c >= ' ' && c <= '~' && c != '"' && c != '\\') {
574 buf.append(c);
575 } else {
576 buf.append("\\u");
577 for (int m = 0; m < 4; m++) {
578 char x = (char) (c & 0x000f);
579 if (x > 10) {
580 x = (char) (x - 10 + 'a');
581 } else {
582 x = (char) (x + '0');
583 }
584 buf.append(x);
585 c >>= 4;
586 }
587 }
588 }
589 buf.append('"');
590 if (i != N - 1) {
591 buf.append(", ");
592 }
593 }
594 buf.append(" ]");
595 }
596 }
597
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -0700598 void render(StringBuilder buf) {
599 buf.append("[ ");
600 renderString(buf, mLabel);
601 buf.append(", ");
602 renderString(buf, mLink);
603 buf.append(", ");
Dirk Doughertye52f6d82013-09-04 17:27:29 -0700604 renderString(buf, mGroup);
605 buf.append(", ");
606 renderTags(buf);
607 buf.append(", ");
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -0700608 renderChildren(buf);
609 buf.append(", ");
610 renderString(buf, mType);
611 buf.append(" ]");
612 }
Dirk Dougherty25586c02013-08-30 16:21:15 -0700613
614 public List<Node> getChildren() {
615 if (mChildren != null) {
616 return mChildren;
617 } else {
618 return null;
619 }
620 }
621
622 public void setChildren(List<Node> node) {
623 mChildren = node;
624 }
625
626 public String getLabel() {
627 return mLabel;
628 }
629
630 public void setLabel(String label) {
631 mLabel = label;
632 }
633
634 public String getType() {
635 return mType.toString();
636 }
637
638 public String getHref() {
639 return mLink;
640 }
641
642 public void setHref(String link) {
643 mLink = link;
644 }
Dirk Doughertye52f6d82013-09-04 17:27:29 -0700645
Dirk Dougherty815f9342013-09-12 00:30:28 -0700646 public String getGroup() {
647 return mGroup;
Dirk Doughertye52f6d82013-09-04 17:27:29 -0700648 }
649
Dirk Dougherty815f9342013-09-12 00:30:28 -0700650 public void setGroup(String group) {
651 mGroup = group;
Dirk Doughertye52f6d82013-09-04 17:27:29 -0700652 }
653
654 public void setTags(String tags) {
655 List<String> tagList = new ArrayList();
656 String[] tagParts = tags.split(",");
657
658 for (int iter = 0; iter < tagParts.length; iter++) {
659 String item = tagParts[iter].replaceAll("\"", "").trim();
660 tagList.add(item);
661 }
662 mTags = tagList;
663 }
664 }
665
666 /**
667 * Write the project's templated _index.html
668 * @deprecated
669 *
670 */
671 public void writeProjectIndex(Data hdf) {
672 //System.out.println(">>-- writing project index for " + mDest );
673 hdf.setValue("projectDir", mProjectDir);
674 hdf.setValue("page.title", mProjectDir + " Sample");
675 hdf.setValue("projectTitle", mTitle);
676 ClearPage.write(hdf, "sampleindex.cs", mDest + "index" + Doclava.htmlExtension);
677 }
678
679 /**
680 * Grab the contents of an _index.html summary from a dir.
681 * @deprecated
682 */
683 public void getSummaryFromDir(Data hdf, File dir, String key) {
684 //System.out.println("Getting summary for " + dir + "/_index.html");
685 hdf.setValue("summary", "");
686 hdf.setValue("summaryFlag", "");
687 String filename = dir.getPath() + "/_index.html";
688 String summary = SampleTagInfo.readFile(new SourcePositionInfo(filename,
689 -1,-1), filename, "sample code", true, false, false, true);
690 if (summary != null) {
691 hdf.setValue(key + "SummaryFlag", "true");
692 hdf.setValue("summary", summary);
693 //set the target for [info] link
694 //hdf.setValue(key + "Href", dir + "/index.html");
695 //return true;
696 }
Dirk Dougherty1b45d1d2010-08-17 17:25:36 -0700697 }
698
Dirk Doughertyc11a4672013-08-23 19:14:10 -0700699 /**
700 * @deprecated
701 */
702 public void writeDirectory(File dir, String relative, boolean offline) {
703 TreeSet<String> dirs = new TreeSet<String>();
704 TreeSet<String> files = new TreeSet<String>();
705
706 String subdir = relative; // .substring(mDest.length());
707
708 for (File f : dir.listFiles()) {
709 String name = f.getName();
710 if (name.startsWith(".") || name.startsWith("_")) {
711 continue;
712 }
713 if (f.isFile()) {
714 String out = relative + name;
715 if (inList(out, IMAGES)) {
716 // copied directly
717 ClearPage.copyFile(false, f, out);
718 writeImagePage(f, convertExtension(out, Doclava.htmlExtension), subdir);
719 files.add(name);
720 }
721 if (inList(out, TEMPLATED)) {
722 // copied and goes through the template
723 ClearPage.copyFile(false, f, out);
724 writePage(f, convertExtension(out, Doclava.htmlExtension), subdir);
725 files.add(name);
726
727 }
728 // else ignored
729 } else if (f.isDirectory()) {
730 writeDirectory(f, relative + name + "/", offline);
731 dirs.add(name);
732 }
733 }
734
735 // write the index page
736 int i;
737
738 Data hdf = writeIndex(dir);
739 hdf.setValue("subdir", subdir);
740 i = 0;
741 for (String d : dirs) {
742 hdf.setValue("subdirs." + i + ".Name", d);
743 hdf.setValue("files." + i + ".Href", convertExtension(d, ".html"));
744 i++;
745 }
746 i = 0;
747 for (String f : files) {
748 hdf.setValue("files." + i + ".Name", f);
749 hdf.setValue("files." + i + ".Href", convertExtension(f, ".html"));
750 i++;
751 }
752
753 if (!offline) relative = "/" + relative;
754 ClearPage.write(hdf, "sampleindex.cs", relative + "index" + Doclava.htmlExtension);
755 }
756
757 /**
758 * @deprecated
759 */
760 public void writeIndexOnly(File dir, String relative, Boolean offline) {
761 Data hdf = writeIndex(dir);
762 if (!offline) relative = "/" + relative;
763
764 System.out.println("writing indexonly at " + relative + "/index" + Doclava.htmlExtension);
765 ClearPage.write(hdf, "sampleindex.cs", relative + "index" + Doclava.htmlExtension);
766 }
767
768 /**
769 * @deprecated
770 */
771 public Data writeIndex(File dir) {
772 Data hdf = Doclava.makeHDF();
773 hdf.setValue("page.title", dir.getName() + " - " + mTitle);
774 hdf.setValue("projectTitle", mTitle);
775
776 String filename = dir.getPath() + "/_index.html";
777 String summary =
778 SampleTagInfo.readFile(new SourcePositionInfo(filename, -1, -1), filename, "sample code",
779 true, false, false, true);
780
781 if (summary == null) {
782 summary = "";
783 }
784 hdf.setValue("summary", summary);
785
786 return hdf;
787 }
788
Dirk Dougherty35427702013-11-18 15:22:01 -0800789 /**
790 * @deprecated
791 */
792 public void writeImagePage(File f, String out, String subdir) {
793 Data hdf = Doclava.makeHDF();
794 String name = f.getName();
795
796 hdf.setValue("samples", "true");
797 setParentDirs(hdf, subdir, name, true);
798 hdf.setValue("page.title", name);
799 hdf.setValue("projectTitle", mTitle);
800 hdf.setValue("projectDir", mProjectDir);
801 hdf.setValue("subdir", subdir);
802 hdf.setValue("realFile", name);
803 hdf.setValue("resTag", "sample");
804 hdf.setValue("resType", "sampleImage");
805 ClearPage.write(hdf, "sample.cs", out);
806 }
Ben Dodson920dbbb2010-08-04 15:21:06 -0700807}