Patch in Brett Johnson's changes from DocLava to support yaml.

http://code.google.com/p/doclava/source/detail?r=335
http://code.google.com/p/doclava/source/detail?r=336

Change-Id: I624f9ac1a8166e5590a845a55c2a6e51d2a078b4
diff --git a/res/assets/templates/yaml_navtree.cs b/res/assets/templates/yaml_navtree.cs
new file mode 100644
index 0000000..d3f8d31
--- /dev/null
+++ b/res/assets/templates/yaml_navtree.cs
@@ -0,0 +1,40 @@
+<?cs
+
+# walk the children pages and print them nested below the parent
+page: the node to insert a label, link and check for children
+whitespace: Whitespace to insert before any text in the structure, which helps
+ with nesting children on recursion.
+isRoot: treat this node as if it has children and insert a section node.
+
+?><?cs
+def:write_child_nodes(page,whitespace,isRoot) ?>
+<?cs var:whitespace ?>- title: "<?cs var:page.label ?>"
+<?cs var:whitespace ?>  path: <?cs var:page.link ?><?cs
+  if:subcount(page.children) || isRoot ?>
+<?cs var:whitespace ?>  section: <?cs
+ /if?><?cs
+  each:child = page.children?>
+<?cs var:whitespace ?>  - title: "<?cs var:child.label ?>"
+<?cs var:whitespace ?>    path: <?cs var:child.link ?><?cs
+    if:subcount(child.children) ?>
+<?cs var:whitespace ?>    section:<?cs
+    call:write_child_nodes(child) ?><?cs
+    /if ?><?cs
+    /each ?><?cs
+/def ?><?cs
+
+
+
+# print out the yaml nav starting with the toc entry and using the first item,
+which is generally the package summary as the root element with the rest of the
+pages as children beneath the package summary.
+
+?>
+toc:<?cs each:page = docs.pages?><?cs
+  if:page.type == "package"?><?cs
+  call:write_child_nodes(page,"",1) ?><?cs
+  else?>
+    <?cs
+    call:write_child_nodes(page,"  ",0) ?><?cs
+  /if?><?cs
+/each ?>
diff --git a/src/com/google/doclava/Doclava.java b/src/com/google/doclava/Doclava.java
index c8b44e7..b7e06cb 100644
--- a/src/com/google/doclava/Doclava.java
+++ b/src/com/google/doclava/Doclava.java
@@ -76,6 +76,7 @@
   public static FederationTagger federationTagger = new FederationTagger();
   private static boolean generateDocs = true;
   private static boolean parseComments = false;
+  private static String yamlNavFile = null;
 
   public static JSilver jSilver = null;
 
@@ -219,6 +220,8 @@
         String name = a[1];
         String file = a[2];
         federationTagger.addSiteApi(name, file);
+      } else if (a[0].equals("-yaml")) {
+        yamlNavFile = a[1];
       }
     }
 
@@ -279,6 +282,11 @@
       // Navigation tree
       NavTree.writeNavTree(javadocDir);
 
+      // Write yaml tree.
+      if (yamlNavFile != null){
+        NavTree.writeYamlTree(javadocDir, yamlNavFile);
+      }
+
       // Packages Pages
       writePackages(javadocDir + "packages" + htmlExtension);
 
@@ -539,6 +547,9 @@
     if (option.equals("-federationapi")) {
       return 3;
     }
+    if (option.equals("-yaml")) {
+      return 2;
+    }
     return 0;
   }
 
@@ -1452,4 +1463,11 @@
 
     return TYPE_NONE;
   }
+
+  /**
+   * Ensures a trailing '/' at the end of a string.
+   */
+  static String ensureSlash(String path) {
+    return path.endsWith("/") ? path : path + "/";
+  }
 }
diff --git a/src/com/google/doclava/NavTree.java b/src/com/google/doclava/NavTree.java
index db4adc0..5323213 100644
--- a/src/com/google/doclava/NavTree.java
+++ b/src/com/google/doclava/NavTree.java
@@ -20,6 +20,8 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.SortedMap;
+import java.util.TreeMap;
 
 public class NavTree {
 
@@ -46,6 +48,82 @@
     ClearPage.write(data, "navtree_data.cs", "navtree_data.js");
   }
 
+  /**
+   * Write the YAML formatted navigation tree.
+   * @see "http://yaml.org/"
+   */
+  public static void writeYamlTree(String dir, String fileName){
+    Data data = Doclava.makeHDF();
+    ClassInfo[] classes = Converter.rootClasses();
+
+    SortedMap<String, Object> sorted = new TreeMap<String, Object>();
+    for (ClassInfo cl : classes) {
+      if (cl.isHidden()) {
+        continue;
+      }
+      sorted.put(cl.qualifiedName(), cl);
+
+      PackageInfo pkg = cl.containingPackage();
+      String name;
+      if (pkg == null) {
+        name = "";
+      } else {
+        name = pkg.name();
+      }
+      sorted.put(name, pkg);
+    }
+
+    data = makeYamlHDF(sorted, "docs.pages", data);
+    ClearPage.write(data, "yaml_navtree.cs", Doclava.ensureSlash(dir) + fileName);
+  }
+
+  public static Data makeYamlHDF(SortedMap<String, Object> sorted, String base, Data data) {
+
+    String key = "docs.pages.";
+    int i = 0;
+    for (String s : sorted.keySet()) {
+      Object o = sorted.get(s);
+
+      if (o instanceof PackageInfo) {
+        PackageInfo pkg = (PackageInfo) o;
+
+        data.setValue("docs.pages." + i + ".id", "" + i);
+        data.setValue("docs.pages." + i + ".label", pkg.name());
+        data.setValue("docs.pages." + i + ".shortname", "API");
+        data.setValue("docs.pages." + i + ".link", pkg.htmlPage());
+        data.setValue("docs.pages." + i + ".type", "package");
+      } else if (o instanceof ClassInfo) {
+        ClassInfo cl = (ClassInfo) o;
+
+       // skip classes that are the child of another class, recursion will handle those.
+       if (cl.containingClass() == null){
+
+         data.setValue("docs.pages." + i + ".id", "" + i);
+         data = makeYamlHDF(cl, "docs.pages."+i, data);
+       }
+     }
+
+     i++;
+   }
+   return data;
+ }
+
+ public static Data makeYamlHDF(ClassInfo cl, String base, Data data) {
+   data.setValue(base + ".label", cl.name());
+   data.setValue(base + ".shortname", cl.name().substring(cl.name().lastIndexOf(".")+1));
+   data.setValue(base + ".link", cl.htmlPage());
+   data.setValue(base + ".type", cl.kind());
+
+   if (cl.innerClasses().size() > 0){
+     int j = 0;
+     for (ClassInfo cl2 : cl.innerClasses()){
+       data = makeYamlHDF(cl2, base + ".children." + j, data);
+       j++;
+     }
+   }
+
+    return data;
+  }
   private static Node makePackageNode(PackageInfo pkg) {
     List<Node> children = new ArrayList<Node>();