Tue, 14 May 2013 10:14:52 -0700
8011650: reduce use of RawHtml nodes in doclet
Reviewed-by: darcy
1 /*
2 * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
26 package com.sun.tools.doclets.internal.toolkit.util.links;
28 import com.sun.javadoc.*;
29 import com.sun.tools.doclets.internal.toolkit.Content;
31 /**
32 * A factory that constructs links from given link information.
33 *
34 * <p><b>This is NOT part of any supported API.
35 * If you write code that depends on this, you do so at your own risk.
36 * This code and its internal interfaces are subject to change or
37 * deletion without notice.</b>
38 *
39 * @author Jamie Ho
40 * @since 1.5
41 */
42 public abstract class LinkFactory {
44 /**
45 * Return an empty instance of a content object.
46 *
47 * @return an empty instance of a content object.
48 */
49 protected abstract Content newContent();
51 /**
52 * Constructs a link from the given link information.
53 *
54 * @param linkInfo the information about the link.
55 * @return the output of the link.
56 */
57 public Content getLink(LinkInfo linkInfo) {
58 if (linkInfo.type != null) {
59 Type type = linkInfo.type;
60 Content link = newContent();
61 if (type.isPrimitive()) {
62 //Just a primitive.
63 linkInfo.displayLength += type.typeName().length();
64 link.addContent(type.typeName());
65 } else if (type.asAnnotatedType() != null && type.dimension().length() == 0) {
66 link.addContent(getTypeAnnotationLinks(linkInfo));
67 linkInfo.type = type.asAnnotatedType().underlyingType();
68 link.addContent(getLink(linkInfo));
69 return link;
70 } else if (type.asWildcardType() != null) {
71 //Wildcard type.
72 linkInfo.isTypeBound = true;
73 linkInfo.displayLength += 1;
74 link.addContent("?");
75 WildcardType wildcardType = type.asWildcardType();
76 Type[] extendsBounds = wildcardType.extendsBounds();
77 for (int i = 0; i < extendsBounds.length; i++) {
78 linkInfo.displayLength += i > 0 ? 2 : 9;
79 link.addContent(i > 0 ? ", " : " extends ");
80 setBoundsLinkInfo(linkInfo, extendsBounds[i]);
81 link.addContent(getLink(linkInfo));
82 }
83 Type[] superBounds = wildcardType.superBounds();
84 for (int i = 0; i < superBounds.length; i++) {
85 linkInfo.displayLength += i > 0 ? 2 : 7;
86 link.addContent(i > 0 ? ", " : " super ");
87 setBoundsLinkInfo(linkInfo, superBounds[i]);
88 link.addContent(getLink(linkInfo));
89 }
90 } else if (type.asTypeVariable()!= null) {
91 link.addContent(getTypeAnnotationLinks(linkInfo));
92 linkInfo.isTypeBound = true;
93 //A type variable.
94 Doc owner = type.asTypeVariable().owner();
95 if ((! linkInfo.excludeTypeParameterLinks) &&
96 owner instanceof ClassDoc) {
97 linkInfo.classDoc = (ClassDoc) owner;
98 Content label = newContent();
99 label.addContent(type.typeName());
100 linkInfo.label = label;
101 link.addContent(getClassLink(linkInfo));
102 } else {
103 //No need to link method type parameters.
104 linkInfo.displayLength += type.typeName().length();
105 link.addContent(type.typeName());
106 }
108 Type[] bounds = type.asTypeVariable().bounds();
109 if (! linkInfo.excludeTypeBounds) {
110 linkInfo.excludeTypeBounds = true;
111 for (int i = 0; i < bounds.length; i++) {
112 linkInfo.displayLength += i > 0 ? 2 : 9;
113 link.addContent(i > 0 ? " & " : " extends ");
114 setBoundsLinkInfo(linkInfo, bounds[i]);
115 link.addContent(getLink(linkInfo));
116 }
117 }
118 } else if (type.asClassDoc() != null) {
119 //A class type.
120 if (linkInfo.isTypeBound &&
121 linkInfo.excludeTypeBoundsLinks) {
122 //Since we are excluding type parameter links, we should not
123 //be linking to the type bound.
124 linkInfo.displayLength += type.typeName().length();
125 link.addContent(type.typeName());
126 link.addContent(getTypeParameterLinks(linkInfo));
127 return link;
128 } else {
129 linkInfo.classDoc = type.asClassDoc();
130 link = newContent();
131 link.addContent(getClassLink(linkInfo));
132 if (linkInfo.includeTypeAsSepLink) {
133 link.addContent(getTypeParameterLinks(linkInfo, false));
134 }
135 }
136 }
138 if (linkInfo.isVarArg) {
139 if (type.dimension().length() > 2) {
140 //Javadoc returns var args as array.
141 //Strip out the first [] from the var arg.
142 linkInfo.displayLength += type.dimension().length()-2;
143 link.addContent(type.dimension().substring(2));
144 }
145 linkInfo.displayLength += 3;
146 link.addContent("...");
147 } else {
148 while (type != null && type.dimension().length() > 0) {
149 linkInfo.displayLength += type.dimension().length();
150 if (type.asAnnotatedType() != null) {
151 linkInfo.type = type;
152 link.addContent(" ");
153 link.addContent(getTypeAnnotationLinks(linkInfo));
154 link.addContent("[]");
155 type = type.asAnnotatedType().underlyingType().getElementType();
156 } else {
157 link.addContent("[]");
158 type = type.getElementType();
159 }
160 }
161 linkInfo.type = type;
162 Content newLink = newContent();
163 newLink.addContent(getTypeAnnotationLinks(linkInfo));
164 newLink.addContent(link);
165 link = newLink;
166 }
167 return link;
168 } else if (linkInfo.classDoc != null) {
169 //Just a class link
170 Content link = newContent();
171 link.addContent(getClassLink(linkInfo));
172 if (linkInfo.includeTypeAsSepLink) {
173 link.addContent(getTypeParameterLinks(linkInfo, false));
174 }
175 return link;
176 } else {
177 return null;
178 }
179 }
181 private void setBoundsLinkInfo(LinkInfo linkInfo, Type bound) {
182 linkInfo.classDoc = null;
183 linkInfo.label = null;
184 linkInfo.type = bound;
185 }
187 /**
188 * Return the link to the given class.
189 *
190 * @param linkInfo the information about the link to construct.
191 *
192 * @return the link for the given class.
193 */
194 protected abstract Content getClassLink(LinkInfo linkInfo);
196 /**
197 * Return the link to the given type parameter.
198 *
199 * @param linkInfo the information about the link to construct.
200 * @param typeParam the type parameter to link to.
201 */
202 protected abstract Content getTypeParameterLink(LinkInfo linkInfo,
203 Type typeParam);
205 protected abstract Content getTypeAnnotationLink(LinkInfo linkInfo,
206 AnnotationDesc annotation);
208 /**
209 * Return the links to the type parameters.
210 *
211 * @param linkInfo the information about the link to construct.
212 * @return the links to the type parameters.
213 */
214 public Content getTypeParameterLinks(LinkInfo linkInfo) {
215 return getTypeParameterLinks(linkInfo, true);
216 }
218 /**
219 * Return the links to the type parameters.
220 *
221 * @param linkInfo the information about the link to construct.
222 * @param isClassLabel true if this is a class label. False if it is
223 * the type parameters portion of the link.
224 * @return the links to the type parameters.
225 */
226 public Content getTypeParameterLinks(LinkInfo linkInfo, boolean isClassLabel) {
227 Content links = newContent();
228 Type[] vars;
229 if (linkInfo.executableMemberDoc != null) {
230 vars = linkInfo.executableMemberDoc.typeParameters();
231 } else if (linkInfo.type != null &&
232 linkInfo.type.asParameterizedType() != null){
233 vars = linkInfo.type.asParameterizedType().typeArguments();
234 } else if (linkInfo.classDoc != null){
235 vars = linkInfo.classDoc.typeParameters();
236 } else {
237 //Nothing to document.
238 return links;
239 }
240 if (((linkInfo.includeTypeInClassLinkLabel && isClassLabel) ||
241 (linkInfo.includeTypeAsSepLink && ! isClassLabel)
242 )
243 && vars.length > 0) {
244 linkInfo.displayLength += 1;
245 links.addContent("<");
246 for (int i = 0; i < vars.length; i++) {
247 if (i > 0) {
248 linkInfo.displayLength += 1;
249 links.addContent(",");
250 }
251 links.addContent(getTypeParameterLink(linkInfo, vars[i]));
252 }
253 linkInfo.displayLength += 1;
254 links.addContent(">");
255 }
256 return links;
257 }
259 public Content getTypeAnnotationLinks(LinkInfo linkInfo) {
260 Content links = newContent();
261 if (linkInfo.type.asAnnotatedType() == null)
262 return links;
263 AnnotationDesc[] annotations = linkInfo.type.asAnnotatedType().annotations();
264 for (int i = 0; i < annotations.length; i++) {
265 if (i > 0) {
266 linkInfo.displayLength += 1;
267 links.addContent(" ");
268 }
269 links.addContent(getTypeAnnotationLink(linkInfo, annotations[i]));
270 }
272 linkInfo.displayLength += 1;
273 links.addContent(" ");
274 return links;
275 }
276 }