2 *******************************************************************************
3 * Copyright (C) 2002-2011, International Business Machines Corporation and *
4 * others. All Rights Reserved. *
5 *******************************************************************************
8 package com.ibm.icu.dev.tool.docs;
10 import java.text.BreakIterator;
11 import java.util.Locale;
14 import com.sun.javadoc.Doc;
15 import com.sun.javadoc.Tag;
16 import com.sun.tools.doclets.internal.toolkit.taglets.Taglet;
17 import com.sun.tools.doclets.internal.toolkit.taglets.TagletOutput;
18 import com.sun.tools.doclets.internal.toolkit.taglets.TagletWriter;
20 public abstract class ICUTaglet implements Taglet {
21 protected final String name;
22 protected final int mask;
24 protected static final int MASK_FIELD = 1;
25 protected static final int MASK_CONSTRUCTOR = 2;
26 protected static final int MASK_METHOD = 4;
27 protected static final int MASK_OVERVIEW = 8;
28 protected static final int MASK_PACKAGE = 16;
29 protected static final int MASK_TYPE = 32;
30 protected static final int MASK_INLINE = 64;
32 protected static final int MASK_DEFAULT = 0x003f; // no inline
33 protected static final int MASK_DEFAULT_INLINE = 0x007f; // includes inline
34 protected static final int MASK_VALID = 0x007f;
36 public static void register(Map taglets) {
37 ICUInternalTaglet.register(taglets);
38 ICUDraftTaglet.register(taglets);
39 ICUStableTaglet.register(taglets);
40 ICUProvisionalTaglet.register(taglets);
41 ICUObsoleteTaglet.register(taglets);
42 ICUIgnoreTaglet.register(taglets);
43 ICUNewTaglet.register(taglets);
44 ICUNoteTaglet.register(taglets);
45 ICUEnhancedTaglet.register(taglets);
48 protected ICUTaglet(String name, int mask) {
50 this.mask = mask & MASK_VALID;
53 public boolean inField() {
54 return (mask & MASK_FIELD) != 0;
57 public boolean inConstructor() {
58 return (mask & MASK_CONSTRUCTOR) != 0;
61 public boolean inMethod() {
62 return (mask & MASK_METHOD) != 0;
65 public boolean inOverview() {
66 return (mask & MASK_OVERVIEW) != 0;
69 public boolean inPackage() {
70 return (mask & MASK_PACKAGE) != 0;
73 public boolean inType() {
74 return (mask & MASK_TYPE) != 0;
77 public boolean isInlineTag() {
78 return (mask & MASK_INLINE) != 0;
81 public String getName() {
85 public String toString(Tag tag) {
89 public String toString(Tag[] tags) {
90 if (!isInlineTag() && tags != null) {
91 if (tags.length > 1) {
92 String msg = "Should not have more than one ICU tag per element:\n";
93 for (int i = 0; i < tags.length; ++i) {
94 msg += " [" + i + "] " + tags[i] + "\n";
96 throw new IllegalStateException(msg);
97 } else if (tags.length > 0) {
98 return toString(tags[0]);
104 public TagletOutput getTagletOutput(Tag tag, TagletWriter writer)
105 throws IllegalArgumentException {
107 TagletOutput out = writer.getTagletOutputInstance();
108 out.setOutput(toString(tag));
112 public TagletOutput getTagletOutput(Doc holder, TagletWriter writer)
113 throws IllegalArgumentException {
115 TagletOutput out = writer.getTagletOutputInstance();
116 Tag[] tags = holder.tags(getName());
117 if (tags.length == 0) {
120 out.setOutput(toString(tags[0]));
124 protected static final String STATUS = "<dt><b>Status:</b></dt>";
126 public static class ICUInternalTaglet extends ICUTaglet {
127 private static final String NAME = "internal";
129 public static void register(Map taglets) {
130 taglets.put(NAME, new ICUInternalTaglet());
133 private ICUInternalTaglet() {
134 super(NAME, MASK_DEFAULT);
137 public String toString(Tag tag) {
138 if (tag.text().toLowerCase(Locale.US).indexOf("technology preview") >= 0) {
139 return STATUS + "<dd><em>Technology Preview</em>. <font color='red'>" +
140 "This API is still in the early stages of development. Use at your own risk.</font></dd>";
142 return STATUS + "<dd><em>Internal</em>. <font color='red'>" +
143 "This API is <em>ICU internal only</em>.</font></dd>";
147 public static class ICUDraftTaglet extends ICUTaglet {
148 private static final String NAME = "draft";
150 public static void register(Map taglets) {
151 taglets.put(NAME, new ICUDraftTaglet());
154 private ICUDraftTaglet() {
155 super(NAME, MASK_DEFAULT);
158 public String toString(Tag tag) {
159 String text = tag.text();
160 if (text.length() == 0) {
161 System.err.println("Warning: empty draft tag");
163 return STATUS + "<dd>Draft " + tag.text() + ".</dd>";
167 public static class ICUStableTaglet extends ICUTaglet {
168 private static final String NAME = "stable";
170 public static void register(Map taglets) {
171 taglets.put(NAME, new ICUStableTaglet());
174 private ICUStableTaglet() {
175 super(NAME, MASK_DEFAULT);
178 public String toString(Tag tag) {
179 String text = tag.text();
180 if (text.length() > 0) {
181 return STATUS + "<dd>Stable " + text + ".</dd>";
183 return STATUS + "<dd>Stable.</dd>";
188 public static class ICUProvisionalTaglet extends ICUTaglet {
189 private static final String NAME = "provisional";
191 public static void register(Map taglets) {
192 taglets.remove(NAME); // override standard deprecated taglet
193 taglets.put(NAME, new ICUProvisionalTaglet());
196 private ICUProvisionalTaglet() {
197 super(NAME, MASK_DEFAULT);
200 public String toString(Tag tag) {
205 public static class ICUObsoleteTaglet extends ICUTaglet {
206 private static final String NAME = "obsolete";
208 public static void register(Map taglets) {
209 taglets.put(NAME, new ICUObsoleteTaglet());
212 private ICUObsoleteTaglet() {
213 super(NAME, MASK_DEFAULT);
216 public String toString(Tag tag) {
217 BreakIterator bi = BreakIterator.getSentenceInstance(Locale.US);
218 String text = tag.text();
220 int first = bi.first();
221 int next = bi.next();
222 if (text.length() == 0) {
225 return STATUS + "<dd><em>Obsolete.</em> <font color='red'>Will be removed in " +
226 text.substring(first, next) + "</font>. " + text.substring(next) + "</dd>";
231 public static class ICUIgnoreTaglet extends ICUTaglet {
232 private static ICUTaglet singleton;
234 public static void register(Map taglets) {
235 if (singleton == null) {
236 singleton = new ICUIgnoreTaglet();
238 taglets.put("bug", singleton);
239 taglets.put("test", singleton);
240 taglets.put("summary", singleton);
243 private ICUIgnoreTaglet() {
244 super(".ignore", MASK_DEFAULT);
247 public String toString(Tag tag) {
252 private static String ICU_LABEL = "<strong><font color=red>[icu]</font></strong>";
255 * This taglet should be used in the first line of the class description of classes
256 * that are enhancements of JDK classes that similar names and APIs. The text should
257 * provide the full package and name of the JDK class. A period should follow the
258 * tag. This puts an 'icu enhancement' message into the first line of the class docs,
259 * where it will also appear in the class summary.
261 * <p>Following this tag (and period), ideally in the first paragraph, the '@icu' tag
262 * should be used with the text '_label_' to generate the standard boilerplate about
263 * how that tag is used in the class docs. See {@link ICUNewTaglet}.
265 * <p>This cumbersome process is necessary because the javadoc code that handles
266 * taglets doesn't look at punctuation in the substitution text to determine when to
267 * end the first line, it looks in the original javadoc comment. So we need a tag to
268 * identify the related java class, then a period, then another tag.
270 public static class ICUEnhancedTaglet extends ICUTaglet {
271 private static final String NAME = "icuenhanced";
273 public static void register(Map taglets) {
274 taglets.put(NAME, new ICUEnhancedTaglet());
277 private ICUEnhancedTaglet() {
278 super(NAME, MASK_DEFAULT_INLINE);
281 public String toString(Tag tag) {
282 String text = tag.text().trim();
284 boolean isClassDoc = tag.holder().isClass() || tag.holder().isInterface();
285 if (isClassDoc && text.length() > 0) {
286 StringBuilder sb = new StringBuilder();
287 return sb.append("<strong><font color=red>[icu enhancement]</font></strong> ")
288 .append("ICU's replacement for <code>")
298 * This taglet should be used in the first line of any icu-specific members in a class
299 * that is an enhancement of a JDK class (see {@link ICUEnhancedTaglet}). It generates
300 * the '[icu]' marker followed by the <strong> text, if any. This does not
301 * start or end a paragraph or provide additional leading or trailing punctuation such
302 * as spaces or periods.
304 * <p>Note: if the text is '_usage_' (without quotes) this spits out a boilerplate
305 * message describing the meaning of the '[icu]' tag. This should be done in the
306 * first paragraph of the class docs of any class containing '@icu' tags.
308 public static class ICUNewTaglet extends ICUTaglet {
309 private static final String NAME = "icu";
311 public static void register(Map taglets) {
312 taglets.put(NAME, new ICUNewTaglet());
315 private ICUNewTaglet() {
316 super(NAME, MASK_DEFAULT_INLINE);
319 public String toString(Tag tag) {
320 String text = tag.text().trim();
321 StringBuilder sb = new StringBuilder();
322 if ("_usage_".equals(text)) {
323 return sb.append(" Methods, fields, and other functionality specific to ICU ")
324 .append("are labeled '" + ICU_LABEL + "'.</p>")
328 sb.append("<strong><font color=red>[icu]</font>");
329 if (text.length() > 0) {
330 sb.append(" ").append(text);
332 sb.append("</strong>");
333 return sb.toString();
338 * This taglet should be used in class or member documentation, after the first line,
339 * where the behavior of the ICU method or class has notable differences from its JDK
340 * counterpart. It starts a new paragraph and generates an '[icu] Note:' header.
342 public static class ICUNoteTaglet extends ICUTaglet {
343 private static final String NAME = "icunote";
345 public static void register(Map taglets) {
346 taglets.put(NAME, new ICUNoteTaglet());
349 private ICUNoteTaglet() {
350 super(NAME, MASK_DEFAULT_INLINE);
353 public String toString(Tag tag) {
354 return "<p><strong><font color=red>[icu]</font> Note:</strong> ";