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 
17 package com.google.doclava;
18 
19 import com.google.clearsilver.jsilver.data.Data;
20 
21 import java.io.*;
22 import java.util.regex.Pattern;
23 import java.util.regex.Matcher;
24 
25 
26 public class DocFile {
27   public static final Pattern LINE = Pattern.compile("(.*)[\r]?\n", Pattern.MULTILINE);
28   public static final Pattern PROP = Pattern.compile("([^=]+)=(.*)");
29 
readFile(String filename)30   public static String readFile(String filename) {
31     try {
32       File f = new File(filename);
33       int length = (int) f.length();
34       FileInputStream is = new FileInputStream(f);
35       InputStreamReader reader = new InputStreamReader(is, "UTF-8");
36       char[] buf = new char[length];
37       int index = 0;
38       int amt;
39       while (true) {
40         amt = reader.read(buf, index, length - index);
41 
42         if (amt < 1) {
43           break;
44         }
45 
46         index += amt;
47       }
48       return new String(buf, 0, index);
49     } catch (IOException e) {
50       return null;
51     }
52   }
53 
54   public static String[] DEVSITE_VALID_LANGS = {"en", "es","ja", "ko",
55       "ru", "zh-cn", "zh-tw", "pt-br"};
56 
getPathRoot(String filename)57   public static String getPathRoot(String filename) {
58     //look for a valid lang string in the file path. If found,
59     //snip the intl/lang from the path.
60     for (String t : DEVSITE_VALID_LANGS) {
61       int langStart = filename.indexOf("/" + t + "/");
62       if (langStart > -1) {
63         int langEnd = filename.indexOf("/", langStart + 1);
64         filename = filename.substring(langEnd + 1);
65         break;
66       }
67     }
68     return filename;
69   }
70 
getPageMetadata(String docfile, Data hdf)71   public static Data getPageMetadata (String docfile, Data hdf) {
72     //utility method for extracting metadata without generating file output.
73     if (hdf == null) {
74       hdf = Doclava.makeHDF();
75     }
76     String filedata = readFile(docfile);
77 
78     // The document is properties up until the line "@jd:body".
79     // Any blank lines are ignored.
80     int start = -1;
81     int lineno = 1;
82     Matcher lines = LINE.matcher(filedata);
83     String line = null;
84     while (lines.find()) {
85       line = lines.group(1);
86       if (line.length() > 0) {
87         if (line.equals("@jd:body")) {
88           start = lines.end();
89           break;
90         }
91         Matcher prop = PROP.matcher(line);
92         if (prop.matches()) {
93           String key = prop.group(1);
94           String value = prop.group(2);
95           hdf.setValue(key, value);
96         } else {
97           break;
98         }
99       }
100       lineno++;
101     }
102     if (start < 0) {
103       System.err.println(docfile + ":" + lineno + ": error parsing docfile");
104       if (line != null) {
105         System.err.println(docfile + ":" + lineno + ":" + line);
106       }
107       System.exit(1);
108     }
109     return hdf;
110   }
111 
writePage(String docfile, String relative, String outfile, Data hdf)112   public static void writePage(String docfile, String relative, String outfile, Data hdf) {
113 
114     /*
115      * System.out.println("docfile='" + docfile + "' relative='" + relative + "'" + "' outfile='" +
116      * outfile + "'");
117      */
118     if (hdf == null) {
119       hdf = Doclava.makeHDF();
120     }
121     String filedata = readFile(docfile);
122 
123     // The document is properties up until the line "@jd:body".
124     // Any blank lines are ignored.
125     int start = -1;
126     int lineno = 1;
127     Matcher lines = LINE.matcher(filedata);
128     String line = null;
129     while (lines.find()) {
130       line = lines.group(1);
131       if (line.length() > 0) {
132         if (line.equals("@jd:body")) {
133           start = lines.end();
134           break;
135         }
136         Matcher prop = PROP.matcher(line);
137         if (prop.matches()) {
138           String key = prop.group(1);
139           String value = prop.group(2);
140           hdf.setValue(key, value);
141         } else {
142           break;
143         }
144       }
145       lineno++;
146     }
147     if (start < 0) {
148       System.err.println(docfile + ":" + lineno + ": error parsing docfile");
149       if (line != null) {
150         System.err.println(docfile + ":" + lineno + ":" + line);
151       }
152       System.exit(1);
153     }
154 
155     // if they asked to only be for a certain template, maybe skip it
156     String fromTemplate = hdf.getValue("template.which", "");
157     String fromPage = hdf.getValue("page.onlyfortemplate", "");
158     if (!"".equals(fromPage) && !fromTemplate.equals(fromPage)) {
159       return;
160     }
161 
162     // and the actual text after that
163     String commentText = filedata.substring(start);
164 
165     Comment comment = new Comment(commentText, null, new SourcePositionInfo(docfile, lineno, 1));
166     TagInfo[] tags = comment.tags();
167 
168     TagInfo.makeHDF(hdf, "root.descr", tags);
169 
170     hdf.setValue("commentText", commentText);
171 
172     // write the page using the appropriate root template, based on the
173     // whichdoc value supplied by build
174     String fromWhichmodule = hdf.getValue("android.whichmodule", "");
175     if (fromWhichmodule.equals("online-pdk")) {
176       // leaving this in just for temporary compatibility with pdk doc
177       hdf.setValue("online-pdk", "true");
178       // add any conditional login for root template here (such as
179       // for custom left nav based on tab etc.
180       ClearPage.write(hdf, "docpage.cs", outfile);
181     } else {
182       String filename = outfile;
183       // Strip out the intl and lang id substr and get back just the
184       // guide, design, distribute, etc.
185       filename = getPathRoot(filename);
186       if (filename.indexOf("design") == 0) {
187         hdf.setValue("design", "true");
188         hdf.setValue("page.type", "design");
189       } else if (filename.indexOf("develop") == 0) {
190         hdf.setValue("develop", "true");
191         hdf.setValue("page.type", "develop");
192       } else if (filename.indexOf("guide") == 0) {
193         hdf.setValue("guide", "true");
194         hdf.setValue("page.type", "guide");
195       } else if (filename.indexOf("training") == 0) {
196         hdf.setValue("training", "true");
197         hdf.setValue("page.type", "training");
198       } else if (filename.indexOf("more") == 0) {
199         hdf.setValue("more", "true");
200       } else if (filename.indexOf("google") == 0) {
201         hdf.setValue("google", "true");
202         hdf.setValue("page.type", "google");
203       } else if (filename.indexOf("samples") == 0) {
204         hdf.setValue("samples", "true");
205         hdf.setValue("page.type", "samples");
206         if (Doclava.samplesNavTree != null) {
207           hdf.setValue("samples_toc_tree", Doclava.samplesNavTree.getValue("samples_toc_tree", ""));
208         }
209       } else if (filename.indexOf("distribute") == 0) {
210         hdf.setValue("distribute", "true");
211         hdf.setValue("page.type", "distribute");
212         if (filename.indexOf("distribute/googleplay") == 0) {
213           hdf.setValue("googleplay", "true");
214         } else if (filename.indexOf("distribute/essentials") == 0) {
215           hdf.setValue("essentials", "true");
216         } else if (filename.indexOf("distribute/users") == 0) {
217           hdf.setValue("users", "true");
218         } else if (filename.indexOf("distribute/engage") == 0) {
219           hdf.setValue("engage", "true");
220         } else if (filename.indexOf("distribute/monetize") == 0) {
221           hdf.setValue("monetize", "true");
222         } else if (filename.indexOf("distribute/analyze") == 0) {
223           hdf.setValue("analyze", "true");
224         } else if (filename.indexOf("distribute/tools") == 0) {
225           hdf.setValue("essentials", "true");
226         } else if (filename.indexOf("distribute/stories") == 0) {
227           hdf.setValue("stories", "true");
228         }
229       } else if (filename.indexOf("about") == 0) {
230         hdf.setValue("about", "true");
231         hdf.setValue("page.type", "about");
232       } else if ((filename.indexOf("tools") == 0) || (filename.indexOf("sdk") == 0)) {
233         hdf.setValue("tools", "true");
234         hdf.setValue("page.type", "tools");
235         fromTemplate = hdf.getValue("page.template", "");
236       } else if (filename.indexOf("devices") == 0) {
237         hdf.setValue("devices", "true");
238         hdf.setValue("page.type", "devices");
239       } else if (filename.indexOf("source") == 0) {
240         hdf.setValue("source", "true");
241       } else if (filename.indexOf("accessories") == 0) {
242         hdf.setValue("accessories", "true");
243       } else if (filename.indexOf("compatibility") == 0) {
244         hdf.setValue("compatibility", "true");
245       } else if (filename.indexOf("wear") == 0) {
246         hdf.setValue("wear", "true");
247       } else if (filename.indexOf("preview") == 0) {
248         hdf.setValue("preview", "true");
249         hdf.setValue("page.type", "preview");
250       } else if (filename.indexOf("auto") == 0) {
251         hdf.setValue("auto", "true");
252       } else if (filename.indexOf("tv") == 0) {
253         hdf.setValue("tv", "true");
254       } else if (filename.indexOf("ndk") == 0) {
255         hdf.setValue("ndk", "true");
256         hdf.setValue("page.type", "ndk");
257         if (filename.indexOf("ndk/guides") == 0) {
258           hdf.setValue("guide", "true");
259         } else if (filename.indexOf("ndk/reference") == 0) {
260           hdf.setValue("reference", "true");
261         } else if (filename.indexOf("ndk/samples") == 0) {
262           hdf.setValue("samples", "true");
263         } else if (filename.indexOf("ndk/downloads") == 0) {
264           hdf.setValue("downloads", "true");
265           fromTemplate = hdf.getValue("page.template", "");
266 
267         }
268       }
269       //set metadata for this file in jd_lists_unified
270       PageMetadata.setPageMetadata(docfile, relative, outfile, hdf, Doclava.sTaglist);
271 
272       if (fromTemplate.equals("sdk")) {
273         ClearPage.write(hdf, "sdkpage.cs", outfile);
274       } else {
275         ClearPage.write(hdf, "docpage.cs", outfile);
276       }
277     }
278   } // writePage
279 }
280