/*
 * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.tools.doclets.internal.toolkit.util;

import java.util.*;
import java.util.regex.Pattern;

import com.sun.javadoc.*;
import com.sun.tools.doclets.internal.toolkit.*;

A data structure that encapsulates the visible members of a particular type for a given class tree. To use this data structor, you must specify the type of member you are interested in (nested class, field, constructor or method) and the leaf of the class tree. The data structure will map all visible members in the leaf and classes above the leaf in the tree.

This is NOT part of any supported API. If you write code that depends on this, you do so at your own risk. This code and its internal interfaces are subject to change or deletion without notice.

Author:Atul M Dambalkar, Jamie Ho (rewrite)
/** * A data structure that encapsulates the visible members of a particular * type for a given class tree. To use this data structor, you must specify * the type of member you are interested in (nested class, field, constructor * or method) and the leaf of the class tree. The data structure will map * all visible members in the leaf and classes above the leaf in the tree. * * <p><b>This is NOT part of any supported API. * If you write code that depends on this, you do so at your own risk. * This code and its internal interfaces are subject to change or * deletion without notice.</b> * * @author Atul M Dambalkar * @author Jamie Ho (rewrite) */
@Deprecated public class VisibleMemberMap { private boolean noVisibleMembers = true; public static final int INNERCLASSES = 0; public static final int ENUM_CONSTANTS = 1; public static final int FIELDS = 2; public static final int CONSTRUCTORS = 3; public static final int METHODS = 4; public static final int ANNOTATION_TYPE_FIELDS = 5; public static final int ANNOTATION_TYPE_MEMBER_OPTIONAL = 6; public static final int ANNOTATION_TYPE_MEMBER_REQUIRED = 7; public static final int PROPERTIES = 8;
The total number of member types is 9.
/** * The total number of member types is {@value}. */
public static final int NUM_MEMBER_TYPES = 9; public static final String STARTLEVEL = "start";
List of ClassDoc objects for which ClassMembers objects are built.
/** * List of ClassDoc objects for which ClassMembers objects are built. */
private final List<ClassDoc> visibleClasses = new ArrayList<>();
Map for each member name on to a map which contains members with same name-signature. The mapped map will contain mapping for each MemberDoc onto it's respecive level string.
/** * Map for each member name on to a map which contains members with same * name-signature. The mapped map will contain mapping for each MemberDoc * onto it's respecive level string. */
private final Map<Object,Map<ProgramElementDoc,String>> memberNameMap = new HashMap<>();
Map of class and it's ClassMembers object.
/** * Map of class and it's ClassMembers object. */
private final Map<ClassDoc,ClassMembers> classMap = new HashMap<>();
Type whose visible members are requested. This is the leaf of the class tree being mapped.
/** * Type whose visible members are requested. This is the leaf of * the class tree being mapped. */
private final ClassDoc classdoc;
Member kind: InnerClasses/Fields/Methods?
/** * Member kind: InnerClasses/Fields/Methods? */
private final int kind;
The configuration this VisibleMemberMap was created with.
/** * The configuration this VisibleMemberMap was created with. */
private final Configuration configuration; private final Utils utils; private static final Map<ClassDoc, ProgramElementDoc[]> propertiesCache = new HashMap<>(); private static final Map<ProgramElementDoc, ProgramElementDoc> classPropertiesMap = new HashMap<>(); private static final Map<ProgramElementDoc, GetterSetter> getterSetterMap = new HashMap<>();
Construct a VisibleMemberMap of the given type for the given class.
Params:
  • classdoc – the class whose members are being mapped.
  • kind – the kind of member that is being mapped.
  • configuration – the configuration to use to construct this VisibleMemberMap. If the field configuration.nodeprecated is true the deprecated members are excluded from the map. If the field configuration.javafx is true the JavaFX features are used.
/** * Construct a VisibleMemberMap of the given type for the given * class. * * @param classdoc the class whose members are being mapped. * @param kind the kind of member that is being mapped. * @param configuration the configuration to use to construct this * VisibleMemberMap. If the field configuration.nodeprecated is true the * deprecated members are excluded from the map. If the field * configuration.javafx is true the JavaFX features are used. */
public VisibleMemberMap(ClassDoc classdoc, int kind, Configuration configuration) { this.classdoc = classdoc; this.kind = kind; this.configuration = configuration; this.utils = configuration.utils; new ClassMembers(classdoc, STARTLEVEL).build(); }
Return the list of visible classes in this map.
Returns:the list of visible classes in this map.
/** * Return the list of visible classes in this map. * * @return the list of visible classes in this map. */
public List<ClassDoc> getVisibleClassesList() { sort(visibleClasses); return visibleClasses; }
Returns the property field documentation belonging to the given member.
Params:
  • ped – the member for which the property documentation is needed.
Returns:the property field documentation, null if there is none.
/** * Returns the property field documentation belonging to the given member. * @param ped the member for which the property documentation is needed. * @return the property field documentation, null if there is none. */
public ProgramElementDoc getPropertyMemberDoc(ProgramElementDoc ped) { return classPropertiesMap.get(ped); }
Returns the getter documentation belonging to the given property method.
Params:
  • propertyMethod – the method for which the getter is needed.
Returns:the getter documentation, null if there is none.
/** * Returns the getter documentation belonging to the given property method. * @param propertyMethod the method for which the getter is needed. * @return the getter documentation, null if there is none. */
public ProgramElementDoc getGetterForProperty(ProgramElementDoc propertyMethod) { return getterSetterMap.get(propertyMethod).getGetter(); }
Returns the setter documentation belonging to the given property method.
Params:
  • propertyMethod – the method for which the setter is needed.
Returns:the setter documentation, null if there is none.
/** * Returns the setter documentation belonging to the given property method. * @param propertyMethod the method for which the setter is needed. * @return the setter documentation, null if there is none. */
public ProgramElementDoc getSetterForProperty(ProgramElementDoc propertyMethod) { return getterSetterMap.get(propertyMethod).getSetter(); }
Return the package private members inherited by the class. Only return if parent is package private and not documented.
Params:
  • configuration – the current configuration of the doclet.
Returns:the package private members inherited by the class.
/** * Return the package private members inherited by the class. Only return * if parent is package private and not documented. * * @param configuration the current configuration of the doclet. * @return the package private members inherited by the class. */
private List<ProgramElementDoc> getInheritedPackagePrivateMethods(Configuration configuration) { List<ProgramElementDoc> results = new ArrayList<>(); for (ClassDoc currentClass : visibleClasses) { if (currentClass != classdoc && currentClass.isPackagePrivate() && !utils.isLinkable(currentClass, configuration)) { // Document these members in the child class because // the parent is inaccessible. results.addAll(getMembersFor(currentClass)); } } return results; }
Return the visible members of the class being mapped. Also append at the end of the list members that are inherited by inaccessible parents. We document these members in the child because the parent is not documented.
Params:
  • configuration – the current configuration of the doclet.
/** * Return the visible members of the class being mapped. Also append at the * end of the list members that are inherited by inaccessible parents. We * document these members in the child because the parent is not documented. * * @param configuration the current configuration of the doclet. */
public List<ProgramElementDoc> getLeafClassMembers(Configuration configuration) { List<ProgramElementDoc> result = getMembersFor(classdoc); result.addAll(getInheritedPackagePrivateMethods(configuration)); return result; }
Retrn the list of members for the given class.
Params:
  • cd – the class to retrieve the list of visible members for.
Returns:the list of members for the given class.
/** * Retrn the list of members for the given class. * * @param cd the class to retrieve the list of visible members for. * * @return the list of members for the given class. */
public List<ProgramElementDoc> getMembersFor(ClassDoc cd) { ClassMembers clmembers = classMap.get(cd); if (clmembers == null) { return new ArrayList<>(); } return clmembers.getMembers(); }
Sort the given mixed list of classes and interfaces to a list of classes followed by interfaces traversed. Don't sort alphabetically.
/** * Sort the given mixed list of classes and interfaces to a list of * classes followed by interfaces traversed. Don't sort alphabetically. */
private void sort(List<ClassDoc> list) { List<ClassDoc> classes = new ArrayList<>(); List<ClassDoc> interfaces = new ArrayList<>(); for (ClassDoc cd : list) { if (cd.isClass()) { classes.add(cd); } else { interfaces.add(cd); } } list.clear(); list.addAll(classes); list.addAll(interfaces); } private void fillMemberLevelMap(List<ProgramElementDoc> list, String level) { for (ProgramElementDoc element : list) { Object key = getMemberKey(element); Map<ProgramElementDoc, String> memberLevelMap = memberNameMap.get(key); if (memberLevelMap == null) { memberLevelMap = new HashMap<>(); memberNameMap.put(key, memberLevelMap); } memberLevelMap.put(element, level); } } private void purgeMemberLevelMap(List<ProgramElementDoc> list, String level) { for (ProgramElementDoc element : list) { Object key = getMemberKey(element); Map<ProgramElementDoc, String> memberLevelMap = memberNameMap.get(key); if (memberLevelMap != null && level.equals(memberLevelMap.get(element))) memberLevelMap.remove(element); } }
Represents a class member. We should be able to just use a ProgramElementDoc instead of this class, but that doesn't take type variables in consideration when comparing.
/** * Represents a class member. We should be able to just use a * ProgramElementDoc instead of this class, but that doesn't take * type variables in consideration when comparing. */
private class ClassMember { private Set<ProgramElementDoc> members; public ClassMember(ProgramElementDoc programElementDoc) { members = new HashSet<>(); members.add(programElementDoc); } public void addMember(ProgramElementDoc programElementDoc) { members.add(programElementDoc); } public boolean isEqual(MethodDoc member) { for (ProgramElementDoc element : members) { if (utils.executableMembersEqual(member, (MethodDoc) element)) { members.add(member); return true; } } return false; } }
A data structure that represents the class members for a visible class.
/** * A data structure that represents the class members for * a visible class. */
private class ClassMembers {
The mapping class, whose inherited members are put in the members list.
/** * The mapping class, whose inherited members are put in the * {@link #members} list. */
private ClassDoc mappingClass;
List of inherited members from the mapping class.
/** * List of inherited members from the mapping class. */
private List<ProgramElementDoc> members = new ArrayList<>();
Level/Depth of inheritance.
/** * Level/Depth of inheritance. */
private String level;
Return list of inherited members from mapping class.
Returns:List Inherited members.
/** * Return list of inherited members from mapping class. * * @return List Inherited members. */
public List<ProgramElementDoc> getMembers() { return members; } private ClassMembers(ClassDoc mappingClass, String level) { this.mappingClass = mappingClass; this.level = level; if (classMap.containsKey(mappingClass) && level.startsWith(classMap.get(mappingClass).level)) { //Remove lower level class so that it can be replaced with //same class found at higher level. purgeMemberLevelMap(getClassMembers(mappingClass, false), classMap.get(mappingClass).level); classMap.remove(mappingClass); visibleClasses.remove(mappingClass); } if (!classMap.containsKey(mappingClass)) { classMap.put(mappingClass, this); visibleClasses.add(mappingClass); } } private void build() { if (kind == CONSTRUCTORS) { addMembers(mappingClass); } else { mapClass(); } } private void mapClass() { addMembers(mappingClass); ClassDoc[] interfaces = mappingClass.interfaces(); for (ClassDoc anInterface : interfaces) { String locallevel = level + 1; ClassMembers cm = new ClassMembers(anInterface, locallevel); cm.mapClass(); } if (mappingClass.isClass()) { ClassDoc superclass = mappingClass.superclass(); if (!(superclass == null || mappingClass.equals(superclass))) { ClassMembers cm = new ClassMembers(superclass, level + "c"); cm.mapClass(); } } }
Get all the valid members from the mapping class. Get the list of members for the class to be included into(ctii), also get the level string for ctii. If mapping class member is not already in the inherited member list and if it is visible in the ctii and not overridden, put such a member in the inherited member list. Adjust member-level-map, class-map.
/** * Get all the valid members from the mapping class. Get the list of * members for the class to be included into(ctii), also get the level * string for ctii. If mapping class member is not already in the * inherited member list and if it is visible in the ctii and not * overridden, put such a member in the inherited member list. * Adjust member-level-map, class-map. */
private void addMembers(ClassDoc fromClass) { List<ProgramElementDoc> cdmembers = getClassMembers(fromClass, true); List<ProgramElementDoc> incllist = new ArrayList<>(); for (ProgramElementDoc pgmelem : cdmembers) { if (!found(members, pgmelem) && memberIsVisible(pgmelem) && !isOverridden(pgmelem, level) && !isTreatedAsPrivate(pgmelem)) { incllist.add(pgmelem); } } if (incllist.size() > 0) { noVisibleMembers = false; } members.addAll(incllist); fillMemberLevelMap(getClassMembers(fromClass, false), level); } private boolean isTreatedAsPrivate(ProgramElementDoc pgmelem) { if (!configuration.javafx) { return false; } Tag[] aspTags = pgmelem.tags("@treatAsPrivate"); boolean result = (aspTags != null) && (aspTags.length > 0); return result; }
Is given doc item visible in given classdoc in terms fo inheritance? The given doc item is visible in the given classdoc if it is public or protected and if it is package-private if it's containing class is in the same package as the given classdoc.
/** * Is given doc item visible in given classdoc in terms fo inheritance? * The given doc item is visible in the given classdoc if it is public * or protected and if it is package-private if it's containing class * is in the same package as the given classdoc. */
private boolean memberIsVisible(ProgramElementDoc pgmdoc) { if (pgmdoc.containingClass().equals(classdoc)) { //Member is in class that we are finding visible members for. //Of course it is visible. return true; } else if (pgmdoc.isPrivate()) { //Member is in super class or implemented interface. //Private, so not inherited. return false; } else if (pgmdoc.isPackagePrivate()) { //Member is package private. Only return true if its class is in //same package. return pgmdoc.containingClass().containingPackage().equals( classdoc.containingPackage()); } else { //Public members are always inherited. return true; } }
Return all available class members.
/** * Return all available class members. */
private List<ProgramElementDoc> getClassMembers(ClassDoc cd, boolean filter) { if (cd.isEnum() && kind == CONSTRUCTORS) { //If any of these rules are hit, return empty array because //we don't document these members ever. return Arrays.asList(new ProgramElementDoc[] {}); } ProgramElementDoc[] members = null; switch (kind) { case ANNOTATION_TYPE_FIELDS: members = cd.fields(filter); break; case ANNOTATION_TYPE_MEMBER_OPTIONAL: members = cd.isAnnotationType() ? filter((AnnotationTypeDoc) cd, false) : new AnnotationTypeElementDoc[] {}; break; case ANNOTATION_TYPE_MEMBER_REQUIRED: members = cd.isAnnotationType() ? filter((AnnotationTypeDoc) cd, true) : new AnnotationTypeElementDoc[] {}; break; case INNERCLASSES: members = cd.innerClasses(filter); break; case ENUM_CONSTANTS: members = cd.enumConstants(); break; case FIELDS: members = cd.fields(filter); break; case CONSTRUCTORS: members = cd.constructors(); break; case METHODS: members = cd.methods(filter); checkOnPropertiesTags((MethodDoc[])members); break; case PROPERTIES: members = properties(cd, filter); break; default: members = new ProgramElementDoc[0]; } // Deprected members should be excluded or not? if (configuration.nodeprecated) { return utils.excludeDeprecatedMembersAsList(members); } return Arrays.asList(members); }
Filter the annotation type members and return either the required members or the optional members, depending on the value of the required parameter.
Params:
  • doc – The annotation type to process.
  • required –
Returns:the annotation type members and return either the required members or the optional members, depending on the value of the required parameter.
/** * Filter the annotation type members and return either the required * members or the optional members, depending on the value of the * required parameter. * * @param doc The annotation type to process. * @param required * @return the annotation type members and return either the required * members or the optional members, depending on the value of the * required parameter. */
private AnnotationTypeElementDoc[] filter(AnnotationTypeDoc doc, boolean required) { AnnotationTypeElementDoc[] members = doc.elements(); List<AnnotationTypeElementDoc> targetMembers = new ArrayList<>(); for (AnnotationTypeElementDoc member : members) { if ((required && member.defaultValue() == null) || ((!required) && member.defaultValue() != null)) { targetMembers.add(member); } } return targetMembers.toArray(new AnnotationTypeElementDoc[]{}); } private boolean found(List<ProgramElementDoc> list, ProgramElementDoc elem) { for (ProgramElementDoc pgmelem : list) { if (utils.matches(pgmelem, elem)) { return true; } } return false; }
Is member overridden? The member is overridden if it is found in the same level hierarchy e.g. member at level "11" overrides member at level "111".
/** * Is member overridden? The member is overridden if it is found in the * same level hierarchy e.g. member at level "11" overrides member at * level "111". */
private boolean isOverridden(ProgramElementDoc pgmdoc, String level) { Map<?,String> memberLevelMap = (Map<?,String>) memberNameMap.get(getMemberKey(pgmdoc)); if (memberLevelMap == null) return false; for (String mappedlevel : memberLevelMap.values()) { if (mappedlevel.equals(STARTLEVEL) || (level.startsWith(mappedlevel) && !level.equals(mappedlevel))) { return true; } } return false; } private ProgramElementDoc[] properties(final ClassDoc cd, final boolean filter) { final MethodDoc[] allMethods = cd.methods(filter); final FieldDoc[] allFields = cd.fields(false); if (propertiesCache.containsKey(cd)) { return propertiesCache.get(cd); } final List<MethodDoc> result = new ArrayList<>(); for (final MethodDoc propertyMethod : allMethods) { if (!isPropertyMethod(propertyMethod)) { continue; } final MethodDoc getter = getterForField(allMethods, propertyMethod); final MethodDoc setter = setterForField(allMethods, propertyMethod); final FieldDoc field = fieldForProperty(allFields, propertyMethod); addToPropertiesMap(setter, getter, propertyMethod, field); getterSetterMap.put(propertyMethod, new GetterSetter(getter, setter)); result.add(propertyMethod); } final ProgramElementDoc[] resultAray = result.toArray(new ProgramElementDoc[result.size()]); propertiesCache.put(cd, resultAray); return resultAray; } private void addToPropertiesMap(MethodDoc setter, MethodDoc getter, MethodDoc propertyMethod, FieldDoc field) { if ((field == null) || (field.getRawCommentText() == null) || field.getRawCommentText().length() == 0) { addToPropertiesMap(setter, propertyMethod); addToPropertiesMap(getter, propertyMethod); addToPropertiesMap(propertyMethod, propertyMethod); } else { addToPropertiesMap(getter, field); addToPropertiesMap(setter, field); addToPropertiesMap(propertyMethod, field); } } private void addToPropertiesMap(ProgramElementDoc propertyMethod, ProgramElementDoc commentSource) { if (null == propertyMethod || null == commentSource) { return; } final String methodRawCommentText = propertyMethod.getRawCommentText(); /* The second condition is required for the property buckets. In * this case the comment is at the property method (not at the field) * and it needs to be listed in the map. */ if ((null == methodRawCommentText || 0 == methodRawCommentText.length()) || propertyMethod.equals(commentSource)) { classPropertiesMap.put(propertyMethod, commentSource); } } private MethodDoc getterForField(MethodDoc[] methods, MethodDoc propertyMethod) { final String propertyMethodName = propertyMethod.name(); final String fieldName = propertyMethodName.substring(0, propertyMethodName.lastIndexOf("Property")); final String fieldNameUppercased = "" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1); final String getterNamePattern; final String fieldTypeName = propertyMethod.returnType().toString(); if ("boolean".equals(fieldTypeName) || fieldTypeName.endsWith("BooleanProperty")) { getterNamePattern = "(is|get)" + fieldNameUppercased; } else { getterNamePattern = "get" + fieldNameUppercased; } for (MethodDoc methodDoc : methods) { if (Pattern.matches(getterNamePattern, methodDoc.name())) { if (0 == methodDoc.parameters().length && (methodDoc.isPublic() || methodDoc.isProtected())) { return methodDoc; } } } return null; } private MethodDoc setterForField(MethodDoc[] methods, MethodDoc propertyMethod) { final String propertyMethodName = propertyMethod.name(); final String fieldName = propertyMethodName.substring(0, propertyMethodName.lastIndexOf("Property")); final String fieldNameUppercased = "" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1); final String setter = "set" + fieldNameUppercased; for (MethodDoc methodDoc : methods) { if (setter.equals(methodDoc.name())) { if (1 == methodDoc.parameters().length && "void".equals(methodDoc.returnType().simpleTypeName()) && (methodDoc.isPublic() || methodDoc.isProtected())) { return methodDoc; } } } return null; } private FieldDoc fieldForProperty(FieldDoc[] fields, MethodDoc property) { for (FieldDoc field : fields) { final String fieldName = field.name(); final String propertyName = fieldName + "Property"; if (propertyName.equals(property.name())) { return field; } } return null; } // properties aren't named setA* or getA* private final Pattern pattern = Pattern.compile("[sg]et\\p{Upper}.*"); private boolean isPropertyMethod(MethodDoc method) { if (!configuration.javafx) { return false; } if (!method.name().endsWith("Property")) { return false; } if (! memberIsVisible(method)) { return false; } if (pattern.matcher(method.name()).matches()) { return false; } if (method.typeParameters().length > 0) { return false; } return 0 == method.parameters().length && !"void".equals(method.returnType().simpleTypeName()); } private void checkOnPropertiesTags(MethodDoc[] members) { for (MethodDoc methodDoc: members) { if (methodDoc.isIncluded()) { for (Tag tag: methodDoc.tags()) { String tagName = tag.name(); if (tagName.equals("@propertySetter") || tagName.equals("@propertyGetter") || tagName.equals("@propertyDescription")) { if (!isPropertyGetterOrSetter(members, methodDoc)) { configuration.message.warning(tag.position(), "doclet.javafx_tag_misuse"); } break; } } } } } private boolean isPropertyGetterOrSetter(MethodDoc[] members, MethodDoc methodDoc) { boolean found = false; String propertyName = utils.propertyNameFromMethodName(configuration, methodDoc.name()); if (!propertyName.isEmpty()) { String propertyMethodName = propertyName + "Property"; for (MethodDoc member: members) { if (member.name().equals(propertyMethodName)) { found = true; break; } } } return found; } } private class GetterSetter { private final ProgramElementDoc getter; private final ProgramElementDoc setter; public GetterSetter(ProgramElementDoc getter, ProgramElementDoc setter) { this.getter = getter; this.setter = setter; } public ProgramElementDoc getGetter() { return getter; } public ProgramElementDoc getSetter() { return setter; } }
Return true if this map has no visible members.
Returns:true if this map has no visible members.
/** * Return true if this map has no visible members. * * @return true if this map has no visible members. */
public boolean noVisibleMembers() { return noVisibleMembers; } private ClassMember getClassMember(MethodDoc member) { for (Object key : memberNameMap.keySet()) { if (key instanceof String) { continue; } else if (((ClassMember) key).isEqual(member)) { return (ClassMember) key; } } return new ClassMember(member); }
Return the key to the member map for the given member.
/** * Return the key to the member map for the given member. */
private Object getMemberKey(ProgramElementDoc doc) { if (doc.isConstructor()) { return doc.name() + ((ExecutableMemberDoc)doc).signature(); } else if (doc.isMethod()) { return getClassMember((MethodDoc) doc); } else if (doc.isField() || doc.isEnumConstant() || doc.isAnnotationTypeElement()) { return doc.name(); } else { // it's a class or interface String classOrIntName = doc.name(); //Strip off the containing class name because we only want the member name. classOrIntName = classOrIntName.indexOf('.') != 0 ? classOrIntName.substring(classOrIntName.lastIndexOf('.'), classOrIntName.length()) : classOrIntName; return "clint" + classOrIntName; } } }