package xtc.translator.representation;
import java.util.List;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import xtc.translator.translation.CppPrinter;
import xtc.tree.GNode;
import xtc.tree.Node;
import xtc.tree.Visitor;
/**
* Visitor subclass which visits a single java Class, and extracts all neccesary
* data from it, to be processed later.
*
*/
public class ClassVisitor extends BaseVisitor implements Cloneable {
private Node sourceNode;
private String identifier;
private List<String> extensions;
private String extension;
private ClassVisitor superClass;
private List<String> modifiers;
private List<ConstructorVisitor> constructorList;
private List<FieldVisitor> fieldList;
private List<MethodVisitor> methodList;
private Map<String, String> implementationMap;
private Map<String, List<Method>> overloadMap;
private ArrayList<FieldVisitor> inheritedFields;
private String packageName;
private List<String> imports;
private ArrayList<String> usedClasses;
public ClassVisitor() {
this.extension = "";
this.extensions = new ArrayList<String>();
this.modifiers = new ArrayList<String>();
this.fieldList = new ArrayList<FieldVisitor>();
this.constructorList = new ArrayList<ConstructorVisitor>();
this.methodList = new ArrayList<MethodVisitor>();
this.implementationMap = new HashMap<String, String>();
this.superClass = null;
this.usedClasses = new ArrayList<String>();
this.imports = new ArrayList<String>();
this.inheritedFields = new ArrayList<FieldVisitor>();
this.overloadMap = new HashMap<String, List<Method>>();
}
/**
* Assign identifier to the class and then recurse through nodes
*
* @param n
*/
public void visitClassDeclaration(GNode n) {
for (Object o : n) {
// record the class name if o is a string
if (o instanceof String) {
this.identifier = (String) o;
}
// otherwise if o is a node, dispatch it
if (GNode.test(o)) {
dispatch(GNode.cast(o));
}
}
// if after all of this ^^^ and we haven't assigned an extension, the
// class extends object
// not sure if this is the best place for it but it works
if (extensions.size() == 0) {
extension = "Object";
extensions.add("Object");
}
}
public void visitModifiers(GNode n) {
for (int i = 0; i < n.size(); i++) {
String modifier = n.getGeneric(0).getString(0);
modifiers.add(modifier);
}
}
/**
* This was a really inelegant solution to getting extensions I changed it a
* bit
*/
public void visitExtension(GNode n) {
Node identifier = n.getGeneric(0).getGeneric(0);
for (int i = 0; i < identifier.size(); i++) {
extension = identifier.getString(i);
extensions.add(identifier.getString(i));
usedClasses.add(extension);
}
}
// parse through the constructor
public void visitConstructorDeclaration(GNode n) {
ConstructorVisitor constructorVisitor = new ConstructorVisitor(n);
constructorVisitor.dispatch(n);
this.constructorList.add(constructorVisitor);
}
public void visitFieldDeclaration(GNode n) {
FieldVisitor fieldVisitor = new FieldVisitor(this);
fieldVisitor.dispatch(n);
this.fieldList.add(fieldVisitor);
}
/**
* If a Method Declaration is visited, create a new MethodVisitor, and
* dispatch it to collect all method information from the node. Add it to
* the method list when finished.
*
*/
public void visitMethodDeclaration(GNode n) {
MethodVisitor methodVisitor = new MethodVisitor(n);
methodVisitor.dispatch(n);
this.methodList.add(methodVisitor);
this.usedClasses.addAll(methodVisitor.getUsedClasses());
}
public void getVTable(CppPrinter cp) {
getVTable(cp, this, this);
}
private void getVTable(CppPrinter cp, ClassVisitor classVisitor, ClassVisitor original) {
if (classVisitor == null) {
// do nothing
} else {
getVTable(cp, classVisitor.getSuperClass(), original);
for (MethodVisitor m : classVisitor.getMethodList()) {
if (!m.isOverride() || !m.isStatic())
cp.indent().p(m.getMethodPointer(original)).pln(";");
}
}
}
public ClassVisitor copy() {
try {
ClassVisitor clone = (ClassVisitor) this.clone();
List<MethodVisitor> clonedMethodList = new ArrayList<MethodVisitor>();
// Clone methodList
for (MethodVisitor m : methodList) {
clonedMethodList.add(m.copy());
}
clone.methodList = clonedMethodList;
return clone;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return null;
}
}
@Override
public String toString() {
return "ClassVisitor [identifier=" + identifier + ", superClass="
+ superClass + ", fieldList=" + fieldList
+ ", implementationMap=" + implementationMap + ", packageName="
+ packageName + "extends: " + this.extension + "]";
}
public String getIdentifier() {
return identifier;
}
public void setIdentifier(String identifier) {
this.identifier = identifier;
}
public String getExtension() {
return extension;
}
public void setExtension(String extension) {
this.extension = extension;
}
public List<String> getExtensions() {
return extensions;
}
public void setExtensions(List<String> extensions) {
this.extensions = extensions;
}
public ClassVisitor getSuperClass() {
return superClass;
}
public void setSuperClass(ClassVisitor superClass) {
this.superClass = superClass;
}
public List<String> getModifiers() {
return modifiers;
}
public void setModifiers(List<String> modifiers) {
this.modifiers = modifiers;
}
public List<ConstructorVisitor> getConstructorList() {
return constructorList;
}
public void setConstructorList(List<ConstructorVisitor> constructorList) {
this.constructorList = constructorList;
}
public List<FieldVisitor> getFieldList() {
return fieldList;
}
public void setFieldList(List<FieldVisitor> fieldList) {
this.fieldList = fieldList;
}
public List<MethodVisitor> getMethodList() {
return methodList;
}
public void setMethodList(List<MethodVisitor> methodList) {
this.methodList = methodList;
}
public Map<String, String> getImplementationMap() {
return implementationMap;
}
public void setImplementationMap(Map<String, String> implementationMap) {
this.implementationMap = implementationMap;
}
public ArrayList<String> getUsedClasses() {
return usedClasses;
}
public String getPackageName() {
return packageName;
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
public List<String> getImports() {
return imports;
}
public void setImports(List<String> imports) {
this.imports = imports;
}
public String makeFullIdentifier() {
return packageName + "." + identifier;
}
public String getFullIdentifier() {
String full = packageName + "." + "__" + identifier;
full = full.replace(".", "::");
return full;
}
public String getFullIdentifierPointer() {
String full = packageName + "." + identifier;
full = full.replace(".", "::");
return full;
}
public Node getSourceNode() {
return sourceNode;
}
public void setSourceNode(Node sourceNode) {
this.sourceNode = sourceNode;
}
public Map<String, List<Method>> getOverloadMap() {
return overloadMap;
}
public void setOverloadMap(Map<String, List<Method>> overloadMap) {
this.overloadMap = overloadMap;
}
public ArrayList<FieldVisitor> getInheritedFields() {
return inheritedFields;
}
public void setInheritedFields(ArrayList<FieldVisitor> inheritedFields) {
this.inheritedFields = inheritedFields;
}
}