PageRenderTime 48ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/atlassian-docco/src/main/java/com/atlassian/docco/DoccoBatch.java

https://bitbucket.org/Arnauld/atlassian-docco
Java | 328 lines | 253 code | 72 blank | 3 comment | 19 complexity | 3e614f3dadcd9eb727893082ddae43b8 MD5 | raw file
  1. package com.atlassian.docco;
  2. import java.io.File;
  3. import java.io.IOException;
  4. import java.net.URISyntaxException;
  5. import java.net.URL;
  6. import java.util.*;
  7. import javax.annotation.Nullable;
  8. import com.atlassian.docco.builder.DoccoBatchBuilder;
  9. import com.atlassian.docco.mapping.DoccoFileMappingManager;
  10. import com.google.common.base.Function;
  11. import com.google.common.collect.*;
  12. import com.google.template.soy.SoyFileSet;
  13. import com.google.template.soy.data.SanitizedContent;
  14. import com.google.template.soy.data.SoyListData;
  15. import com.google.template.soy.data.SoyMapData;
  16. import com.google.template.soy.tofu.SoyTofu;
  17. import org.apache.commons.io.DirectoryWalker;
  18. import org.apache.commons.io.FileUtils;
  19. import org.apache.commons.lang.StringUtils;
  20. import org.codehaus.plexus.util.DirectoryScanner;
  21. import static com.google.common.base.Preconditions.checkNotNull;
  22. import static com.google.common.base.Preconditions.checkState;
  23. /**
  24. * @since 1.0
  25. */
  26. public final class DoccoBatch
  27. {
  28. public static final String[] DEFAULT_EXCLUDES = new String[]{"**/.*/","**/.*","**/target/**"};
  29. private final File basePath;
  30. private final File outputPath;
  31. private final DoccoFileMappingManager fileMappings;
  32. private final String title;
  33. private final String indexFilename;
  34. private final String[] excludes;
  35. private final String[] includes;
  36. private final boolean skipNoDocco;
  37. private final Docco docco;
  38. private final SoyTofu horizontalTofu;
  39. private final SoyTofu verticalTofu;
  40. public DoccoBatch(Docco docco, File basePath, File outputPath, String[] excludes, String[] includes, URL horizonatlSoyTemplate, URL verticalSoyTemplate, DoccoFileMappingManager fileMappings, String title, String indexFilename, boolean skipNoDocco)
  41. {
  42. this.docco = docco;
  43. this.basePath = basePath;
  44. this.outputPath = outputPath;
  45. this.excludes = excludes;
  46. this.includes = includes;
  47. this.fileMappings = fileMappings;
  48. this.title = title;
  49. this.indexFilename = indexFilename;
  50. this.skipNoDocco = skipNoDocco;
  51. SoyFileSet soyFileSetH = new SoyFileSet.Builder().add(horizonatlSoyTemplate).build();
  52. this.horizontalTofu = soyFileSetH.compileToJavaObj().forNamespace("atlassian.docco");
  53. SoyFileSet soyFileSetV = new SoyFileSet.Builder().add(verticalSoyTemplate).build();
  54. this.verticalTofu = soyFileSetV.compileToJavaObj().forNamespace("atlassian.docco");
  55. }
  56. public void generateDocco() throws URISyntaxException, IOException
  57. {
  58. File hBase = new File(outputPath, "horizontal");
  59. FileUtils.forceMkdir(hBase);
  60. File vBase = new File(outputPath, "vertical");
  61. FileUtils.forceMkdir(vBase);
  62. docco.copyResources(hBase,vBase);
  63. String[] extensions = Lists.transform(fileMappings.getMappedFileExtensions(), new Function<String, String>()
  64. {
  65. @Override
  66. public String apply(@Nullable String s)
  67. {
  68. return "**/*." + s;
  69. }
  70. }).toArray(new String[0]);
  71. DirectoryScanner scanner = new DirectoryScanner();
  72. scanner.setBasedir(basePath);
  73. scanner.setIncludes(getIncludes(extensions));
  74. scanner.setExcludes(getExcludes());
  75. scanner.addDefaultExcludes();
  76. scanner.scan();
  77. Collection<File> sourceFiles = Collections2.transform(Arrays.asList(scanner.getIncludedFiles()), new Function<String, File>() {
  78. @Override
  79. public File apply(@Nullable String s)
  80. {
  81. return new File(basePath,s);
  82. }
  83. });
  84. List<DoccoResult> results = new ArrayList<DoccoResult>(sourceFiles.size());
  85. for (File sourceFile : sourceFiles)
  86. {
  87. DoccoResult result = doccoSourceFile(sourceFile);
  88. if(null != result)
  89. {
  90. results.add(result);
  91. }
  92. }
  93. Multimap<String,String> hIndexMap = createIndexMap(results,hBase);
  94. Multimap<String,String> vIndexMap = createIndexMap(results,vBase);
  95. SoyListData hSoyIndex = getSoyIndexFiles(hIndexMap);
  96. SoyListData vSoyIndex = getSoyIndexFiles(vIndexMap);
  97. writeHtmlFiles(results,hBase,vBase,hSoyIndex,vSoyIndex);
  98. doccoIndex(hSoyIndex,hBase,horizontalTofu);
  99. doccoIndex(vSoyIndex,vBase,verticalTofu);
  100. }
  101. private DoccoResult doccoSourceFile(File sourceFile) throws IOException
  102. {
  103. DoccoParts parts = docco.getDoccoParts(sourceFile);
  104. List<Section> sections = parts.getSections();
  105. if(skipNoDocco && (sections.size() < 2 && parts.getHeader().isEmpty()))
  106. {
  107. return null;
  108. }
  109. return new DoccoResult(sourceFile,parts);
  110. }
  111. private void writeHtmlFiles(List<DoccoResult> results,File hBase, File vBase, SoyListData hIndex, SoyListData vIndex) throws IOException
  112. {
  113. for(DoccoResult result : results)
  114. {
  115. String syntax = fileMappings.getSyntaxForFile(result.getSourceFile());
  116. writeHtml(result.getSourceFile(), syntax, result.getParts().getHeader(), result.getParts().getSections(), hIndex, hBase, horizontalTofu);
  117. writeHtml(result.getSourceFile(), syntax, result.getParts().getHeader(), result.getParts().getSections(), vIndex, vBase, verticalTofu);
  118. }
  119. }
  120. private File writeHtml(File sourceFile, String syntax, Header header, List<Section> sections, SoyListData index, File baseOutputPath, SoyTofu tofu) throws IOException
  121. {
  122. String relativeName = getRelativeName(sourceFile);
  123. File htmlFile = new File(baseOutputPath, relativeName);
  124. FileUtils.forceMkdir(htmlFile.getParentFile());
  125. String relativeBase = getRelativeBase(htmlFile,baseOutputPath);
  126. Map<String,String> replaceMap = ImmutableMap.<String,String> builder().put("${basePath}",relativeBase).build();
  127. SanitizedContent headerHtml = new SanitizedContent(header.getDocWithTokenReplacement(replaceMap), SanitizedContent.ContentKind.HTML);
  128. SoyMapData soyData = new SoyMapData("title", StringUtils.substringBeforeLast(htmlFile.getName(), "."),"nameWithoutExtension", StringUtils.substringBeforeLast(sourceFile.getName(), "."),"syntax", syntax, "groups", index, "basePath", relativeBase, "myPath", relativeName, "header", headerHtml, "sections", Docco.getSoySectionDataWithTokenReplacement(sections, replaceMap));
  129. String rendered = tofu.newRenderer(".batchPage").setData(soyData).render();
  130. FileUtils.writeStringToFile(htmlFile, rendered);
  131. return htmlFile;
  132. }
  133. private File doccoIndex(SoyListData index, File baseOutputPath, SoyTofu tofu) throws IOException
  134. {
  135. SoyMapData soyData = new SoyMapData("basePath",".","title",title,"groups",index);
  136. String rendered = tofu.newRenderer(".indexPage").setData(soyData).render();
  137. File indexFile = new File(baseOutputPath,indexFilename);
  138. FileUtils.touch(indexFile);
  139. FileUtils.writeStringToFile(indexFile, rendered);
  140. return indexFile;
  141. }
  142. private SoyListData getSoyIndexFiles(Multimap<String, String> indexMap) throws IOException
  143. {
  144. SoyListData listData = new SoyListData();
  145. for(String group : indexMap.keySet())
  146. {
  147. SoyListData fileList = new SoyListData();
  148. Collection<String> htmlFiles = indexMap.get(group);
  149. for(String htmlFile : htmlFiles)
  150. {
  151. SoyMapData fileMap = new SoyMapData("dir",StringUtils.substringBeforeLast(htmlFile,"/"),"file",StringUtils.substringAfterLast(htmlFile,"/"));
  152. fileList.add(fileMap);
  153. }
  154. SoyMapData dirMap = new SoyMapData("name",group,"files",fileList);
  155. listData.add(dirMap);
  156. }
  157. return listData;
  158. }
  159. private Multimap<String, String> createIndexMap(List<DoccoResult> results, File baseOutputPath) throws IOException
  160. {
  161. Multimap<String, String> indexMap = ArrayListMultimap.<String,String>create();
  162. for(DoccoResult result : results)
  163. {
  164. String relativeName = getRelativeName(result.getSourceFile());
  165. for(String group : result.getParts().getGroups())
  166. {
  167. String groupName = group;
  168. if(group.startsWith("file://"))
  169. {
  170. String groupPath = StringUtils.substringAfter(group,"file://");
  171. if(groupPath.equals(basePath.getCanonicalPath()))
  172. {
  173. groupName = groupPath + "/";
  174. }
  175. else
  176. {
  177. groupName = groupPath.substring(basePath.getCanonicalPath().length() + 1) + "/";
  178. }
  179. }
  180. String groupKey = StringUtils.replace(groupName,File.separator,"/");
  181. String fileValue = StringUtils.replace(StringUtils.substringBeforeLast(relativeName,"."),File.separator,"/");
  182. indexMap.put(groupName,fileValue);
  183. }
  184. }
  185. Multimap<String,String> sorted = ImmutableMultimap.<String,String> builder().orderKeysBy(new Comparator<String>() {
  186. @Override
  187. public int compare(String s1, String s2)
  188. {
  189. return s1.compareTo(s2);
  190. }
  191. }).putAll(indexMap).build();
  192. return sorted;
  193. }
  194. private String getRelativeBase(File htmlFile, File baseOutputPath) throws IOException
  195. {
  196. String relativeFile = StringUtils.substringAfter(htmlFile.getCanonicalPath(),baseOutputPath.getCanonicalPath());
  197. int numDirs = StringUtils.countMatches(relativeFile,File.separator) - 1;
  198. return StringUtils.chomp(StringUtils.repeat(".." + "/", numDirs), "/");
  199. }
  200. private String getRelativeName(File sourceFile) throws IOException
  201. {
  202. return sourceFile.getCanonicalPath().substring(basePath.getCanonicalPath().length() + 1) + ".html";
  203. }
  204. private String[] getExcludes()
  205. {
  206. int excludesLength = excludes == null ? 0 : excludes.length;
  207. String[] newExcludes;
  208. newExcludes = new String[excludesLength + DEFAULT_EXCLUDES.length];
  209. if(excludesLength > 0)
  210. {
  211. System.arraycopy( excludes, 0, newExcludes, 0, excludes.length );
  212. }
  213. for(int i=0; i<DEFAULT_EXCLUDES.length; i++)
  214. {
  215. newExcludes[i + excludesLength] = DEFAULT_EXCLUDES[i];
  216. }
  217. return newExcludes;
  218. }
  219. private String[] getIncludes(String[] defaultIncludes)
  220. {
  221. int includesLength = includes == null ? 0 : includes.length;
  222. String[] newIncludes;
  223. newIncludes = new String[includesLength + defaultIncludes.length];
  224. if(includesLength > 0)
  225. {
  226. System.arraycopy( includes, 0, newIncludes, 0, includes.length );
  227. }
  228. for(int i=0; i<defaultIncludes.length; i++)
  229. {
  230. newIncludes[i + includesLength] = defaultIncludes[i];
  231. }
  232. return newIncludes;
  233. }
  234. public static DoccoBatchBuilder builder(File basePath, File ouputPath)
  235. {
  236. return new DoccoBatchBuilder(basePath,ouputPath);
  237. }
  238. private class DoccoResult
  239. {
  240. private File sourceFile;
  241. private DoccoParts parts;
  242. private DoccoResult(File sourceFile, DoccoParts parts)
  243. {
  244. this.sourceFile = sourceFile;
  245. this.parts = parts;
  246. }
  247. public File getSourceFile()
  248. {
  249. return sourceFile;
  250. }
  251. public DoccoParts getParts()
  252. {
  253. return parts;
  254. }
  255. }
  256. }