Modify format of samples_navtree_data.js to sort projects group tag.

Change-Id: I3155cdff749640100436feec6eb9f1cff36a5229
diff --git a/src/com/google/doclava/Doclava.java b/src/com/google/doclava/Doclava.java
index b95c8cb..e10bbbc 100644
--- a/src/com/google/doclava/Doclava.java
+++ b/src/com/google/doclava/Doclava.java
@@ -65,6 +65,8 @@
 
   public static int showLevel = SHOW_PROTECTED;
 
+  public static final boolean SORT_BY_NAV_GROUPS = true;
+
   public static String outputPathBase = "/";
   public static ArrayList<String> inputPathHtmlDirs = new ArrayList<String>();
   public static ArrayList<String> inputPathHtmlDir2 = new ArrayList<String>();
@@ -76,6 +78,7 @@
 
   public static RootDoc root;
   public static ArrayList<String[]> mHDFData = new ArrayList<String[]>();
+  public static ArrayList<SampleCode> sampleCodeGroups = new ArrayList<SampleCode>();
   public static Map<Character, String> escapeChars = new HashMap<Character, String>();
   public static String title = "";
   public static SinceTagger sinceTagger = new SinceTagger();
@@ -163,6 +166,8 @@
         ClearPage.toroot = a[1];
       } else if (a[0].equals("-samplecode")) {
         sampleCodes.add(new SampleCode(a[1], a[2], a[3]));
+      } else if (a[0].equals("-samplegroup")) {
+        sampleCodeGroups.add(new SampleCode(null, null, a[1]));
       //the destination output path for main htmldir
       } else if (a[0].equals("-htmldir")) {
         inputPathHtmlDirs.add(a[1]);
@@ -325,8 +330,8 @@
 
       // Sample code pages
       if (samplesRef) {
-        //always write samples without offlineMode behaviors
-        writeSamples(false, sampleCodes);
+        // always write samples without offlineMode behaviors
+        writeSamples(false, sampleCodes, SORT_BY_NAV_GROUPS);
       }
       
       // Navigation tree
@@ -524,6 +529,9 @@
       samplesRef = true;
       return 4;
     }
+    if (option.equals("-samplegroup")) {
+      return 2;
+    }
     if (option.equals("-devsite")) {
       return 1;
     }
@@ -1656,16 +1664,25 @@
   * Process samples dirs that are specified in Android.mk. Generate html
   * wrapped pages, copy files to output dir, and generate a SampleCode NavTree.
   */
-  public static void writeSamples(boolean offlineMode, ArrayList<SampleCode> sampleCodes) {
+  public static void writeSamples(boolean offlineMode, ArrayList<SampleCode> sampleCodes,
+      boolean sortNavByGroups) {
     // Go through SCs processing files. Create a root list for SC nodes,
     // pass it to SCs for their NavTree children and append them.
     List<SampleCode.Node> samplesList = new ArrayList<SampleCode.Node>();
+    List<SampleCode.Node> sampleGroupsRootNodes = null;
     for (SampleCode sc : sampleCodes) {
       samplesList.add(sc.write(offlineMode));
     }
+    if (sortNavByGroups) {
+      sampleGroupsRootNodes = new ArrayList<SampleCode.Node>();
+      for (SampleCode gsc : sampleCodeGroups) {
+        sampleGroupsRootNodes.add(new SampleCode.Node(gsc.mTitle, null, null, null, null,
+            "groupholder"));
+      }
+    }
     // Pass full samplesList to SC to render to js file
     if (!offlineMode) {
-      SampleCode.writeSamplesNavTree(samplesList);
+      SampleCode.writeSamplesNavTree(samplesList, sampleGroupsRootNodes);
     }
   }
 
diff --git a/src/com/google/doclava/SampleCode.java b/src/com/google/doclava/SampleCode.java
index 980dbf6..466d247 100644
--- a/src/com/google/doclava/SampleCode.java
+++ b/src/com/google/doclava/SampleCode.java
@@ -34,13 +34,14 @@
     mTitle = title;
     mTags = null;
 
-    int len = dest.length();
-    if (len > 1 && dest.charAt(len - 1) != '/') {
-      mDest = dest + '/';
-    } else {
-      mDest = dest;
+    if (dest != null) {
+      int len = dest.length();
+      if (len > 1 && dest.charAt(len - 1) != '/') {
+        mDest = dest + '/';
+      } else {
+        mDest = dest;
+      }
     }
-
     //System.out.println("SampleCode init: source: " + mSource);
     //System.out.println("SampleCode init: dest: " + mDest);
     //System.out.println("SampleCode init: title: " + mTitle);
@@ -341,9 +342,17 @@
   /**
   * Render a SC node to a navtree js file.
   */
-  public static void writeSamplesNavTree(List<Node> tnode) {
+  public static void writeSamplesNavTree(List<Node> tnode, List<Node> groupnodes) {
+
     Node node = new Node("Reference", "packages.html", null, null, tnode, null);
 
+    if (groupnodes != null) {
+      for (int i = 0; i < tnode.size(); i++) {
+        groupnodes = appendNodeGroups(tnode.get(i), groupnodes);
+      }
+      node.setChildren(groupnodes);
+    }
+
     StringBuilder buf = new StringBuilder();
     if (false) {
     // if you want a root node
@@ -361,6 +370,27 @@
   }
 
   /**
+  * Iterate the list of projects and sort them by their groups. Samples the reference
+  * a valid sample group tag are added to a list for that group. Samples declare a
+  * sample.group tag in their _index.jd files.
+  */
+  private static List<Node> appendNodeGroups(Node gNode, List<Node> groupnodes) {
+    List<Node> mgrouplist = new ArrayList<Node>();
+    final int N = groupnodes.size();
+    for (int i = 0; i < N; i++) {
+      if (groupnodes.get(i).getLabel().equals(gNode.getGroup())) {
+        if (groupnodes.get(i).getChildren() == null) {
+          groupnodes.get(i).setChildren(mgrouplist);
+        }
+        mgrouplist.add(gNode);
+        //System.out.println("Added " + gNode.getLabel() + " to group " + group);
+        break;
+      } //?? no match
+    }
+    return groupnodes;
+  }
+
+  /**
   * Sort by type and name (alpha), with manifest and src always at top.
   */
   Comparator<File> byTypeAndName = new Comparator<File>() {
@@ -382,7 +412,7 @@
   /**
   * Concatenate dirs that only hold dirs to simplify nav tree
   */
-  public static List<Node> squashNodes(List<Node> tnode){
+  public static List<Node> squashNodes(List<Node> tnode) {
     List<Node> list = tnode;
 
     for(int i = 0; i < list.size(); ++i) {
@@ -558,11 +588,12 @@
       mLink = link;
     }
 
-    public void setGroup(String group) {
-      mGroup = group;
+    public String getGroup() {
+      return mGroup;
     }
 
-    public void setTagss(String tags) {
+    public void setGroup(String group) {
+      mGroup = group;
     }
 
     public void setTags(String tags) {