Package org.moxie.ant

Source Code of org.moxie.ant.MxDoc$DepNode

/*
* Copyright 2012 James Moger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.moxie.ant;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.types.FileSet;
import org.moxie.Build;
import org.moxie.Dependency;
import org.moxie.Doc;
import org.moxie.DocElement;
import org.moxie.DocMenu;
import org.moxie.DocPage;
import org.moxie.DocStructure;
import org.moxie.Docs;
import org.moxie.ExcludeText;
import org.moxie.Load;
import org.moxie.Logo;
import org.moxie.NoMarkdown;
import org.moxie.Prop;
import org.moxie.References;
import org.moxie.Regex;
import org.moxie.Scope;
import org.moxie.Substitute;
import org.moxie.Toolkit;
import org.moxie.Toolkit.Key;
import org.moxie.WikiText;
import org.moxie.WikiText.Syntax;
import org.moxie.utils.FileUtils;
import org.moxie.utils.LessUtils;
import org.moxie.utils.StringUtils;


public class MxDoc extends MxTask {

  Doc doc = new Doc();
 
  String customLessFile;
 
  Logo logo;
 
  Logo favicon;

  List<org.moxie.Resource> resources = new ArrayList<org.moxie.Resource>();
 
  public MxDoc() {
    super();
    setTaskName("mx:doc");
  }

  public DocStructure createStructure() {
    DocStructure struct = new DocStructure();
    doc.structure = struct;
    return struct;
  }
 
  public References createReferences() {
    References references = new References();
    doc.references = references;
    return references;
  }

  public Substitute createReplace() {
    Substitute sub = new Substitute();
    doc.substitutions.add(sub);
    return sub;
  }

  public Load createLoad() {
    Load load = new Load();
    doc.loads.add(load);
    return load;
  }

  public Prop createProperties() {
    Prop prop = new Prop();
    doc.props.add(prop);
    return prop;
  }

  public NoMarkdown createNomarkdown() {
    NoMarkdown nomd = new NoMarkdown();
    doc.nomarkdowns.add(nomd);
    return nomd;
  }
 
  private WikiText createWikiText() {
    WikiText nomd = new WikiText();
    doc.nomarkdowns.add(nomd);
    return nomd;
  }

  public Regex createRegex() {
    Regex regex = new Regex();
    doc.regexes.add(regex);
    return regex;
  }

  public org.moxie.Resource createResource() {
    org.moxie.Resource rsc = new org.moxie.Resource();
    resources.add(rsc);
    return rsc;
  }
 
  public Logo createLogo() {
    logo = new Logo();
    return logo;
  }
 
  public Logo createFavicon() { 
    favicon = new Logo();
    return favicon;   
  }

  public DocPage createPage() {
    DocPage page = new DocPage();   
    doc.freeformPages.add(page);
    return page;
  }

  public void setName(String name) {
    doc.name = name;
  }

  public void setSourceDir(File folder) {
    doc.sourceDirectory = folder;
  }
 
  public void setTemplateDir(File folder) {
    doc.templateDirectory = folder;
  }

  public void setTodir(File dir) {
    doc.outputDirectory = dir;
  }

  public void setDestdir(File dir) {
    doc.outputDirectory = dir;
  }

  public void setCustomLess(String name) {
    customLessFile = name;
  }

  public void setPrettifyTheme(String value) {
    doc.prettifyTheme = value;
  }

  public void setMinify(boolean value) {
    doc.minify = value;
  }

  public void setGoogleAnalyticsid(String value) {
    doc.googleAnalyticsId = value;
  }

  public void setGooglePlusid(String value) {
    doc.googlePlusId = value;
  }

  public void setGooglePlusOne(boolean value) {
    doc.googlePlusOne = value;
  }
 
  public void setResponsiveLayout(boolean value) {
    doc.isResponsiveLayout = value;
  }
 
  public void setRssfeed(String feed) {
    doc.rssFeed = feed;
  }

  public void setAtomfeed(String feed) {
    doc.atomFeed = feed;
  }

  protected void setToken(String token, Object value) {
    if (value == null) {
      value = "${" + token + "}";
    }
    createReplace().set("${" + token + "}", value);
  }

  @Override
  public void execute() throws BuildException {
    Build build = getBuild();
   
    // automatically setup substitution tokens
    setToken(Toolkit.Key.name.projectId(), build.getPom().name);
    setToken(Toolkit.Key.description.projectId(), build.getPom().description);
    setToken(Toolkit.Key.url.projectId(), build.getPom().url);
    setToken(Toolkit.Key.issuesUrl.projectId(), build.getPom().issuesUrl);
    setToken(Toolkit.Key.inceptionYear.projectId(), build.getPom().inceptionYear);
    setToken(Toolkit.Key.organization.projectId(), build.getPom().organization);
    setToken(Toolkit.Key.organizationUrl.projectId(), build.getPom().organizationUrl);
    setToken(Toolkit.Key.forumUrl.projectId(), build.getPom().forumUrl);
    setToken(Toolkit.Key.socialNetworkUrl.projectId(), build.getPom().socialNetworkUrl);
    setToken(Toolkit.Key.blogUrl.projectId(), build.getPom().blogUrl);
    setToken(Toolkit.Key.ciUrl.projectId(), build.getPom().ciUrl);
    setToken(Toolkit.Key.mavenUrl.projectId(), build.getPom().mavenUrl);
    if (build.getPom().scm != null) {
      setToken(Key.scmUrl.projectId(), build.getPom().scm.url);
    }

    setToken(Toolkit.Key.groupId.projectId(), build.getPom().groupId);
    setToken(Toolkit.Key.artifactId.projectId(), build.getPom().artifactId);
    setToken(Toolkit.Key.version.projectId(), build.getPom().version);
    setToken(Toolkit.Key.coordinates.projectId(), build.getPom().getCoordinates());
   
    setToken(Toolkit.Key.buildDate.projectId(), build.getBuildDateString());
    setToken(Toolkit.Key.buildTimestamp.projectId(), build.getBuildTimestamp());
   
    setToken(Toolkit.Key.releaseVersion.projectId(), build.getPom().releaseVersion);
    setToken(Toolkit.Key.releaseDate.projectId(), build.getReleaseDateString());

    setToken(Toolkit.Key.releaseDate.referenceId(), build.getReleaseDate());
    setToken(Toolkit.Key.buildDate.referenceId(), build.getBuildDate());

    for (Map.Entry<String, String> entry : build.getPom().getProperties().entrySet()) {
      setToken(entry.getKey(), entry.getValue());
    }
   
    if (doc.name == null) {
      doc.name = build.getPom().name;
    }
   
    if (doc.sourceDirectory == null) {
      doc.sourceDirectory = build.getConfig().getSiteSourceDirectory();
    }

    if (doc.outputDirectory == null) {
      doc.outputDirectory = build.getConfig().getSiteTargetDirectory();
    }
   
    if (doc.templateDirectory == null) {
      doc.templateDirectory = new File(build.getConfig().getSiteSourceDirectory(), "templates");
    }
   
    doc.customLessFile = findFile(customLessFile);
    if (logo != null) {
      doc.logo = findFile(logo.getFile());
    }
    if (favicon != null) {
      doc.favicon = findFile(favicon.getFile());
    }
   
    titleClass(build.getPom().name);

    loadRuntimeDependencies(build,
        new Dependency("mx:pegdown"),
        new Dependency("mx:wikitext-core"),
        new Dependency("mx:wikitext-twiki"),
        new Dependency("mx:wikitext-textile"),
        new Dependency("mx:wikitext-tracwiki"),
        new Dependency("mx:wikitext-mediawiki"),
        new Dependency("mx:wikitext-confluence"),
        new Dependency("mx:freemarker"));

    Dependency bootstrap = new Dependency("mx:bootstrap");
    Dependency jquery = new Dependency("mx:jquery");
    Dependency d3js = new Dependency("mx:d3js");
    Dependency prettify = new Dependency("mx:prettify");
    Dependency less = new Dependency("mx:lesscss-engine");
   
    loadRuntimeDependencies(build, bootstrap, jquery, d3js, prettify, less);

    if (doc.outputDirectory.exists()) {
      FileUtils.delete(doc.outputDirectory);
    }
    doc.outputDirectory.mkdirs();
   
    if (doc.logo != null && doc.logo.exists()) {
      try {
        FileUtils.copy(doc.outputDirectory, doc.logo);
      } catch (IOException e) {
        getConsole().error(e, "Failed to copy logo file!");
      }
    }
   
    if (doc.favicon != null && doc.favicon.exists()) {
      try {
        FileUtils.copy(doc.outputDirectory, doc.favicon);
      } catch (IOException e) {
        getConsole().error(e, "Failed to copy favicon file!");
      }
    }
   
    extractBootstrap(bootstrap, less, doc.outputDirectory);
    extractJQuery(jquery, doc.outputDirectory);
    extractD3js(d3js, doc.outputDirectory);
    extractPrettify(prettify, doc.outputDirectory);
   
    // setup prev/next pager links
    preparePages(doc.structure.elements);
   
    for (DocPage page : doc.freeformPages) {
      // process out-of-structure template pages
      prepareTemplatePage(page);
    }
   
    // block directives
    createNomarkdown().configure("---NOMARKDOWN---", false, false);
    createNomarkdown().configure("---ESCAPE---", true, false);
    createNomarkdown().configure("---FIXED---", true, true);
    createNomarkdown().configure("```", true, true);
    doc.nomarkdowns.add(new ExcludeText("---EXCLUDE---"));
   
    // wikitext transform directives
    createWikiText().configureSyntax(Syntax.TWIKI);
    createWikiText().configureSyntax(Syntax.TEXTILE);
    createWikiText().configureSyntax(Syntax.TRACWIKI);
    createWikiText().configureSyntax(Syntax.MEDIAWIKI);
    createWikiText().configureSyntax(Syntax.CONFLUENCE);
   
    // language syntax highlighting directives
    createNomarkdown().configureLanguage("---CODE---", null);
    createNomarkdown().configureLanguage("---CSS---", "lang-css");
    createNomarkdown().configureLanguage("---JAVA---", "lang-java");
    createNomarkdown().configureLanguage("---JSON---", "lang-json");
    createNomarkdown().configureLanguage("---SQL---", "lang-sql");
    createNomarkdown().configureLanguage("---WIKI---", "lang-wiki");
    createNomarkdown().configureLanguage("---XML---", "lang-xml");
    createNomarkdown().configureLanguage("---YAML---", "lang-yaml");

    Docs.execute(build, doc, isVerbose());
   
    writeDependenciesAsJson();
   
    // add site resource directories
    for (File dir : build.getConfig().getResourceDirectories(Scope.site)) {
      createResource().createFileset().setDir(dir);
    }

    for (org.moxie.Resource resource : resources) {
      File destdir = doc.outputDirectory;
      if (!StringUtils.isEmpty(resource.prefix)) {
        destdir = new File(doc.outputDirectory, resource.prefix);
      }
      try {
        if (resource.file != null) {
          FileUtils.copy(destdir, resource.file);
        } else {
          for (FileSet fs : resource.filesets) {
            DirectoryScanner ds = fs.getDirectoryScanner(getProject());
            File fromDir = fs.getDir(getProject());

            for (String srcFile : ds.getIncludedFiles()) {
              File dir = destdir;
              if (srcFile.indexOf(File.separatorChar) > -1) {
                dir = new File(dir, srcFile.substring(0, srcFile.lastIndexOf(File.separatorChar)));
              }
              File file = new File(fromDir, srcFile);
              FileUtils.copy(dir, file);
            }
          }
        }
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }
 
  protected void preparePages(List<DocElement> elements) {
    for (DocElement element : elements) {
      if (element instanceof DocMenu) {
        DocMenu menu = (DocMenu) element;

        for (int i = 0, maxIndex = menu.elements.size() - 1; i <= maxIndex; i++) {
          DocElement subElement = menu.elements.get(i);
          if (subElement instanceof DocPage) {
            prepareTemplatePage((DocPage) subElement);

            if (menu.showPager) {
              // link to previous page
              DocPage page = (DocPage) subElement;
              DocElement prev = i == 0 ? null : menu.elements.get(i - 1);
              if (prev != null && prev instanceof DocPage) {
                page.prevPage = (DocPage) prev;
              }

              // link to next page
              DocElement next = i == maxIndex ? null : menu.elements.get(i + 1);
              if (next != null && next instanceof DocPage) {
                page.nextPage = (DocPage) next;
              }

              // show pager is dependent on having at least a prev or next
              page.showPager = page.prevPage != null || page.nextPage != null;
              page.pagerLayout = menu.pagerLayout;
              page.pagerPlacement = menu.pagerPlacement;
            }

          } else if (subElement instanceof DocMenu) {
            // process menu/submenu
            preparePages(Arrays.asList(subElement));
          }
        }
      } else if (element instanceof DocPage) {
        // pages which are generated from a Freemarker template
        // process navbar items
        prepareTemplatePage((DocPage) element);
      }
    }
  }

  protected File findFile(String filename) {
    if (!StringUtils.isEmpty(filename)) {
      List<File> dirs = new ArrayList<File>();
      dirs.add(null); // dir specified in filename
      dirs.add(getBuild().getConfig().getSiteSourceDirectory());
      dirs.addAll(getBuild().getConfig().getResourceDirectories(Scope.site));
      for (File dir : dirs) {
        File aFile = new File(dir, filename);
        if (aFile.exists()) {
          return aFile;
        }
      }
    }
    return null;
  }

  protected void extractBootstrap(Dependency bsDep, Dependency lessDep, File outputFolder) {
    getConsole().debug("injecting Twitter Bootstrap");

    String wj = MessageFormat.format("META-INF/resources/webjars/{0}/{1}/", bsDep.artifactId, bsDep.version);

    extractResource(outputFolder, wj + "js/bootstrap.min.js", "bootstrap/js/bootstrap.min.js", true);
    extractResource(outputFolder, wj + "css/bootstrap-responsive.min.css", "bootstrap/css/bootstrap-responsive.min.css", true);
    extractResource(outputFolder, wj + "img/glyphicons-halflings.png", "bootstrap/img/glyphicons-halflings.png", true);
    extractResource(outputFolder, wj + "img/glyphicons-halflings-white.png", "bootstrap/img/glyphicons-halflings-white.png", true);

    String [] modules = { "accordion", "alerts", "bootstrap", "breadcrumbs", "button-groups", "buttons",
        "carousel", "close", "code", "component-animations", "dropdowns", "forms", "grid", "hero-unit",
        "labels-badges", "layouts", "media", "mixins", "modals", "navbar", "navs", "pager", "pagination",
        "popovers", "progress-bars", "reset", "scaffolding", "sprites", "tables", "thumbnails", "tooltip",
        "type", "utilities", "variables", "wells" };
   
    for (String module : modules) {
      extractResource(outputFolder, wj + "less/" + module + ".less", "bootstrap/less/" + module + ".less", true);
    }

    // extract Moxie's Bootstrap overrides
    extractResource(outputFolder, "moxie.less");
   
    File bsLess = new File(outputFolder, "bootstrap/less/bootstrap.less");
    String content = FileUtils.readContent(bsLess, "\n");
    content += "\n" + FileUtils.readContent(new File(outputFolder, "moxie.less"), "\n");
    if (doc.customLessFile != null && doc.customLessFile.exists()) {
      content += "\n" + FileUtils.readContent(doc.customLessFile, "\n");
    }
    FileUtils.writeContent(bsLess, content);

    Build build = getBuild();   
    loadRuntimeDependencies(build, new Dependency("mx:rhino"));

    // compile Bootstrap and custom.less overrides into css
    try {
      File bsCss = new File(outputFolder, "bootstrap/css/bootstrap.css");
      if (doc.minify) {
        getConsole().log("compiling and minifying {0}...", bsCss.getAbsolutePath());
      } else {
        getConsole().log("compiling {0}...", bsCss.getAbsolutePath());
      }

      long start = System.currentTimeMillis();
      String css = LessUtils.compile(bsLess, doc.minify);
      FileUtils.writeContent(bsCss, css);

      getConsole().log("css generated in {0} msecs", System.currentTimeMillis() - start);
     
    } catch (Exception e) {
      getConsole().error(e,  "Failed to compile LESS!");
    }
   
    // remove less folder
    FileUtils.delete(new File(outputFolder, "bootstrap/less"));
  }

  protected void extractJQuery(Dependency dep, File outputFolder) {
    getConsole().debug("injecting JQuery");

    String wj = MessageFormat.format("META-INF/resources/webjars/{0}/{1}/", dep.artifactId, dep.version);

    extractResource(outputFolder, wj + "jquery.min.js", "bootstrap/js/jquery.js", true);
  }

  protected void extractD3js(Dependency dep, File outputFolder) {
    getConsole().debug("injecting D3");
    String wj = MessageFormat.format("META-INF/resources/webjars/{0}/{1}/", dep.artifactId, dep.version);
    extractResource(outputFolder, wj + "d3.v2.min.js", "d3/d3.js", true);
   
    extractResource(outputFolder, "d3/rings.css");
    extractResource(outputFolder, "d3/rings.js");
  }

  protected void extractPrettify(Dependency dep, File outputFolder) {
    getConsole().debug("injecting GoogleCode Prettify");

    String wj = MessageFormat.format("META-INF/resources/webjars/{0}/{1}/", dep.artifactId, dep.version);

    extractResource(outputFolder, wj + "prettify.js", "prettify/prettify.js", true);
    extractResource(outputFolder, wj + "prettify.css", "prettify/prettify.css", true);
   
    String [] langs = { "apollo", "clj", "css", "go", "hs", "lisp", "lua", "ml", "n", "proto", "scala",
        "sql", "tex", "vb", "vhdl", "wiki", "xq", "yaml" };
   
    for (String lang : langs) {
      extractResource(outputFolder, wj + "lang-" + lang + ".js", "prettify/lang-" + lang + ".js", true);
    }
   
    extractZippedResource("prettify-themes.zip", outputFolder, "prettify");
  }
 
  protected void extractZippedResource(String zipResource, File outputDirectory, String toDir) {
    try {
      ZipInputStream is = new ZipInputStream(getClass().getResourceAsStream("/" + zipResource));
      File destFolder = new File(outputDirectory, toDir);
      destFolder.mkdirs();
      ZipEntry entry = null;
      while ((entry = is.getNextEntry()) != null) {
        if (entry.isDirectory()) {
          File file = new File(destFolder, entry.getName());
          file.mkdirs();
          continue;
        }
        FileOutputStream os = new FileOutputStream(new File(destFolder,  entry.getName()));
        byte[] buffer = new byte[32767];
        int len = 0;
        while ((len = is.read(buffer)) > -1) {
          os.write(buffer, 0, len);
        }
        os.close();
        is.closeEntry();
      }
      is.close();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

 
  protected void deleteResource(File baseFolder, String file) {
    new File(baseFolder, file).delete();
  }
 
  protected void prepareTemplatePage(DocPage page) {
    // pages which are generated from a Freemarker template
    if (StringUtils.isEmpty(page.src) &&
        page.templates != null && page.templates.size() == 1) {
      String token = "%-" + page.as + "%";
      page.templates.get(0).setToken(token);
      page.content = token;
    }
  }
 
  void writeDependenciesAsJson() {
    DepNode root = new DepNode(new Dependency(getBuild().getPom().getCoordinates()));
    Set<Dependency> dependencies = getBuild().getSolver().getDependencies(Scope.test);
    DepNode currRoot = root;
    for (Dependency dep : dependencies) {
      if (currRoot.dep.ring == dep.ring) {
        // dep is at same ring as curr root, add to parent
        currRoot = currRoot.parent.add(dep);
      } else if (dep.ring > currRoot.dep.ring) {
        // dep is one ring lower then curr root, add to curr root
        // and reset curr root
        currRoot = currRoot.add(dep);
      } else if (dep.ring < currRoot.dep.ring) {
        // find the parent node for this dep
        currRoot = currRoot.parentAt(dep.ring - 1);
        // add dep to the parent node
        currRoot = currRoot.add(dep);
      }
    }
    String json = root.asJSON();
    File file  = new File(getBuild().getConfig().getSiteTargetDirectory(), "moxie-dependencies.json");
    FileUtils.writeContent(file, json);
  }
 
  private class DepNode {
    DepNode parent;
    Dependency dep;
   
   
    List<DepNode> children;
   
    DepNode(Dependency dep) {
      this(dep, null);
    }
    DepNode(Dependency dep, DepNode parent) {
      this.dep = dep;
      this.parent = parent;
      children = new ArrayList<DepNode>();
    }
   
    DepNode add(Dependency dep) {
      DepNode node = new DepNode(dep, this);
      children.add(node);
      return node;
    }
   
    DepNode parentAt(int ring) {
      DepNode node = this;
      while (node != null && node.dep.ring >= ring) {
        if (node.parent == null) {
          break;
        }
        node = node.parent;
      }
      return node;
    }
   
    String asJSON() {
      StringBuilder sb = new StringBuilder("{\n");
      sb.append(MessageFormat.format("    \"ring\" : \"{0}\",\n", dep.ring));
      sb.append(MessageFormat.format("    \"name\" : \"{0} {1}\"", dep.artifactId, dep.version));
      if (children.size() == 0) {
        //sb.append(MessageFormat.format(",\n    \"colour\" : \"{0}\"", "#"));
      } else if (children.size() > 0) {
        sb.append(",\n    \"children\" : [\n");
        for (DepNode node : children) {
          sb.append(StringUtils.insertSoftTab(node.asJSON()));
          sb.append(",\n");
        }
        // trim trailing comma,newline
        sb.setLength(sb.length() - 2);
        sb.append("\n    ]\n");
      }
      sb.append("\n}\n");
      return sb.toString();
    }
  }
}
TOP

Related Classes of org.moxie.ant.MxDoc$DepNode

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.