Merge "Suppress deprecation warning for classes from jar files"
am: 15887cc71b

Change-Id: Ief014358c7a2ccf5a9cf42c44c4ab7c3350e448e
diff --git a/build.gradle b/build.gradle
index 0fdc5d1..de34436 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,6 +1,6 @@
 apply plugin: 'java'
 
-import com.android.internal.BuildUtils
+import javax.tools.ToolProvider
 
 sourceSets {
     main {
@@ -13,17 +13,9 @@
     }
 }
 
-// TODO put this function in a plugin
-// TODO remove when prebuilt's case will always properly work with BuildUtils's version.
-String findToolsJar() {
-    new ByteArrayOutputStream().withStream { os ->
-        project.exec {
-            executable "../../build/core/find-jdk-tools-jar.sh"
-
-            standardOutput = os
-        }
-        return os.toString().trim()
-    }
+dependencies {
+    // tools.jar required for com.sun.javadoc
+    compile files(((URLClassLoader) ToolProvider.getSystemToolClassLoader()).getURLs())
 }
 
 if (project.hasProperty("usePrebuilts") && project.usePrebuilts == "true") {
@@ -31,20 +23,15 @@
         maven { url '../../prebuilts/tools/common/m2/repository' }
     }
 
-    // TODO refactor to allow referencing the "gradle way"
     dependencies {
-        compile files(findToolsJar())
-        compile files('../../prebuilts/misc/common/antlr/antlr-3.4-complete.jar')
+        compile 'org.antlr:antlr:3.5.2'
         compile 'com.google.jsilver:jsilver:1.0.0'
-        // TODO add tagsoup to prebuils to fully support building using prebuilts
-        compile project(':tagsoup')
+        compile 'org.ccil.cowan.tagsoup:tagsoup:1.2.1'
         // required by jsilver
         compile 'com.google.guava:guava:15.0'
-        //compile project(path: ':junit', configuration: 'target')
     }
 } else {
     dependencies {
-        compile files(BuildUtils.findToolsJar(project))
         compile project(path: ':antlr', configuration: 'antlrRuntime')
         compile project(':jsilver')
         compile project(':tagsoup')
diff --git a/res/assets/templates/at_links_navtree.cs b/res/assets/templates/at_links_navtree.cs
new file mode 100644
index 0000000..853d0a6
--- /dev/null
+++ b/res/assets/templates/at_links_navtree.cs
@@ -0,0 +1 @@
+<?cs var:navtree ?>
\ No newline at end of file
diff --git a/res/assets/templates/components.cs b/res/assets/templates/components.cs
index 6ec1e81..1665e4d 100644
--- a/res/assets/templates/components.cs
+++ b/res/assets/templates/components.cs
@@ -1,10 +1,10 @@
-<?cs # This default template file is meant to be replaced. ?>
-<?cs # Use the -tempatedir arg to javadoc to set your own directory with a replacement for this file in it. ?>
+<?cs
+# This default template file is meant to be replaced. ?><?cs
+# Use the -tempatedir arg to javadoc to set your own directory with a replacement for this file in it. ?><?cs
 
-<?cs include:"components/search_box.cs" ?>
-<?cs include:"components/api_filter.cs" ?>
+include:"components/search_box.cs" ?><?cs
+include:"components/api_filter.cs" ?><?cs
 
-<?cs include:"components/masthead.cs" ?>
-<?cs include:"components/left_nav.cs" ?>
-
-<?cs include:"customizations.cs" ?>
\ No newline at end of file
+include:"components/masthead.cs" ?><?cs
+include:"components/left_nav.cs" ?><?cs
+include:"customizations.cs" ?>
\ No newline at end of file
diff --git a/res/assets/templates/macros.cs b/res/assets/templates/macros.cs
index 750a31d..f403302 100644
--- a/res/assets/templates/macros.cs
+++ b/res/assets/templates/macros.cs
@@ -1,11 +1,10 @@
 <?cs # A link to a package ?><?cs
+
 def:package_link(pkg) ?>
   <a href="<?cs var:toroot ?><?cs var:pkg.link ?>"><?cs var:pkg.name ?></a><?cs
-/def ?>
+  /def ?><?cs
 
-
-
-<?cs # A link to a type, or not if it is a primitive type
+# A link to a type, or not if it is a primitive type
         link: whether to create a link at the top level, always creates links in
               recursive invocations.
               Overloaded version to support use of 'nav' parameter, which when true,
@@ -16,9 +15,9 @@
             .isPrimitive
             .superBounds.N.(more links)   (... super ... & ...)
             .extendsBounds.N.(more links) (... extends ... & ...)
-            .typeArguments.N.(more links) (< ... >)
-?><?cs
+            .typeArguments.N.(more links) (< ... >) ?><?cs
 def:type_link_impl(type, link) ?><?cs call:type_link_impl2(type, link, "false") ?><?cs /def ?><?cs
+
 def:type_link_impl2(type, link, nav) ?><?cs
   if:type.link && link=="true" ?><?cs
     if:type.federated ?><a href="<?cs var:type.link ?>"><?cs
@@ -44,9 +43,8 @@
           if:!last(t) ?>,&nbsp;<?cs /if ?><?cs
       /each ?>&gt;<?cs
   /if ?><?cs
-/def ?>
+/def ?><?cs
 
-<?cs
 def:simple_type_link(type)?><?cs
   if:type.link?><?cs
     if:type.federated ?><a href="<?cs var:type.link ?>"><?cs var:type.label ?></a><?cs
@@ -61,34 +59,37 @@
       /if ?><?cs
     /each ?>&gt;<?cs
   /if ?><?cs
-/def ?>
+/def ?><?cs
 
-<?cs def:class_name(type) ?><?cs call:type_link_impl(type, "false") ?><?cs /def ?>
-<?cs def:type_link2(type,nav) ?><?cs call:type_link_impl2(type, "true", nav) ?><?cs /def ?>
-<?cs def:type_link(type) ?><?cs call:type_link2(type, "false") ?><?cs /def ?>
+def:class_name(type) ?><?cs call:type_link_impl(type, "false") ?><?cs
+/def ?><?cs
+def:type_link2(type,nav) ?><?cs call:type_link_impl2(type, "true", nav) ?><?cs
+/def ?><?cs
+def:type_link(type) ?><?cs call:type_link2(type, "false") ?><?cs
+/def ?><?cs
 
-<?cs # a conditional link.
-      if the "condition" parameter evals to true then the link is displayed
-      otherwise only the text is displayed
-?><?cs
+# a conditional link.
+  if the "condition" parameter evals to true then the link is displayed
+  otherwise only the text is displayed ?><?cs
 def:cond_link(text, root, path, condition) ?><?cs
-  if:condition ?><a href="<?cs var:root ?><?cs var:path ?>"><?cs /if ?><?cs var:text ?><?cs if:condition ?></a><?cs /if ?><?cs
-/def ?>
+  if:condition ?><a href="<?cs var:root ?><?cs
+  var:path ?>"><?cs /if ?><?cs var:text ?><?cs
+  if:condition ?></a><?cs /if ?><?cs
+/def ?><?cs
 
-<?cs # A comma separated parameter list ?><?cs
+# A comma separated parameter list ?><?cs
 def:parameter_list(params) ?><?cs
   each:param = params ?><?cs
       call:simple_type_link(param.type)?> <?cs
       var:param.name ?><?cs
       if: name(param)!=subcount(params)-1?>, <?cs /if ?><?cs
   /each ?><?cs
-/def ?>
+/def ?><?cs
 
-<?cs def:doc_root_override()
+def:doc_root_override()
   ?><?cs var:toroot ?><?cs
-/def ?>
-
-<?cs # Print a list of tags (e.g. description text ?><?cs
+/def ?><?cs
+# Print a list of tags (e.g. description text ?><?cs
 def:tag_list(tags) ?><?cs
   each:tag = tags ?><?cs
       if:tag.name == "Text" ?><?cs var:tag.text?><?cs
@@ -130,9 +131,9 @@
       else ?>{<?cs var:tag.name?> <?cs var:tag.text ?>}<?cs
       /if ?><?cs
   /each ?><?cs
-/def ?>
+/def ?><?cs
 
-<?cs # Print output for block tags that are not "standard" javadoc tags ?><?cs
+# Print output for block tags that are not "standard" javadoc tags ?><?cs
 def:block_tag_list(tags) ?><?cs
   each:tag = tags ?><?cs
       if:tag.kind == "@apiNote" ?>
@@ -154,9 +155,9 @@
         </div><?cs
       /if ?><?cs
   /each ?><?cs
-/def ?>
+/def ?><?cs
 
-<?cs # Show the short-form description of something.  These come from shortDescr and deprecated ?><?cs
+# Show the short-form description of something.  These come from shortDescr and deprecated ?><?cs
 def:short_descr(obj) ?><?cs
   if:subcount(obj.deprecated) ?><em><?cs
     if:obj.deprecatedsince ?>
@@ -172,10 +173,8 @@
     <div><?cs var:annodoc.text?></div><?cs
     /each?><?cs /if?><?cs
   /if ?><?cs
-/def ?>
+/def ?><?cs
 
-
-<?cs
 # Show a list of annotations associated with obj
 #
 # pre is an HTML string to start the list.
@@ -202,14 +201,14 @@
       var:post ?><?cs
     /if ?><?cs
   /each ?><?cs
-/def ?>
+/def ?><?cs
 
-<?cs # Show a comma-separated list of annotations associated with obj ?><?cs
+# Show a comma-separated list of annotations associated with obj ?><?cs
 def:show_simple_annotations_list(obj, pre, post) ?><?cs
   call:show_annotations_list(obj, pre, ", ", post) ?><?cs
-/def ?>
+/def ?><?cs
 
-<?cs # Show the red box with the deprecated warning ?><?cs
+# Show the red box with the deprecated warning ?><?cs
 def:deprecated_warning(obj) ?><?cs
   if:subcount(obj.deprecated) ?><p>
   <p class="caution"><strong><?cs
@@ -222,9 +221,9 @@
     <?cs call:tag_list(obj.deprecated) ?>
   </p><?cs
   /if ?><?cs
-/def ?>
+/def ?><?cs
 
-<?cs # print the See Also: section ?><?cs
+# print the See Also: section ?><?cs
 def:see_also_tags(also) ?><?cs
   if:subcount(also) ?>
   <div>
@@ -241,15 +240,16 @@
       </ul>
   </div><?cs
   /if ?>
-<?cs /def ?>
+<?cs /def ?><?cs
 
-<?cs # print the API Level ?><?cs
+# print the API Level ?><?cs
 def:since_tags(obj) ?><?cs
 if:reference.apilevels && obj.since ?>
   Added in <a href="<?cs var:toroot ?>guide/topics/manifest/uses-sdk-element.html#ApiLevels">API level <?cs var:obj.since ?></a><?cs
 /if ?><?cs
-/def ?>
-<?cs def:federated_refs(obj) ?>
+/def ?><?cs
+
+def:federated_refs(obj) ?>
   <?cs if:subcount(obj.federated) ?>
     <div>
     Also:
@@ -259,8 +259,8 @@
     <?cs /each ?>
     </div>
   <?cs /if ?>
-<?cs /def ?>
-<?cs
+<?cs /def ?><?cs
+
 #
 # Print the long-form description for something.
 # Uses the following fields: deprecated descr seeAlso since
@@ -350,9 +350,9 @@
   <?cs
   /if ?><?cs
   call:see_also_tags(obj.seeAlso) ?><?cs
-/def ?>
+/def ?><?cs
 
-<?cs # A table of links to classes with descriptions, as in a package file or the nested classes ?><?cs
+# A table of links to classes with descriptions, as in a package file or the nested classes ?><?cs
 def:class_link_table(classes) ?><?cs
   set:count = #1 ?>
   <table class="jd-sumtable-expando"><?cs
@@ -363,9 +363,9 @@
           </tr><?cs set:count = count + #1 ?><?cs
       /each ?>
   </table><?cs
-/def ?>
+/def ?><?cs
 
-<?cs # A list of links to classes, for use in the side navigation of classes when viewing a package (panel nav) ?><?cs
+# A list of links to classes, for use in the side navigation of classes when viewing a package (panel nav) ?><?cs
 def:class_link_list(label, classes) ?><?cs
   if:subcount(classes) ?>
     <li><h2><?cs var:label ?></h2>
@@ -376,9 +376,9 @@
       </ul>
     </li><?cs
   /if ?><?cs
-/def ?>
+/def ?><?cs
 
-<?cs # A list of links to classes, for use in the side navigation of classes when viewing a class (panel nav) ?><?cs
+# A list of links to classes, for use in the side navigation of classes when viewing a class (panel nav) ?><?cs
 def:list(label, classes) ?><?cs
   if:subcount(classes) ?>
     <li><h2><?cs var:label ?></h2>
@@ -389,25 +389,25 @@
       </ul>
     </li><?cs
   /if ?><?cs
-/def ?>
+/def ?><?cs
 
-<?cs # A list of links to packages, for use in the side navigation of packages (panel nav) ?><?cs
+# A list of links to packages, for use in the side navigation of packages (panel nav) ?><?cs
 def:package_link_list(packages) ?><?cs
   each:pkg=packages ?>
     <li class="<?cs if:(class.package.name == pkg.name) || (package.name == pkg.name)?>selected <?cs /if ?>api apilevel-<?cs var:pkg.since ?>"><?cs call:package_link(pkg) ?></li><?cs
   /each ?><?cs
-/def ?>
+/def ?><?cs
 
-<?cs # An expando trigger ?><?cs
+# An expando trigger ?><?cs
 def:expando_trigger(id, default) ?>
   <a href="#" onclick="return toggleInherited(this, null)" id="<?cs var:id ?>" class="jd-expando-trigger closed"
           ><img height="34" id="<?cs var:id ?>-trigger"
           src="<?cs var:toroot ?>assets/images/styles/disclosure_<?cs
             if:default == 'closed' ?>down<?cs else ?>up<?cs /if ?>.png"
           class="jd-expando-trigger-img" /></a><?cs
-/def ?>
+/def ?><?cs
 
-<?cs # An expandable list of classes ?><?cs
+# An expandable list of classes ?><?cs
 def:expandable_class_list(id, classes, default) ?>
   <div id="<?cs var:id ?>">
       <div id="<?cs var:id ?>-list"
@@ -437,6 +437,5 @@
           call:class_link_table(classes) ?>
       </div>
   </div><?cs
-/def ?>
-
-<?cs include:"components.cs" ?>
+/def ?><?cs
+include:"components.cs" ?>
\ No newline at end of file
diff --git a/src/com/google/doclava/AtLinksNavTree.java b/src/com/google/doclava/AtLinksNavTree.java
new file mode 100644
index 0000000..532e8b6
--- /dev/null
+++ b/src/com/google/doclava/AtLinksNavTree.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2016 Google Inc.
+ *
+ * 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 com.google.doclava;
+
+import com.google.clearsilver.jsilver.data.Data;
+
+import java.util.ArrayList;
+
+/**
+* Class for writing a JSON dictionary of Android package/class/member info that can be used for
+* dereferencing javadoc style {@link} tags.
+*/
+
+public class AtLinksNavTree {
+
+  /**
+  * Write a JSON dictionary of Android package/class/member info. The hierarchy will follow this
+  * format: package name -> class name -> member name and signature -> parent package.class name
+  * if the member was inherited (or an empty string if the member was not inherited).
+  *
+  * <p>For example:
+  * <pre>{
+  *   "android": {
+  *     "Manifest": {
+  *       "Manifest()": "",
+  *       "clone()": "java.lang.Object",
+  *       "equals(java.lang.Object)": "java.lang.Object",
+  *       ...
+  *     },
+  *     ...
+  *   },
+  *   ...
+  * }</pre>
+  *
+  * @param dir The directory path to prepend to the output path if the generated navtree is for
+  *        the /support/test or /support/wearable reference docs.
+  */
+  public static void writeAtLinksNavTree(String dir) {
+    StringBuilder buf = new StringBuilder();
+
+    buf.append("{");
+    addPackages(buf, Doclava.choosePackages());
+    buf.append("\n}");
+
+    Data data = Doclava.makeHDF();
+    data.setValue("navtree", buf.toString());
+
+    String output_path;
+    if (Doclava.USE_DEVSITE_LOCALE_OUTPUT_PATHS && Doclava.testSupportRef) {
+      output_path = dir + Doclava.testSupportPath + "at_links_navtree.json";
+    } else if (Doclava.USE_DEVSITE_LOCALE_OUTPUT_PATHS && Doclava.wearableSupportRef) {
+      output_path = dir + Doclava.wearableSupportPath + "at_links_navtree.json";
+    } else {
+      output_path = "at_links_navtree.json";
+    }
+
+    ClearPage.write(data, "at_links_navtree.cs", output_path);
+  }
+
+  /**
+  * Append the provided string builder with the navtree info for the provided list of packages.
+  *
+  * @param buf The string builder to append to.
+  * @param packages A list of PackageInfo objects. Navtree info for each package will be appended
+  *        to the provided string builder.
+  */
+  private static void addPackages(StringBuilder buf, PackageInfo[] packages) {
+    boolean is_first_package = true;
+    for (PackageInfo pkg : Doclava.choosePackages()) {
+      if (!pkg.name().contains(".internal.")) {
+        if (!is_first_package) {
+          buf.append(",");
+        }
+        buf.append("\n  \"" + pkg.name() + "\": {");
+
+        boolean is_first_class = true;
+        is_first_class = addClasses(buf, pkg.annotations(), is_first_class);
+        is_first_class = addClasses(buf, pkg.interfaces(), is_first_class);
+        is_first_class = addClasses(buf, pkg.ordinaryClasses(), is_first_class);
+        is_first_class = addClasses(buf, pkg.enums(), is_first_class);
+        is_first_class = addClasses(buf, pkg.exceptions(), is_first_class);
+        addClasses(buf, pkg.errors(), is_first_class);
+
+        buf.append("\n  }");
+        is_first_package = false;
+      }
+    }
+  }
+
+  /**
+  * Append the provided string builder with the navtree info for the provided list of classes.
+  *
+  * @param buf The string builder to append to.
+  * @param classes A list of ClassInfo objects. Navtree info for each class will be appended
+  *        to the provided string builder.
+  * @param is_first_class True if this is the first child class listed under the parent package.
+  */
+  private static boolean addClasses(StringBuilder buf, ClassInfo[] classes,
+      boolean is_first_class) {
+    for (ClassInfo cl : classes) {
+      if (!is_first_class) {
+        buf.append(",");
+      }
+      buf.append("\n    \"" + cl.name() + "\": {");
+
+      boolean is_first_member = true;
+      is_first_member = addFields(buf, cl.fields(), is_first_member, cl);
+      is_first_member = addMethods(buf, cl.constructors(), is_first_member, cl);
+      addMethods(buf, cl.methods(), is_first_member, cl);
+
+      buf.append("\n    }");
+      is_first_class = false;
+    }
+    return is_first_class;
+  }
+
+  /**
+  * Append the provided string builder with the navtree info for the provided list of fields.
+  *
+  * @param buf The string builder to append to.
+  * @param fields A list of FieldInfo objects. Navtree info for each field will be appended
+  *        to the provided string builder.
+  * @param is_first_member True if this is the first child member listed under the parent class.
+  * @param cl The ClassInfo object for the parent class of this field.
+  */
+  private static boolean addFields(StringBuilder buf, ArrayList<FieldInfo> fields,
+      boolean is_first_member, ClassInfo cl) {
+    for (FieldInfo field : fields) {
+      if (!field.containingClass().qualifiedName().contains(".internal.")) {
+        if (!is_first_member) {
+          buf.append(",");
+        }
+        buf.append("\n      \"" + field.name() + "\": \"");
+        if (!field.containingClass().qualifiedName().equals(cl.qualifiedName())) {
+          buf.append(field.containingClass().qualifiedName());
+        }
+        buf.append("\"");
+        is_first_member = false;
+      }
+    }
+    return is_first_member;
+  }
+
+  /**
+  * Append the provided string builder with the navtree info for the provided list of methods.
+  *
+  * @param buf The string builder to append to.
+  * @param methods A list of MethodInfo objects. Navtree info for each method will be appended
+  *        to the provided string builder.
+  * @param is_first_member True if this is the first child member listed under the parent class.
+  * @param cl The ClassInfo object for the parent class of this method.
+  */
+  private static boolean addMethods(StringBuilder buf, ArrayList<MethodInfo> methods,
+      boolean is_first_member, ClassInfo cl) {
+    for (MethodInfo method : methods) {
+      if (!method.containingClass().qualifiedName().contains(".internal.")) {
+        if (!is_first_member) {
+          buf.append(",");
+        }
+        buf.append("\n      \"" + method.name() + method.signature() + "\": \"");
+        if (!method.containingClass().qualifiedName().equals(cl.qualifiedName())) {
+          buf.append(method.containingClass().qualifiedName());
+        }
+        buf.append("\"");
+        is_first_member = false;
+      }
+    }
+    return is_first_member;
+  }
+
+}
diff --git a/src/com/google/doclava/ClearPage.java b/src/com/google/doclava/ClearPage.java
index 853e49d..1b4b5ca 100644
--- a/src/com/google/doclava/ClearPage.java
+++ b/src/com/google/doclava/ClearPage.java
@@ -107,9 +107,6 @@
       }
     }
     data.setValue("toroot", toroot);
