Home | History | Annotate | Download | only in docs
      1 //  2016 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html#License
      3 /**
      4 *******************************************************************************
      5 * Copyright (C) 2002-2016 International Business Machines Corporation   *
      6 * and others. All Rights Reserved.                                            *
      7 *******************************************************************************
      8 */
      9 
     10 package com.ibm.icu.dev.tool.docs;
     11 
     12 import java.text.BreakIterator;
     13 import java.util.Locale;
     14 import java.util.Map;
     15 
     16 import com.sun.javadoc.Tag;
     17 import com.sun.tools.doclets.internal.toolkit.taglets.Taglet;
     18 
     19 public abstract class ICUTaglet extends ICUTagletAdapter implements Taglet {
     20     protected final String name;
     21     protected final int mask;
     22 
     23     protected static final int MASK_FIELD = 1;
     24     protected static final int MASK_CONSTRUCTOR = 2;
     25     protected static final int MASK_METHOD = 4;
     26     protected static final int MASK_OVERVIEW = 8;
     27     protected static final int MASK_PACKAGE = 16;
     28     protected static final int MASK_TYPE = 32;
     29     protected static final int MASK_INLINE = 64;
     30 
     31     protected static final int MASK_DEFAULT = 0x003f; // no inline
     32     protected static final int MASK_DEFAULT_INLINE = 0x007f; // includes inline
     33     protected static final int MASK_VALID = 0x007f;
     34 
     35     public static void register(Map taglets) {
     36         ICUInternalTaglet.register(taglets);
     37         ICUDraftTaglet.register(taglets);
     38         ICUStableTaglet.register(taglets);
     39         ICUProvisionalTaglet.register(taglets);
     40         ICUObsoleteTaglet.register(taglets);
     41         ICUIgnoreTaglet.register(taglets);
     42         ICUNewTaglet.register(taglets);
     43         ICUNoteTaglet.register(taglets);
     44         ICUEnhancedTaglet.register(taglets);
     45         ICUDiscouragedTaglet.register(taglets);
     46     }
     47 
     48     protected ICUTaglet(String name, int mask) {
     49         this.name = name;
     50         this.mask = mask & MASK_VALID;
     51     }
     52 
     53     public boolean inField() {
     54         return (mask & MASK_FIELD) != 0;
     55     }
     56 
     57     public boolean inConstructor() {
     58         return (mask & MASK_CONSTRUCTOR) != 0;
     59     }
     60 
     61     public boolean inMethod() {
     62         return (mask & MASK_METHOD) != 0;
     63     }
     64 
     65     public boolean inOverview() {
     66         return (mask & MASK_OVERVIEW) != 0;
     67     }
     68 
     69     public boolean inPackage() {
     70         return (mask & MASK_PACKAGE) != 0;
     71     }
     72 
     73     public boolean inType() {
     74         return (mask & MASK_TYPE) != 0;
     75     }
     76 
     77     public boolean isInlineTag() {
     78         return (mask & MASK_INLINE) != 0;
     79     }
     80 
     81     public String getName() {
     82         return name;
     83     }
     84 
     85     public String toString(Tag tag) {
     86         return tag.text();
     87     }
     88 
     89     public String toString(Tag[] tags) {
     90 
     91       if (!isInlineTag() && tags != null) {
     92             if (tags.length > 1) {
     93                 String msg = "Should not have more than one ICU tag per element:\n";
     94                 for (int i = 0; i < tags.length; ++i) {
     95                     msg += "  [" + i + "] " + tags[i] + "\n";
     96                 }
     97                 throw new IllegalStateException(msg);
     98             } else if (tags.length > 0) {
     99                 return toString(tags[0]);
    100             }
    101         }
    102         return null;
    103     }
    104 
    105     protected static final String STATUS = "<dt><b>Status:</b></dt>";
    106 
    107     public static class ICUDiscouragedTaglet extends ICUTaglet {
    108         private static final String NAME = "discouraged";
    109 
    110         public static void register(Map taglets) {
    111             taglets.put(NAME, new ICUDiscouragedTaglet());
    112         }
    113 
    114         private ICUDiscouragedTaglet() {
    115             super(NAME, MASK_DEFAULT);
    116         }
    117 
    118         public String toString(Tag tag) {
    119             String text = tag.text();
    120             if (text.length() == 0) {
    121                 System.err.println("Error: empty discouraged tag ");
    122             }
    123             return "<dt><b><font color=red>Discouraged:</font></b></dt><dd>" + text + "</dd>";
    124         }
    125     }
    126 
    127     public static class ICUInternalTaglet extends ICUTaglet {
    128         private static final String NAME = "internal";
    129 
    130         public static void register(Map taglets) {
    131             taglets.put(NAME, new ICUInternalTaglet());
    132         }
    133 
    134         private ICUInternalTaglet() {
    135             super(NAME, MASK_DEFAULT);
    136         }
    137 
    138         public String toString(Tag tag) {
    139             if (tag.text().toLowerCase(Locale.US).indexOf("technology preview") >= 0) {
    140                 return STATUS + "<dd><em>Technology Preview</em>. <font color='red'>" +
    141                     "This API is still in the early stages of development. Use at your own risk.</font></dd>";
    142             }
    143             return STATUS + "<dd><em>Internal</em>. <font color='red'>" +
    144                 "This API is <em>ICU internal only</em>.</font></dd>";
    145         }
    146     }
    147 
    148     public static class ICUDraftTaglet extends ICUTaglet {
    149         private static final String NAME = "draft";
    150 
    151         public static void register(Map taglets) {
    152             taglets.put(NAME, new ICUDraftTaglet());
    153         }
    154 
    155         private ICUDraftTaglet() {
    156             super(NAME, MASK_DEFAULT);
    157         }
    158 
    159         public String toString(Tag tag) {
    160             String text = tag.text();
    161             if (text.length() == 0) {
    162                 System.err.println("Warning: empty draft tag");
    163             }
    164             return STATUS + "<dd>Draft " + tag.text() + ".</dd>";
    165         }
    166     }
    167 
    168     public static class ICUStableTaglet extends ICUTaglet {
    169         private static final String NAME = "stable";
    170 
    171         public static void register(Map taglets) {
    172             taglets.put(NAME, new ICUStableTaglet());
    173         }
    174 
    175         private ICUStableTaglet() {
    176             super(NAME, MASK_DEFAULT);
    177         }
    178 
    179         public String toString(Tag tag) {
    180             String text = tag.text();
    181             if (text.length() > 0) {
    182                 return STATUS + "<dd>Stable " + text + ".</dd>";
    183             } else {
    184                 return STATUS + "<dd>Stable.</dd>";
    185             }
    186         }
    187     }
    188 
    189     public static class ICUProvisionalTaglet extends ICUTaglet {
    190         private static final String NAME = "provisional";
    191 
    192         public static void register(Map taglets) {
    193             taglets.remove(NAME); // override standard deprecated taglet
    194             taglets.put(NAME, new ICUProvisionalTaglet());
    195         }
    196 
    197         private ICUProvisionalTaglet() {
    198             super(NAME, MASK_DEFAULT);
    199         }
    200 
    201         public String toString(Tag tag) {
    202             return null;
    203         }
    204     }
    205 
    206     public static class ICUObsoleteTaglet extends ICUTaglet {
    207         private static final String NAME = "obsolete";
    208 
    209         public static void register(Map taglets) {
    210             taglets.put(NAME, new ICUObsoleteTaglet());
    211         }
    212 
    213         private ICUObsoleteTaglet() {
    214             super(NAME, MASK_DEFAULT);
    215         }
    216 
    217         public String toString(Tag tag) {
    218             BreakIterator bi = BreakIterator.getSentenceInstance(Locale.US);
    219             String text = tag.text();
    220             bi.setText(text);
    221             int first = bi.first();
    222             int next = bi.next();
    223             if (text.length() == 0) {
    224                 first = next = 0;
    225             }
    226             return STATUS + "<dd><em>Obsolete.</em> <font color='red'>Will be removed in " +
    227                 text.substring(first, next) + "</font>. " + text.substring(next) + "</dd>";
    228 
    229         }
    230     }
    231 
    232     public static class ICUIgnoreTaglet extends ICUTaglet {
    233         private static ICUTaglet singleton;
    234 
    235         public static void register(Map taglets) {
    236             if (singleton == null) {
    237                 singleton = new ICUIgnoreTaglet();
    238             }
    239             taglets.put("bug", singleton);
    240             taglets.put("test", singleton);
    241             taglets.put("summary", singleton);
    242         }
    243 
    244         private ICUIgnoreTaglet() {
    245             super(".ignore", MASK_DEFAULT);
    246         }
    247 
    248         public String toString(Tag tag) {
    249             return null;
    250         }
    251     }
    252 
    253     private static String ICU_LABEL = "<strong><font color=red>[icu]</font></strong>";
    254 
    255     /**
    256      * This taglet should be used in the first line of the class description of classes
    257      * that are enhancements of JDK classes that similar names and APIs.  The text should
    258      * provide the full package and name of the JDK class.  A period should follow the
    259      * tag.  This puts an 'icu enhancement' message into the first line of the class docs,
    260      * where it will also appear in the class summary.
    261      *
    262      * <p>Following this tag (and period), ideally in the first paragraph, the '@icu' tag
    263      * should be used with the text '_label_' to generate the standard boilerplate about
    264      * how that tag is used in the class docs.  See {@link ICUNewTaglet}.
    265      *
    266      * <p>This cumbersome process is necessary because the javadoc code that handles
    267      * taglets doesn't look at punctuation in the substitution text to determine when to
    268      * end the first line, it looks in the original javadoc comment.  So we need a tag to
    269      * identify the related java class, then a period, then another tag.
    270      */
    271      public static class ICUEnhancedTaglet extends ICUTaglet {
    272         private static final String NAME = "icuenhanced";
    273 
    274         public static void register(Map taglets) {
    275             taglets.put(NAME, new ICUEnhancedTaglet());
    276         }
    277 
    278         private ICUEnhancedTaglet() {
    279             super(NAME, MASK_DEFAULT_INLINE);
    280         }
    281 
    282         public String toString(Tag tag) {
    283             String text = tag.text().trim();
    284 
    285             boolean isClassDoc = tag.holder().isClass() || tag.holder().isInterface();
    286             if (isClassDoc && text.length() > 0) {
    287                 StringBuilder sb = new StringBuilder();
    288                 return sb.append("<strong><font color=red>[icu enhancement]</font></strong> ")
    289                     .append("ICU's replacement for <code>")
    290                     .append(text)
    291                     .append("</code>")
    292                     .toString();
    293             }
    294             return "";
    295         }
    296     }
    297 
    298     /**
    299      * This taglet should be used in the first line of any icu-specific members in a class
    300      * that is an enhancement of a JDK class (see {@link ICUEnhancedTaglet}). It generates
    301      * the '[icu]' marker followed by the &lt;strong&gt; text, if any.  This does not
    302      * start or end a paragraph or provide additional leading or trailing punctuation such
    303      * as spaces or periods.
    304      *
    305      * <p>Note: if the text is '_usage_' (without quotes) this spits out a boilerplate
    306      * message describing the meaning of the '[icu]' tag.  This should be done in the
    307      * first paragraph of the class docs of any class containing '@icu' tags.
    308      */
    309     public static class ICUNewTaglet extends ICUTaglet {
    310         private static final String NAME = "icu";
    311 
    312         public static void register(Map taglets) {
    313             taglets.put(NAME, new ICUNewTaglet());
    314         }
    315 
    316         private ICUNewTaglet() {
    317             super(NAME, MASK_DEFAULT_INLINE);
    318         }
    319 
    320         public String toString(Tag tag) {
    321             String text = tag.text().trim();
    322             StringBuilder sb = new StringBuilder();
    323             if ("_usage_".equals(text)) {
    324                 return sb.append(" Methods, fields, and other functionality specific to ICU ")
    325                     .append("are labeled '" + ICU_LABEL + "'.</p>")
    326                     .toString();
    327             }
    328 
    329             sb.append("<strong><font color=red>[icu]</font>");
    330             if (text.length() > 0) {
    331                 sb.append(" ").append(text);
    332             }
    333             sb.append("</strong>");
    334             return sb.toString();
    335         }
    336     }
    337 
    338     /**
    339      * This taglet should be used in class or member documentation, after the first line,
    340      * where the behavior of the ICU method or class has notable differences from its JDK
    341      * counterpart. It starts a new paragraph and generates an '[icu] Note:' header.
    342      */
    343     public static class ICUNoteTaglet extends ICUTaglet {
    344         private static final String NAME = "icunote";
    345 
    346         public static void register(Map taglets) {
    347             taglets.put(NAME, new ICUNoteTaglet());
    348         }
    349 
    350         private ICUNoteTaglet() {
    351             super(NAME, MASK_DEFAULT_INLINE);
    352         }
    353 
    354         public String toString(Tag tag) {
    355             return "<p><strong><font color=red>[icu]</font> Note:</strong> ";
    356         }
    357     }
    358 }
    359