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.io.*;
22import java.util.regex.Pattern;
23import java.util.regex.Matcher;
24
25
26public class DocFile {
27  public static final Pattern LINE = Pattern.compile("(.*)[\r]?\n", Pattern.MULTILINE);
28  public static final Pattern PROP = Pattern.compile("([^=]+)=(.*)");
29
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
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
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
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("disttools", "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      } else if (filename.indexOf("auto") == 0) {
250        hdf.setValue("auto", "true");
251      } else if (filename.indexOf("tv") == 0) {
252        hdf.setValue("tv", "true");
253      }
254      //set metadata for this file in jd_lists_unified
255      PageMetadata.setPageMetadata(docfile, relative, outfile, hdf, Doclava.sTaglist);
256
257      if (fromTemplate.equals("sdk")) {
258        ClearPage.write(hdf, "sdkpage.cs", outfile);
259      } else {
260        ClearPage.write(hdf, "docpage.cs", outfile);
261      }
262    }
263  } // writePage
264}
265