-    if (Doclava.USE_UPDATED_TEMPLATES) {
-      data.setValue("useUpdatedTemplates", "true");
-    }
     data.setValue("filename", filename);
 
     if (!fullPath) {
diff --git a/src/com/google/doclava/Comment.java b/src/com/google/doclava/Comment.java
index 1a4498f..c0a0e3e 100644
--- a/src/com/google/doclava/Comment.java
+++ b/src/com/google/doclava/Comment.java
@@ -330,7 +330,12 @@
     } else if (name.equals("@see")) {
       mSeeTagsList.add(new SeeTagInfo("@see", "@see", text, mBase, pos));
     } else if (name.equals("@link")) {
-      mInlineTagsList.add(new SeeTagInfo(name, "@see", text, mBase, pos));
+      if (Doclava.DEVSITE_IGNORE_JDLINKS) {
+        TagInfo linkTag = new TextTagInfo(name, name, text, pos);
+        mInlineTagsList.add(linkTag);
+      } else {
+        mInlineTagsList.add(new SeeTagInfo(name, "@see", text, mBase, pos));
+      }
     } else if (name.equals("@linkplain")) {
       mInlineTagsList.add(new SeeTagInfo(name, "@linkplain", text, mBase, pos));
     } else if (name.equals("@value")) {
diff --git a/src/com/google/doclava/DocFile.java b/src/com/google/doclava/DocFile.java
index 1a6746f..9fb25c1 100644
--- a/src/com/google/doclava/DocFile.java
+++ b/src/com/google/doclava/DocFile.java
@@ -12,6 +12,7 @@
  * 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 com.google.doclava;
@@ -51,7 +52,7 @@
     }
   }
 
