/* gnu.classpath.tools.gjdoc.ClassDocImpl
Copyright (C) 2001 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath 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 for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
package gnu.classpath.tools.gjdoc;
import com.sun.javadoc.*;
import java.util.*;
import java.io.*;
import gnu.classpath.tools.gjdoc.expr.EvaluatorEnvironment;
import gnu.classpath.tools.gjdoc.expr.CircularExpressionException;
import gnu.classpath.tools.gjdoc.expr.IllegalExpressionException;
import gnu.classpath.tools.gjdoc.expr.UnknownIdentifierException;
public class ClassDocImpl
extends ProgramElementDocImpl
implements ClassDoc, WritableType, EvaluatorEnvironment {
private ClassDoc baseClassDoc;
private ClassDoc[] importedClasses;
private PackageDoc[] importedPackages;
private boolean definesSerializableFields;
private FieldDoc[] serialPersistentField;
private MethodDoc[] serializationMethods;
private String dimension = "";
public ClassDocImpl(ClassDoc containingClass,
PackageDoc containingPackage,
int accessLevel,
boolean isFinal,
boolean isStatic,
SourcePosition position) {
super(containingClass, containingPackage, accessLevel, isFinal, isStatic,
position);
this.baseClassDoc = this;
}
public ClassDocImpl(ClassDoc containingClass,
PackageDoc containingPackage,
ClassDoc[] importedClasses,
PackageDoc[] importedPackages,
SourcePosition position) {
super(containingClass, containingPackage,
position);
this.importedClasses=importedClasses;
this.importedPackages=importedPackages;
this.baseClassDoc = this;
}
// Return constructors in class.
public ConstructorDoc[] constructors() {
return constructors(true);
}
public ConstructorDoc[] constructors(boolean filter) {
return filter ? filteredConstructors : unfilteredConstructors;
}
// Return true if Serializable fields are explicitly defined with the special class member serialPersistentFields.
public boolean definesSerializableFields() {
return definesSerializableFields;
}
// Return fields in class.
public FieldDoc[] fields() {
return fields(true);
}
public FieldDoc[] fields(boolean filter) {
return filter ? filteredFields : unfilteredFields;
}
private static Set primitiveNames;
static {
primitiveNames = new HashSet();
primitiveNames.add("int");
primitiveNames.add("long");
primitiveNames.add("char");
primitiveNames.add("short");
primitiveNames.add("byte");
primitiveNames.add("float");
primitiveNames.add("double");
primitiveNames.add("boolean");
}
private Map findClassCache = new HashMap();
public ClassDoc findClass(String className, String dimension)
{
ClassDoc cached = (ClassDoc)findClassCache.get(className + dimension);
if (null != cached) {
return cached;
}
else {
ClassDoc classDoc = findClass(className);
if (null!=classDoc) {
try {
if (classDoc.dimension().equals(dimension)) {
return classDoc;
}
else {
ClassDoc rc = (ClassDoc) ((WritableType)classDoc).clone();
((WritableType)rc).setDimension(dimension);
findClassCache.put(className + dimension, rc);
return rc;
}
}
catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
else {
return null;
}
}
}
public ClassDoc findClass(String className)
{
String qualifiedName = Main.getRootDoc().resolveClassName(className, this);
ClassDoc rc=Main.getRootDoc().classNamed(qualifiedName);
if (null == rc) {
for (ClassDoc cdi=this; cdi!=null; cdi=cdi.containingClass()) {
for (ClassDoc sdi=cdi; sdi!=null; sdi=sdi.superclass()) {
if (sdi instanceof ClassDocProxy) {
ClassDoc realClass = Main.getRootDoc().classNamed(sdi.qualifiedName());
if (null != realClass) {
sdi = realClass;
}
}
rc=Main.getRootDoc().classNamed(sdi.qualifiedName()+"."+className);
if (rc!=null) return rc;
}
}
}
return rc;
}
// Get the list of classes declared as imported.
public ClassDoc[] importedClasses() {
return importedClasses;
}
// Get the list of packages declared as imported.
public PackageDoc[] importedPackages() {
return importedPackages;
}
// Return inner classes within this class.
public ClassDoc[] innerClasses() {
return innerClasses(true);
}
public ClassDoc[] innerClasses(boolean filtered) {
return filtered ? filteredInnerClasses : unfilteredInnerClasses;
}
void setFilteredInnerClasses(ClassDoc[] filteredInnerClasses) {
this.filteredInnerClasses=filteredInnerClasses;
}
void setInnerClasses(ClassDoc[] unfilteredInnerClasses) {
this.unfilteredInnerClasses=unfilteredInnerClasses;
}
// Return interfaces implemented by this class or interfaces extended by this interface.
public ClassDoc[] interfaces() {
return interfaces;
}
public void setInterfaces(ClassDoc[] interfaces) {
this.interfaces=interfaces;
}
// Return true if this class is abstract
public boolean isAbstract() {
return isAbstract || isInterface();
}
public boolean isInterface() {
return isInterface;
}
public boolean isAnnotation() {
return isAnnotation;
}
public boolean isEnum()
{
return isEnum;
}
// Return true if this class is abstract
public void setIsAbstract(boolean b) {
this.isAbstract=b;
}
// Return true if this class implements java.io.Externalizable.
public boolean isExternalizable() {
return implementsInterface("java.io.Externalizable");
}
// Return true if this class implements java.io.Serializable.
public boolean isSerializable() {
return implementsInterface("java.io.Serializable");
}
public boolean implementsInterface(String name) {
for (ClassDoc cdi=this; cdi!=null; cdi=(ClassDoc)cdi.superclass()) {
if (cdi instanceof ClassDocImpl) {
ClassDoc[] cdiInterfaces=(ClassDoc[])cdi.interfaces();
if (null != cdiInterfaces) {
for (int i=0; i<cdiInterfaces.length; ++i) {
if (cdiInterfaces[i].qualifiedName().equals(name))
return true;
}
}
}
else {
//throw new RuntimeException("implementsInterface(\""+name+"\") failed: Not a ClassDocImpl:"+cdi);
}
}
return false;
}
// Return methods in class.
public MethodDoc[] methods() {
return methods(true);
}
// Return methods in class.
public MethodDoc[] methods(boolean filter) {
return filter ? filteredMethods : unfilteredMethods;
}
// Return the Serializable fields of class. Return either a list of default fields documented by serial tag or return a single FieldDoc for serialPersistentField member.
public FieldDoc[] serializableFields() {
if (serialPersistentField!=null) {
return serialPersistentField;
}
else{
return serializableFields;
}
}
// Return the serialization methods for this class.
public MethodDoc[] serializationMethods() {
return serializationMethods;
}
// Test whether this class is a subclass of the specified class.
public boolean subclassOf(ClassDoc cd) {
for (ClassDocImpl cdi=(ClassDocImpl)superclass(); cdi!=null; cdi=(ClassDocImpl)cdi.superclass()) {
if (cdi.equals(cd))
return true;
}
return false;
}
// Return the superclass of this class
public ClassDoc superclass() {
return superclass;
}
// Implementation of Interface Type
public ClassDoc asClassDoc() {
return (ClassDoc)this;
}
public String typeName() { return name(); }
public String qualifiedTypeName() {
return (containingPackage()!=null && !containingPackage().equals(PackageDocImpl.DEFAULT_PACKAGE))?(containingPackage().name()+"."+name()):(name());
}
public String qualifiedName() { return qualifiedTypeName(); }
public String dimension() { return dimension; }
public String toString() { return "ClassDoc{"+qualifiedTypeName()+"}"; }
public TypeVariable asTypeVariable() { return null; }
public static ClassDocImpl createInstance(ClassDoc containingClass,
PackageDoc containingPackage,
ClassDoc[] importedClasses,
PackageDoc[] importedPackages,
char[] source, int startIndex, int endIndex,
List importStatementList) throws ParseException, IOException {
String superclassName = "java.lang.Object";
ClassDocImpl rc=new ClassDocImpl(containingClass,
containingPackage,
importedClasses,
importedPackages,
null);
rc.setImportStatementList(importStatementList);
List implementedInterfaces = new ArrayList();
String word="";
int item=0;
final int STATE_NORMAL = 1;
final int STATE_SLASHC = 2;
final int STATE_STARC = 3;
final int STATE_ANNO = 4;
int state=STATE_NORMAL;
int varLevel=0;
int parLevel=0;
char prev=0;
for (int ndx=startIndex; ndx<=endIndex; ++ndx) {
char c=(ndx==endIndex)?10:source[ndx];
boolean processWord=false;
if (state==STATE_SLASHC) {
if (c=='\n') {
state=STATE_NORMAL;
c=0;
}
}
else if (state==STATE_STARC) {
if (c=='/' && prev=='*') {
state=STATE_NORMAL;
c=0;
}
}
else {
if (c=='/' && prev=='/') {
state=STATE_SLASHC;
c=0;
word=word.substring(0,word.length()-1);
processWord=true;
}
else if (c=='*' && prev=='/') {
state=STATE_STARC;
c=0;
word=word.substring(0,word.length()-1);
processWord=true;
}
else if (c=='@') {
state=STATE_ANNO;
word += c;
}
else if (c=='(' && state==STATE_ANNO) {
++parLevel;
word += c;
}
else if (c==')' && state==STATE_ANNO) {
--parLevel;
word += c;
if (parLevel == 0)
state=STATE_NORMAL;
}
else if (c=='<')
{
++varLevel;
word += c;
}
else if (c=='>')
{
--varLevel;
word += c;
}
else if (c=='{' && parLevel == 0 ||
c==',' && varLevel == 0 && parLevel == 0 ||
Parser.WHITESPACE.indexOf(c)>=0 && parLevel == 0 && varLevel == 0) {
processWord=true;
state=STATE_NORMAL;
}
else {
word+=c;
}
if (processWord && word.length()>0) {
if (item==0) {
if (rc.processModifier(word)) {
}
else if (word.equals("abstract")) {
rc.setIsAbstract(true);
}
else if (word.equals("class")) {
rc.setIsInterface(false);
item=1;
}
else if (word.equals("enum"))
{
rc.setIsEnum(true);
item = 1;
}
else if (word.equals("interface")) {
rc.setIsInterface(true);
item=1;
}
else if (word.equals("@interface")) {
rc.setIsInterface(true);
rc.setIsAnnotation(true);
item=1;
}
else if (word.equals("strictfp")) {
}
else {
Main.getRootDoc().printWarning("unknown modifier '"+word+"'");
}
}
else if (word.equals("extends") && !rc.isAnnotation()) {
if (rc.isInterface()) {
item=3;
}
else {
item=2;
}
}
else if (word.equals("implements") && !rc.isAnnotation()) {
item=3;
}
else if (item==1) {
int parameterIndex = word.indexOf("<");
if (parameterIndex == -1)
rc.setClass(word);
else
{
rc.setClass(word.substring(0, parameterIndex));
parseTypeVariables(rc,word.substring(parameterIndex,
word.length()));
}
}
else if (item==2) {
//Debug.log(9,"setting baseclass of "+rc+" to "+word);
int parameterIndex = word.indexOf("<");
if (parameterIndex == -1)
superclassName=word;
else
{
/* FIXME: Parse type parameters */
superclassName=word.substring(0,parameterIndex);
}
}
else if (item==3) {
int parameterIndex = word.indexOf("<");
if (parameterIndex == -1)
implementedInterfaces.add(word);
else
{
/* FIXME: Parse type parameters */
implementedInterfaces.add(word.substring(0,parameterIndex));
}
}
word="";
}
if (c=='{' && state==STATE_NORMAL) break;
}
prev=c;
}
if (null != containingClass
&& containingClass.isInterface()) {
rc.accessLevel = ACCESS_PUBLIC;
}
if (rc.name()==null) {
throw new ParseException("No classdef found in expression \""+new String(source,startIndex,endIndex-startIndex)+"\"");
}
rc.setPosition(ClassDocImpl.getPosition(rc, source, startIndex));
ClassDoc superclassProxy=new ClassDocProxy(superclassName, rc);
if (!rc.qualifiedName().equals("java.lang.Object")) {
rc.setSuperclass(superclassProxy);
}
ClassDoc[] interfaces=new ClassDoc[implementedInterfaces.size()];
for (int i=0; i<interfaces.length; ++i) {
interfaces[i]=new ClassDocProxy((String)implementedInterfaces.get(i), rc);
}
rc.setInterfaces(interfaces);
if (rc.isInterface() && rc.containingClass()!=null) {
rc.setIsStatic(true);
}
return rc;
}
public void setFields(FieldDoc[] fields) {
this.unfilteredFields=fields;
}
public void setFilteredFields(FieldDoc[] fields) {
this.filteredFields=fields;
}
public void setSerializableFields(FieldDoc[] sfields) {
this.serializableFields=sfields;
}
public void setMethods(MethodDoc[] methods) {
this.unfilteredMethods=methods;
}
public void setFilteredMethods(MethodDoc[] methods) {
this.filteredMethods=methods;
}
public void setConstructors(ConstructorDoc[] constructors) {
this.unfilteredConstructors=constructors;
}
public void setFilteredConstructors(ConstructorDoc[] constructors) {
this.filteredConstructors=constructors;
}
// Returns the name of this Doc item.
public String name() {
if (containingClass==null) {
return className;
}
else {
return containingClass.name()+"."+className;
}
}
public String getClassName() {
return className;
}
public void setClass(String className) {
this.className=className;
}
void setSuperclass(ClassDoc superclass) {
this.superclass=superclass;
}
public void resolve() throws ParseException {
if (!resolved) {
resolved=true;
if (containingClass!=null)
((ClassDocImpl)containingClass).resolve();
//Debug.log(9,"resolving class '"+qualifiedName()+"'");
/*
for (int i=0; i<importedPackages.length; ++i) {
Debug.log(9,"class "+qualifiedName()+" imports "+importedPackages[i].name());
}
*/
if (superclass instanceof ClassDocProxy) {
ClassDoc realClassDoc=findClass(superclass.qualifiedName());
if (realClassDoc==null) {
/*
if (true) { // Main.recursiveClasses) {
throw new ParseException("In class '"+qualifiedName()+"': class '"+className+"' not found.");
}
*/
}
else {
superclass=realClassDoc;
}
}
if (null != interfaces) {
for (int i=0; i<interfaces.length; ++i) {
if (interfaces[i] instanceof ClassDocProxy) {
//Debug.log(9,"class "+qualifiedName()+" implements "+interfaces[i].qualifiedName());
ClassDoc realClassDoc=findClass(interfaces[i].qualifiedName());
if (realClassDoc==null) {
/*
if (Main.recursiveClasses) {
throw new ParseException("In class '"+qualifiedName()+"': class '"+className+"' not found.");
}
*/
}
else {
//Debug.log(9,"found class '"+className+"': "+interfaces[i]);
interfaces[i]=realClassDoc;
}
}
}
}
if (unfilteredFields!=null) {
for (int i=0; i<unfilteredFields.length; ++i) {
((FieldDocImpl)unfilteredFields[i]).resolve();
if (unfilteredFields[i].name().equals("serialPersistentField")) {
serialPersistentField=new FieldDoc[]{unfilteredFields[i]};
definesSerializableFields=true;
}
}
}
if (unfilteredMethods!=null) {
for (int i=0; i<unfilteredMethods.length; ++i) {
((MethodDocImpl)unfilteredMethods[i]).resolve();
}
}
if (unfilteredConstructors!=null) {
for (int i=0; i<unfilteredConstructors.length; ++i) {
((ConstructorDocImpl)unfilteredConstructors[i]).resolve();
}
}
List isSerMethodList=new ArrayList();
if (null != maybeSerMethodList) {
for (Iterator it=maybeSerMethodList.iterator(); it.hasNext(); ) {
MethodDocImpl method=(MethodDocImpl)it.next();
method.resolve();
if (((method.name().equals("readObject")
&& method.signature().equals("(java.io.ObjectInputStream)"))
|| (method.name().equals("writeObject")
&& method.signature().equals("(java.io.ObjectOutputStream)"))
|| (method.name().equals("readExternal")
&& method.signature().equals("(java.io.ObjectInput)"))
|| (method.name().equals("writeExternal")
&& method.signature().equals("(java.io.ObjectOutput)"))
|| (method.name().equals("readResolve")
&& method.signature().equals("()")))) {
isSerMethodList.add(method);
}
}
this.serializationMethods=(MethodDoc[])isSerMethodList.toArray(new MethodDoc[0]);
maybeSerMethodList=null;
}
}
}
public FieldDoc findFieldRec(String name) {
return findFieldRec(this, name);
}
private static FieldDoc findFieldRec(ClassDoc classDoc, String name)
{
FieldDoc field = findField(classDoc, name);
if (null!=field) {
return field;
}
else {
ClassDoc[] interfaces = classDoc.interfaces();
for (int i=0; i<interfaces.length; ++i) {
field = findFieldRec(interfaces[i], name);
if (null != field) {
return field;
}
}
if (null != classDoc.superclass()) {
return findFieldRec(classDoc.superclass(), name);
}
else {
return null;
}
}
}
private static FieldDoc findField(ClassDoc classDoc, String name)
{
FieldDoc[] fields = classDoc.fields(false);
for (int i=0; i<fields.length; ++i) {
if (fields[i].name().equals(name)) {
return fields[i];
}
}
return null;
}
public FieldDoc findField(String fieldName) {
for (int i=0; i<filteredFields.length; ++i) {
if (filteredFields[i].name().equals(fieldName)) {
return filteredFields[i];
}
}
return null;
}
public void resolveComments() {
super.resolveComments();
if (null != unfilteredFields) {
for (int i=0; i<unfilteredFields.length; ++i) {
((FieldDocImpl)unfilteredFields[i]).resolveComments();
}
}
if (null != serializableFields) {
for (int i=0; i<serializableFields.length; ++i) {
((FieldDocImpl)serializableFields[i]).resolveComments();
}
}
if (null != unfilteredMethods) {
for (int i=0; i<unfilteredMethods.length; ++i) {
((MethodDocImpl)unfilteredMethods[i]).resolveComments();
}
}
if (null != unfilteredConstructors) {
for (int i=0; i<unfilteredConstructors.length; ++i) {
((ConstructorDocImpl)unfilteredConstructors[i]).resolveComments();
}
}
resolveTags();
}
private String className=null;
private boolean isAbstract;
private boolean isInterface;
private boolean isAnnotation;
private boolean isEnum;
private ClassDoc[] interfaces;
private ClassDoc[] filteredInnerClasses;
private ClassDoc[] unfilteredInnerClasses;
private FieldDoc[] filteredFields;
private FieldDoc[] unfilteredFields;
private FieldDoc[] serializableFields;
private MethodDoc[] filteredMethods;
private MethodDoc[] unfilteredMethods;
private ConstructorDoc[] filteredConstructors;
private ConstructorDoc[] unfilteredConstructors;
private TypeVariable[] typeParameters;
private boolean resolved=false;
private ClassDoc superclass;
// Is this Doc item a class.
public boolean isClass() {
return !isInterface;
}
// return true if this Doc is include in the active set.
public boolean isIncluded() {
if (this == baseClassDoc) {
return isIncluded
|| (null != containingClass && Main.getInstance().includeAccessLevel(accessLevel));
}
else {
return baseClassDoc.isIncluded();
}
}
void setIsIncluded(boolean b) {
this.isIncluded=b;
}
private boolean isIncluded=false;
void setImportedClasses(ClassDoc[] importedClasses) {
this.importedClasses=importedClasses;
}
private static Map typeMap = new HashMap();
Type typeForString(String typeName) throws ParseException {
String orgTypename=typeName;
int ndx=typeName.indexOf('[');
String dim="";
if (ndx>=0) {
for (int i=ndx; i<typeName.length(); ++i) {
if ("[]".indexOf(typeName.charAt(i))>=0) {
dim+=typeName.charAt(i);
}
}
typeName=typeName.substring(0,ndx).trim();
}
ClassDoc classDoc = findClass(typeName, dim);
if (null != classDoc) {
return classDoc;
}
Type type = (Type)typeMap.get(typeName+dim);
if (null!=type) {
try {
if (type.dimension().equals(dim)) {
return type;
}
else {
Type rc = (Type) ((WritableType)type).clone();
((WritableType)rc).setDimension(dim);
return rc;
}
}
catch (CloneNotSupportedException e) {
throw new ParseException(e.toString());
}
}
if ("boolean".equals(typeName)
|| "char".equals(typeName)
|| "byte".equals(typeName)
|| "short".equals(typeName)
|| "int".equals(typeName)
|| "long".equals(typeName)
|| "void".equals(typeName)
|| "float".equals(typeName)
|| "double".equals(typeName)) {
Type rc=new TypeImpl(null, typeName, dim);
typeMap.put(typeName+dim, rc);
return rc;
}
if (Main.getInstance().isDocletRunning()) {
//System.err.println(findClass("java.lang.String"));
//throw new ParseException("Doclet running, class not found: "+typeName+" ("+orgTypename+")");
}
Type rc=new ClassDocProxy(typeName, this);
((WritableType)rc).setDimension(dim);
return rc;
}
public boolean isException() {
for (ClassDoc cdi=this;
cdi!=null;
cdi=cdi.superclass()) {
if ("java.lang.Exception".equals(cdi.qualifiedName()))
return true;
}
return false;
}
public boolean isError() {
for (ClassDoc cdi=this; cdi!=null; cdi=cdi.superclass()) {
if ("java.lang.Error".equals(cdi.qualifiedName()))
return true;
}
return false;
}
public boolean isOrdinaryClass() {
return !isException() && !isError() && !isInterface();
}
public void setIsInterface(boolean b) {
this.isInterface=b;
}
public void setIsAnnotation(boolean b) {
this.isAnnotation=b;
}
public void setIsEnum(boolean b)
{
isEnum = b;
}
public ExecutableMemberDoc findExecutableRec(String nameAndSignature) {
ExecutableMemberDoc rc;
for (ClassDoc cdi=this; cdi!=null; ) {
rc=findMethod(cdi, nameAndSignature);
if (rc!=null) return rc;
rc=findConstructor(cdi, nameAndSignature);
if (rc!=null) return rc;
ClassDoc _superclass = cdi.superclass();
if (null == _superclass) {
break;
}
else {
cdi = _superclass;
}
}
return null;
}
public static ConstructorDoc findConstructor(ClassDoc classDoc, String nameAndSignature) {
int ndx=nameAndSignature.indexOf('(');
if (ndx<=0)
return null;
else {
String fullSignature = resolveSignature(classDoc, nameAndSignature.substring(ndx));
return findConstructor(classDoc,
nameAndSignature.substring(0,ndx),
fullSignature);
}
}
public static ConstructorDoc findConstructor(ClassDoc classDoc, String name, String signature) {
ConstructorDoc[] filteredConstructors = classDoc.constructors(true);
if (null != filteredConstructors) {
for (int i=0; i<filteredConstructors.length; ++i) {
ConstructorDoc constructor = filteredConstructors[i];
if (constructor.name().equals(name) && constructor.signature().equals(signature))
return constructor;
}
}
return null;
}
public static MethodDoc findMethod(ClassDoc classDoc, String nameAndSignature) {
int ndx=nameAndSignature.indexOf('(');
if (ndx<=0) {
return null;
}
else {
String name = nameAndSignature.substring(0,ndx);
String fullSignature = resolveSignature(classDoc, nameAndSignature.substring(ndx));
return findMethod(classDoc, name, fullSignature);
}
}
private static String resolveSignature(ClassDoc classDoc, String signature)
{
signature = signature.substring(1, signature.length() - 1).trim();
if (0 == signature.length()) {
return "()";
}
StringTokenizer st = new StringTokenizer(signature, ",");
StringBuffer fullSignature = new StringBuffer("(");
while (st.hasMoreTokens()) {
String type = st.nextToken().trim();
int ndx = type.length();
while (ndx > 0 && type.charAt(ndx - 1) == '[' || type.charAt(ndx - 1) == ']') {
-- ndx;
}
String dim = type.substring(ndx);
type = type.substring(0, ndx);
ClassDoc typeClass = classDoc.findClass(type);
if (fullSignature.length() > 1) {
fullSignature.append(",");
}
if (null != typeClass) {
fullSignature.append(typeClass.qualifiedName());
}
else {
fullSignature.append(type);
}
fullSignature.append(dim);
}
fullSignature.append(')');
return fullSignature.toString();
}
public static MethodDoc findMethod(ClassDoc classDoc, String name, String signature) {
MethodDoc[] filteredMethods = classDoc.methods(true);
if (null != filteredMethods) {
for (int i=0; i<filteredMethods.length; ++i) {
MethodDoc method = filteredMethods[i];
if (method.name().equals(name) && method.signature().equals(signature))
return method;
}
}
return null;
}
public boolean equals(Object o) {
return (o!=null) && (o instanceof ClassDoc) && ((ClassDoc)o).qualifiedName().equals(qualifiedName());
}
private List maybeSerMethodList;
void setMaybeSerMethodList(List maybeSerMethodList) {
this.maybeSerMethodList=maybeSerMethodList;
}
public void setDimension(String dimension) {
this.dimension = dimension;
}
public Object clone() throws CloneNotSupportedException {
ClassDocImpl result = (ClassDocImpl)super.clone();
result.baseClassDoc = baseClassDoc;
return result;
}
public int superHashCode()
{
return super.hashCode();
}
public int hashCode()
{
return qualifiedTypeName().hashCode();
}
public ClassDoc getBaseClassDoc()
{
return baseClassDoc;
}
public FieldDoc getFieldDoc(String name)
{
for (int i=0; i<unfilteredFields.length; ++i) {
if (name.equals(unfilteredFields[i].name())) {
return unfilteredFields[i];
}
}
return null;
}
public MethodDoc getMethodDoc(String name, String signature)
{
for (int i=0; i<unfilteredMethods.length; ++i) {
if (name.equals(unfilteredMethods[i].name())
&& signature.equals(unfilteredMethods[i].signature())) {
return unfilteredMethods[i];
}
}
return null;
}
public ConstructorDoc getConstructorDoc(String signature)
{
for (int i=0; i<unfilteredConstructors.length; ++i) {
if (signature.equals(unfilteredConstructors[i].signature())) {
return unfilteredConstructors[i];
}
}
return null;
}
private Object findFieldValue(String identifier,
ClassDoc classDoc,
String fieldName,
Set visitedFields)
throws UnknownIdentifierException, IllegalExpressionException
{
while (classDoc != null) {
if (classDoc instanceof ClassDocImpl) {
FieldDocImpl fieldDoc
= (FieldDocImpl)((ClassDocImpl)classDoc).getFieldDoc(fieldName);
if (visitedFields.contains(fieldDoc)) {
throw new CircularExpressionException("Circular reference detected");
}
else if (null != fieldDoc) {
return fieldDoc.constantValue(visitedFields);
}
}
else {
ClassDoc[] _interfaces = classDoc.interfaces();
if (null != _interfaces) {
for (int i=0; i<_interfaces.length; ++i) {
if (_interfaces[i] instanceof ClassDocImpl) {
FieldDocImpl fieldDoc
= (FieldDocImpl)((ClassDocImpl)_interfaces[i]).getFieldDoc(fieldName);
if (visitedFields.contains(fieldDoc)) {
throw new CircularExpressionException("Circular reference detected");
}
else if (null != fieldDoc) {
return fieldDoc.constantValue(visitedFields);
}
}
}
}
}
classDoc = classDoc.superclass();
}
throw new UnknownIdentifierException(identifier);
}
public Object getValue(String identifier, Set visitedFields)
throws UnknownIdentifierException, IllegalExpressionException
{
int ndx = identifier.lastIndexOf('.');
if (ndx >= 0) {
String _className = identifier.substring(0, ndx);
String _fieldName = identifier.substring(ndx + 1);
ClassDoc _classDoc = findClass(_className);
if (null != _classDoc) {
return findFieldValue(identifier, _classDoc, _fieldName, visitedFields);
}
else {
throw new UnknownIdentifierException(identifier);
}
}
else {
return findFieldValue(identifier, this, identifier, visitedFields);
}
}
public boolean isPrimitive()
{
return false;
}
// Compares this Object with the specified Object for order.
public int compareTo(java.lang.Object o) {
int rc;
if (o instanceof ClassDocImpl) {
ClassDocImpl c1 = this;
ClassDocImpl c2 = (ClassDocImpl)o;
if (null != c1.containingClass() && null == c2.containingClass()) {
rc = c1.containingClass().compareTo(c2);
if (0 == rc) {
rc = 1;
}
return rc;
}
else if (null == c1.containingClass() && null != c2.containingClass()) {
rc = c1.compareTo(c2.containingClass());
if (0 == rc) {
rc = -1;
}
return rc;
}
else if (null != c1.containingClass() && null != c2.containingClass()) {
rc = c1.containingClass().compareTo(c2.containingClass());
if (0 != rc) {
return rc;
}
}
rc = super.compareTo(o);
if (0 == rc) {
return Main.getInstance().getCollator().compare(containingPackage().name(),
((ClassDocImpl)o).containingPackage().name());
}
else {
return rc;
}
}
else {
return 1;
}
}
private List importStatementList;
public void setImportStatementList(List importStatementList)
{
this.importStatementList = new LinkedList();
this.importStatementList.addAll(importStatementList);
}
public List getImportSpecifierList()
{
return importStatementList;
}
public TypeVariable[] typeParameters()
{
return typeParameters;
}
/**
* <p>
* Parses the type variables declared in the class definition.
* The syntax is:
* </p>
* <p>
* <dl>
* <dt>TypeParameters:</dt>
* <dd><code>< <em>TypeParameter</em> { <em>, TypeParameter }</code></dd>
* <dt>TypeParameter:</dt>
* <dd><code><em>Identifier</em> { <strong>extends</strong> <em>Bound</em>
* }</dd>
* <dt>Bound:</dt>
* <dd><code><em>Type</em>{<strong>&</strong> <em>Type</em> } </dd>
* </dl>
*
* @param rc the owning class.
* @param typeVariables the string to be parsed.
* @throws ParseException if parsing fails.
*/
public static void parseTypeVariables(ClassDocImpl rc,
String typeVariables)
throws ParseException
{
List parsedBounds = null;
StringTokenizer parameters = new StringTokenizer(typeVariables,
Parser.WHITESPACE +
"<>,");
List variables = new ArrayList();
while (parameters.hasMoreTokens())
{
String parameter = parameters.nextToken();
StringTokenizer parts = new StringTokenizer(parameter,
Parser.WHITESPACE);
TypeVariableImpl variable = new TypeVariableImpl(rc.qualifiedName(),
parts.nextToken(),"",
rc);
if (parts.hasMoreTokens())
{
if (!parts.nextToken().equals("extends"))
throw new ParseException("Invalid type parameter: " + parameter);
StringTokenizer bounds = new StringTokenizer(parts.nextToken(),
Parser.WHITESPACE
+ "&");
parsedBounds = new ArrayList();
while (bounds.hasMoreTokens())
{
String bound = bounds.nextToken();
int nameSep = bound.lastIndexOf(".");
String packageName = bound.substring(0, nameSep);
String boundName = bound.substring(nameSep, bound.length());
parsedBounds.add(new TypeImpl(packageName,boundName,""));
}
}
if (parsedBounds != null)
variable.setBounds(parsedBounds);
variables.add(variable);
}
rc.setTypeParameters(variables);
}
/**
* Set the type parameters to the contents of the supplied list.
*
* @param variables a list of type parameters.
*/
void setTypeParameters(List variables)
{
typeParameters =
(TypeVariable[]) variables.toArray(new TypeVariable[variables.size()]);
}
}