/*
* Copyright 2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.gradle.build.docs.dsl.source.model;
import org.apache.commons.lang.StringUtils;
import org.gradle.api.Action;
import org.gradle.api.Transformer;
import org.gradle.build.docs.model.Attachable;
import org.gradle.build.docs.model.ClassMetaDataRepository;
import org.gradle.util.GUtil;
import java.io.Serializable;
import java.util.*;
/**
* Static meta-data about a class extracted from the source for the class.
*/
public class ClassMetaData extends AbstractLanguageElement implements Serializable, Attachable<ClassMetaData>, TypeContainer {
private final String className;
private String superClassName;
private final String packageName;
private final MetaType metaType;
private final boolean isGroovy;
private final List<String> imports = new ArrayList<String>();
private final List<String> interfaceNames = new ArrayList<String>();
private final Map<String, PropertyMetaData> declaredProperties = new HashMap<String, PropertyMetaData>();
private final Set<MethodMetaData> declaredMethods = new HashSet<MethodMetaData>();
private final List<String> innerClassNames = new ArrayList<String>();
private String outerClassName;
private transient ClassMetaDataRepository<ClassMetaData> metaDataRepository;
public final HashMap<String, String> constants = new HashMap<String, String>();
private final List<EnumConstantMetaData> enumConstants = new ArrayList<EnumConstantMetaData>();
public ClassMetaData(String className, String packageName, MetaType metaType, boolean isGroovy, String rawClassComment) {
super(rawClassComment);
this.className = className;
this.packageName = packageName;
this.metaType = metaType;
this.isGroovy = isGroovy;
}
public ClassMetaData(String className) {
this(className, StringUtils.substringBeforeLast(className, "."), MetaType.CLASS, false, "");
}
@Override
public String toString() {
return className;
}
public String getClassName() {
return className;
}
public String getSimpleName() {
return StringUtils.substringAfterLast(className, ".");
}
public String getPackageName() {
return packageName;
}
public boolean isInterface() {
return metaType == MetaType.INTERFACE;
}
public boolean isGroovy() {
return isGroovy;
}
public boolean isEnum() {
return metaType == MetaType.ENUM;
}
public String getSuperClassName() {
return superClassName;
}
public void setSuperClassName(String superClassName) {
this.superClassName = superClassName;
}
public ClassMetaData getSuperClass() {
return superClassName == null ? null : metaDataRepository.find(superClassName);
}
public List<String> getInterfaceNames() {
return interfaceNames;
}
public void addInterfaceName(String name) {
interfaceNames.add(name);
}
public List<ClassMetaData> getInterfaces() {
List<ClassMetaData> interfaces = new ArrayList<ClassMetaData>();
for (String interfaceName : interfaceNames) {
ClassMetaData interfaceMetaData = metaDataRepository.find(interfaceName);
if (interfaceMetaData != null) {
interfaces.add(interfaceMetaData);
}
}
return interfaces;
}
public List<String> getInnerClassNames() {
return innerClassNames;
}
public void addInnerClassName(String innerClassName) {
innerClassNames.add(innerClassName);
}
public String getOuterClassName() {
return outerClassName;
}
public void setOuterClassName(String outerClassName) {
this.outerClassName = outerClassName;
}
public List<String> getImports() {
return imports;
}
public void addImport(String importName) {
imports.add(importName);
}
public PropertyMetaData addReadableProperty(String name, TypeMetaData type, String rawCommentText, MethodMetaData getterMethod) {
PropertyMetaData property = getProperty(name);
property.setType(type);
property.setRawCommentText(rawCommentText);
property.setGetter(getterMethod);
return property;
}
public PropertyMetaData addWriteableProperty(String name, TypeMetaData type, String rawCommentText, MethodMetaData setterMethod) {
PropertyMetaData property = getProperty(name);
if (property.getType() == null) {
property.setType(type);
}
if (!GUtil.isTrue(property.getRawCommentText())) {
property.setRawCommentText(rawCommentText);
}
property.setSetter(setterMethod);
return property;
}
public PropertyMetaData findDeclaredProperty(String name) {
return declaredProperties.get(name);
}
public Set<String> getDeclaredPropertyNames() {
return declaredProperties.keySet();
}
public Set<PropertyMetaData> getDeclaredProperties() {
return new HashSet<PropertyMetaData>(declaredProperties.values());
}
public Set<MethodMetaData> getDeclaredMethods() {
return declaredMethods;
}
public Set<String> getDeclaredMethodNames() {
Set<String> names = new HashSet<String>();
for (MethodMetaData declaredMethod : declaredMethods) {
names.add(declaredMethod.getName());
}
return names;
}
public MethodMetaData findDeclaredMethod(String signature) {
for (MethodMetaData method : declaredMethods) {
if (method.getOverrideSignature().equals(signature)) {
return method;
}
}
return null;
}
public List<MethodMetaData> findDeclaredMethods(String name) {
List<MethodMetaData> methods = new ArrayList<MethodMetaData>();
for (MethodMetaData method : declaredMethods) {
if (method.getName().equals(name)) {
methods.add(method);
}
}
return methods;
}
/**
* Finds a property by name. Includes inherited properties.
*
* @param name The property name.
* @return The property, or null if no such property exists.
*/
public PropertyMetaData findProperty(String name) {
PropertyMetaData propertyMetaData = declaredProperties.get(name);
if (propertyMetaData != null) {
return propertyMetaData;
}
ClassMetaData superClass = getSuperClass();
if (superClass != null) {
return superClass.findProperty(name);
}
return null;
}
/**
* Returns the set of property names for this class, including inherited properties.
*
* @return The set of property names.
*/
public Set<String> getPropertyNames() {
Set<String> propertyNames = new TreeSet<String>();
propertyNames.addAll(declaredProperties.keySet());
ClassMetaData superClass = getSuperClass();
if (superClass != null) {
propertyNames.addAll(superClass.getPropertyNames());
}
return propertyNames;
}
private PropertyMetaData getProperty(String name) {
PropertyMetaData property = declaredProperties.get(name);
if (property == null) {
property = new PropertyMetaData(name, this);
declaredProperties.put(name, property);
}
return property;
}
public Map<String, String> getConstants() {
return constants;
}
public void addEnumConstant(String name) {
enumConstants.add(new EnumConstantMetaData(name, this));
}
public List<EnumConstantMetaData> getEnumConstants() {
return enumConstants;
}
public EnumConstantMetaData getEnumConstant(String name) {
for (EnumConstantMetaData enumConstant : enumConstants) {
if (enumConstant.getName().equals(name)) {
return enumConstant;
}
}
return null;
}
public void attach(ClassMetaDataRepository<ClassMetaData> metaDataRepository) {
this.metaDataRepository = metaDataRepository;
}
public MethodMetaData addMethod(String name, TypeMetaData returnType, String rawCommentText) {
MethodMetaData method = new MethodMetaData(name, this);
declaredMethods.add(method);
method.setReturnType(returnType);
method.setRawCommentText(rawCommentText);
return method;
}
public void resolveTypes(Transformer<String, String> transformer) {
super.resolveTypes(transformer);
if (superClassName != null) {
superClassName = transformer.transform(superClassName);
}
for (int i = 0; i < interfaceNames.size(); i++) {
interfaceNames.set(i, transformer.transform(interfaceNames.get(i)));
}
for (PropertyMetaData propertyMetaData : declaredProperties.values()) {
propertyMetaData.resolveTypes(transformer);
}
for (MethodMetaData methodMetaData : declaredMethods) {
methodMetaData.resolveTypes(transformer);
}
}
public void visitTypes(Action<TypeMetaData> action) {
for (PropertyMetaData propertyMetaData : declaredProperties.values()) {
propertyMetaData.visitTypes(action);
}
for (MethodMetaData methodMetaData : declaredMethods) {
methodMetaData.visitTypes(action);
}
}
public static enum MetaType {
CLASS, INTERFACE, ENUM, ANNOTATION
}
}