-  public static String[] DEVSITE_VALID_LANGS = {"en", "es", "in", "ja", "ko",
+  public static String[] DEVSITE_VALID_LANGS = {"en", "es", "id", "in", "ja", "ko",
       "ru", "vi", "zh-cn", "zh-tw", "pt-br"};
 
   public static String getPathRoot(String filename) {
@@ -189,275 +190,151 @@
       // guide, design, distribute, etc.
       filename = getPathRoot(filename);
 
-      if (Doclava.USE_UPDATED_TEMPLATES) {
-        //remap types to design, dev, distribute etc.
-        if (filename.indexOf("design") == 0) {
-          hdf.setValue("design", "true");
-          hdf.setValue("page.type", "design");
-          hdf.setValue("page.category", "design");
-        } else if (filename.indexOf("develop") == 0) {
-          hdf.setValue("develop", "true");
+      // map types to design, dev, distribute etc.
+      if (filename.indexOf("design") == 0) {
+        hdf.setValue("design", "true");
+        hdf.setValue("page.type", "design");
+        hdf.setValue("page.category", "design");
+      } else if (filename.indexOf("develop") == 0) {
+        hdf.setValue("develop", "true");
+        hdf.setValue("page.type", "develop");
+        hdf.setValue("page.category", "develop");
+      } else if (filename.indexOf("guide") == 0) {
+        hdf.setValue("guide", "true");
+        hdf.setValue("page.type", "develop");
+        if (filename.indexOf("guide/topics/manif") == 0) {
+          hdf.setValue("page.category", "app manifest");
+        } else {
+          hdf.setValue("page.category", "guide");
+        }
+      } else if (filename.indexOf("training") == 0) {
+        hdf.setValue("training", "true");
+        hdf.setValue("page.type", "develop");
+        hdf.setValue("page.category", "training");
+      } else if (filename.indexOf("more") == 0) {
+        hdf.setValue("more", "true");
+      } else if (filename.indexOf("google") == 0) {
+        hdf.setValue("google", "true");
+        hdf.setValue("page.type", "develop");
+        hdf.setValue("page.category", "google");
+      } else if (filename.indexOf("samples") == 0) {
+        hdf.setValue("samples", "true");
+        hdf.setValue("samplesDocPage", "true");
+        hdf.setValue("page.type", "develop");
+        hdf.setValue("page.category", "samples");
+        if (Doclava.samplesNavTree != null) {
+          hdf.setValue("samples_toc_tree", Doclava.samplesNavTree.getValue("samples_toc_tree", ""));
+        }
+      } else if (filename.indexOf("topic/") == 0) {
+        hdf.setValue("topic", "true");
+        hdf.setValue("page.type", "develop");
+        if (filename.indexOf("topic/libraries") == 0) {
+          hdf.setValue("page.category", "libraries");
           hdf.setValue("page.type", "develop");
-          hdf.setValue("page.category", "develop");
-        } else if (filename.indexOf("guide") == 0) {
-          hdf.setValue("guide", "true");
+          hdf.setValue("libraries", "true");
+        } else if (filename.indexOf("topic/instant-apps") == 0) {
+          hdf.setValue("instantapps", "true");
           hdf.setValue("page.type", "develop");
-          if (filename.indexOf("guide/topics/manif") == 0) {
-            hdf.setValue("page.category", "app manifest");
-          } else {
-            hdf.setValue("page.category", "guide");
-          }
-        } else if (filename.indexOf("training") == 0) {
-          hdf.setValue("training", "true");
+          hdf.setValue("page.category", "instant apps");
+        } else if (filename.indexOf("topic/performance") == 0) {
+          hdf.setValue("perf", "true");
           hdf.setValue("page.type", "develop");
-          hdf.setValue("page.category", "training");
-        } else if (filename.indexOf("more") == 0) {
-          hdf.setValue("more", "true");
-        } else if (filename.indexOf("google") == 0) {
-          hdf.setValue("google", "true");
+          hdf.setValue("page.category", "performance");
+        } else if (filename.indexOf("topic/arc") == 0) {
+          hdf.setValue("arc", "true");
           hdf.setValue("page.type", "develop");
-          hdf.setValue("page.category", "google");
-        } else if (filename.indexOf("samples") == 0) {
-          hdf.setValue("samples", "true");
-          hdf.setValue("samplesDocPage", "true");
-          hdf.setValue("page.type", "develop");
-          hdf.setValue("page.category", "samples");
-          if (Doclava.samplesNavTree != null) {
-            hdf.setValue("samples_toc_tree", Doclava.samplesNavTree.getValue("samples_toc_tree", ""));
-          }
-        } else if (filename.indexOf("topic/") == 0) {
-          hdf.setValue("topic", "true");
-          hdf.setValue("page.type", "develop");
-          if (filename.indexOf("topic/libraries") == 0) {
-            hdf.setValue("page.category", "libraries");
-            hdf.setValue("page.type", "develop");
-            hdf.setValue("libraries", "true");
-          } else if (filename.indexOf("topic/instant-apps") == 0) {
-            hdf.setValue("instantapps", "true");
-            hdf.setValue("page.type", "develop");
-            hdf.setValue("page.category", "instant apps");
-          }
-        } else if (filename.indexOf("distribute") == 0) {
-          hdf.setValue("distribute", "true");
+          hdf.setValue("page.category", "arc");
+        }
+      } else if (filename.indexOf("distribute") == 0) {
+        hdf.setValue("distribute", "true");
+        hdf.setValue("page.type", "distribute");
+        hdf.setValue("page.category", "distribute");
+        if (filename.indexOf("distribute/googleplay") == 0) {
+          hdf.setValue("page.category", "googleplay");
           hdf.setValue("page.type", "distribute");
-          hdf.setValue("page.category", "distribute");
-          if (filename.indexOf("distribute/googleplay") == 0) {
-            hdf.setValue("page.category", "googleplay");
-            hdf.setValue("page.type", "distribute");
-            hdf.setValue("googleplay", "true");
-          } else if (filename.indexOf("distribute/essentials") == 0) {
-            hdf.setValue("page.category", "essentials");
-            hdf.setValue("essentials", "true");
-          } else if (filename.indexOf("distribute/users") == 0) {
-            hdf.setValue("page.category", "users");
-            hdf.setValue("users", "true");
-          } else if (filename.indexOf("distribute/engage") == 0) {
-            hdf.setValue("page.category", "engage");
-            hdf.setValue("engage", "true");
-          } else if (filename.indexOf("distribute/monetize") == 0) {
-            hdf.setValue("page.category", "monetize");
-            hdf.setValue("monetize", "true");
-          } else if (filename.indexOf("distribute/analyze") == 0) {
-            hdf.setValue("page.category", "analyze");
-            hdf.setValue("analyze", "true");
-          } else if (filename.indexOf("distribute/tools") == 0) {
-            hdf.setValue("page.category", "essentials");
-            hdf.setValue("essentials", "true");
-          } else if (filename.indexOf("distribute/stories") == 0) {
-            hdf.setValue("page.category", "stories");
-            hdf.setValue("stories", "true");
-          }
-        } else if (filename.indexOf("about") == 0) {
-          hdf.setValue("about", "true");
-          hdf.setValue("page.type", "about");
-          hdf.setValue("page.category", "about");
-          if ((filename.indexOf("about/versions") == 0)) {
-            hdf.setValue("versions", "true");
-            hdf.setValue("page.category", "versions");
-          //todo remove this because there's no file at this location
-          } else if ((filename.indexOf("wear") == 0)) {
-            hdf.setValue("wear", "true");
-            hdf.setValue("page.category", "wear");
-          } else if ((filename.indexOf("tv") == 0)) {
-            hdf.setValue("tv", "true");
-            hdf.setValue("page.category", "tv");
-          } else if ((filename.indexOf("auto") == 0)) {
-            hdf.setValue("auto", "true");
-            hdf.setValue("page.category", "auto");
-          }
-        } else if (filename.indexOf("wear/preview") == 0) {
-          hdf.setValue("wearpreview", "true");
-          hdf.setValue("page.type", "about");
-          hdf.setValue("page.category", "wear preview");
-        } else if ((filename.indexOf("tools") == 0) || (filename.indexOf("sdk") == 0)) {
-          hdf.setValue("tools", "true");
-          hdf.setValue("page.type", "develop");
-          hdf.setValue("page.category", "tools");
-          fromTemplate = hdf.getValue("page.template", "");
-        } else if (filename.indexOf("devices") == 0) {
-          hdf.setValue("devices", "true");
-          hdf.setValue("page.type", "devices");
-        } else if (filename.indexOf("source") == 0) {
-          hdf.setValue("source", "true");
-        } else if (filename.indexOf("security") == 0) {
-          hdf.setValue("security", "true");
-        } else if (filename.indexOf("compatibility") == 0) {
-          hdf.setValue("compatibility", "true");
-        } else if (filename.indexOf("wear") == 0) {
+          hdf.setValue("googleplay", "true");
+        } else if (filename.indexOf("distribute/essentials") == 0) {
+          hdf.setValue("page.category", "essentials");
+          hdf.setValue("essentials", "true");
+        } else if (filename.indexOf("distribute/users") == 0) {
+          hdf.setValue("page.category", "users");
+          hdf.setValue("users", "true");
+        } else if (filename.indexOf("distribute/engage") == 0) {
+          hdf.setValue("page.category", "engage");
+          hdf.setValue("engage", "true");
+        } else if (filename.indexOf("distribute/monetize") == 0) {
+          hdf.setValue("page.category", "monetize");
+          hdf.setValue("monetize", "true");
+        } else if (filename.indexOf("distribute/analyze") == 0) {
+          hdf.setValue("page.category", "analyze");
+          hdf.setValue("analyze", "true");
+        } else if (filename.indexOf("distribute/tools") == 0) {
+          hdf.setValue("page.category", "essentials");
+          hdf.setValue("essentials", "true");
+        } else if (filename.indexOf("distribute/stories") == 0) {
+          hdf.setValue("page.category", "stories");
+          hdf.setValue("stories", "true");
+        }
+      } else if (filename.indexOf("about") == 0) {
+        hdf.setValue("about", "true");
+        hdf.setValue("page.type", "about");
+        hdf.setValue("page.category", "about");
+        if ((filename.indexOf("about/versions") == 0)) {
+          hdf.setValue("versions", "true");
+          hdf.setValue("page.category", "versions");
+        //todo remove this because there's no file at this location
+        } else if ((filename.indexOf("wear") == 0)) {
           hdf.setValue("wear", "true");
-          hdf.setValue("about", "true");
-          hdf.setValue("page.type", "about");
           hdf.setValue("page.category", "wear");
-        } else if (filename.indexOf("work") == 0) {
-          hdf.setValue("work", "true");
-          hdf.setValue("page.type", "about");
-          hdf.setValue("page.category", "work");
-        } else if (filename.indexOf("preview") == 0) {
-          hdf.setValue("page.type", "develop");
-          hdf.setValue("page.category", "preview");
-          hdf.setValue("preview", "true");
-        } else if (filename.indexOf("auto") == 0) {
-          hdf.setValue("auto", "true");
-          hdf.setValue("about", "true");
-          hdf.setValue("page.type", "about");
-          hdf.setValue("page.category", "auto");
-        } else if (filename.indexOf("tv") == 0) {
+        } else if ((filename.indexOf("tv") == 0)) {
           hdf.setValue("tv", "true");
-          hdf.setValue("about", "true");
-          hdf.setValue("page.type", "about");
           hdf.setValue("page.category", "tv");
-        } else if (filename.indexOf("ndk") == 0) {
-          hdf.setValue("ndk", "true");
-          hdf.setValue("page.type", "ndk");
-          hdf.setValue("page.category", "ndk");
-          if (filename.indexOf("ndk/guides") == 0) {
-            hdf.setValue("guide", "true");
-            hdf.setValue("page.type", "ndk");
-            hdf.setValue("page.category", "guide");
-          } else if (filename.indexOf("ndk/reference") == 0) {
-            hdf.setValue("reference", "true");
-            hdf.setValue("page.type", "ndk");
-            hdf.setValue("page.category", "reference");
-          } else if (filename.indexOf("ndk/samples") == 0) {
-            hdf.setValue("samples", "true");
-            hdf.setValue("page.type", "ndk");
-            hdf.setValue("page.category", "samples");
-            hdf.setValue("samplesDocPage", "true");
-          } else if (filename.indexOf("ndk/downloads") == 0) {
-            hdf.setValue("downloads", "true");
-            hdf.setValue("page.type", "ndk");
-            hdf.setValue("page.category", "downloads");
-            fromTemplate = hdf.getValue("page.template", "");
-          }
-        }
-      } else {
-        //support the old mappings
-        if (filename.indexOf("design") == 0) {
-          hdf.setValue("design", "true");
-          hdf.setValue("page.type", "design");
-        } else if (filename.indexOf("develop") == 0) {
-          hdf.setValue("develop", "true");
-          hdf.setValue("page.type", "develop");
-        } else if (filename.indexOf("guide") == 0) {
-          hdf.setValue("guide", "true");
-          hdf.setValue("page.type", "guide");
-        } else if (filename.indexOf("training") == 0) {
-          hdf.setValue("training", "true");
-          hdf.setValue("page.type", "training");
-        } else if (filename.indexOf("more") == 0) {
-          hdf.setValue("more", "true");
-        } else if (filename.indexOf("google") == 0) {
-          hdf.setValue("google", "true");
-          hdf.setValue("page.type", "google");
-        } else if (filename.indexOf("samples") == 0) {
-          hdf.setValue("samples", "true");
-          hdf.setValue("samplesDocPage", "true");
-          hdf.setValue("page.type", "samples");
-          if (Doclava.samplesNavTree != null) {
-            hdf.setValue("samples_toc_tree", Doclava.samplesNavTree.getValue("samples_toc_tree", ""));
-          }
-        } else if (filename.indexOf("distribute") == 0) {
-          hdf.setValue("distribute", "true");
-          hdf.setValue("page.type", "distribute");
-          if (filename.indexOf("distribute/googleplay") == 0) {
-            hdf.setValue("googleplay", "true");
-          } else if (filename.indexOf("distribute/essentials") == 0) {
-            hdf.setValue("essentials", "true");
-          } else if (filename.indexOf("distribute/users") == 0) {
-            hdf.setValue("users", "true");
-          } else if (filename.indexOf("distribute/engage") == 0) {
-            hdf.setValue("engage", "true");
-          } else if (filename.indexOf("distribute/monetize") == 0) {
-            hdf.setValue("monetize", "true");
-          } else if (filename.indexOf("distribute/analyze") == 0) {
-            hdf.setValue("analyze", "true");
-          } else if (filename.indexOf("distribute/tools") == 0) {
-            hdf.setValue("essentials", "true");
-          } else if (filename.indexOf("distribute/stories") == 0) {
-            hdf.setValue("stories", "true");
-          }
-        } else if (filename.indexOf("about") == 0) {
-          hdf.setValue("about", "true");
-          hdf.setValue("page.type", "about");
-        } else if ((filename.indexOf("tools") == 0) || (filename.indexOf("sdk") == 0)) {
-          hdf.setValue("tools", "true");
-          hdf.setValue("page.type", "tools");
-          fromTemplate = hdf.getValue("page.template", "");
-        } else if (filename.indexOf("devices") == 0) {
-          hdf.setValue("devices", "true");
-          hdf.setValue("page.type", "devices");
-        } else if (filename.indexOf("source") == 0) {
-          hdf.setValue("source", "true");
-        } else if (filename.indexOf("security") == 0) {
-          hdf.setValue("security", "true");
-        } else if (filename.indexOf("compatibility") == 0) {
-          hdf.setValue("compatibility", "true");
-        } else if (filename.indexOf("topic/") == 0) {
-          hdf.setValue("topic", "true");
-          hdf.setValue("page.type", "develop");
-          if (filename.indexOf("topic/libraries") == 0) {
-            hdf.setValue("page.category", "libraries");
-            hdf.setValue("page.type", "develop");
-            hdf.setValue("libraries", "true");
-          } else if (filename.indexOf("topic/instant-apps") == 0) {
-            hdf.setValue("instantapps", "true");
-            hdf.setValue("page.type", "develop");
-            hdf.setValue("page.category", "instant apps");
-          }
-        } else if (filename.indexOf("wear/preview") == 0) {
-          hdf.setValue("wearpreview", "true");
-          hdf.setValue("page.type", "about");
-          hdf.setValue("page.category", "wear preview");
-        } else if (filename.indexOf("wear") == 0) {
-          hdf.setValue("wear", "true");
-        } else if (filename.indexOf("work") == 0) {
-          hdf.setValue("work", "true");
-          hdf.setValue("page.type", "about");
-          hdf.setValue("page.category", "work");
-        } else if (filename.indexOf("preview") == 0) {
-          hdf.setValue("page.type", "preview");
-          hdf.setValue("page.category", "preview");
-          hdf.setValue("preview", "true");
-        } else if (filename.indexOf("auto") == 0) {
+        } else if ((filename.indexOf("auto") == 0)) {
           hdf.setValue("auto", "true");
-        } else if (filename.indexOf("tv") == 0) {
-          hdf.setValue("tv", "true");
-        } else if (filename.indexOf("ndk") == 0) {
-          hdf.setValue("ndk", "true");
-          hdf.setValue("page.type", "ndk");
-          if (filename.indexOf("ndk/guides") == 0) {
-            hdf.setValue("guide", "true");
-          } else if (filename.indexOf("ndk/reference") == 0) {
-            hdf.setValue("reference", "true");
-          } else if (filename.indexOf("ndk/samples") == 0) {
-            hdf.setValue("samples", "true");
-            hdf.setValue("samplesDocPage", "true");
-          } else if (filename.indexOf("ndk/downloads") == 0) {
-            hdf.setValue("downloads", "true");
-            fromTemplate = hdf.getValue("page.template", "");
-          }
+          hdf.setValue("page.category", "auto");
         }
+      } else if (filename.indexOf("wear/preview") == 0) {
+        hdf.setValue("wearpreview", "true");
+        hdf.setValue("page.type", "about");
+        hdf.setValue("page.category", "wear preview");
+      } else if (filename.indexOf("devices") == 0) {
+        hdf.setValue("devices", "true");
+        hdf.setValue("page.type", "devices");
+      } else if (filename.indexOf("source") == 0) {
+        hdf.setValue("source", "true");
+      } else if (filename.indexOf("security") == 0) {
+        hdf.setValue("security", "true");
+      } else if (filename.indexOf("compatibility") == 0) {
+        hdf.setValue("compatibility", "true");
+      } else if (filename.indexOf("wear") == 0) {
+        hdf.setValue("wear", "true");
+        hdf.setValue("about", "true");
+        hdf.setValue("page.type", "about");
+        hdf.setValue("page.category", "wear");
+      } else if (filename.indexOf("work") == 0) {
+        hdf.setValue("work", "true");
+        hdf.setValue("page.type", "about");
+        hdf.setValue("page.category", "work");
+      } else if (filename.indexOf("preview") == 0) {
+        hdf.setValue("page.type", "develop");
+        hdf.setValue("page.category", "preview");
+        hdf.setValue("preview", "true");
+      } else if (filename.indexOf("auto") == 0) {
+        hdf.setValue("auto", "true");
+        hdf.setValue("about", "true");
+        hdf.setValue("page.type", "about");
+        hdf.setValue("page.category", "auto");
+      } else if (filename.indexOf("tv") == 0) {
+        hdf.setValue("tv", "true");
+        hdf.setValue("about", "true");
+        hdf.setValue("page.type", "about");
+        hdf.setValue("page.category", "tv");
+      } else {
+        hdf.setValue("about", "true");
+        hdf.setValue("page.type", "about");
+        hdf.setValue("page.category", "about");
       }
+      
       //set metadata for this file in jd_lists_unified
       PageMetadata.setPageMetadata(docfile, relative, outfile, hdf, Doclava.sTaglist);
 
@@ -466,11 +343,7 @@
         outfile = outfile.replaceFirst("^intl/", "");
       }
 
-      if (fromTemplate.equals("sdk")) {
-        ClearPage.write(hdf, "sdkpage.cs", outfile);
-      } else {
-        ClearPage.write(hdf, "docpage.cs", outfile);
-      }
+      ClearPage.write(hdf, "docpage.cs", outfile);
     }
   } // writePage
 }
