Sun, 24 Feb 2013 11:36:58 -0800
7112427: The doclet needs to be able to generate JavaFX documentation.
Reviewed-by: jjg
Contributed-by: jan.valenta@oracle.com
1 /*
2 * Copyright (c) 1999, 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;
28 import java.io.*;
29 import java.lang.annotation.ElementType;
30 import java.util.*;
32 import com.sun.javadoc.*;
33 import com.sun.javadoc.AnnotationDesc.ElementValuePair;
34 import com.sun.tools.doclets.internal.toolkit.*;
35 import javax.tools.StandardLocation;
37 /**
38 * Utilities Class for Doclets.
39 *
40 * <p><b>This is NOT part of any supported API.
41 * If you write code that depends on this, you do so at your own risk.
42 * This code and its internal interfaces are subject to change or
43 * deletion without notice.</b>
44 *
45 * @author Atul M Dambalkar
46 * @author Jamie Ho
47 */
48 public class Util {
50 /**
51 * Return array of class members whose documentation is to be generated.
52 * If the member is deprecated do not include such a member in the
53 * returned array.
54 *
55 * @param members Array of members to choose from.
56 * @return ProgramElementDoc[] Array of eligible members for whom
57 * documentation is getting generated.
58 */
59 public static ProgramElementDoc[] excludeDeprecatedMembers(
60 ProgramElementDoc[] members) {
61 return
62 toProgramElementDocArray(excludeDeprecatedMembersAsList(members));
63 }
65 /**
66 * Return array of class members whose documentation is to be generated.
67 * If the member is deprecated do not include such a member in the
68 * returned array.
69 *
70 * @param members Array of members to choose from.
71 * @return List List of eligible members for whom
72 * documentation is getting generated.
73 */
74 public static List<ProgramElementDoc> excludeDeprecatedMembersAsList(
75 ProgramElementDoc[] members) {
76 List<ProgramElementDoc> list = new ArrayList<ProgramElementDoc>();
77 for (int i = 0; i < members.length; i++) {
78 if (members[i].tags("deprecated").length == 0) {
79 list.add(members[i]);
80 }
81 }
82 Collections.sort(list);
83 return list;
84 }
86 /**
87 * Return the list of ProgramElementDoc objects as Array.
88 */
89 public static ProgramElementDoc[] toProgramElementDocArray(List<ProgramElementDoc> list) {
90 ProgramElementDoc[] pgmarr = new ProgramElementDoc[list.size()];
91 for (int i = 0; i < list.size(); i++) {
92 pgmarr[i] = list.get(i);
93 }
94 return pgmarr;
95 }
97 /**
98 * Return true if a non-public member found in the given array.
99 *
100 * @param members Array of members to look into.
101 * @return boolean True if non-public member found, false otherwise.
102 */
103 public static boolean nonPublicMemberFound(ProgramElementDoc[] members) {
104 for (int i = 0; i < members.length; i++) {
105 if (!members[i].isPublic()) {
106 return true;
107 }
108 }
109 return false;
110 }
112 /**
113 * Search for the given method in the given class.
114 *
115 * @param cd Class to search into.
116 * @param method Method to be searched.
117 * @return MethodDoc Method found, null otherwise.
118 */
119 public static MethodDoc findMethod(ClassDoc cd, MethodDoc method) {
120 MethodDoc[] methods = cd.methods();
121 for (int i = 0; i < methods.length; i++) {
122 if (executableMembersEqual(method, methods[i])) {
123 return methods[i];
125 }
126 }
127 return null;
128 }
130 /**
131 * @param member1 the first method to compare.
132 * @param member2 the second method to compare.
133 * @return true if member1 overrides/hides or is overriden/hidden by member2.
134 */
135 public static boolean executableMembersEqual(ExecutableMemberDoc member1,
136 ExecutableMemberDoc member2) {
137 if (! (member1 instanceof MethodDoc && member2 instanceof MethodDoc))
138 return false;
140 MethodDoc method1 = (MethodDoc) member1;
141 MethodDoc method2 = (MethodDoc) member2;
142 if (method1.isStatic() && method2.isStatic()) {
143 Parameter[] targetParams = method1.parameters();
144 Parameter[] currentParams;
145 if (method1.name().equals(method2.name()) &&
146 (currentParams = method2.parameters()).length ==
147 targetParams.length) {
148 int j;
149 for (j = 0; j < targetParams.length; j++) {
150 if (! (targetParams[j].typeName().equals(
151 currentParams[j].typeName()) ||
152 currentParams[j].type() instanceof TypeVariable ||
153 targetParams[j].type() instanceof TypeVariable)) {
154 break;
155 }
156 }
157 if (j == targetParams.length) {
158 return true;
159 }
160 }
161 return false;
162 } else {
163 return method1.overrides(method2) ||
164 method2.overrides(method1) ||
165 member1 == member2;
166 }
167 }
169 /**
170 * According to
171 * <cite>The Java™ Language Specification</cite>,
172 * all the outer classes and static inner classes are core classes.
173 */
174 public static boolean isCoreClass(ClassDoc cd) {
175 return cd.containingClass() == null || cd.isStatic();
176 }
178 public static boolean matches(ProgramElementDoc doc1,
179 ProgramElementDoc doc2) {
180 if (doc1 instanceof ExecutableMemberDoc &&
181 doc2 instanceof ExecutableMemberDoc) {
182 ExecutableMemberDoc ed1 = (ExecutableMemberDoc)doc1;
183 ExecutableMemberDoc ed2 = (ExecutableMemberDoc)doc2;
184 return executableMembersEqual(ed1, ed2);
185 } else {
186 return doc1.name().equals(doc2.name());
187 }
188 }
190 /**
191 * Copy the given directory contents from the source package directory
192 * to the generated documentation directory. For example for a package
193 * java.lang this method find out the source location of the package using
194 * {@link SourcePath} and if given directory is found in the source
195 * directory structure, copy the entire directory, to the generated
196 * documentation hierarchy.
197 *
198 * @param configuration The configuration of the current doclet.
199 * @param path The relative path to the directory to be copied.
200 * @param dir The original directory name to copy from.
201 * @param overwrite Overwrite files if true.
202 */
203 public static void copyDocFiles(Configuration configuration, PackageDoc pd) {
204 copyDocFiles(configuration, DocPath.forPackage(pd).resolve(DocPaths.DOC_FILES));
205 }
207 public static void copyDocFiles(Configuration configuration, DocPath dir) {
208 try {
209 boolean first = true;
210 for (DocFile f : DocFile.list(configuration, StandardLocation.SOURCE_PATH, dir)) {
211 if (!f.isDirectory()) {
212 continue;
213 }
214 DocFile srcdir = f;
215 DocFile destdir = DocFile.createFileForOutput(configuration, dir);
216 if (srcdir.isSameFile(destdir)) {
217 continue;
218 }
220 for (DocFile srcfile: srcdir.list()) {
221 DocFile destfile = destdir.resolve(srcfile.getName());
222 if (srcfile.isFile()) {
223 if (destfile.exists() && !first) {
224 configuration.message.warning((SourcePosition) null,
225 "doclet.Copy_Overwrite_warning",
226 srcfile.getPath(), destdir.getPath());
227 } else {
228 configuration.message.notice(
229 "doclet.Copying_File_0_To_Dir_1",
230 srcfile.getPath(), destdir.getPath());
231 destfile.copyFile(srcfile);
232 }
233 } else if (srcfile.isDirectory()) {
234 if (configuration.copydocfilesubdirs
235 && !configuration.shouldExcludeDocFileDir(srcfile.getName())) {
236 copyDocFiles(configuration, dir.resolve(srcfile.getName()));
237 }
238 }
239 }
241 first = false;
242 }
243 } catch (SecurityException exc) {
244 throw new DocletAbortException();
245 } catch (IOException exc) {
246 throw new DocletAbortException();
247 }
248 }
250 /**
251 * We want the list of types in alphabetical order. However, types are not
252 * comparable. We need a comparator for now.
253 */
254 private static class TypeComparator implements Comparator<Type> {
255 public int compare(Type type1, Type type2) {
256 return type1.qualifiedTypeName().toLowerCase().compareTo(
257 type2.qualifiedTypeName().toLowerCase());
258 }
259 }
261 /**
262 * For the class return all implemented interfaces including the
263 * superinterfaces of the implementing interfaces, also iterate over for
264 * all the superclasses. For interface return all the extended interfaces
265 * as well as superinterfaces for those extended interfaces.
266 *
267 * @param type type whose implemented or
268 * super interfaces are sought.
269 * @param configuration the current configuration of the doclet.
270 * @param sort if true, return list of interfaces sorted alphabetically.
271 * @return List of all the required interfaces.
272 */
273 public static List<Type> getAllInterfaces(Type type,
274 Configuration configuration, boolean sort) {
275 Map<ClassDoc,Type> results = sort ? new TreeMap<ClassDoc,Type>() : new LinkedHashMap<ClassDoc,Type>();
276 Type[] interfaceTypes = null;
277 Type superType = null;
278 if (type instanceof ParameterizedType) {
279 interfaceTypes = ((ParameterizedType) type).interfaceTypes();
280 superType = ((ParameterizedType) type).superclassType();
281 } else if (type instanceof ClassDoc) {
282 interfaceTypes = ((ClassDoc) type).interfaceTypes();
283 superType = ((ClassDoc) type).superclassType();
284 } else {
285 interfaceTypes = type.asClassDoc().interfaceTypes();
286 superType = type.asClassDoc().superclassType();
287 }
289 for (int i = 0; i < interfaceTypes.length; i++) {
290 Type interfaceType = interfaceTypes[i];
291 ClassDoc interfaceClassDoc = interfaceType.asClassDoc();
292 if (! (interfaceClassDoc.isPublic() ||
293 (configuration == null ||
294 isLinkable(interfaceClassDoc, configuration)))) {
295 continue;
296 }
297 results.put(interfaceClassDoc, interfaceType);
298 List<Type> superInterfaces = getAllInterfaces(interfaceType, configuration, sort);
299 for (Iterator<Type> iter = superInterfaces.iterator(); iter.hasNext(); ) {
300 Type t = iter.next();
301 results.put(t.asClassDoc(), t);
302 }
303 }
304 if (superType == null)
305 return new ArrayList<Type>(results.values());
306 //Try walking the tree.
307 addAllInterfaceTypes(results,
308 superType,
309 interfaceTypesOf(superType),
310 false, configuration);
311 List<Type> resultsList = new ArrayList<Type>(results.values());
312 if (sort) {
313 Collections.sort(resultsList, new TypeComparator());
314 }
315 return resultsList;
316 }
318 private static Type[] interfaceTypesOf(Type type) {
319 if (type instanceof AnnotatedType)
320 type = ((AnnotatedType)type).underlyingType();
321 return type instanceof ClassDoc ?
322 ((ClassDoc)type).interfaceTypes() :
323 ((ParameterizedType)type).interfaceTypes();
324 }
326 public static List<Type> getAllInterfaces(Type type, Configuration configuration) {
327 return getAllInterfaces(type, configuration, true);
328 }
330 private static void findAllInterfaceTypes(Map<ClassDoc,Type> results, ClassDoc c, boolean raw,
331 Configuration configuration) {
332 Type superType = c.superclassType();
333 if (superType == null)
334 return;
335 addAllInterfaceTypes(results, superType,
336 interfaceTypesOf(superType),
337 raw, configuration);
338 }
340 private static void findAllInterfaceTypes(Map<ClassDoc,Type> results, ParameterizedType p,
341 Configuration configuration) {
342 Type superType = p.superclassType();
343 if (superType == null)
344 return;
345 addAllInterfaceTypes(results, superType,
346 interfaceTypesOf(superType),
347 false, configuration);
348 }
350 private static void addAllInterfaceTypes(Map<ClassDoc,Type> results, Type type,
351 Type[] interfaceTypes, boolean raw,
352 Configuration configuration) {
353 for (int i = 0; i < interfaceTypes.length; i++) {
354 Type interfaceType = interfaceTypes[i];
355 ClassDoc interfaceClassDoc = interfaceType.asClassDoc();
356 if (! (interfaceClassDoc.isPublic() ||
357 (configuration != null &&
358 isLinkable(interfaceClassDoc, configuration)))) {
359 continue;
360 }
361 if (raw)
362 interfaceType = interfaceType.asClassDoc();
363 results.put(interfaceClassDoc, interfaceType);
364 List<Type> superInterfaces = getAllInterfaces(interfaceType, configuration);
365 for (Iterator<Type> iter = superInterfaces.iterator(); iter.hasNext(); ) {
366 Type superInterface = iter.next();
367 results.put(superInterface.asClassDoc(), superInterface);
368 }
369 }
370 if (type instanceof AnnotatedType)
371 type = ((AnnotatedType)type).underlyingType();
373 if (type instanceof ParameterizedType)
374 findAllInterfaceTypes(results, (ParameterizedType) type, configuration);
375 else if (((ClassDoc) type).typeParameters().length == 0)
376 findAllInterfaceTypes(results, (ClassDoc) type, raw, configuration);
377 else
378 findAllInterfaceTypes(results, (ClassDoc) type, true, configuration);
379 }
381 /**
382 * Enclose in quotes, used for paths and filenames that contains spaces
383 */
384 public static String quote(String filepath) {
385 return ("\"" + filepath + "\"");
386 }
388 /**
389 * Given a package, return its name.
390 * @param packageDoc the package to check.
391 * @return the name of the given package.
392 */
393 public static String getPackageName(PackageDoc packageDoc) {
394 return packageDoc == null || packageDoc.name().length() == 0 ?
395 DocletConstants.DEFAULT_PACKAGE_NAME : packageDoc.name();
396 }
398 /**
399 * Given a package, return its file name without the extension.
400 * @param packageDoc the package to check.
401 * @return the file name of the given package.
402 */
403 public static String getPackageFileHeadName(PackageDoc packageDoc) {
404 return packageDoc == null || packageDoc.name().length() == 0 ?
405 DocletConstants.DEFAULT_PACKAGE_FILE_NAME : packageDoc.name();
406 }
408 /**
409 * Given a string, replace all occurrences of 'newStr' with 'oldStr'.
410 * @param originalStr the string to modify.
411 * @param oldStr the string to replace.
412 * @param newStr the string to insert in place of the old string.
413 */
414 public static String replaceText(String originalStr, String oldStr,
415 String newStr) {
416 if (oldStr == null || newStr == null || oldStr.equals(newStr)) {
417 return originalStr;
418 }
419 return originalStr.replace(oldStr, newStr);
420 }
422 /**
423 * Given a string, escape all special html characters and
424 * return the result.
425 *
426 * @param s The string to check.
427 * @return the original string with all of the HTML characters escaped.
428 */
429 public static String escapeHtmlChars(String s) {
430 for (int i = 0; i < s.length(); i++) {
431 char ch = s.charAt(i);
432 switch (ch) {
433 // only start building a new string if we need to
434 case '<': case '>': case '&':
435 StringBuilder sb = new StringBuilder(s.substring(0, i));
436 for ( ; i < s.length(); i++) {
437 ch = s.charAt(i);
438 switch (ch) {
439 case '<': sb.append("<"); break;
440 case '>': sb.append(">"); break;
441 case '&': sb.append("&"); break;
442 default: sb.append(ch); break;
443 }
444 }
445 return sb.toString();
446 }
447 }
448 return s;
449 }
451 /**
452 * Escape all special html characters in a string buffer.
453 *
454 * @param sb The string buffer to update
455 */
456 public static void escapeHtmlChars(StringBuilder sb) {
457 // scan backwards, replacing characters as needed.
458 for (int i = sb.length() - 1; i >= 0; i--) {
459 switch (sb.charAt(i)) {
460 case '<': sb.replace(i, i+1, "<"); break;
461 case '>': sb.replace(i, i+1, ">"); break;
462 case '&': sb.replace(i, i+1, "&"); break;
463 }
464 }
465 }
467 /**
468 * Given a string, strips all html characters and
469 * return the result.
470 *
471 * @param rawString The string to check.
472 * @return the original string with all of the HTML characters
473 * stripped.
474 *
475 */
476 public static String stripHtml(String rawString) {
477 // remove HTML tags
478 rawString = rawString.replaceAll("\\<.*?>", " ");
479 // consolidate multiple spaces between a word to a single space
480 rawString = rawString.replaceAll("\\b\\s{2,}\\b", " ");
481 // remove extra whitespaces
482 return rawString.trim();
483 }
485 /**
486 * Given an annotation, return true if it should be documented and false
487 * otherwise.
488 *
489 * @param annotationDoc the annotation to check.
490 *
491 * @return true return true if it should be documented and false otherwise.
492 */
493 public static boolean isDocumentedAnnotation(AnnotationTypeDoc annotationDoc) {
494 AnnotationDesc[] annotationDescList = annotationDoc.annotations();
495 for (int i = 0; i < annotationDescList.length; i++) {
496 if (annotationDescList[i].annotationType().qualifiedName().equals(
497 java.lang.annotation.Documented.class.getName())){
498 return true;
499 }
500 }
501 return false;
502 }
504 private static boolean isDeclarationTarget(AnnotationDesc targetAnno) {
505 // The error recovery steps here are analogous to TypeAnnotations
506 ElementValuePair[] elems = targetAnno.elementValues();
507 if (elems == null
508 || elems.length != 1
509 || !"value".equals(elems[0].element().name())
510 || !(elems[0].value().value() instanceof AnnotationValue[]))
511 return true; // error recovery
513 AnnotationValue[] values = (AnnotationValue[])elems[0].value().value();
514 for (int i = 0; i < values.length; i++) {
515 Object value = values[i].value();
516 if (!(value instanceof FieldDoc))
517 return true; // error recovery
519 FieldDoc eValue = (FieldDoc)value;
520 if (Util.isJava5DeclarationElementType(eValue)) {
521 return true;
522 }
523 }
525 return false;
526 }
528 /**
529 * Returns true if the {@code annotationDoc} is to be treated
530 * as a declaration annotation, when targeting the
531 * {@code elemType} element type.
532 *
533 * @param annotationDoc the annotationDoc to check
534 * @param elemType the targeted elemType
535 * @return true if annotationDoc is a declaration annotation
536 */
537 public static boolean isDeclarationAnnotation(AnnotationTypeDoc annotationDoc,
538 boolean isJava5DeclarationLocation) {
539 if (!isJava5DeclarationLocation)
540 return false;
541 AnnotationDesc[] annotationDescList = annotationDoc.annotations();
542 // Annotations with no target are treated as declaration as well
543 if (annotationDescList.length==0)
544 return true;
545 for (int i = 0; i < annotationDescList.length; i++) {
546 if (annotationDescList[i].annotationType().qualifiedName().equals(
547 java.lang.annotation.Target.class.getName())) {
548 if (isDeclarationTarget(annotationDescList[i]))
549 return true;
550 }
551 }
552 return false;
553 }
555 /**
556 * Return true if this class is linkable and false if we can't link to the
557 * desired class.
558 * <br>
559 * <b>NOTE:</b> You can only link to external classes if they are public or
560 * protected.
561 *
562 * @param classDoc the class to check.
563 * @param configuration the current configuration of the doclet.
564 *
565 * @return true if this class is linkable and false if we can't link to the
566 * desired class.
567 */
568 public static boolean isLinkable(ClassDoc classDoc,
569 Configuration configuration) {
570 return
571 ((classDoc.isIncluded() && configuration.isGeneratedDoc(classDoc))) ||
572 (configuration.extern.isExternal(classDoc) &&
573 (classDoc.isPublic() || classDoc.isProtected()));
574 }
576 /**
577 * Given a class, return the closest visible super class.
578 *
579 * @param classDoc the class we are searching the parent for.
580 * @param configuration the current configuration of the doclet.
581 * @return the closest visible super class. Return null if it cannot
582 * be found (i.e. classDoc is java.lang.Object).
583 */
584 public static Type getFirstVisibleSuperClass(ClassDoc classDoc,
585 Configuration configuration) {
586 if (classDoc == null) {
587 return null;
588 }
589 Type sup = classDoc.superclassType();
590 ClassDoc supClassDoc = classDoc.superclass();
591 while (sup != null &&
592 (! (supClassDoc.isPublic() ||
593 isLinkable(supClassDoc, configuration))) ) {
594 if (supClassDoc.superclass().qualifiedName().equals(supClassDoc.qualifiedName()))
595 break;
596 sup = supClassDoc.superclassType();
597 supClassDoc = supClassDoc.superclass();
598 }
599 if (classDoc.equals(supClassDoc)) {
600 return null;
601 }
602 return sup;
603 }
605 /**
606 * Given a class, return the closest visible super class.
607 *
608 * @param classDoc the class we are searching the parent for.
609 * @param configuration the current configuration of the doclet.
610 * @return the closest visible super class. Return null if it cannot
611 * be found (i.e. classDoc is java.lang.Object).
612 */
613 public static ClassDoc getFirstVisibleSuperClassCD(ClassDoc classDoc,
614 Configuration configuration) {
615 if (classDoc == null) {
616 return null;
617 }
618 ClassDoc supClassDoc = classDoc.superclass();
619 while (supClassDoc != null &&
620 (! (supClassDoc.isPublic() ||
621 isLinkable(supClassDoc, configuration))) ) {
622 supClassDoc = supClassDoc.superclass();
623 }
624 if (classDoc.equals(supClassDoc)) {
625 return null;
626 }
627 return supClassDoc;
628 }
630 /**
631 * Given a ClassDoc, return the name of its type (Class, Interface, etc.).
632 *
633 * @param cd the ClassDoc to check.
634 * @param lowerCaseOnly true if you want the name returned in lower case.
635 * If false, the first letter of the name is capitalized.
636 * @return
637 */
638 public static String getTypeName(Configuration config,
639 ClassDoc cd, boolean lowerCaseOnly) {
640 String typeName = "";
641 if (cd.isOrdinaryClass()) {
642 typeName = "doclet.Class";
643 } else if (cd.isInterface()) {
644 typeName = "doclet.Interface";
645 } else if (cd.isException()) {
646 typeName = "doclet.Exception";
647 } else if (cd.isError()) {
648 typeName = "doclet.Error";
649 } else if (cd.isAnnotationType()) {
650 typeName = "doclet.AnnotationType";
651 } else if (cd.isEnum()) {
652 typeName = "doclet.Enum";
653 }
654 return config.getText(
655 lowerCaseOnly ? typeName.toLowerCase() : typeName);
656 }
658 /**
659 * Replace all tabs with the appropriate number of spaces.
660 * @param configuration the doclet configuration defining the setting for the
661 * tab length.
662 * @param sb the StringBuilder in which to replace the tabs
663 */
664 public static void replaceTabs(Configuration configuration, StringBuilder sb) {
665 int tabLength = configuration.sourcetab;
666 String whitespace = configuration.tabSpaces;
667 int index = 0;
668 while ((index = sb.indexOf("\t", index)) != -1) {
669 int spaceCount = tabLength - index % tabLength;
670 sb.replace(index, index+1, whitespace.substring(0, spaceCount));
671 index += spaceCount;
672 }
673 }
675 /**
676 * The documentation for values() and valueOf() in Enums are set by the
677 * doclet.
678 */
679 public static void setEnumDocumentation(Configuration configuration,
680 ClassDoc classDoc) {
681 MethodDoc[] methods = classDoc.methods();
682 for (int j = 0; j < methods.length; j++) {
683 MethodDoc currentMethod = methods[j];
684 if (currentMethod.name().equals("values") &&
685 currentMethod.parameters().length == 0) {
686 currentMethod.setRawCommentText(
687 configuration.getText("doclet.enum_values_doc", classDoc.name()));
688 } else if (currentMethod.name().equals("valueOf") &&
689 currentMethod.parameters().length == 1) {
690 Type paramType = currentMethod.parameters()[0].type();
691 if (paramType != null &&
692 paramType.qualifiedTypeName().equals(String.class.getName())) {
693 currentMethod.setRawCommentText(
694 configuration.getText("doclet.enum_valueof_doc"));
695 }
696 }
697 }
698 }
700 /**
701 * Return true if the given Doc is deprecated.
702 *
703 * @param doc the Doc to check.
704 * @return true if the given Doc is deprecated.
705 */
706 public static boolean isDeprecated(Doc doc) {
707 if (doc.tags("deprecated").length > 0) {
708 return true;
709 }
710 AnnotationDesc[] annotationDescList;
711 if (doc instanceof PackageDoc)
712 annotationDescList = ((PackageDoc)doc).annotations();
713 else
714 annotationDescList = ((ProgramElementDoc)doc).annotations();
715 for (int i = 0; i < annotationDescList.length; i++) {
716 if (annotationDescList[i].annotationType().qualifiedName().equals(
717 java.lang.Deprecated.class.getName())){
718 return true;
719 }
720 }
721 return false;
722 }
724 /**
725 * A convenience method to get property name from the name of the
726 * getter or setter method.
727 * @param name name of the getter or setter method.
728 * @return the name of the property of the given setter of getter.
729 */
730 public static String propertyNameFromMethodName(String name) {
731 String propertyName = null;
732 if (name.startsWith("get") || name.startsWith("set")) {
733 propertyName = name.substring(3);
734 } else if (name.startsWith("is")) {
735 propertyName = name.substring(2);
736 }
737 if ((propertyName == null) || propertyName.isEmpty()){
738 return "";
739 }
740 return propertyName.substring(0, 1).toLowerCase()
741 + propertyName.substring(1);
742 }
744 /**
745 * In case of JavaFX mode on, filters out classes that are private,
746 * package private or having the @treatAsPrivate annotation. Those are not
747 * documented in JavaFX mode.
748 *
749 * @param classes array of classes to be filtered.
750 * @param javafx set to true if in JavaFX mode.
751 * @return list of filtered classes.
752 */
753 public static ClassDoc[] filterOutPrivateClasses(final ClassDoc[] classes,
754 boolean javafx) {
755 if (!javafx) {
756 return classes;
757 }
758 final List<ClassDoc> filteredOutClasses =
759 new ArrayList<ClassDoc>(classes.length);
760 for (ClassDoc classDoc : classes) {
761 if (classDoc.isPrivate() || classDoc.isPackagePrivate()) {
762 continue;
763 }
764 Tag[] aspTags = classDoc.tags("treatAsPrivate");
765 if (aspTags != null && aspTags.length > 0) {
766 continue;
767 }
768 filteredOutClasses.add(classDoc);
769 }
771 return filteredOutClasses.toArray(new ClassDoc[0]);
772 }
774 /**
775 * Test whether the given FieldDoc is one of the declaration annotation ElementTypes
776 * defined in Java 5.
777 * Instead of testing for one of the new enum constants added in Java 8, test for
778 * the old constants. This prevents bootstrapping problems.
779 *
780 * @param elt The FieldDoc to test
781 * @return true, iff the given ElementType is one of the constants defined in Java 5
782 * @since 1.8
783 */
784 public static boolean isJava5DeclarationElementType(FieldDoc elt) {
785 return elt.name().contentEquals(ElementType.ANNOTATION_TYPE.name()) ||
786 elt.name().contentEquals(ElementType.CONSTRUCTOR.name()) ||
787 elt.name().contentEquals(ElementType.FIELD.name()) ||
788 elt.name().contentEquals(ElementType.LOCAL_VARIABLE.name()) ||
789 elt.name().contentEquals(ElementType.METHOD.name()) ||
790 elt.name().contentEquals(ElementType.PACKAGE.name()) ||
791 elt.name().contentEquals(ElementType.PARAMETER.name()) ||
792 elt.name().contentEquals(ElementType.TYPE.name());
793 }
794 }