/*******************************************************************************
* Copyright (c) 2002,2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package x10.sncode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
/**
* This is the core class for reading class file data.
*
* ClassReader performs lazy parsing, and thus most of the methods can throw an
* InvalidClassFileException.
*/
public final class ClassEditor extends MemberEditor implements SnConstants {
public final static int INV = 0;
public final static int COV = 1;
public final static int CONTRAV = -1;
/** List of fields */
List<FieldEditor> fields;
/** List of methods */
List<MethodEditor> methods;
/** List of constructors */
List<ConstructorEditor> constructors;
/** List of typedefs */
List<TypedefEditor> typedefs;
/** List of member classes */
List<ClassEditor> memberClasses;
String packageName;
Type superClass;
List<Type> interfaces;
List<Type> typeFormals;
List<Type> typeActuals;
List<Constraint> typeActualConstraints;
List<Integer> variances;
Constraint classInvariant;
public ClassEditor() {
interfaces = new ArrayList<Type>(0);
typeFormals = new ArrayList<Type>(0);
typeActuals = new ArrayList<Type>(0);
typeActualConstraints = new ArrayList<Constraint>(0);
variances = new ArrayList<Integer>(0);
fields = new ArrayList<FieldEditor>(1);
methods = new ArrayList<MethodEditor>(1);
constructors = new ArrayList<ConstructorEditor>(1);
typedefs = new ArrayList<TypedefEditor>(1);
memberClasses = new ArrayList<ClassEditor>(1);
attributes = new ArrayList<Tree>(1);
}
public String getPackageName() {
return packageName;
}
public void setPackage(String pkg) {
packageName = pkg;
}
public void setSuperClass(Type t) {
superClass = t;
}
public Type getSuperClass() throws InvalidClassFileException {
return superClass;
}
public void addInterface(Type t) {
interfaces.add(t);
}
public List<Type> getInterfaces() {
return interfaces;
}
public void addTypeFormal(Type t, int variance) {
typeFormals.add(t);
variances.add(variance);
}
public List<Type> getTypeFormals() {
return typeFormals;
}
public void addTypeActual(Type t) {
typeActuals.add(t);
}
public List<Type> getTypeActuals() {
return typeActuals;
}
public void addTypeActualConstraint(Constraint c) {
typeActualConstraints.add(c);
}
public List<Constraint> getTypeActualConstraints() {
return typeActualConstraints;
}
public Constraint getClassInvariant() {
return classInvariant;
}
public void setClassInvariant(Constraint t) {
classInvariant = t;
}
public List<FieldEditor> fields() {
return fields;
}
public List<MethodEditor> methods() {
return methods;
}
public List<ConstructorEditor> constructors() {
return constructors;
}
public List<TypedefEditor> typedefs() {
return typedefs;
}
public List<ClassEditor> memberClasses() {
return memberClasses;
}
List toList(Object o) throws InvalidClassFileException {
if (o instanceof Object[])
return Arrays.asList((Object[]) o);
throw new InvalidClassFileException(0, "bad array " + o);
}
public void readFrom(final SnFile sn, Tree tree) throws InvalidClassFileException {
name = (String) tree.find("Name");
typeFormals = (List) toList(tree.find("TypeFormals"));
variances = (List) toList(tree.find("Variances"));
typeActuals = (List) toList(tree.find("TypeActuals"));
typeActualConstraints = (List) toList(tree.find("TypeActualConstraints"));
classInvariant = (Constraint) tree.find("ClassInvariant");
superClass = (Type) tree.find("SuperClass");
interfaces = (List<Type>) toList(tree.find("Interfaces"));
typedefs = mapList(tree.findAll("Typedef"), new Mapper<Tree, TypedefEditor, InvalidClassFileException>() {
TypedefEditor map(Tree t) throws InvalidClassFileException {
TypedefEditor e = new TypedefEditor();
e.readFrom(sn, t);
return e;
}
});
fields = mapList(tree.findAll("Field"), new Mapper<Tree, FieldEditor, InvalidClassFileException>() {
FieldEditor map(Tree t) throws InvalidClassFileException {
FieldEditor e = new FieldEditor();
e.readFrom(sn, t);
return e;
}
});
methods = mapList(tree.findAll("Method"), new Mapper<Tree, MethodEditor, InvalidClassFileException>() {
MethodEditor map(Tree t) throws InvalidClassFileException {
MethodEditor e = new MethodEditor();
e.readFrom(sn, t);
return e;
}
});
constructors = mapList(tree.findAll("Constructor"), new Mapper<Tree, ConstructorEditor, InvalidClassFileException>() {
ConstructorEditor map(Tree t) throws InvalidClassFileException {
ConstructorEditor e = new ConstructorEditor();
e.readFrom(sn, t);
return e;
}
});
memberClasses = mapList(tree.findAll("Class"), new Mapper<Tree, ClassEditor, InvalidClassFileException>() {
ClassEditor map(Tree t) throws InvalidClassFileException {
ClassEditor e = new ClassEditor();
e.readFrom(sn, t);
return e;
}
});
String[] keys = new String[] { "Name", "TypeFormals", "TypeActuals", "TypeActualConstraints", "ClassInvariant",
"SuperClass", "Interfaces", "Field", "Method", "Constructor", "Typedef", "Class" };
attributes = new ArrayList<Tree>(tree.getChildren().size());
for (Iterator<Tree> i = tree.getChildren().iterator(); i.hasNext();) {
Tree ti = i.next();
if (Arrays.asList(keys).contains(ti.key))
;
else
attributes.add(ti);
}
}
public Tree makeTree() {
Tree.Branch t = new Tree.Branch("Class",
new Tree.Leaf("Package", packageName),
new Tree.Leaf("Name", name),
new Tree.Leaf("TypeFormals", SnFile.nonnull(typeFormals).toArray(new Type[0])),
new Tree.Leaf("Variances", SnFile.nonnull(variances).toArray(new Integer[0])),
new Tree.Leaf("TypeActuals", SnFile.nonnull(typeActuals).toArray(new Type[0])),
new Tree.Leaf("TypeActualConstraints", SnFile.nonnull(typeActualConstraints).toArray(new Constraint[0])),
new Tree.Leaf("ClassInvariant", classInvariant), new Tree.Leaf("SuperClass", superClass),
new Tree.Leaf("Interfaces", SnFile.nonnull(interfaces).toArray(new Type[0])));
for (FieldEditor f : fields) {
t.add(f.makeTree());
}
for (MethodEditor m : methods) {
t.add(m.makeTree());
}
for (ConstructorEditor c : constructors) {
t.add(c.makeTree());
}
for (ProcEditor d : typedefs) {
t.add(d.makeTree());
}
for (ClassEditor c : memberClasses) {
t.add(c.makeTree());
}
for (Tree a : attributes) {
t.add(a);
}
return t;
}
public List<Integer> getTypeFormalVariances() {
return variances;
}
}