diff --git a/src/com/google/doclava/Doclava.java b/src/com/google/doclava/Doclava.java
index 4e5bc91..385b2f7 100644
--- a/src/com/google/doclava/Doclava.java
+++ b/src/com/google/doclava/Doclava.java
@@ -68,12 +68,18 @@
   public static final boolean SORT_BY_NAV_GROUPS = true;
   /* Debug output for PageMetadata, format urls from site root */
   public static boolean META_DBG=false;
-  /* Remove after updated templates are launched */
-  public static boolean USE_UPDATED_TEMPLATES = false;
+  /* Generate the static html docs with devsite tempating only */
+  public static boolean DEVSITE_STATIC_ONLY = false;
+  /* Don't resolve @link refs found in devsite pages */
+  public static boolean DEVSITE_IGNORE_JDLINKS = false;
   /* Show Preview navigation and process preview docs */
   public static boolean INCLUDE_PREVIEW = false;
   /* output en, es, ja without parent intl/ container */
   public static boolean USE_DEVSITE_LOCALE_OUTPUT_PATHS = false;
+  /* generate navtree.js without other docs */
+  public static boolean NAVTREE_ONLY = false;
+  /* Generate reference navtree.js with all inherited members */
+  public static boolean AT_LINKS_NAVTREE = false;
   public static String outputPathBase = "/";
   public static ArrayList<String> inputPathHtmlDirs = new ArrayList<String>();
   public static ArrayList<String> inputPathHtmlDir2 = new ArrayList<String>();
