*** qdox.iml Wed Dec 31 14:00:00 1969 --- qdox.iml Tue Aug 24 12:39:14 2004 *************** *** 0 **** --- 1,20 ---- + + + + + + + + + + + + + + + + + + + + *** src/java/com/thoughtworks/qdox/model/AbstractInheritableJavaEntityImpl.java Wed Dec 31 14:00:00 1969 --- src/java/com/thoughtworks/qdox/model/AbstractInheritableJavaEntityImpl.java Tue Aug 24 12:57:24 2004 *************** *** 0 **** --- 1,13 ---- + package com.thoughtworks.qdox.model; + + /** + * @author Aslak Hellesøy + * @version $Revision: 1.5 $ + */ + public abstract class AbstractInheritableJavaEntityImpl extends AbstractJavaEntityImpl implements AbstractInheritableJavaEntity { + + public DocletTag getTagByName(String name, boolean inherited) { + DocletTag[] tags = getTagsByName(name, inherited); + return tags.length > 0 ? tags[0] : null; + } + } *** src/java/com/thoughtworks/qdox/model/AbstractJavaEntityImpl.java Wed Dec 31 14:00:00 1969 --- src/java/com/thoughtworks/qdox/model/AbstractJavaEntityImpl.java Tue Aug 24 17:33:17 2004 *************** *** 0 **** --- 1,243 ---- + package com.thoughtworks.qdox.model; + + import java.util.ArrayList; + import java.util.Arrays; + import java.util.Iterator; + import java.util.List; + + public abstract class AbstractJavaEntityImpl implements AbstractJavaEntity { + + protected String name; + protected List modifiers = new ArrayList(); + private String comment; + private DocletTag[] tags = new DocletTag[0]; + private int lineNumber = -1; + private JavaClassParent parent; + + public int getLineNumber() { + return lineNumber; + } + + public String getName() { + return name; + } + + /** + * Return list of modifiers as Strings. + * (public, private, protected, final, abstract, static) + */ + public String[] getModifiers() { + return (String[]) modifiers.toArray(new String[modifiers.size()]); + } + + public String getComment() { + return comment; + } + + public DocletTag[] getTags() { + return tags; + } + + public DocletTag[] getTagsByName(String name) { + List specifiedTags = new ArrayList(); + for (int i = 0; i < tags.length; i++) { + DocletTag docletTag = tags[i]; + if (docletTag.getName().equals(name)) { + specifiedTags.add(docletTag); + } + } + return (DocletTag[]) specifiedTags.toArray(new DocletTag[specifiedTags.size()]); + } + + public DocletTag getTagByName(String name) { + for (int i = 0; i < tags.length; i++) { + DocletTag docletTag = tags[i]; + if (docletTag.getName().equals(name)) { + return docletTag; + } + } + return null; + } + + /** + * Convenience method for getTagByName(String).getNamedParameter(String) + * that also checks for null tag. + * @since 1.3 + */ + public String getNamedParameter(String tagName, String parameterName) { + DocletTag tag = getTagByName(tagName); + if(tag != null) { + return tag.getNamedParameter(parameterName); + } else { + return null; + } + } + + public void commentHeader(IndentBuffer buffer) { + if (comment == null && (tags == null || tags.length == 0)) { + return; + } else { + buffer.write("/**"); + buffer.newline(); + + if (comment != null && comment.length() > 0) { + buffer.write(" * "); + buffer.write(comment); + buffer.newline(); + } + + if (tags != null && tags.length > 0) { + if (comment != null && comment.length() > 0) { + buffer.write(" *"); + buffer.newline(); + } + for (int i = 0; i < tags.length; i++) { + DocletTag docletTag = tags[i]; + buffer.write(" * @"); + buffer.write(docletTag.getName()); + if (docletTag.getValue().length() > 0) { + buffer.write(' '); + buffer.write(docletTag.getValue()); + } + buffer.newline(); + } + } + + buffer.write(" */"); + buffer.newline(); + } + } + + public String toString() { + IndentBuffer result = new IndentBuffer(); + write(result); + return result.toString(); + } + + public void write(IndentBuffer result) { + commentHeader(result); + writeBody(result); + } + + protected abstract void writeBody(IndentBuffer result); + + public void setName(String name) { + this.name = name; + } + + public void setModifiers(String[] modifiers) { + this.modifiers = Arrays.asList(modifiers); + } + + public void setComment(String comment) { + this.comment = comment; + } + + public void setTags(List tagList) { + this.tags = new DocletTag[tagList.size()]; + tagList.toArray(this.tags); + } + + //helper methods for querying the modifiers + public boolean isAbstract() { + return isModifierPresent("abstract"); + } + + public boolean isPublic() { + return isModifierPresent("public"); + } + + public boolean isPrivate() { + return isModifierPresent("private"); + } + + public boolean isProtected() { + return isModifierPresent("protected"); + } + + public boolean isStatic() { + return isModifierPresent("static"); + } + + public boolean isFinal() { + return isModifierPresent("final"); + } + + public boolean isSynchronized() { + return isModifierPresent("synchronized"); + } + + public boolean isTransient() { + return isModifierPresent("transient"); + } + + /** + * @since 1.4 + */ + public boolean isVolatile() { + return isModifierPresent("volatile"); + } + + /** + * @since 1.4 + */ + public boolean isNative() { + return isModifierPresent("native"); + } + + /** + * @since 1.4 + */ + public boolean isStrictfp() { + return isModifierPresent("strictfp"); + } + + private boolean isModifierPresent(String modifier) { + return modifiers.contains(modifier); + } + + protected void writeNonAccessibilityModifiers(IndentBuffer result) { + // modifiers (anything else) + for (Iterator iter = modifiers.iterator(); iter.hasNext();) { + String modifier = (String) iter.next(); + if (!modifier.startsWith("p")) { + result.write(modifier); + result.write(' '); + } + } + } + + protected void writeAccessibilityModifier(IndentBuffer result) { + for (Iterator iter = modifiers.iterator(); iter.hasNext();) { + String modifier = (String) iter.next(); + if (modifier.startsWith("p")) { + result.write(modifier); + result.write(' '); + } + } + } + + protected void writeAllModifiers(IndentBuffer result) { + for (Iterator iter = modifiers.iterator(); iter.hasNext();) { + String modifier = (String) iter.next(); + result.write(modifier); + result.write(' '); + } + } + + public void setLineNumber(int lineNumber) { + this.lineNumber = lineNumber; + } + + public JavaClassParent getParent() { + return parent; + } + + public void setParent(JavaClassParent parent) { + this.parent = parent; + } + + public JavaSource getSource() { + return parent.getParentSource(); + } + } *** src/java/com/thoughtworks/qdox/model/JavaClassImpl.java Wed Dec 31 14:00:00 1969 --- src/java/com/thoughtworks/qdox/model/JavaClassImpl.java Tue Aug 24 18:09:41 2004 *************** *** 0 **** --- 1,577 ---- + package com.thoughtworks.qdox.model; + + import com.thoughtworks.qdox.JavaDocBuilder; + import com.thoughtworks.qdox.model.util.OrderedMap; + + import java.util.ArrayList; + import java.util.Collection; + import java.util.HashSet; + import java.util.Iterator; + import java.util.LinkedList; + import java.util.List; + import java.util.Map; + import java.util.Set; + + /** + * @author Joe Walnes + * @author Aslak Hellesøy + */ + public class JavaClassImpl extends AbstractInheritableJavaEntityImpl implements JavaClass { + + private static Type OBJECT = new TypeImpl("java.lang.Object"); + + private List methods = new LinkedList(); + private JavaMethod[] methodsArray; + private List fields = new LinkedList(); + private JavaField[] fieldsArray; + private List classes = new LinkedList(); + private JavaClass[] classesArray; + private boolean interfce; + + // Don't access this directly. Use asType() to get my Type + private Type type; + private Type superClass; + private Type[] implementz = new TypeImpl[0]; + private JavaClassCache javaClassCache; + + protected JavaClassImpl() { + } + + public JavaClassImpl(String name) { + setName(name); + } + + public void setJavaClassCache(JavaClassCache javaClassCache) { + this.javaClassCache = javaClassCache; + + // reassign OBJECT. This will make it have a "source" too, + // causing Type.getJavaClass() to return a JavaClass, instead + // of null. + OBJECT = javaClassCache.getClassByName("java.lang.Object").asType(); + } + + /** + * Interface or class? + */ + public boolean isInterface() { + return interfce; + } + + public Type getSuperClass() { + boolean iAmJavaLangObject = OBJECT.equals(asType()); + + if (!interfce && (superClass == null) && !iAmJavaLangObject) { + return OBJECT; + } + + return superClass; + } + + /** + * Shorthand for getSuperClass().getJavaClass() with null checking. + */ + public JavaClass getSuperJavaClass() { + if (getSuperClass() != null) { + return getSuperClass().getJavaClass(); + } else { + return null; + } + } + + public Type[] getImplements() { + return implementz; + } + + /** + * @since 1.3 + */ + public JavaClass[] getImplementedInterfaces() { + Type[] type = getImplements(); + JavaClass[] result = new JavaClass[type.length]; + + for (int i = 0; i < result.length; i++) { + result[i] = type[i].getJavaClass(); + } + + return result; + } + + protected void writeBody(IndentBuffer result) { + writeAccessibilityModifier(result); + writeNonAccessibilityModifiers(result); + + result.write(interfce ? "interface " : "class "); + result.write(name); + + // subclass + if (superClass != null) { + result.write(" extends "); + result.write(superClass.getValue()); + } + + // implements + if (implementz.length > 0) { + result.write(interfce ? " extends " : " implements "); + + for (int i = 0; i < implementz.length; i++) { + if (i > 0) { + result.write(", "); + } + + result.write(implementz[i].getValue()); + } + } + + result.write(" {"); + result.newline(); + result.indent(); + + // fields + for (Iterator iterator = fields.iterator(); iterator.hasNext();) { + JavaField javaField = (JavaField) iterator.next(); + + result.newline(); + javaField.write(result); + } + + // methods + for (Iterator iterator = methods.iterator(); iterator.hasNext();) { + JavaMethod javaMethod = (JavaMethod) iterator.next(); + + result.newline(); + javaMethod.write(result); + } + + // inner-classes + for (Iterator iterator = classes.iterator(); iterator.hasNext();) { + JavaClass javaClass = (JavaClass) iterator.next(); + + result.newline(); + javaClass.write(result); + } + + result.deindent(); + result.newline(); + result.write('}'); + result.newline(); + } + + public void setInterface(boolean interfce) { + this.interfce = interfce; + } + + public void addMethod(JavaMethod meth) { + meth.setParent(this); + methods.add(meth); + methodsArray = null; + } + + public void setSuperClass(Type type) { + superClass = type; + } + + public void setImplementz(Type[] implementz) { + this.implementz = implementz; + } + + public void addField(JavaField javaField) { + javaField.setParent(this); + fields.add(javaField); + fieldsArray = null; + } + + public JavaSource getParentSource() { + JavaClassParent parent = getParent(); + return ((parent == null) ? null : parent.getParentSource()); + } + + public String getPackage() { + return getParentSource().getPackage(); + } + + public String getFullyQualifiedName() { + return getParent().getClassNamePrefix() + getName(); + } + + /** + * @since 1.3 + */ + public boolean isInner() { + return getParent() instanceof JavaClass; + } + + public String resolveType(String typeName) { + // Maybe it's an inner class? + JavaClass[] innerClasses = getInnerClasses(); + for (int i = 0; i < innerClasses.length; i++) { + if (innerClasses[i].getName().equals(typeName)) { + return innerClasses[i].getFullyQualifiedName(); + } + } + + return getParent().resolveType(typeName); + } + + public ClassLibrary getClassLibrary() { + return getParent().getClassLibrary(); + } + + public String getClassNamePrefix() { + return getFullyQualifiedName() + "$"; + } + + public Type asType() { + if (type == null) { + type = new TypeImpl(getFullyQualifiedName(), 0, this); + } + + return type; + } + + public JavaMethod[] getMethods() { + if (methodsArray == null) { + methodsArray = new JavaMethod[methods.size()]; + methods.toArray(methodsArray); + } + + return methodsArray; + } + + /** + * @since 1.3 + */ + public JavaMethod[] getMethods(boolean superclasses) { + if (superclasses) { + Set signatures = new HashSet(); + List methods = new ArrayList(); + + addMethodsFromSuperclassAndInterfaces(signatures, methods, this); + + return (JavaMethod[]) methods.toArray(new JavaMethod[methods.size()]); + } else { + return getMethods(); + } + } + + private void addMethodsFromSuperclassAndInterfaces(Set signatures, + List methodList, JavaClass clazz) { + JavaMethod[] methods = clazz.getMethods(); + + addNewMethods(signatures, methodList, methods); + + JavaClass superclass = clazz.getSuperJavaClass(); + + // TODO workaround for a bug in getSuperJavaClass + if ((superclass != null) && (superclass != clazz)) { + addMethodsFromSuperclassAndInterfaces(signatures, methodList, + superclass); + } + + JavaClass[] implementz = clazz.getImplementedInterfaces(); + + for (int i = 0; i < implementz.length; i++) { + if (implementz[i] != null) { + addMethodsFromSuperclassAndInterfaces(signatures, methodList, + implementz[i]); + } + } + } + + private void addNewMethods(Set signatures, List methodList, + JavaMethod[] methods) { + for (int i = 0; i < methods.length; i++) { + JavaMethod method = methods[i]; + + if (!method.isPrivate()) { + String signature = method.getDeclarationSignature(false); + + if (!signatures.contains(signature)) { + methodList.add(method); + signatures.add(signature); + } + } + } + } + + /** + * @param name method name + * @param parameterTypes parameter types or null if there are no parameters. + * @return the matching method or null if no match is found. + */ + public JavaMethod getMethodBySignature(String name, Type[] parameterTypes) { + JavaMethod[] methods = getMethods(); + + for (int i = 0; i < methods.length; i++) { + if (methods[i].signatureMatches(name, parameterTypes)) { + return methods[i]; + } + } + + return null; + } + + public JavaMethod getMethodBySignature(String name, Type[] parameterTypes, + boolean superclasses) { + JavaMethod[] result = getMethodsBySignature(name, parameterTypes, + superclasses); + + return (result.length > 0) ? result[0] : null; + } + + public JavaMethod[] getMethodsBySignature(String name, + Type[] parameterTypes, boolean superclasses) { + List result = new ArrayList(); + + JavaMethod methodInThisClass = getMethodBySignature(name, parameterTypes); + + if (methodInThisClass != null) { + result.add(methodInThisClass); + } + + if (superclasses) { + JavaClass superclass = getSuperJavaClass(); + + if (superclass != null) { + JavaMethod method = superclass.getMethodBySignature(name, + parameterTypes, true); + + // todo: ideally we should check on package privacy too. oh well. + if ((method != null) && !method.isPrivate()) { + result.add(method); + } + } + + JavaClass[] implementz = getImplementedInterfaces(); + + for (int i = 0; i < implementz.length; i++) { + JavaMethod method = implementz[i].getMethodBySignature(name, + parameterTypes, true); + + if (method != null) { + result.add(method); + } + } + } + + return (JavaMethod[]) result.toArray(new JavaMethod[result.size()]); + } + + public JavaField[] getFields() { + if (fieldsArray == null) { + fieldsArray = new JavaFieldImpl[fields.size()]; + fields.toArray(fieldsArray); + } + + return fieldsArray; + } + + public JavaField getFieldByName(String name) { + JavaField[] fields = getFields(); + + for (int i = 0; i < fields.length; i++) { + if (fields[i].getName().equals(name)) { + return fields[i]; + } + } + + return null; + } + + public void addClass(JavaClass cls) { + cls.setParent(this); + classes.add(cls); + classesArray = null; + } + + /** + * @deprecated Use {@link #getInnerClasses()} instead. + */ + public JavaClass[] getClasses() { + return getInnerClasses(); + } + + /** + * @since 1.3 + */ + public JavaClass[] getInnerClasses() { + if (classesArray == null) { + classesArray = new JavaClassImpl[classes.size()]; + classes.toArray(classesArray); + } + + return classesArray; + } + + public JavaClass getInnerClassByName(String name) { + JavaClass[] classes = getInnerClasses(); + + for (int i = 0; i < classes.length; i++) { + if (classes[i].getName().equals(name)) { + return classes[i]; + } + } + + return null; + } + + /** + * @since 1.3 + */ + public boolean isA(String fullClassName) { + Type type = new TypeImpl(fullClassName, 0, this); + return asType().isA(type); + } + + /** + * @since 1.3 + */ + public boolean isA(JavaClass javaClass) { + return asType().isA(javaClass.asType()); + } + + /** + * Gets bean properties without looking in superclasses or interfaces. + * + * @since 1.3 + */ + public BeanProperty[] getBeanProperties() { + return getBeanProperties(false); + } + + /** + * @since 1.3 + */ + public BeanProperty[] getBeanProperties(boolean superclasses) { + Map beanPropertyMap = getBeanPropertyMap(superclasses); + Collection beanPropertyCollection = beanPropertyMap.values(); + + return (BeanProperty[]) beanPropertyCollection.toArray(new BeanProperty[beanPropertyCollection + .size()]); + } + + private Map getBeanPropertyMap(boolean superclasses) { + JavaMethod[] methods = getMethods(superclasses); + Map beanPropertyMap = new OrderedMap(); + + // loop over the methods. + for (int i = 0; i < methods.length; i++) { + JavaMethod method = methods[i]; + + if (method.isPropertyAccessor()) { + String propertyName = method.getPropertyName(); + BeanProperty beanProperty = getOrCreateProperty(beanPropertyMap, + propertyName); + + beanProperty.setAccessor(method); + beanProperty.setType(method.getPropertyType()); + } else if (method.isPropertyMutator()) { + String propertyName = method.getPropertyName(); + BeanProperty beanProperty = getOrCreateProperty(beanPropertyMap, + propertyName); + + beanProperty.setMutator(method); + beanProperty.setType(method.getPropertyType()); + } + } + + return beanPropertyMap; + } + + private BeanProperty getOrCreateProperty(Map beanPropertyMap, + String propertyName) { + BeanProperty result = (BeanProperty) beanPropertyMap.get(propertyName); + + if (result == null) { + result = new BeanProperty(propertyName); + beanPropertyMap.put(propertyName, result); + } + + return result; + } + + /** + * Gets bean property without looking in superclasses or interfaces. + * + * @since 1.3 + */ + public BeanProperty getBeanProperty(String propertyName) { + return getBeanProperty(propertyName, false); + } + + /** + * @since 1.3 + */ + public BeanProperty getBeanProperty(String propertyName, + boolean superclasses) { + return (BeanProperty) getBeanPropertyMap(superclasses).get(propertyName); + } + + /** + * Gets the known derived classes. That is, subclasses or implementing classes. + * + * @return + */ + public JavaClass[] getDerivedClasses() { + List result = new ArrayList(); + JavaDocBuilder builder = (JavaDocBuilder) javaClassCache; + JavaClass[] classes = builder.getClasses(); + + for (int i = 0; i < classes.length; i++) { + JavaClass clazz = classes[i]; + + if (clazz.isA(this) && !(clazz == this)) { + result.add(clazz); + } + } + + return (JavaClass[]) result.toArray(new JavaClass[result.size()]); + } + + public DocletTag[] getTagsByName(String name, boolean superclasses) { + List result = new ArrayList(); + + addTagsRecursive(result, this, name, superclasses); + + return (DocletTag[]) result.toArray(new DocletTag[result.size()]); + } + + private void addTagsRecursive(List result, JavaClass javaClass, + String name, boolean superclasses) { + DocletTag[] tags = javaClass.getTagsByName(name); + + addNewTags(result, tags); + + if (superclasses) { + JavaClass superclass = javaClass.getSuperJavaClass(); + + // THIS IS A HACK AROUND A BUG THAT MUST BE SOLVED!!! + // SOMETIMES A CLASS RETURNS ITSELF AS SUPER ?!?!?!?!?! + if ((superclass != null) && (superclass != javaClass)) { + addTagsRecursive(result, superclass, name, superclasses); + } + + JavaClass[] implementz = javaClass.getImplementedInterfaces(); + + for (int h = 0; h < implementz.length; h++) { + if (implementz[h] != null) { + addTagsRecursive(result, implementz[h], name, superclasses); + } + } + } + } + + private void addNewTags(List list, DocletTag[] tags) { + for (int i = 0; i < tags.length; i++) { + DocletTag superTag = tags[i]; + + if (!list.contains(superTag)) { + list.add(superTag); + } + } + } + + public int compareTo(Object o) { + return getFullyQualifiedName().compareTo(((JavaClass) o).getFullyQualifiedName()); + } + + } *** src/java/com/thoughtworks/qdox/model/JavaFieldImpl.java Wed Dec 31 14:00:00 1969 --- src/java/com/thoughtworks/qdox/model/JavaFieldImpl.java Tue Aug 24 18:09:41 2004 *************** *** 0 **** --- 1,55 ---- + package com.thoughtworks.qdox.model; + + public class JavaFieldImpl extends AbstractJavaEntityImpl implements JavaField { + + private Type type; + private JavaClass parent; + + protected JavaFieldImpl() { + } + + public JavaFieldImpl(String name) { + setName(name); + } + + protected JavaFieldImpl(Type type, String name) { + setType(type); + setName(name); + } + + public Type getType() { + return type; + } + + protected void writeBody(IndentBuffer result) { + writeAllModifiers(result); + result.write(type.toString()); + result.write(' '); + result.write(name); + result.write(';'); + result.newline(); + } + + public void setType(Type type) { + this.type = type; + } + + public int compareTo(Object o) { + return getName().compareTo(((JavaField)o).getName()); + } + + public String getDeclarationSignature(boolean withModifiers) { + IndentBuffer result = new IndentBuffer(); + if (withModifiers) { + writeAllModifiers(result); + } + result.write(type.toString()); + result.write(' '); + result.write(name); + return result.toString(); + } + + public String getCallSignature() { + return getName(); + } + } *** src/java/com/thoughtworks/qdox/model/JavaMethodImpl.java Wed Dec 31 14:00:00 1969 --- src/java/com/thoughtworks/qdox/model/JavaMethodImpl.java Tue Aug 24 18:09:41 2004 *************** *** 0 **** --- 1,293 ---- + package com.thoughtworks.qdox.model; + + import java.beans.Introspector; + import java.util.List; + import java.util.ArrayList; + + public class JavaMethodImpl extends AbstractInheritableJavaEntityImpl implements JavaMethod { + + private Type returns = TypeImpl.VOID; + private JavaParameter[] parameters = JavaParameterImpl.EMPTY_ARRAY; + private Type[] exceptions = TypeImpl.EMPTY_ARRAY; + private boolean constructor; + + protected JavaMethodImpl() { + } + + public JavaMethodImpl(String name) { + setName(name); + } + + protected JavaMethodImpl(Type returns, String name) { + setReturns(returns); + setName(name); + } + + public Type getReturns() { + return returns; + } + + public JavaParameter[] getParameters() { + return parameters; + } + + public JavaParameter getParameterByName(String name) { + JavaParameter[] parameters = getParameters(); + for (int i = 0; i < parameters.length; i++) { + if (parameters[i].getName().equals(name)) { + return parameters[i]; + } + } + return null; + } + + public Type[] getExceptions() { + return exceptions; + } + + public boolean isConstructor() { + return constructor; + } + + protected void writeBody(IndentBuffer result) { + writeBody(result, true, true, true); + } + + /** + * @since 1.3 + */ + protected void writeBody(IndentBuffer result, boolean withModifiers, boolean isDeclaration, boolean isPrettyPrint) { + if (withModifiers) { + writeAccessibilityModifier(result); + writeNonAccessibilityModifiers(result); + } + + if (!constructor) { + if(isDeclaration) { + result.write(returns.toString()); + result.write(' '); + } + } + + result.write(name); + result.write('('); + for (int i = 0; i < parameters.length; i++) { + JavaParameter parameter = parameters[i]; + if (i > 0) result.write(", "); + if (isDeclaration) { + result.write(parameter.getType().toString()); + result.write(' '); + } + result.write(parameter.getName()); + } + result.write(')'); + if (isDeclaration) { + if (exceptions.length > 0) { + result.write(" throws "); + for (int i = 0; i < exceptions.length; i++) { + if (i > 0) result.write(", "); + result.write(exceptions[i].getValue()); + } + } + } + if (isPrettyPrint) { + result.write(';'); + result.newline(); + } + } + + /** + * @since 1.3 + */ + private String getSignature(boolean withModifiers, boolean isDeclaration) { + IndentBuffer result = new IndentBuffer(); + writeBody(result, withModifiers, isDeclaration, false); + return result.toString(); + } + + /** + * @since 1.3 + */ + public String getDeclarationSignature(boolean withModifiers) { + return getSignature(withModifiers, true); + } + + /** + * @since 1.3 + */ + public String getCallSignature() { + return getSignature(false, false); + } + + public void setReturns(Type returns) { + this.returns = returns; + } + + public void setParameters(JavaParameter[] parameters) { + for (int i = 0; i < parameters.length; i++) { + parameters[i].setParentMethod(this); + } + this.parameters = parameters; + } + + public void setExceptions(Type[] exceptions) { + this.exceptions = exceptions; + } + + public void setConstructor(boolean constructor) { + this.constructor = constructor; + } + + public boolean equals(Object obj) { + if (obj == null) return false; + JavaMethod m = (JavaMethod) obj; + + if (m.isConstructor() != isConstructor()) return false; + + if (m.getName() == null) return (getName() == null); + if (!m.getName().equals(getName())) return false; + + if (m.getReturns() == null) return (getReturns() == null); + if (!m.getReturns().equals(getReturns())) return false; + + JavaParameter[] myParams = getParameters(); + JavaParameter[] otherParams = m.getParameters(); + if (otherParams.length != myParams.length) return false; + for (int i = 0; i < myParams.length; i++) { + if (!otherParams[i].equals(myParams[i])) return false; + } + + return true; + } + + /** + * @param name method name + * @param parameterTypes parameter types or null if there are no parameters. + * @return true if the signature and parameters match. + */ + public boolean signatureMatches(String name, Type[] parameterTypes) { + if (!name.equals(this.name)) return false; + parameterTypes = parameterTypes == null ? new Type[0] : parameterTypes; + if (parameterTypes.length != this.parameters.length) return false; + for (int i = 0; i < parameters.length; i++) { + if (!parameters[i].getType().equals(parameterTypes[i])) { + return false; + } + } + return true; + } + + public int hashCode() { + int hashCode = name.hashCode(); + if (returns != null) hashCode *= returns.hashCode(); + hashCode *= getParameters().length; + return hashCode; + } + + public JavaClass getParentClass() { + return (JavaClass) getParent(); + } + + public void setParentClass(JavaClass parentClass) { + setParent(parentClass); + } + + public boolean isPublic() { + return super.isPublic() || getParentClass().isInterface(); + } + + /** + * @return true if this method is a Java Bean accessor + * @since 1.3 + */ + public boolean isPropertyAccessor() { + if (isStatic()) return false; + if (getParameters().length != 0) return false; + + if (getName().startsWith("is")) { + return (getName().length() > 2 + && Character.isUpperCase(getName().charAt(2))); + } + if (getName().startsWith("get")) { + return (getName().length() > 3 + && Character.isUpperCase(getName().charAt(3))); + } + + return false; + } + + /** + * @return true if this method is a Java Bean accessor + * @since 1.3 + */ + public boolean isPropertyMutator() { + if (isStatic()) return false; + if (getParameters().length != 1) return false; + + if (getName().startsWith("set")) { + return (getName().length() > 3 + && Character.isUpperCase(getName().charAt(3))); + } + + return false; + } + + /** + * @return the type of the property this method represents, or null if this method + * is not a property mutator or property accessor. + * @since 1.3 + */ + public Type getPropertyType() { + if (isPropertyAccessor()) { + return getReturns(); + } + if (isPropertyMutator()) { + return getParameters()[0].getType(); + } + return null; + } + + /** + * @return the name of the property this method represents, or null if this method + * is not a property mutator or property accessor. + * @since 1.3 + */ + public String getPropertyName() { + int start = -1; + if (getName().startsWith("get") || getName().startsWith("set")) { + start = 3; + } else if (getName().startsWith("is")) { + start = 2; + } else { + return null; + } + return Introspector.decapitalize(getName().substring(start)); + } + + public DocletTag[] getTagsByName(String name, boolean inherited) { + JavaClass clazz = getParentClass(); + JavaParameter[] params = getParameters(); + Type[] types = new TypeImpl[params.length]; + for (int i = 0; i < types.length; i++) { + types[i] = params[i].getType(); + } + JavaMethod[] methods = clazz.getMethodsBySignature(getName(), types, true); + + List result = new ArrayList(); + for (int i = 0; i < methods.length; i++) { + JavaMethod method = methods[i]; + DocletTag[] tags = method.getTagsByName(name); + for (int j = 0; j < tags.length; j++) { + DocletTag tag = tags[j]; + if(!result.contains(tag)) { + result.add(tag); + } + } + } + return (DocletTag[]) result.toArray(new DocletTag[result.size()]); + } + + public int compareTo(Object o) { + return getDeclarationSignature(false).compareTo(((JavaMethod)o).getDeclarationSignature(false)); + } + } *** src/java/com/thoughtworks/qdox/model/JavaParameterImpl.java Wed Dec 31 14:00:00 1969 --- src/java/com/thoughtworks/qdox/model/JavaParameterImpl.java Tue Aug 24 13:29:24 2004 *************** *** 0 **** --- 1,47 ---- + /* + * Copyright (c) 2004 Your Corporation. All Rights Reserved. + */ + package com.thoughtworks.qdox.model; + + import java.io.Serializable; + + public class JavaParameterImpl implements JavaParameter { + + public static final JavaParameter[] + EMPTY_ARRAY = new JavaParameterImpl[0]; + + private String name; + private Type type; + private JavaMethod parentMethod; + + public JavaParameterImpl(Type type, String name) { + this.name = name; + this.type = type; + } + + public String getName() { + return name; + } + + public Type getType() { + return type; + } + + public boolean equals(Object obj) { + JavaParameter p = (JavaParameter) obj; + // name isn't used in equality check. + return getType().equals(p.getType()); + } + + public int hashCode() { + return getType().hashCode(); + } + + public JavaMethod getParentMethod() { + return parentMethod; + } + + public void setParentMethod(JavaMethod parentMethod) { + this.parentMethod = parentMethod; + } + } *** src/java/com/thoughtworks/qdox/model/JavaSourceImpl.java Wed Dec 31 14:00:00 1969 --- src/java/com/thoughtworks/qdox/model/JavaSourceImpl.java Tue Aug 24 13:30:33 2004 *************** *** 0 **** --- 1,228 ---- + /* + * Copyright (c) 2004 Your Corporation. All Rights Reserved. + */ + package com.thoughtworks.qdox.model; + + import java.io.File; + import java.io.Serializable; + import java.util.HashMap; + import java.util.HashSet; + import java.util.LinkedList; + import java.util.List; + import java.util.Map; + import java.util.Set; + import java.net.URL; + import java.net.MalformedURLException; + + public class JavaSourceImpl implements JavaSource { + + private static final Set PRIMITIVE_TYPES = new HashSet(); + + static { + PRIMITIVE_TYPES.add("boolean"); + PRIMITIVE_TYPES.add("byte"); + PRIMITIVE_TYPES.add("char"); + PRIMITIVE_TYPES.add("double"); + PRIMITIVE_TYPES.add("float"); + PRIMITIVE_TYPES.add("int"); + PRIMITIVE_TYPES.add("long"); + PRIMITIVE_TYPES.add("short"); + PRIMITIVE_TYPES.add("void"); + } + + private String packge; + private List imports = new LinkedList(); + private String[] importsArray; + private List classes = new LinkedList(); + private JavaClass[] classesArray; + private ClassLibrary classLibrary; + private Map resolvedTypeCache = new HashMap(); + private URL url; + + /** + * @since 1.4 + */ + public void setURL(URL url) { + this.url = url; + } + + /** + * @since 1.4 + */ + public URL getURL() { + return url; + } + + /** + * @deprecated use setURL + */ + public void setFile(File file) { + try { + setURL(file.toURL()); + } catch (MalformedURLException e) { + throw new IllegalStateException(e.getMessage()); + } + } + + /** + * @deprecated use getURL + */ + public File getFile() { + return new File(url.getFile()); + } + + public String getPackage() { + return packge; + } + + public void setPackage(String packge) { + this.packge = packge; + } + + public void addImport(String imp) { + imports.add(imp); + importsArray = null; + } + + public String[] getImports() { + if (importsArray == null) { + importsArray = new String[imports.size()]; + imports.toArray(importsArray); + } + return importsArray; + } + + public void addClass(JavaClass cls) { + cls.setParent(this); + classes.add(cls); + classesArray = null; + } + + public JavaClass[] getClasses() { + if (classesArray == null) { + classesArray = new JavaClassImpl[classes.size()]; + classes.toArray(classesArray); + } + return classesArray; + } + + public ClassLibrary getClassLibrary() { + return classLibrary; + } + + public void setClassLibrary(ClassLibrary classLibrary) { + this.classLibrary = classLibrary; + } + + public String toString() { + IndentBuffer result = new IndentBuffer(); + + // package statement + if (packge != null) { + result.write("package "); + result.write(packge); + result.write(';'); + result.newline(); + result.newline(); + } + + // import statement + String[] imports = getImports(); + for (int i = 0; imports != null && i < imports.length; i++) { + result.write("import "); + result.write(imports[i]); + result.write(';'); + result.newline(); + } + if (imports != null && imports.length > 0) { + result.newline(); + } + + // classes + JavaClass[] classes = getClasses(); + for (int i = 0; i < classes.length; i++) { + if (i > 0) result.newline(); + classes[i].write(result); + } + + return result.toString(); + } + + public String resolveType(String typeName) { + if (resolvedTypeCache.containsKey(typeName)) { + return (String) resolvedTypeCache.get(typeName); + } + String resolved = resolveTypeInternal(typeName); + if (resolved != null) { + resolvedTypeCache.put(typeName, resolved); + } + return resolved; + } + + private String resolveTypeInternal(String typeName) { + + // primitive types + if (PRIMITIVE_TYPES.contains(typeName)) return typeName; + + // check if a matching fully-qualified import + String[] imports = getImports(); + for (int i = 0; i < imports.length; i++) { + if (imports[i].equals(typeName)) return typeName; + if (imports[i].endsWith("." + typeName)) return imports[i]; + } + + if (getClassLibrary() == null) return null; + + // check for fully-qualified class + if (getClassLibrary().contains(typeName)) { + return typeName; + } + + // check for a class in the same package + { + String fqn = getClassNamePrefix() + typeName; + if (getClassLibrary().contains(fqn)) { + return fqn; + } + } + + // check for wildcard imports + for (int i = 0; i < imports.length; i++) { + if (imports[i].endsWith(".*")) { + String fqn = + imports[i].substring(0, imports[i].length() - 1) + + typeName; + if (getClassLibrary().contains(fqn)) { + return fqn; + } + } + } + + // try java.lang.* + { + String fqn = "java.lang." + typeName; + if (getClassLibrary().contains(fqn)) { + return fqn; + } + } + + // maybe it's an inner-class reference + int indexOfLastDot = typeName.lastIndexOf('.'); + if (indexOfLastDot != -1) { + String root = typeName.substring(0,indexOfLastDot); + String leaf = typeName.substring(indexOfLastDot+1); + return resolveType(root + "$" + leaf); + } + + return null; + } + + public String getClassNamePrefix() { + if (getPackage() == null) return ""; + return getPackage() + "."; + } + + public JavaSource getParentSource() { + return this; + } + } *** src/java/com/thoughtworks/qdox/model/TypeImpl.java Wed Dec 31 14:00:00 1969 --- src/java/com/thoughtworks/qdox/model/TypeImpl.java Tue Aug 24 13:34:28 2004 *************** *** 0 **** --- 1,130 ---- + package com.thoughtworks.qdox.model; + + import java.io.Serializable; + + public class TypeImpl implements Type { + + public static final Type[] EMPTY_ARRAY = new TypeImpl[0]; + public static final Type VOID = new TypeImpl("void"); + + private String name; + private JavaClassParent context; + private String fullName; + private int dimensions; + + public TypeImpl(String fullName, String name, int dimensions, JavaClassParent context) { + this.fullName = fullName; + this.name = name; + this.dimensions = dimensions; + this.context = context; + } + + public TypeImpl(String fullName, int dimensions, JavaClassParent context) { + this(fullName, null, dimensions, context); + } + + public TypeImpl(String fullName, int dimensions) { + this(fullName, dimensions, null); + } + + public TypeImpl(String fullName) { + this(fullName, 0); + } + + public static Type createUnresolved(String name, int dimensions, JavaClassParent context) { + return new TypeImpl(null, name, dimensions, context); + } + + public JavaClassParent getJavaClassParent() { + return context; + } + + public String getValue() { + return isResolved() ? fullName : name; + } + + public boolean isResolved() { + if (fullName == null && context != null) { + fullName = context.resolveType(name); + } + return (fullName != null); + } + + /** + * @see java.lang.Comparable#compareTo(Object) + */ + public int compareTo(Object o) { + if (!(o instanceof Type)) + return 0; + + return getValue().compareTo(((Type) o).getValue()); + } + + public boolean isArray() { + return dimensions > 0; + } + + public int getDimensions() { + return dimensions; + } + + public String toString() { + if (dimensions == 0) return getValue(); + StringBuffer buff = new StringBuffer(getValue()); + for (int i = 0; i < dimensions; i++) buff.append("[]"); + String result = buff.toString(); + return result; + } + + public boolean equals(Object obj) { + if (obj == null) return false; + Type t = (Type) obj; + return getValue().equals(t.getValue()) && t.getDimensions() == getDimensions(); + } + + public int hashCode() { + return getValue().hashCode(); + } + + public JavaClass getJavaClass() { + JavaClassParent javaClassParent = getJavaClassParent(); + if (javaClassParent == null) { + return null; + } + ClassLibrary classLibrary = javaClassParent.getClassLibrary(); + if (classLibrary == null) { + return null; + } + return classLibrary.getClassByName(getValue()); + } + + /** + * @since 1.3 + */ + public boolean isA(Type type) { + if (this.equals(type)) { + return true; + } else { + JavaClass javaClass = getJavaClass(); + if (javaClass != null) { + // ask our interfaces + Type[] implementz = javaClass.getImplements(); + for (int i = 0; i < implementz.length; i++) { + if (implementz[i].isA(type)) { + return true; + } + } + + // ask our superclass + Type supertype = javaClass.getSuperClass(); + if (supertype != null) { + if (supertype.isA(type)) { + return true; + } + } + } + } + // We'we walked up the hierarchy and found nothing. + return false; + } + } *** bootstrap/yacc.linux --- bootstrap/yacc.linux *** bootstrap/yacc.solaris --- bootstrap/yacc.solaris *** src/java/com/thoughtworks/qdox/JavaDocBuilder.java --- src/java/com/thoughtworks/qdox/JavaDocBuilder.java *** src/java/com/thoughtworks/qdox/model/AbstractInheritableJavaEntity.java --- src/java/com/thoughtworks/qdox/model/AbstractInheritableJavaEntity.java *** src/java/com/thoughtworks/qdox/model/AbstractJavaEntity.java --- src/java/com/thoughtworks/qdox/model/AbstractJavaEntity.java *** src/java/com/thoughtworks/qdox/model/JavaClass.java --- src/java/com/thoughtworks/qdox/model/JavaClass.java *** src/java/com/thoughtworks/qdox/model/JavaClassParent.java --- src/java/com/thoughtworks/qdox/model/JavaClassParent.java *** src/java/com/thoughtworks/qdox/model/JavaField.java --- src/java/com/thoughtworks/qdox/model/JavaField.java *** src/java/com/thoughtworks/qdox/model/JavaMethod.java --- src/java/com/thoughtworks/qdox/model/JavaMethod.java *** src/java/com/thoughtworks/qdox/model/JavaParameter.java --- src/java/com/thoughtworks/qdox/model/JavaParameter.java *** src/java/com/thoughtworks/qdox/model/JavaSource.java --- src/java/com/thoughtworks/qdox/model/JavaSource.java *** src/java/com/thoughtworks/qdox/model/ModelBuilder.java --- src/java/com/thoughtworks/qdox/model/ModelBuilder.java *** src/java/com/thoughtworks/qdox/model/Type.java --- src/java/com/thoughtworks/qdox/model/Type.java *** src/java/com/thoughtworks/qdox/parser/Lexer.java --- src/java/com/thoughtworks/qdox/parser/Lexer.java *** src/java/com/thoughtworks/qdox/parser/structs/TypeDef.java --- src/java/com/thoughtworks/qdox/parser/structs/TypeDef.java *** src/test/com/thoughtworks/qdox/JavaDocBuilderTest.java --- src/test/com/thoughtworks/qdox/JavaDocBuilderTest.java *** src/test/com/thoughtworks/qdox/model/AbstractJavaEntityTest.java --- src/test/com/thoughtworks/qdox/model/AbstractJavaEntityTest.java *** src/test/com/thoughtworks/qdox/model/ClassLibraryTest.java --- src/test/com/thoughtworks/qdox/model/ClassLibraryTest.java *** src/test/com/thoughtworks/qdox/model/JavaClassTest.java --- src/test/com/thoughtworks/qdox/model/JavaClassTest.java *** src/test/com/thoughtworks/qdox/model/JavaFieldTest.java --- src/test/com/thoughtworks/qdox/model/JavaFieldTest.java *** src/test/com/thoughtworks/qdox/model/JavaMethodTest.java --- src/test/com/thoughtworks/qdox/model/JavaMethodTest.java *** src/test/com/thoughtworks/qdox/model/JavaParameterTest.java --- src/test/com/thoughtworks/qdox/model/JavaParameterTest.java *** src/test/com/thoughtworks/qdox/model/JavaSourceTest.java --- src/test/com/thoughtworks/qdox/model/JavaSourceTest.java *** src/test/com/thoughtworks/qdox/model/ModelBuilderTest.java --- src/test/com/thoughtworks/qdox/model/ModelBuilderTest.java *** src/test/com/thoughtworks/qdox/model/TypeTest.java --- src/test/com/thoughtworks/qdox/model/TypeTest.java *** src/test/com/thoughtworks/qdox/parser/LexerTest.java --- src/test/com/thoughtworks/qdox/parser/LexerTest.java *** src/test/com/thoughtworks/qdox/parser/MockLexer.java --- src/test/com/thoughtworks/qdox/parser/MockLexer.java *** src/test/com/thoughtworks/qdox/traversal/TraversalTest.java --- src/test/com/thoughtworks/qdox/traversal/TraversalTest.java *** xdocs/index.xml --- xdocs/index.xml *** xdocs/license.xml --- xdocs/license.xml *** xdocs/navigation.xml --- xdocs/navigation.xml *** xdocs/tasks.xml --- xdocs/tasks.xml