/** ******************************************************************************* * Copyright (C) 2002-2010, International Business Machines Corporation and * * others. All Rights Reserved. * ******************************************************************************* */ package com.ibm.icu.dev.tool.docs; import java.text.BreakIterator; import java.util.Locale; import java.util.Map; import com.sun.javadoc.Doc; import com.sun.javadoc.Tag; import com.sun.tools.doclets.internal.toolkit.taglets.Taglet; import com.sun.tools.doclets.internal.toolkit.taglets.TagletOutput; import com.sun.tools.doclets.internal.toolkit.taglets.TagletWriter; public abstract class ICUTaglet implements Taglet { protected final String name; protected final int mask; protected static final int MASK_FIELD = 1; protected static final int MASK_CONSTRUCTOR = 2; protected static final int MASK_METHOD = 4; protected static final int MASK_OVERVIEW = 8; protected static final int MASK_PACKAGE = 16; protected static final int MASK_TYPE = 32; protected static final int MASK_INLINE = 64; protected static final int MASK_DEFAULT = 0x003f; // no inline protected static final int MASK_DEFAULT_INLINE = 0x007f; // includes inline protected static final int MASK_VALID = 0x007f; public static void register(Map taglets) { ICUInternalTaglet.register(taglets); ICUDraftTaglet.register(taglets); ICUStableTaglet.register(taglets); ICUProvisionalTaglet.register(taglets); ICUObsoleteTaglet.register(taglets); ICUIgnoreTaglet.register(taglets); ICUNewTaglet.register(taglets); ICUNoteTaglet.register(taglets); ICUEnhancedTaglet.register(taglets); } protected ICUTaglet(String name, int mask) { this.name = name; this.mask = mask & MASK_VALID; } public boolean inField() { return (mask & MASK_FIELD) != 0; } public boolean inConstructor() { return (mask & MASK_CONSTRUCTOR) != 0; } public boolean inMethod() { return (mask & MASK_METHOD) != 0; } public boolean inOverview() { return (mask & MASK_OVERVIEW) != 0; } public boolean inPackage() { return (mask & MASK_PACKAGE) != 0; } public boolean inType() { return (mask & MASK_TYPE) != 0; } public boolean isInlineTag() { return (mask & MASK_INLINE) != 0; } public String getName() { return name; } public String toString(Tag tag) { return tag.text(); } public String toString(Tag[] tags) { if (!isInlineTag() && tags != null) { if (tags.length > 1) { String msg = "Should not have more than one ICU tag per element:\n"; for (int i = 0; i < tags.length; ++i) { msg += " [" + i + "] " + tags[i] + "\n"; } throw new IllegalStateException(msg); } else if (tags.length > 0) { return toString(tags[0]); } } return null; } public TagletOutput getTagletOutput(Tag tag, TagletWriter writer) throws IllegalArgumentException { TagletOutput out = writer.getTagletOutputInstance(); out.setOutput(toString(tag)); return out; } public TagletOutput getTagletOutput(Doc holder, TagletWriter writer) throws IllegalArgumentException { TagletOutput out = writer.getTagletOutputInstance(); Tag[] tags = holder.tags(getName()); if (tags.length == 0) { return null; } out.setOutput(toString(tags[0])); return out; } protected static final String STATUS = "
Status:
"; public static class ICUInternalTaglet extends ICUTaglet { private static final String NAME = "internal"; public static void register(Map taglets) { taglets.put(NAME, new ICUInternalTaglet()); } private ICUInternalTaglet() { super(NAME, MASK_DEFAULT); } public String toString(Tag tag) { return STATUS + "
Internal. " + "This API is ICU internal only.
"; } } public static class ICUDraftTaglet extends ICUTaglet { private static final String NAME = "draft"; public static void register(Map taglets) { taglets.put(NAME, new ICUDraftTaglet()); } private ICUDraftTaglet() { super(NAME, MASK_DEFAULT); } public String toString(Tag tag) { String text = tag.text(); if (text.length() == 0) { System.err.println("Warning: empty draft tag"); } return STATUS + "
Draft " + tag.text() + ".
"; } } public static class ICUStableTaglet extends ICUTaglet { private static final String NAME = "stable"; public static void register(Map taglets) { taglets.put(NAME, new ICUStableTaglet()); } private ICUStableTaglet() { super(NAME, MASK_DEFAULT); } public String toString(Tag tag) { String text = tag.text(); if (text.length() > 0) { return STATUS + "
Stable " + text + ".
"; } else { return STATUS + "
Stable.
"; } } } public static class ICUProvisionalTaglet extends ICUTaglet { private static final String NAME = "provisional"; public static void register(Map taglets) { taglets.remove(NAME); // override standard deprecated taglet taglets.put(NAME, new ICUProvisionalTaglet()); } private ICUProvisionalTaglet() { super(NAME, MASK_DEFAULT); } public String toString(Tag tag) { return null; } } public static class ICUObsoleteTaglet extends ICUTaglet { private static final String NAME = "obsolete"; public static void register(Map taglets) { taglets.put(NAME, new ICUObsoleteTaglet()); } private ICUObsoleteTaglet() { super(NAME, MASK_DEFAULT); } public String toString(Tag tag) { BreakIterator bi = BreakIterator.getSentenceInstance(Locale.US); String text = tag.text(); bi.setText(text); int first = bi.first(); int next = bi.next(); if (text.length() == 0) { first = next = 0; } return STATUS + "
Obsolete. Will be removed in " + text.substring(first, next) + ". " + text.substring(next) + "
"; } } public static class ICUIgnoreTaglet extends ICUTaglet { private static ICUTaglet singleton; public static void register(Map taglets) { if (singleton == null) { singleton = new ICUIgnoreTaglet(); } taglets.put("bug", singleton); taglets.put("test", singleton); taglets.put("summary", singleton); } private ICUIgnoreTaglet() { super(".ignore", MASK_DEFAULT); } public String toString(Tag tag) { return null; } } private static String ICU_LABEL = "[icu]"; /** * This taglet should be used in the first line of the class description of classes * that are enhancements of JDK classes that similar names and APIs. The text should * provide the full package and name of the JDK class. A period should follow the * tag. This puts an 'icu enhancement' message into the first line of the class docs, * where it will also appear in the class summary. * *

Following this tag (and period), ideally in the first paragraph, the '@icu' tag * should be used with the text '_label_' to generate the standard boilerplate about * how that tag is used in the class docs. See {@link ICUNewTaglet}. * *

This cumbersome process is necessary because the javadoc code that handles * taglets doesn't look at punctuation in the substitution text to determine when to * end the first line, it looks in the original javadoc comment. So we need a tag to * identify the related java class, then a period, then another tag. */ public static class ICUEnhancedTaglet extends ICUTaglet { private static final String NAME = "icuenhanced"; public static void register(Map taglets) { taglets.put(NAME, new ICUEnhancedTaglet()); } private ICUEnhancedTaglet() { super(NAME, MASK_DEFAULT_INLINE); } public String toString(Tag tag) { String text = tag.text().trim(); boolean isClassDoc = tag.holder().isClass() || tag.holder().isInterface(); if (isClassDoc && text.length() > 0) { StringBuilder sb = new StringBuilder(); return sb.append("[icu enhancement] ") .append("ICU's replacement for ") .append(text) .append("") .toString(); } return ""; } } /** * This taglet should be used in the first line of any icu-specific members in a class * that is an enhancement of a JDK class (see {@link ICUEnhancedTaglet}). It generates * the '[icu]' marker followed by the <strong> text, if any. This does not * start or end a paragraph or provide additional leading or trailing punctuation such * as spaces or periods. * *

Note: if the text is '_usage_' (without quotes) this spits out a boilerplate * message describing the meaning of the '[icu]' tag. This should be done in the * first paragraph of the class docs of any class containing '@icu' tags. */ public static class ICUNewTaglet extends ICUTaglet { private static final String NAME = "icu"; public static void register(Map taglets) { taglets.put(NAME, new ICUNewTaglet()); } private ICUNewTaglet() { super(NAME, MASK_DEFAULT_INLINE); } public String toString(Tag tag) { String text = tag.text().trim(); StringBuilder sb = new StringBuilder(); if ("_usage_".equals(text)) { return sb.append(" Methods, fields, and other functionality specific to ICU ") .append("are labeled '" + ICU_LABEL + "'.

") .toString(); } sb.append("[icu]"); if (text.length() > 0) { sb.append(" ").append(text); } sb.append(""); return sb.toString(); } } /** * This taglet should be used in class or member documentation, after the first line, * where the behavior of the ICU method or class has notable differences from its JDK * counterpart. It starts a new paragraph and generates an '[icu] Note:' header. */ public static class ICUNoteTaglet extends ICUTaglet { private static final String NAME = "icunote"; public static void register(Map taglets) { taglets.put(NAME, new ICUNoteTaglet()); } private ICUNoteTaglet() { super(NAME, MASK_DEFAULT_INLINE); } public String toString(Tag tag) { return "

[icu] Note: "; } } }