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 */ 25 26package com.sun.tools.doclets.internal.toolkit.util.links; 27 28import com.sun.javadoc.*; 29import com.sun.tools.doclets.internal.toolkit.Content; 30 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@Deprecated 43public abstract class LinkFactory { 44 45 /** 46 * Return an empty instance of a content object. 47 * 48 * @return an empty instance of a content object. 49 */ 50 protected abstract Content newContent(); 51 52 /** 53 * Constructs a link from the given link information. 54 * 55 * @param linkInfo the information about the link. 56 * @return the output of the link. 57 */ 58 public Content getLink(LinkInfo linkInfo) { 59 if (linkInfo.type != null) { 60 Type type = linkInfo.type; 61 Content link = newContent(); 62 if (type.isPrimitive()) { 63 //Just a primitive. 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 link.addContent("?"); 74 WildcardType wildcardType = type.asWildcardType(); 75 Type[] extendsBounds = wildcardType.extendsBounds(); 76 for (int i = 0; i < extendsBounds.length; i++) { 77 link.addContent(i > 0 ? ", " : " extends "); 78 setBoundsLinkInfo(linkInfo, extendsBounds[i]); 79 link.addContent(getLink(linkInfo)); 80 } 81 Type[] superBounds = wildcardType.superBounds(); 82 for (int i = 0; i < superBounds.length; i++) { 83 link.addContent(i > 0 ? ", " : " super "); 84 setBoundsLinkInfo(linkInfo, superBounds[i]); 85 link.addContent(getLink(linkInfo)); 86 } 87 } else if (type.asTypeVariable()!= null) { 88 link.addContent(getTypeAnnotationLinks(linkInfo)); 89 linkInfo.isTypeBound = true; 90 //A type variable. 91 Doc owner = type.asTypeVariable().owner(); 92 if ((! linkInfo.excludeTypeParameterLinks) && 93 owner instanceof ClassDoc) { 94 linkInfo.classDoc = (ClassDoc) owner; 95 Content label = newContent(); 96 label.addContent(type.typeName()); 97 linkInfo.label = label; 98 link.addContent(getClassLink(linkInfo)); 99 } else { 100 //No need to link method type parameters. 101 link.addContent(type.typeName()); 102 } 103 104 Type[] bounds = type.asTypeVariable().bounds(); 105 if (! linkInfo.excludeTypeBounds) { 106 linkInfo.excludeTypeBounds = true; 107 for (int i = 0; i < bounds.length; i++) { 108 link.addContent(i > 0 ? " & " : " extends "); 109 setBoundsLinkInfo(linkInfo, bounds[i]); 110 link.addContent(getLink(linkInfo)); 111 } 112 } 113 } else if (type.asClassDoc() != null) { 114 //A class type. 115 if (linkInfo.isTypeBound && 116 linkInfo.excludeTypeBoundsLinks) { 117 //Since we are excluding type parameter links, we should not 118 //be linking to the type bound. 119 link.addContent(type.typeName()); 120 link.addContent(getTypeParameterLinks(linkInfo)); 121 return link; 122 } else { 123 linkInfo.classDoc = type.asClassDoc(); 124 link = newContent(); 125 link.addContent(getClassLink(linkInfo)); 126 if (linkInfo.includeTypeAsSepLink) { 127 link.addContent(getTypeParameterLinks(linkInfo, false)); 128 } 129 } 130 } 131 132 if (linkInfo.isVarArg) { 133 if (type.dimension().length() > 2) { 134 //Javadoc returns var args as array. 135 //Strip out the first [] from the var arg. 136 link.addContent(type.dimension().substring(2)); 137 } 138 link.addContent("..."); 139 } else { 140 while (type != null && type.dimension().length() > 0) { 141 if (type.asAnnotatedType() != null) { 142 linkInfo.type = type; 143 link.addContent(" "); 144 link.addContent(getTypeAnnotationLinks(linkInfo)); 145 link.addContent("[]"); 146 type = type.asAnnotatedType().underlyingType().getElementType(); 147 } else { 148 link.addContent("[]"); 149 type = type.getElementType(); 150 } 151 } 152 linkInfo.type = type; 153 Content newLink = newContent(); 154 newLink.addContent(getTypeAnnotationLinks(linkInfo)); 155 newLink.addContent(link); 156 link = newLink; 157 } 158 return link; 159 } else if (linkInfo.classDoc != null) { 160 //Just a class link 161 Content link = newContent(); 162 link.addContent(getClassLink(linkInfo)); 163 if (linkInfo.includeTypeAsSepLink) { 164 link.addContent(getTypeParameterLinks(linkInfo, false)); 165 } 166 return link; 167 } else { 168 return null; 169 } 170 } 171 172 private void setBoundsLinkInfo(LinkInfo linkInfo, Type bound) { 173 linkInfo.classDoc = null; 174 linkInfo.label = null; 175 linkInfo.type = bound; 176 } 177 178 /** 179 * Return the link to the given class. 180 * 181 * @param linkInfo the information about the link to construct. 182 * 183 * @return the link for the given class. 184 */ 185 protected abstract Content getClassLink(LinkInfo linkInfo); 186 187 /** 188 * Return the link to the given type parameter. 189 * 190 * @param linkInfo the information about the link to construct. 191 * @param typeParam the type parameter to link to. 192 */ 193 protected abstract Content getTypeParameterLink(LinkInfo linkInfo, 194 Type typeParam); 195 196 protected abstract Content getTypeAnnotationLink(LinkInfo linkInfo, 197 AnnotationDesc annotation); 198 199 /** 200 * Return the links to the type parameters. 201 * 202 * @param linkInfo the information about the link to construct. 203 * @return the links to the type parameters. 204 */ 205 public Content getTypeParameterLinks(LinkInfo linkInfo) { 206 return getTypeParameterLinks(linkInfo, true); 207 } 208 209 /** 210 * Return the links to the type parameters. 211 * 212 * @param linkInfo the information about the link to construct. 213 * @param isClassLabel true if this is a class label. False if it is 214 * the type parameters portion of the link. 215 * @return the links to the type parameters. 216 */ 217 public Content getTypeParameterLinks(LinkInfo linkInfo, boolean isClassLabel) { 218 Content links = newContent(); 219 Type[] vars; 220 if (linkInfo.executableMemberDoc != null) { 221 vars = linkInfo.executableMemberDoc.typeParameters(); 222 } else if (linkInfo.type != null && 223 linkInfo.type.asParameterizedType() != null){ 224 vars = linkInfo.type.asParameterizedType().typeArguments(); 225 } else if (linkInfo.classDoc != null){ 226 vars = linkInfo.classDoc.typeParameters(); 227 } else { 228 //Nothing to document. 229 return links; 230 } 231 if (((linkInfo.includeTypeInClassLinkLabel && isClassLabel) || 232 (linkInfo.includeTypeAsSepLink && ! isClassLabel) 233 ) 234 && vars.length > 0) { 235 links.addContent("<"); 236 for (int i = 0; i < vars.length; i++) { 237 if (i > 0) { 238 links.addContent(","); 239 } 240 links.addContent(getTypeParameterLink(linkInfo, vars[i])); 241 } 242 links.addContent(">"); 243 } 244 return links; 245 } 246 247 public Content getTypeAnnotationLinks(LinkInfo linkInfo) { 248 Content links = newContent(); 249 if (linkInfo.type.asAnnotatedType() == null) 250 return links; 251 AnnotationDesc[] annotations = linkInfo.type.asAnnotatedType().annotations(); 252 for (int i = 0; i < annotations.length; i++) { 253 if (i > 0) { 254 links.addContent(" "); 255 } 256 links.addContent(getTypeAnnotationLink(linkInfo, annotations[i])); 257 } 258 259 links.addContent(" "); 260 return links; 261 } 262} 263