@@ -105,6 +111,7 @@
   public static String documentAnnotationsPath = null;
   public static Map<String, String> annotationDocumentationMap = null;
   public static boolean referenceOnly = false;
+  public static boolean staticOnly = false;
 
   public static JSilver jSilver = null;
 
@@ -177,12 +184,7 @@
       if (a[0].equals("-d")) {
         outputPathBase = outputPathHtmlDirs = ClearPage.outputDir = a[1];
       } else if (a[0].equals("-templatedir")) {
-        if (USE_UPDATED_TEMPLATES) {
-          /* remove with updated templates are launched */
-          ClearPage.addTemplateDir("build/tools/droiddoc/templates-sdk-dev");
-        } else {
-          ClearPage.addTemplateDir(a[1]);
-        }
+        ClearPage.addTemplateDir(a[1]);
       } else if (a[0].equals("-hdf")) {
         mHDFData.add(new String[] {a[1], a[2]});
       } else if (a[0].equals("-knowntags")) {
@@ -202,7 +204,7 @@
       //the destination output path for additional htmldir
       } else if (a[0].equals("-htmldir2")) {
           if (a[2].equals("default")) {
-          inputPathHtmlDirs.add(a[1]);
+          inputPathHtmlDir2.add(a[1]);
         } else {
           inputPathHtmlDir2.add(a[1]);
           outputPathHtmlDir2 = a[2];
@@ -276,10 +278,12 @@
         offlineMode = true;
       } else if (a[0].equals("-metadataDebug")) {
         META_DBG = true;
-      } else if (a[0].equals("-useUpdatedTemplates")) {
-        USE_UPDATED_TEMPLATES = true;
       } else if (a[0].equals("-includePreview")) {
         INCLUDE_PREVIEW = true;
+      } else if (a[0].equals("-ignoreJdLinks")) {
+        if (DEVSITE_STATIC_ONLY) {
+          DEVSITE_IGNORE_JDLINKS = true;
+        }
       } else if (a[0].equals("-federate")) {
         try {
           String name = a[1];
@@ -295,17 +299,29 @@
         federationTagger.addSiteApi(name, file);
       } else if (a[0].equals("-yaml")) {
         yamlNavFile = a[1];
-      } else if (a[0].equals("-devsite")) {
-        // Don't copy the doclava assets to devsite output (ie use proj assets only)
-        includeDefaultAssets = false;
-        USE_DEVSITE_LOCALE_OUTPUT_PATHS = true;
-        mHDFData.add(new String[] {"devsite", "true"});
       } else if (a[0].equals("-documentannotations")) {
         documentAnnotations = true;
         documentAnnotationsPath = a[1];
       } else if (a[0].equals("-referenceonly")) {
         referenceOnly = true;
         mHDFData.add(new String[] {"referenceonly", "1"});
+      } else if (a[0].equals("-staticonly")) {
+        staticOnly = true;
+        mHDFData.add(new String[] {"staticonly", "1"});
+      } else if (a[0].equals("-navtreeonly")) {
+        NAVTREE_ONLY = true;
+      } else if (a[0].equals("-atLinksNavtree")) {
+        AT_LINKS_NAVTREE = true;
+      } else if (a[0].equals("-devsite")) {
+        // Don't copy the doclava assets to devsite output (ie use proj assets only)
+        includeDefaultAssets = false;
+        USE_DEVSITE_LOCALE_OUTPUT_PATHS = true;
+        mHDFData.add(new String[] {"devsite", "1"});
+        if (staticOnly) {
+          DEVSITE_STATIC_ONLY = true;
+          System.out.println("  ... Generating static html only for devsite");
+        }
+        yamlNavFile = "_book.yaml";
       }
     }
 
@@ -340,27 +356,37 @@
         return false;
       }
 
