001: /*
002: * Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package com.sun.tools.doclets.internal.toolkit.util.links;
027:
028: import com.sun.javadoc.*;
029:
030: /**
031: * A factory that constructs links from given link information.
032: *
033: * @author Jamie Ho
034: * @since 1.5
035: */
036: public abstract class LinkFactory {
037:
038: /**
039: * Return an empty instance of the link output object.
040: *
041: * @return an empty instance of the link output object.
042: */
043: protected abstract LinkOutput getOutputInstance();
044:
045: /**
046: * Constructs a link from the given link information.
047: *
048: * @param linkInfo the information about the link.
049: * @return the output of the link.
050: */
051: public LinkOutput getLinkOutput(LinkInfo linkInfo) {
052: if (linkInfo.type != null) {
053: Type type = linkInfo.type;
054: LinkOutput linkOutput = getOutputInstance();
055: if (type.isPrimitive()) {
056: //Just a primitive.
057: linkInfo.displayLength += type.typeName().length();
058: linkOutput.append(type.typeName());
059: } else if (type.asWildcardType() != null) {
060: //Wildcard type.
061: linkInfo.isTypeBound = true;
062: linkInfo.displayLength += 1;
063: linkOutput.append("?");
064: WildcardType wildcardType = type.asWildcardType();
065: Type[] extendsBounds = wildcardType.extendsBounds();
066: for (int i = 0; i < extendsBounds.length; i++) {
067: linkInfo.displayLength += i > 0 ? 2 : 9;
068: linkOutput.append(i > 0 ? ", " : " extends ");
069: setBoundsLinkInfo(linkInfo, extendsBounds[i]);
070: linkOutput.append(getLinkOutput(linkInfo));
071: }
072: Type[] super Bounds = wildcardType.super Bounds();
073: for (int i = 0; i < super Bounds.length; i++) {
074: linkInfo.displayLength += i > 0 ? 2 : 7;
075: linkOutput.append(i > 0 ? ", " : " super ");
076: setBoundsLinkInfo(linkInfo, super Bounds[i]);
077: linkOutput.append(getLinkOutput(linkInfo));
078: }
079: } else if (type.asTypeVariable() != null) {
080: linkInfo.isTypeBound = true;
081: //A type variable.
082: Doc owner = type.asTypeVariable().owner();
083: if ((!linkInfo.excludeTypeParameterLinks)
084: && owner instanceof ClassDoc) {
085: linkInfo.classDoc = (ClassDoc) owner;
086: linkInfo.label = type.typeName();
087: linkOutput
088: .append(getClassLink((LinkInfo) linkInfo));
089: } else {
090: //No need to link method type parameters.
091: linkInfo.displayLength += type.typeName().length();
092: linkOutput.append(type.typeName());
093: }
094:
095: Type[] bounds = type.asTypeVariable().bounds();
096: if (!linkInfo.excludeTypeBounds) {
097: linkInfo.excludeTypeBounds = true;
098: for (int i = 0; i < bounds.length; i++) {
099: linkInfo.displayLength += i > 0 ? 2 : 9;
100: linkOutput.append(i > 0 ? " & " : " extends ");
101: setBoundsLinkInfo(linkInfo, bounds[i]);
102: linkOutput.append(getLinkOutput(linkInfo));
103: }
104: }
105: } else if (type.asClassDoc() != null) {
106: //A class type.
107: if (linkInfo.isTypeBound
108: && linkInfo.excludeTypeBoundsLinks) {
109: //Since we are excluding type parameter links, we should not
110: //be linking to the type bound.
111: linkInfo.displayLength += type.typeName().length();
112: linkOutput.append(type.typeName());
113: linkOutput.append(getTypeParameterLinks(linkInfo));
114: return linkOutput;
115: } else {
116: linkInfo.classDoc = type.asClassDoc();
117: linkOutput = getClassLink((LinkInfo) linkInfo);
118: if (linkInfo.includeTypeAsSepLink) {
119: linkOutput.append(getTypeParameterLinks(
120: linkInfo, false));
121: }
122: }
123: }
124:
125: if (linkInfo.isVarArg) {
126: if (type.dimension().length() > 2) {
127: //Javadoc returns var args as array.
128: //Strip out the first [] from the var arg.
129: linkInfo.displayLength += type.dimension().length() - 2;
130: linkOutput.append(type.dimension().substring(2));
131: }
132: linkInfo.displayLength += 3;
133: linkOutput.append("...");
134: } else {
135: linkInfo.displayLength += type.dimension().length();
136: linkOutput.append(type.dimension());
137: }
138: return linkOutput;
139: } else if (linkInfo.classDoc != null) {
140: //Just a class link
141: LinkOutput linkOutput = getClassLink((LinkInfo) linkInfo);
142: if (linkInfo.includeTypeAsSepLink) {
143: linkOutput
144: .append(getTypeParameterLinks(linkInfo, false));
145: }
146: return linkOutput;
147: } else {
148: return null;
149: }
150: }
151:
152: private void setBoundsLinkInfo(LinkInfo linkInfo, Type bound) {
153: linkInfo.classDoc = null;
154: linkInfo.label = null;
155: linkInfo.type = bound;
156: }
157:
158: /**
159: * Return the link to the given class.
160: *
161: * @param linkInfo the information about the link to construct.
162: *
163: * @return the link for the given class.
164: */
165: protected abstract LinkOutput getClassLink(LinkInfo linkInfo);
166:
167: /**
168: * Return the link to the given type parameter.
169: *
170: * @param linkInfo the information about the link to construct.
171: * @param typeParam the type parameter to link to.
172: */
173: protected abstract LinkOutput getTypeParameterLink(
174: LinkInfo linkInfo, Type typeParam);
175:
176: /**
177: * Return the links to the type parameters.
178: *
179: * @param linkInfo the information about the link to construct.
180: * @return the links to the type parameters.
181: */
182: public LinkOutput getTypeParameterLinks(LinkInfo linkInfo) {
183: return getTypeParameterLinks(linkInfo, true);
184: }
185:
186: /**
187: * Return the links to the type parameters.
188: *
189: * @param linkInfo the information about the link to construct.
190: * @param isClassLabel true if this is a class label. False if it is
191: * the type parameters portion of the link.
192: * @return the links to the type parameters.
193: */
194: public LinkOutput getTypeParameterLinks(LinkInfo linkInfo,
195: boolean isClassLabel) {
196: LinkOutput output = getOutputInstance();
197: Type[] vars;
198: if (linkInfo.executableMemberDoc != null) {
199: vars = linkInfo.executableMemberDoc.typeParameters();
200: } else if (linkInfo.type != null
201: && linkInfo.type.asParameterizedType() != null) {
202: vars = linkInfo.type.asParameterizedType().typeArguments();
203: } else if (linkInfo.classDoc != null) {
204: vars = linkInfo.classDoc.typeParameters();
205: } else {
206: //Nothing to document.
207: return output;
208: }
209: if (((linkInfo.includeTypeInClassLinkLabel && isClassLabel) || (linkInfo.includeTypeAsSepLink && !isClassLabel))
210: && vars.length > 0) {
211: linkInfo.displayLength += 1;
212: output.append(getLessThanString());
213: for (int i = 0; i < vars.length; i++) {
214: if (i > 0) {
215: linkInfo.displayLength += 1;
216: output.append(",");
217: }
218: output.append(getTypeParameterLink(linkInfo, vars[i]));
219: }
220: linkInfo.displayLength += 1;
221: output.append(getGreaterThanString());
222: }
223: return output;
224: }
225:
226: /**
227: * Return &lt;, which is used in type parameters. Override this
228: * if your doclet uses something different.
229: *
230: * @return return &lt;, which is used in type parameters.
231: */
232: protected String getLessThanString() {
233: return "<";
234: }
235:
236: /**
237: * Return &gt;, which is used in type parameters. Override this
238: * if your doclet uses something different.
239: *
240: * @return return &gt;, which is used in type parameters.
241: */
242: protected String getGreaterThanString() {
243: return ">";
244: }
245: }
|