Thu, 31 Aug 2017 15:17:03 +0800
merge
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.util.*;
29 import java.util.regex.Pattern;
31 import com.sun.javadoc.*;
32 import com.sun.tools.doclets.internal.toolkit.*;
34 /**
35 * A data structure that encapsulates the visible members of a particular
36 * type for a given class tree. To use this data structor, you must specify
37 * the type of member you are interested in (nested class, field, constructor
38 * or method) and the leaf of the class tree. The data structure will map
39 * all visible members in the leaf and classes above the leaf in the tree.
40 *
41 * <p><b>This is NOT part of any supported API.
42 * If you write code that depends on this, you do so at your own risk.
43 * This code and its internal interfaces are subject to change or
44 * deletion without notice.</b>
45 *
46 * @author Atul M Dambalkar
47 * @author Jamie Ho (rewrite)
48 */
49 public class VisibleMemberMap {
51 private boolean noVisibleMembers = true;
53 public static final int INNERCLASSES = 0;
54 public static final int ENUM_CONSTANTS = 1;
55 public static final int FIELDS = 2;
56 public static final int CONSTRUCTORS = 3;
57 public static final int METHODS = 4;
58 public static final int ANNOTATION_TYPE_FIELDS = 5;
59 public static final int ANNOTATION_TYPE_MEMBER_OPTIONAL = 6;
60 public static final int ANNOTATION_TYPE_MEMBER_REQUIRED = 7;
61 public static final int PROPERTIES = 8;
63 /**
64 * The total number of member types is {@value}.
65 */
66 public static final int NUM_MEMBER_TYPES = 9;
68 public static final String STARTLEVEL = "start";
70 /**
71 * List of ClassDoc objects for which ClassMembers objects are built.
72 */
73 private final List<ClassDoc> visibleClasses = new ArrayList<ClassDoc>();
75 /**
76 * Map for each member name on to a map which contains members with same
77 * name-signature. The mapped map will contain mapping for each MemberDoc
78 * onto it's respecive level string.
79 */
80 private final Map<Object,Map<ProgramElementDoc,String>> memberNameMap = new HashMap<Object,Map<ProgramElementDoc,String>>();
82 /**
83 * Map of class and it's ClassMembers object.
84 */
85 private final Map<ClassDoc,ClassMembers> classMap = new HashMap<ClassDoc,ClassMembers>();
87 /**
88 * Type whose visible members are requested. This is the leaf of
89 * the class tree being mapped.
90 */
91 private final ClassDoc classdoc;
93 /**
94 * Member kind: InnerClasses/Fields/Methods?
95 */
96 private final int kind;
98 /**
99 * The configuration this VisibleMemberMap was created with.
100 */
101 private final Configuration configuration;
103 private static final Map<ClassDoc, ProgramElementDoc[]> propertiesCache =
104 new HashMap<ClassDoc, ProgramElementDoc[]>();
105 private static final Map<ProgramElementDoc, ProgramElementDoc> classPropertiesMap =
106 new HashMap<ProgramElementDoc, ProgramElementDoc>();
107 private static final Map<ProgramElementDoc, GetterSetter> getterSetterMap =
108 new HashMap<ProgramElementDoc, GetterSetter>();
110 /**
111 * Construct a VisibleMemberMap of the given type for the given
112 * class.
113 *
114 * @param classdoc the class whose members are being mapped.
115 * @param kind the kind of member that is being mapped.
116 * @param configuration the configuration to use to construct this
117 * VisibleMemberMap. If the field configuration.nodeprecated is true the
118 * deprecated members are excluded from the map. If the field
119 * configuration.javafx is true the JavaFX features are used.
120 */
121 public VisibleMemberMap(ClassDoc classdoc,
122 int kind,
123 Configuration configuration) {
124 this.classdoc = classdoc;
125 this.kind = kind;
126 this.configuration = configuration;
127 new ClassMembers(classdoc, STARTLEVEL).build();
128 }
130 /**
131 * Return the list of visible classes in this map.
132 *
133 * @return the list of visible classes in this map.
134 */
135 public List<ClassDoc> getVisibleClassesList() {
136 sort(visibleClasses);
137 return visibleClasses;
138 }
140 /**
141 * Returns the property field documentation belonging to the given member.
142 * @param ped the member for which the property documentation is needed.
143 * @return the property field documentation, null if there is none.
144 */
145 public ProgramElementDoc getPropertyMemberDoc(ProgramElementDoc ped) {
146 return classPropertiesMap.get(ped);
147 }
149 /**
150 * Returns the getter documentation belonging to the given property method.
151 * @param propertyMethod the method for which the getter is needed.
152 * @return the getter documentation, null if there is none.
153 */
154 public ProgramElementDoc getGetterForProperty(ProgramElementDoc propertyMethod) {
155 return getterSetterMap.get(propertyMethod).getGetter();
156 }
158 /**
159 * Returns the setter documentation belonging to the given property method.
160 * @param propertyMethod the method for which the setter is needed.
161 * @return the setter documentation, null if there is none.
162 */
163 public ProgramElementDoc getSetterForProperty(ProgramElementDoc propertyMethod) {
164 return getterSetterMap.get(propertyMethod).getSetter();
165 }
167 /**
168 * Return the package private members inherited by the class. Only return
169 * if parent is package private and not documented.
170 *
171 * @param configuration the current configuration of the doclet.
172 * @return the package private members inherited by the class.
173 */
174 private List<ProgramElementDoc> getInheritedPackagePrivateMethods(Configuration configuration) {
175 List<ProgramElementDoc> results = new ArrayList<ProgramElementDoc>();
176 for (Iterator<ClassDoc> iter = visibleClasses.iterator(); iter.hasNext(); ) {
177 ClassDoc currentClass = iter.next();
178 if (currentClass != classdoc &&
179 currentClass.isPackagePrivate() &&
180 !Util.isLinkable(currentClass, configuration)) {
181 // Document these members in the child class because
182 // the parent is inaccessible.
183 results.addAll(getMembersFor(currentClass));
184 }
185 }
186 return results;
187 }
189 /**
190 * Return the visible members of the class being mapped. Also append at the
191 * end of the list members that are inherited by inaccessible parents. We
192 * document these members in the child because the parent is not documented.
193 *
194 * @param configuration the current configuration of the doclet.
195 */
196 public List<ProgramElementDoc> getLeafClassMembers(Configuration configuration) {
197 List<ProgramElementDoc> result = getMembersFor(classdoc);
198 result.addAll(getInheritedPackagePrivateMethods(configuration));
199 return result;
200 }
202 /**
203 * Retrn the list of members for the given class.
204 *
205 * @param cd the class to retrieve the list of visible members for.
206 *
207 * @return the list of members for the given class.
208 */
209 public List<ProgramElementDoc> getMembersFor(ClassDoc cd) {
210 ClassMembers clmembers = classMap.get(cd);
211 if (clmembers == null) {
212 return new ArrayList<ProgramElementDoc>();
213 }
214 return clmembers.getMembers();
215 }
217 /**
218 * Sort the given mixed list of classes and interfaces to a list of
219 * classes followed by interfaces traversed. Don't sort alphabetically.
220 */
221 private void sort(List<ClassDoc> list) {
222 List<ClassDoc> classes = new ArrayList<ClassDoc>();
223 List<ClassDoc> interfaces = new ArrayList<ClassDoc>();
224 for (int i = 0; i < list.size(); i++) {
225 ClassDoc cd = list.get(i);
226 if (cd.isClass()) {
227 classes.add(cd);
228 } else {
229 interfaces.add(cd);
230 }
231 }
232 list.clear();
233 list.addAll(classes);
234 list.addAll(interfaces);
235 }
237 private void fillMemberLevelMap(List<ProgramElementDoc> list, String level) {
238 for (int i = 0; i < list.size(); i++) {
239 Object key = getMemberKey(list.get(i));
240 Map<ProgramElementDoc,String> memberLevelMap = memberNameMap.get(key);
241 if (memberLevelMap == null) {
242 memberLevelMap = new HashMap<ProgramElementDoc,String>();
243 memberNameMap.put(key, memberLevelMap);
244 }
245 memberLevelMap.put(list.get(i), level);
246 }
247 }
249 private void purgeMemberLevelMap(List<ProgramElementDoc> list, String level) {
250 for (int i = 0; i < list.size(); i++) {
251 Object key = getMemberKey(list.get(i));
252 Map<ProgramElementDoc, String> memberLevelMap = memberNameMap.get(key);
253 if (level.equals(memberLevelMap.get(list.get(i))))
254 memberLevelMap.remove(list.get(i));
255 }
256 }
258 /**
259 * Represents a class member. We should be able to just use a
260 * ProgramElementDoc instead of this class, but that doesn't take
261 * type variables in consideration when comparing.
262 */
263 private class ClassMember {
264 private Set<ProgramElementDoc> members;
266 public ClassMember(ProgramElementDoc programElementDoc) {
267 members = new HashSet<ProgramElementDoc>();
268 members.add(programElementDoc);
269 }
271 public void addMember(ProgramElementDoc programElementDoc) {
272 members.add(programElementDoc);
273 }
275 public boolean isEqual(MethodDoc member) {
276 for (Iterator<ProgramElementDoc> iter = members.iterator(); iter.hasNext(); ) {
277 MethodDoc member2 = (MethodDoc) iter.next();
278 if (Util.executableMembersEqual(member, member2)) {
279 members.add(member);
280 return true;
281 }
282 }
283 return false;
284 }
285 }
287 /**
288 * A data structure that represents the class members for
289 * a visible class.
290 */
291 private class ClassMembers {
293 /**
294 * The mapping class, whose inherited members are put in the
295 * {@link #members} list.
296 */
297 private ClassDoc mappingClass;
299 /**
300 * List of inherited members from the mapping class.
301 */
302 private List<ProgramElementDoc> members = new ArrayList<ProgramElementDoc>();
304 /**
305 * Level/Depth of inheritance.
306 */
307 private String level;
309 /**
310 * Return list of inherited members from mapping class.
311 *
312 * @return List Inherited members.
313 */
314 public List<ProgramElementDoc> getMembers() {
315 return members;
316 }
318 private ClassMembers(ClassDoc mappingClass, String level) {
319 this.mappingClass = mappingClass;
320 this.level = level;
321 if (classMap.containsKey(mappingClass) &&
322 level.startsWith(classMap.get(mappingClass).level)) {
323 //Remove lower level class so that it can be replaced with
324 //same class found at higher level.
325 purgeMemberLevelMap(getClassMembers(mappingClass, false),
326 classMap.get(mappingClass).level);
327 classMap.remove(mappingClass);
328 visibleClasses.remove(mappingClass);
329 }
330 if (!classMap.containsKey(mappingClass)) {
331 classMap.put(mappingClass, this);
332 visibleClasses.add(mappingClass);
333 }
335 }
337 private void build() {
338 if (kind == CONSTRUCTORS) {
339 addMembers(mappingClass);
340 } else {
341 mapClass();
342 }
343 }
345 private void mapClass() {
346 addMembers(mappingClass);
347 ClassDoc[] interfaces = mappingClass.interfaces();
348 for (int i = 0; i < interfaces.length; i++) {
349 String locallevel = level + 1;
350 ClassMembers cm = new ClassMembers(interfaces[i], locallevel);
351 cm.mapClass();
352 }
353 if (mappingClass.isClass()) {
354 ClassDoc superclass = mappingClass.superclass();
355 if (!(superclass == null || mappingClass.equals(superclass))) {
356 ClassMembers cm = new ClassMembers(superclass,
357 level + "c");
358 cm.mapClass();
359 }
360 }
361 }
363 /**
364 * Get all the valid members from the mapping class. Get the list of
365 * members for the class to be included into(ctii), also get the level
366 * string for ctii. If mapping class member is not already in the
367 * inherited member list and if it is visible in the ctii and not
368 * overridden, put such a member in the inherited member list.
369 * Adjust member-level-map, class-map.
370 */
371 private void addMembers(ClassDoc fromClass) {
372 List<ProgramElementDoc> cdmembers = getClassMembers(fromClass, true);
373 List<ProgramElementDoc> incllist = new ArrayList<ProgramElementDoc>();
374 for (int i = 0; i < cdmembers.size(); i++) {
375 ProgramElementDoc pgmelem = cdmembers.get(i);
376 if (!found(members, pgmelem) &&
377 memberIsVisible(pgmelem) &&
378 !isOverridden(pgmelem, level) &&
379 !isTreatedAsPrivate(pgmelem)) {
380 incllist.add(pgmelem);
381 }
382 }
383 if (incllist.size() > 0) {
384 noVisibleMembers = false;
385 }
386 members.addAll(incllist);
387 fillMemberLevelMap(getClassMembers(fromClass, false), level);
388 }
390 private boolean isTreatedAsPrivate(ProgramElementDoc pgmelem) {
391 if (!configuration.javafx) {
392 return false;
393 }
395 Tag[] aspTags = pgmelem.tags("@treatAsPrivate");
396 boolean result = (aspTags != null) && (aspTags.length > 0);
397 return result;
398 }
400 /**
401 * Is given doc item visible in given classdoc in terms fo inheritance?
402 * The given doc item is visible in the given classdoc if it is public
403 * or protected and if it is package-private if it's containing class
404 * is in the same package as the given classdoc.
405 */
406 private boolean memberIsVisible(ProgramElementDoc pgmdoc) {
407 if (pgmdoc.containingClass().equals(classdoc)) {
408 //Member is in class that we are finding visible members for.
409 //Of course it is visible.
410 return true;
411 } else if (pgmdoc.isPrivate()) {
412 //Member is in super class or implemented interface.
413 //Private, so not inherited.
414 return false;
415 } else if (pgmdoc.isPackagePrivate()) {
416 //Member is package private. Only return true if its class is in
417 //same package.
418 return pgmdoc.containingClass().containingPackage().equals(
419 classdoc.containingPackage());
420 } else {
421 //Public members are always inherited.
422 return true;
423 }
424 }
426 /**
427 * Return all available class members.
428 */
429 private List<ProgramElementDoc> getClassMembers(ClassDoc cd, boolean filter) {
430 if (cd.isEnum() && kind == CONSTRUCTORS) {
431 //If any of these rules are hit, return empty array because
432 //we don't document these members ever.
433 return Arrays.asList(new ProgramElementDoc[] {});
434 }
435 ProgramElementDoc[] members = null;
436 switch (kind) {
437 case ANNOTATION_TYPE_FIELDS:
438 members = cd.fields(filter);
439 break;
440 case ANNOTATION_TYPE_MEMBER_OPTIONAL:
441 members = cd.isAnnotationType() ?
442 filter((AnnotationTypeDoc) cd, false) :
443 new AnnotationTypeElementDoc[] {};
444 break;
445 case ANNOTATION_TYPE_MEMBER_REQUIRED:
446 members = cd.isAnnotationType() ?
447 filter((AnnotationTypeDoc) cd, true) :
448 new AnnotationTypeElementDoc[] {};
449 break;
450 case INNERCLASSES:
451 members = cd.innerClasses(filter);
452 break;
453 case ENUM_CONSTANTS:
454 members = cd.enumConstants();
455 break;
456 case FIELDS:
457 members = cd.fields(filter);
458 break;
459 case CONSTRUCTORS:
460 members = cd.constructors();
461 break;
462 case METHODS:
463 members = cd.methods(filter);
464 checkOnPropertiesTags((MethodDoc[])members);
465 break;
466 case PROPERTIES:
467 members = properties(cd, filter);
468 break;
469 default:
470 members = new ProgramElementDoc[0];
471 }
472 // Deprected members should be excluded or not?
473 if (configuration.nodeprecated) {
474 return Util.excludeDeprecatedMembersAsList(members);
475 }
476 return Arrays.asList(members);
477 }
479 /**
480 * Filter the annotation type members and return either the required
481 * members or the optional members, depending on the value of the
482 * required parameter.
483 *
484 * @param doc The annotation type to process.
485 * @param required
486 * @return the annotation type members and return either the required
487 * members or the optional members, depending on the value of the
488 * required parameter.
489 */
490 private AnnotationTypeElementDoc[] filter(AnnotationTypeDoc doc,
491 boolean required) {
492 AnnotationTypeElementDoc[] members = doc.elements();
493 List<AnnotationTypeElementDoc> targetMembers = new ArrayList<AnnotationTypeElementDoc>();
494 for (int i = 0; i < members.length; i++) {
495 if ((required && members[i].defaultValue() == null) ||
496 ((!required) && members[i].defaultValue() != null)){
497 targetMembers.add(members[i]);
498 }
499 }
500 return targetMembers.toArray(new AnnotationTypeElementDoc[]{});
501 }
503 private boolean found(List<ProgramElementDoc> list, ProgramElementDoc elem) {
504 for (int i = 0; i < list.size(); i++) {
505 ProgramElementDoc pgmelem = list.get(i);
506 if (Util.matches(pgmelem, elem)) {
507 return true;
508 }
509 }
510 return false;
511 }
514 /**
515 * Is member overridden? The member is overridden if it is found in the
516 * same level hierarchy e.g. member at level "11" overrides member at
517 * level "111".
518 */
519 private boolean isOverridden(ProgramElementDoc pgmdoc, String level) {
520 Map<?,String> memberLevelMap = (Map<?,String>) memberNameMap.get(getMemberKey(pgmdoc));
521 if (memberLevelMap == null)
522 return false;
523 String mappedlevel = null;
524 Iterator<String> iterator = memberLevelMap.values().iterator();
525 while (iterator.hasNext()) {
526 mappedlevel = iterator.next();
527 if (mappedlevel.equals(STARTLEVEL) ||
528 (level.startsWith(mappedlevel) &&
529 !level.equals(mappedlevel))) {
530 return true;
531 }
532 }
533 return false;
534 }
536 private ProgramElementDoc[] properties(final ClassDoc cd, final boolean filter) {
537 final MethodDoc[] allMethods = cd.methods(filter);
538 final FieldDoc[] allFields = cd.fields(false);
540 if (propertiesCache.containsKey(cd)) {
541 return propertiesCache.get(cd);
542 }
544 final List<MethodDoc> result = new ArrayList<MethodDoc>();
546 for (final MethodDoc propertyMethod : allMethods) {
548 if (!isPropertyMethod(propertyMethod)) {
549 continue;
550 }
552 final MethodDoc getter = getterForField(allMethods, propertyMethod);
553 final MethodDoc setter = setterForField(allMethods, propertyMethod);
554 final FieldDoc field = fieldForProperty(allFields, propertyMethod);
556 addToPropertiesMap(setter, getter, propertyMethod, field);
557 getterSetterMap.put(propertyMethod, new GetterSetter(getter, setter));
558 result.add(propertyMethod);
559 }
560 final ProgramElementDoc[] resultAray =
561 result.toArray(new ProgramElementDoc[result.size()]);
562 propertiesCache.put(cd, resultAray);
563 return resultAray;
564 }
566 private void addToPropertiesMap(MethodDoc setter,
567 MethodDoc getter,
568 MethodDoc propertyMethod,
569 FieldDoc field) {
570 if ((field == null)
571 || (field.getRawCommentText() == null)
572 || field.getRawCommentText().length() == 0) {
573 addToPropertiesMap(setter, propertyMethod);
574 addToPropertiesMap(getter, propertyMethod);
575 addToPropertiesMap(propertyMethod, propertyMethod);
576 } else {
577 addToPropertiesMap(getter, field);
578 addToPropertiesMap(setter, field);
579 addToPropertiesMap(propertyMethod, field);
580 }
581 }
583 private void addToPropertiesMap(ProgramElementDoc propertyMethod,
584 ProgramElementDoc commentSource) {
585 if (null == propertyMethod || null == commentSource) {
586 return;
587 }
588 final String methodRawCommentText = propertyMethod.getRawCommentText();
590 /* The second condition is required for the property buckets. In
591 * this case the comment is at the property method (not at the field)
592 * and it needs to be listed in the map.
593 */
594 if ((null == methodRawCommentText || 0 == methodRawCommentText.length())
595 || propertyMethod.equals(commentSource)) {
596 classPropertiesMap.put(propertyMethod, commentSource);
597 }
598 }
600 private MethodDoc getterForField(MethodDoc[] methods,
601 MethodDoc propertyMethod) {
602 final String propertyMethodName = propertyMethod.name();
603 final String fieldName =
604 propertyMethodName.substring(0,
605 propertyMethodName.lastIndexOf("Property"));
606 final String fieldNameUppercased =
607 "" + Character.toUpperCase(fieldName.charAt(0))
608 + fieldName.substring(1);
609 final String getterNamePattern;
610 final String fieldTypeName = propertyMethod.returnType().toString();
611 if ("boolean".equals(fieldTypeName)
612 || fieldTypeName.endsWith("BooleanProperty")) {
613 getterNamePattern = "(is|get)" + fieldNameUppercased;
614 } else {
615 getterNamePattern = "get" + fieldNameUppercased;
616 }
618 for (MethodDoc methodDoc : methods) {
619 if (Pattern.matches(getterNamePattern, methodDoc.name())) {
620 if (0 == methodDoc.parameters().length
621 && (methodDoc.isPublic() || methodDoc.isProtected())) {
622 return methodDoc;
623 }
624 }
625 }
626 return null;
627 }
629 private MethodDoc setterForField(MethodDoc[] methods,
630 MethodDoc propertyMethod) {
631 final String propertyMethodName = propertyMethod.name();
632 final String fieldName =
633 propertyMethodName.substring(0,
634 propertyMethodName.lastIndexOf("Property"));
635 final String fieldNameUppercased =
636 "" + Character.toUpperCase(fieldName.charAt(0))
637 + fieldName.substring(1);
638 final String setter = "set" + fieldNameUppercased;
640 for (MethodDoc methodDoc : methods) {
641 if (setter.equals(methodDoc.name())) {
642 if (1 == methodDoc.parameters().length
643 && "void".equals(methodDoc.returnType().simpleTypeName())
644 && (methodDoc.isPublic() || methodDoc.isProtected())) {
645 return methodDoc;
646 }
647 }
648 }
649 return null;
650 }
652 private FieldDoc fieldForProperty(FieldDoc[] fields, MethodDoc property) {
654 for (FieldDoc field : fields) {
655 final String fieldName = field.name();
656 final String propertyName = fieldName + "Property";
657 if (propertyName.equals(property.name())) {
658 return field;
659 }
660 }
661 return null;
662 }
664 // properties aren't named setA* or getA*
665 private final Pattern pattern = Pattern.compile("[sg]et\\p{Upper}.*");
666 private boolean isPropertyMethod(MethodDoc method) {
667 if (!method.name().endsWith("Property")) {
668 return false;
669 }
671 if (! memberIsVisible(method)) {
672 return false;
673 }
675 if (pattern.matcher(method.name()).matches()) {
676 return false;
677 }
679 return 0 == method.parameters().length
680 && !"void".equals(method.returnType().simpleTypeName());
681 }
683 private void checkOnPropertiesTags(MethodDoc[] members) {
684 for (MethodDoc methodDoc: members) {
685 if (methodDoc.isIncluded()) {
686 for (Tag tag: methodDoc.tags()) {
687 String tagName = tag.name();
688 if (tagName.equals("@propertySetter")
689 || tagName.equals("@propertyGetter")
690 || tagName.equals("@propertyDescription")) {
691 if (!isPropertyGetterOrSetter(members, methodDoc)) {
692 configuration.message.warning(tag.position(),
693 "doclet.javafx_tag_misuse");
694 }
695 break;
696 }
697 }
698 }
699 }
700 }
702 private boolean isPropertyGetterOrSetter(MethodDoc[] members,
703 MethodDoc methodDoc) {
704 boolean found = false;
705 String propertyName = Util.propertyNameFromMethodName(configuration, methodDoc.name());
706 if (!propertyName.isEmpty()) {
707 String propertyMethodName = propertyName + "Property";
708 for (MethodDoc member: members) {
709 if (member.name().equals(propertyMethodName)) {
710 found = true;
711 break;
712 }
713 }
714 }
715 return found;
716 }
717 }
719 private class GetterSetter {
720 private final ProgramElementDoc getter;
721 private final ProgramElementDoc setter;
723 public GetterSetter(ProgramElementDoc getter, ProgramElementDoc setter) {
724 this.getter = getter;
725 this.setter = setter;
726 }
728 public ProgramElementDoc getGetter() {
729 return getter;
730 }
732 public ProgramElementDoc getSetter() {
733 return setter;
734 }
735 }
737 /**
738 * Return true if this map has no visible members.
739 *
740 * @return true if this map has no visible members.
741 */
742 public boolean noVisibleMembers() {
743 return noVisibleMembers;
744 }
746 private ClassMember getClassMember(MethodDoc member) {
747 for (Iterator<?> iter = memberNameMap.keySet().iterator(); iter.hasNext();) {
748 Object key = iter.next();
749 if (key instanceof String) {
750 continue;
751 } else if (((ClassMember) key).isEqual(member)) {
752 return (ClassMember) key;
753 }
754 }
755 return new ClassMember(member);
756 }
758 /**
759 * Return the key to the member map for the given member.
760 */
761 private Object getMemberKey(ProgramElementDoc doc) {
762 if (doc.isConstructor()) {
763 return doc.name() + ((ExecutableMemberDoc)doc).signature();
764 } else if (doc.isMethod()) {
765 return getClassMember((MethodDoc) doc);
766 } else if (doc.isField() || doc.isEnumConstant() || doc.isAnnotationTypeElement()) {
767 return doc.name();
768 } else { // it's a class or interface
769 String classOrIntName = doc.name();
770 //Strip off the containing class name because we only want the member name.
771 classOrIntName = classOrIntName.indexOf('.') != 0 ? classOrIntName.substring(classOrIntName.lastIndexOf('.'), classOrIntName.length()) : classOrIntName;
772 return "clint" + classOrIntName;
773 }
774 }
775 }