-      //startTime = System.nanoTime();
-
-      // Apply @since tags from the XML file
-      sinceTagger.tagAll(Converter.rootClasses());
-
-      // Apply details of federated documentation
-      federationTagger.tagAll(Converter.rootClasses());
-
-      // Files for proofreading
-      if (proofreadFile != null) {
-        Proofread.initProofread(proofreadFile);
-      }
-      if (todoFile != null) {
-        TodoFile.writeTodoFile(todoFile);
+      // if requested, only generate the navtree for ds use-case
+      if (NAVTREE_ONLY) {
+        if (AT_LINKS_NAVTREE) {
+          AtLinksNavTree.writeAtLinksNavTree(javadocDir);
+        } else {
+          NavTree.writeNavTree(javadocDir, "");
+        }
+        return true;
       }
 
-      if (samplesRef) {
-        // always write samples without offlineMode behaviors
-        writeSamples(false, sampleCodes, SORT_BY_NAV_GROUPS);
-      }
+      // don't do ref doc tasks in devsite static-only builds
+      if (!DEVSITE_STATIC_ONLY) {
+        // Apply @since tags from the XML file
+        sinceTagger.tagAll(Converter.rootClasses());
 
+        // Apply details of federated documentation
+        federationTagger.tagAll(Converter.rootClasses());
+
+        // Files for proofreading
+        if (proofreadFile != null) {
+          Proofread.initProofread(proofreadFile);
+        }
+        if (todoFile != null) {
+          TodoFile.writeTodoFile(todoFile);
+        }
+
+        if (samplesRef) {
+          // always write samples without offlineMode behaviors
+          writeSamples(false, sampleCodes, SORT_BY_NAV_GROUPS);
+        }
+      }
       if (!referenceOnly) {
         // HTML2 Pages -- Generate Pages from optional secondary dir
         if (!inputPathHtmlDir2.isEmpty()) {
@@ -386,49 +412,52 @@
 
       writeAssets();
 
-      // Navigation tree
-      String refPrefix = new String();
-      if(gmsRef){
-        refPrefix = "gms-";
-      } else if(gcmRef){
-        refPrefix = "gcm-";
+      // don't do ref doc tasks in devsite static-only builds
+      if (!DEVSITE_STATIC_ONLY) {
+        // Navigation tree
+        String refPrefix = new String();
+        if(gmsRef){
+          refPrefix = "gms-";
+        } else if(gcmRef){
+          refPrefix = "gcm-";
+        }
+        NavTree.writeNavTree(javadocDir, refPrefix);
+
+        // Write yaml tree.
+        if (yamlNavFile != null){
+          NavTree.writeYamlTree(javadocDir, yamlNavFile);
+        }
+
+        // Packages Pages
+        writePackages(javadocDir + refPrefix + "packages" + htmlExtension);
+
+        // Classes
+        writeClassLists();
+        writeClasses();
+        writeHierarchy();
+        // writeKeywords();
+
+        // Lists for JavaScript
+        writeLists();
+        if (keepListFile != null) {
+          writeKeepList(keepListFile);
+        }
+
+        // Index page
+        writeIndex();
+
+        Proofread.finishProofread(proofreadFile);
+
+        if (sdkValuePath != null) {
+          writeSdkValues(sdkValuePath);
+        }
       }
-      NavTree.writeNavTree(javadocDir, refPrefix);
-
-      // Write yaml tree.
-      if (yamlNavFile != null){
-        NavTree.writeYamlTree(javadocDir, yamlNavFile);
-      }
-
-      // Packages Pages
-      writePackages(javadocDir + refPrefix + "packages" + htmlExtension);
-
-      // Classes
-  writeClassLists();
-  writeClasses();
-  writeHierarchy();
-      // writeKeywords();
-
-      // Lists for JavaScript
-  writeLists();
-      if (keepListFile != null) {
-        writeKeepList(keepListFile);
-      }
-
-      // Index page
-  writeIndex();
-
-  Proofread.finishProofread(proofreadFile);
-
-  if (sdkValuePath != null) {
-    writeSdkValues(sdkValuePath);
-  }
-      // Write metadata for all processed files to jd_lists_unified.js in out dir
+      // Write metadata for all processed files to jd_lists_unified in out dir
       if (!sTaglist.isEmpty()) {
-        if (USE_UPDATED_TEMPLATES) {
-          PageMetadata.WriteListByLang(sTaglist);
-        } else {
-          PageMetadata.WriteList(sTaglist);
+        PageMetadata.WriteListByLang(sTaglist);
+        // For devsite (ds) reference only, write samples_metadata to out dir
+        if ((USE_DEVSITE_LOCALE_OUTPUT_PATHS) && (!DEVSITE_STATIC_ONLY)) {
+          PageMetadata.WriteSamplesListByLang(sTaglist);
         }
       }
     }
@@ -599,6 +628,9 @@
     if (option.equals("-devsite")) {
       return 1;
     }
+    if (option.equals("-ignoreJdLinks")) {
+      return 1;
+    }
     if (option.equals("-htmldir")) {
       return 2;
     }
@@ -714,9 +746,6 @@
     if (option.equals("-metadataDebug")) {
       return 1;
     }
-    if (option.equals("-useUpdatedTemplates")) {
-      return 1;
-    }
     if (option.equals("-includePreview")) {
       return 1;
     }
@@ -726,6 +755,15 @@
     if (option.equals("-referenceonly")) {
       return 1;
     }
+    if (option.equals("-staticonly")) {
+      return 1;
+    }
+    if (option.equals("-navtreeonly")) {
+      return 1;
+    }
+    if (option.equals("-atLinksNavtree")) {
+      return 1;
+    }
     return 0;
   }
   public static boolean validOptions(String[][] options, DocErrorReporter r) {
diff --git a/src/com/google/doclava/PageMetadata.java b/src/com/google/doclava/PageMetadata.java
index ca4ecf3..8774d48 100644
--- a/src/com/google/doclava/PageMetadata.java
+++ b/src/com/google/doclava/PageMetadata.java
@@ -92,9 +92,9 @@
   *
   * @param rootTypeNodesList A list of root metadata nodes, each
   *        representing a type and it's member child pages.
+  * @deprecated
   */
   public static void WriteList(List<Node> rootTypeNodesList) {
-
     Collections.sort(rootTypeNodesList, BY_TYPE_NAME);
     Node pageMeta = new Node.Builder().setLabel("TOP").setChildren(rootTypeNodesList).build();
 
@@ -105,7 +105,7 @@
     // write the taglist to js file
     Data data = Doclava.makeHDF();
     data.setValue("reference_tree", buf.toString());
-    ClearPage.write(data, "jd_lists_unified.cs", "jd_lists_unified.js");
+    ClearPage.write(data, "jd_lists_unified.cs",  "jd_lists_unified.js");
   }
 
   /**
@@ -143,6 +143,42 @@
   }
 
   /**
+  * Given a list of metadata nodes organized by lang, sort the
+  * root nodes by type name and render the types and their child
+  * samples metadata nodes only to separate lang-specific json files
+  * in the out dir. Only used by devsite (ds) builds.
+  *
+  * @param rootNodesList A list of root metadata nodes, each
+  *        representing a type and it's member child pages.
+  */
+  public static void WriteSamplesListByLang(List<Node> rootNodesList) {
+    Collections.sort(rootNodesList, BY_LANG_NAME);
+    for (Node n : rootNodesList) {
+      boolean langHasSamples = false;
+      String langFilename = "";
+      String langname = n.getLang();
+      langFilename = "_" + langname;
+      Collections.sort(n.getChildren(), BY_TYPE_NAME);
+      Node pageMeta = new Node.Builder().setLabel("TOP").setChildren(n.getChildren()).build();
+
+      StringBuilder buf = new StringBuilder();
+      // write the taglist to string format
+      langHasSamples = pageMeta.renderSamplesResources(buf,langname);
+      // write the taglist to js file
+      Data data = Doclava.makeHDF();
+      data.setValue("reference_tree", buf.toString());
+      data.setValue("metadata.lang", langname);
+
+      if (langHasSamples) {
+        data.setValue("samples_only", "1");
+        // write out jd_lists_unified for each lang
+        String unifiedFilename = "android_samples_metadata" + langFilename + ".js";
+        ClearPage.write(data, "jd_lists_unified.cs", unifiedFilename);
+      }
+    }
+  }
+
+  /**
   * Extract supported metadata values from a page and add them as
   * a child node of a root node based on type. Some metadata values
   * are normalized. Unsupported metadata fields are ignored. See
@@ -181,11 +217,7 @@
       pageMeta.setLang(getLangStringNormalized(hdf, filename));
       pageMeta.setType(getStringValueNormalized(hdf, "page.type"));
       pageMeta.setTimestamp(hdf.getValue("page.timestamp",""));
-      if (Doclava.USE_UPDATED_TEMPLATES) {
-        appendMetaNodeByLang(pageMeta, tagList);
-      } else {
-        appendMetaNodeByType(pageMeta, tagList);
-      }
+      appendMetaNodeByLang(pageMeta, tagList);
     }
   }
 
@@ -267,6 +299,7 @@
             XPathConstants.NODESET);
         if (imgNodes.getLength() > 0) {
           imageUrl = imgNodes.item(0).getNodeValue();
+          imageUrl = getImageUrlNormalized(imageUrl);
           imgFrom = "itemprop";
         } else {
           XPathExpression FirstImgExpr = xpath.compile("//img/@src");
@@ -375,7 +408,7 @@
       }
       outString.append(tagList.trim());
       return outString.toString();
-    } 
+    }
   }
 
   /**
@@ -635,15 +668,6 @@
     File f = new File(ClearPage.outputDir + "/" + extrasFilename);
     if (f.exists() && !f.isDirectory()) {
       ClearPage.copyFile(true, f, unifiedFilename, true);
-      try {
-        if (f.delete()) {
-          if (Doclava.META_DBG) System.out.println("    >>>>> Delete succeeded");
-        } else {
-          if (Doclava.META_DBG) System.out.println("    >>>>> Delete failed");
-        }
-      } catch (Exception e) {
-        if (Doclava.META_DBG) System.out.println("    >>>>> Exception: " + e + "\n");
-      }
     }
   }
 
@@ -757,6 +781,31 @@
         }
       }
     }
+
+    /**
+    * Render a tree of metadata nodes of type 'develop' to extract
+    * samples metadata. Only used by devsite (ds) builds.
+    * @param buf Output buffer to render to.
+    * @return true if samples were rendered to buf
+    */
+    boolean renderSamplesResources(StringBuilder buf, String langname) {
+      boolean langHasSamples = false;
+      List<Node> list = mChildren; //list of type rootnodes
+      if (list == null || list.size() == 0) {
+        buf.append("null");
+      } else {
+        final int n = list.size();
+        for (int i = 0; i < n; i++) {
+          //samples are always in type 'develop', so restrict
+          if ("develop".equals(list.get(i).mType)) {
+            //render this type's children
+            langHasSamples = list.get(i).renderTypeForSamples(buf);
+          }
+        }
+      }
+      return langHasSamples;
+    }
+
     /**
     * Render all metadata nodes for a specific type.
     * @param buf Output buffer to render to.
@@ -805,6 +854,61 @@
     }
 
     /**
+    * Render all metadata nodes for samples only.
+    * Only used by devsite (ds) builds.
+    * @param buf Output buffer to render to.
+    * @return whether any samples were rendered to buf
+    */
+    boolean renderTypeForSamples(StringBuilder buf) {
+      boolean typeHasSamples = false;
+      List<Node> list = mChildren;
+      if (list == null || list.size() == 0) {
+        buf.append("nulltype");
+      } else {
+        final int n = list.size();
+        for (int i = 0; i < n; i++) {
+          // valid samples must have category 'samples'
+          if ("samples".equals(list.get(i).mCategory)) {
+            typeHasSamples = true;
+            buf.append("\n      {\n");
+            buf.append("        \"title\":\"");
+            renderStrWithUcs(buf, list.get(i).mLabel);
+            buf.append("\",\n" );
+            buf.append("        \"summary\":\"");
+            renderStrWithUcs(buf, list.get(i).mSummary);
+            buf.append("\",\n" );
+            buf.append("        \"url\":\"" + list.get(i).mLink + "\",\n" );
+            if (!"".equals(list.get(i).mImage)) {
+              buf.append("        \"image\":\"" + list.get(i).mImage + "\",\n" );
+            }
+            if (!"".equals(list.get(i).mGroup)) {
+              buf.append("        \"group\":\"");
+              renderStrWithUcs(buf, list.get(i).mGroup);
+              buf.append("\",\n" );
+            }
+            if (!"".equals(list.get(i).mCategory)) {
+              buf.append("        \"category\":\"" + list.get(i).mCategory + "\",\n" );
+            }
+            if ((list.get(i).mType != null) && (list.get(i).mType != "")) {
+              buf.append("        \"type\":\"" + list.get(i).mType + "\",\n");
+            }
+            list.get(i).renderArrayType(buf, list.get(i).mKeywords, "keywords");
+            list.get(i).renderArrayType(buf, list.get(i).mTags, "tags");
+            if (!"".equals(list.get(i).mTimestamp)) {
+              buf.append("        \"timestamp\":\"" + list.get(i).mTimestamp + "\",\n");
+            }
+            buf.append("        \"lang\":\"" + list.get(i).mLang + "\"" );
+            buf.append("\n      }");
+            if (i != n - 1) {
+              buf.append(", ");
+            }
+          }
+        }
+      }
+      return typeHasSamples;
+    }
+
+    /**
     * Build and render a list of tags associated with each type.
     * @param buf Output buffer to render to.
     */
@@ -896,7 +1000,7 @@
           buf.append(String.format("\\u%04x",codePoint));
         } else if (c >= ' ' && c <= '~' && c != '\\') {
           buf.append(c);
-        } else { 
+        } else {
           // we are encoding a two byte character
           buf.append(String.format("\\u%04x", (int) c));
         }
diff --git a/src/com/google/doclava/TypeInfo.java b/src/com/google/doclava/TypeInfo.java
index ad26def..689ff88 100644
--- a/src/com/google/doclava/TypeInfo.java
+++ b/src/com/google/doclava/TypeInfo.java
@@ -54,7 +54,6 @@
         if (c == ',' && bracketNesting == 0) {
           String entry = typeString.substring(entryStartPos, i).trim();
           TypeInfo info = new TypeInfo(entry);
-          info.setIsTypeVariable(true);
           generics.add(info);
           entryStartPos = i + 1;
         } else if (c == '<') {
@@ -70,8 +69,8 @@
       }
 
       TypeInfo info = new TypeInfo(typeString.substring(entryStartPos, paramEndPos).trim());
-      info.setIsTypeVariable(true);
       generics.add(info);
+      addResolution(new Resolution("variability", "", null));
 
       mTypeArguments = generics;
 
@@ -483,6 +482,13 @@
               } else {
                   mClass = InfoBuilder.Caches.obtainClass(qualifiedClassName.toString());
               }
+          } else if ("variability".equals(resolution.getVariable())) {
+              StringBuilder qualifiedClassName = new StringBuilder();
+              for (TypeInfo arg : mTypeArguments) {
+                InfoBuilder.resolveQualifiedName(arg.simpleTypeName(), qualifiedClassName,
+                        resolution.getInfoBuilder());
+                arg.setIsTypeVariable(!("".equals(qualifiedClassName.toString())));
+              }
           }
       }
 
