/** ******************************************************************************* * 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 = "
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: "; } } }