Home | History | Annotate | Download | only in doclava
      1 /*
      2  * Copyright (C) 2016 Google Inc.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.google.doclava;
     18 
     19 import com.google.clearsilver.jsilver.data.Data;
     20 
     21 import java.util.ArrayList;
     22 
     23 /**
     24 * Class for writing a JSON dictionary of Android package/class/member info that can be used for
     25 * dereferencing javadoc style {@link} tags.
     26 */
     27 
     28 public class AtLinksNavTree {
     29 
     30   /**
     31   * Write a JSON dictionary of Android package/class/member info. The hierarchy will follow this
     32   * format: package name -> class name -> member name and signature -> parent package.class name
     33   * if the member was inherited (or an empty string if the member was not inherited).
     34   *
     35   * <p>For example:
     36   * <pre>{
     37   *   "android": {
     38   *     "Manifest": {
     39   *       "Manifest()": "",
     40   *       "clone()": "java.lang.Object",
     41   *       "equals(java.lang.Object)": "java.lang.Object",
     42   *       ...
     43   *     },
     44   *     ...
     45   *   },
     46   *   ...
     47   * }</pre>
     48   *
     49   * @param dir The directory path to prepend to the output path if the generated navtree is for
     50   *        one the a supplemental library references (such as the wearable support library)
     51   */
     52   public static void writeAtLinksNavTree(String dir) {
     53     StringBuilder buf = new StringBuilder();
     54 
     55     buf.append("{");
     56     addPackages(buf, Doclava.choosePackages());
     57     buf.append("\n}");
     58 
     59     Data data = Doclava.makeHDF();
     60     data.setValue("navtree", buf.toString());
     61 
     62     String output_path;
     63     if (Doclava.USE_DEVSITE_LOCALE_OUTPUT_PATHS && (Doclava.libraryRoot != null)) {
     64       output_path = dir + Doclava.libraryRoot + "at_links_navtree.json";
     65     } else {
     66       output_path = "at_links_navtree.json";
     67     }
     68 
     69     ClearPage.write(data, "at_links_navtree.cs", output_path);
     70   }
     71 
     72   /**
     73   * Append the provided string builder with the navtree info for the provided list of packages.
     74   *
     75   * @param buf The string builder to append to.
     76   * @param packages A list of PackageInfo objects. Navtree info for each package will be appended
     77   *        to the provided string builder.
     78   */
     79   private static void addPackages(StringBuilder buf, PackageInfo[] packages) {
     80     boolean is_first_package = true;
     81     for (PackageInfo pkg : Doclava.choosePackages()) {
     82       if (!pkg.name().contains(".internal.")) {
     83         if (!is_first_package) {
     84           buf.append(",");
     85         }
     86         buf.append("\n  \"" + pkg.name() + "\": {");
     87 
     88         boolean is_first_class = true;
     89         is_first_class = addClasses(buf, pkg.annotations(), is_first_class);
     90         is_first_class = addClasses(buf, pkg.interfaces(), is_first_class);
     91         is_first_class = addClasses(buf, pkg.ordinaryClasses(), is_first_class);
     92         is_first_class = addClasses(buf, pkg.enums(), is_first_class);
     93         is_first_class = addClasses(buf, pkg.exceptions(), is_first_class);
     94         addClasses(buf, pkg.errors(), is_first_class);
     95 
     96         buf.append("\n  }");
     97         is_first_package = false;
     98       }
     99     }
    100   }
    101 
    102   /**
    103   * Append the provided string builder with the navtree info for the provided list of classes.
    104   *
    105   * @param buf The string builder to append to.
    106   * @param classes A list of ClassInfo objects. Navtree info for each class will be appended
    107   *        to the provided string builder.
    108   * @param is_first_class True if this is the first child class listed under the parent package.
    109   */
    110   private static boolean addClasses(StringBuilder buf, ClassInfo[] classes,
    111       boolean is_first_class) {
    112     for (ClassInfo cl : classes) {
    113       if (!is_first_class) {
    114         buf.append(",");
    115       }
    116       buf.append("\n    \"" + cl.name() + "\": {");
    117 
    118       boolean is_first_member = true;
    119       is_first_member = addFields(buf, cl.fields(), is_first_member, cl);
    120       is_first_member = addMethods(buf, cl.constructors(), is_first_member, cl);
    121       addMethods(buf, cl.methods(), is_first_member, cl);
    122 
    123       buf.append("\n    }");
    124       is_first_class = false;
    125     }
    126     return is_first_class;
    127   }
    128 
    129   /**
    130   * Append the provided string builder with the navtree info for the provided list of fields.
    131   *
    132   * @param buf The string builder to append to.
    133   * @param fields A list of FieldInfo objects. Navtree info for each field will be appended
    134   *        to the provided string builder.
    135   * @param is_first_member True if this is the first child member listed under the parent class.
    136   * @param cl The ClassInfo object for the parent class of this field.
    137   */
    138   private static boolean addFields(StringBuilder buf, ArrayList<FieldInfo> fields,
    139       boolean is_first_member, ClassInfo cl) {
    140     for (FieldInfo field : fields) {
    141       if (!field.containingClass().qualifiedName().contains(".internal.")) {
    142         if (!is_first_member) {
    143           buf.append(",");
    144         }
    145         buf.append("\n      \"" + field.name() + "\": \"");
    146         if (!field.containingClass().qualifiedName().equals(cl.qualifiedName())) {
    147           buf.append(field.containingClass().qualifiedName());
    148         }
    149         buf.append("\"");
    150         is_first_member = false;
    151       }
    152     }
    153     return is_first_member;
    154   }
    155 
    156   /**
    157   * Append the provided string builder with the navtree info for the provided list of methods.
    158   *
    159   * @param buf The string builder to append to.
    160   * @param methods A list of MethodInfo objects. Navtree info for each method will be appended
    161   *        to the provided string builder.
    162   * @param is_first_member True if this is the first child member listed under the parent class.
    163   * @param cl The ClassInfo object for the parent class of this method.
    164   */
    165   private static boolean addMethods(StringBuilder buf, ArrayList<MethodInfo> methods,
    166       boolean is_first_member, ClassInfo cl) {
    167     for (MethodInfo method : methods) {
    168       if (!method.containingClass().qualifiedName().contains(".internal.")) {
    169         if (!is_first_member) {
    170           buf.append(",");
    171         }
    172         buf.append("\n      \"" + method.name() + method.signature() + "\": \"");
    173         if (!method.containingClass().qualifiedName().equals(cl.qualifiedName())) {
    174           buf.append(method.containingClass().qualifiedName());
    175         }
    176         buf.append("\"");
    177         is_first_member = false;
    178       }
    179     }
    180     return is_first_member;
    181   }
    182 
    183 }
    184