diff --git a/src/com/google/doclava/apicheck/ApiFile.java b/src/com/google/doclava/apicheck/ApiFile.java
index d865e20..14a8ab3 100644
--- a/src/com/google/doclava/apicheck/ApiFile.java
+++ b/src/com/google/doclava/apicheck/ApiFile.java
@@ -166,11 +166,13 @@
     name = token;
     qname = qualifiedName(pkg.name(), name, null);
     final TypeInfo typeInfo = Converter.obtainTypeFromString(qname);
+    // Simple type info excludes the package name (but includes enclosing class names)
+    final TypeInfo simpleTypeInfo = Converter.obtainTypeFromString(name);
     token = tokenizer.requireToken();
-    cl = new ClassInfo(null/*classDoc*/, ""/*rawCommentText*/, tokenizer.pos(), pub, prot, 
-        pkgpriv, false/*isPrivate*/, stat, iface, abs, true/*isOrdinaryClass*/, 
+    cl = new ClassInfo(null/*classDoc*/, ""/*rawCommentText*/, tokenizer.pos(), pub, prot,
+        pkgpriv, false/*isPrivate*/, stat, iface, abs, true/*isOrdinaryClass*/,
         false/*isException*/, false/*isError*/, false/*isEnum*/, false/*isAnnotation*/,
-        fin, false/*isIncluded*/, typeInfo.simpleTypeName(), typeInfo.qualifiedTypeName(),
+        fin, false/*isIncluded*/, simpleTypeInfo.qualifiedTypeName(), typeInfo.qualifiedTypeName(),
         null/*qualifiedTypeName*/, false/*isPrimitive*/);
     cl.setTypeInfo(typeInfo);
     cl.setDeprecated(dep);
@@ -755,4 +757,3 @@
     return true;
   }
 }
-