package agg.attribute.parser.javaExpr;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Vector;
import agg.attribute.handler.SymbolTable;
import agg.attribute.impl.AttrSession;
import agg.attribute.impl.VerboseControl;
/**
* @version $Id: SimpleNode.java,v 1.10 2010/09/23 08:15:01 olga Exp $
* @author $Author: olga $
*/
public class SimpleNode implements Node {
static final long serialVersionUID = 1L;
protected Node parent;
protected java.util.Vector<Node> children;
protected String identifier;
protected Object info;
private String error;
public SimpleNode(String id) {
this.identifier = id;
typeInit();
this.error = "";
}
public static Node jjtCreate(String id) {
return new SimpleNode(id);
}
public void jjtOpen() {
}
public void jjtClose() {
if (this.children != null) {
this.children.trimToSize();
}
}
public void jjtSetParent(Node n) {
this.parent = n;
}
public Node jjtGetParent() {
return this.parent;
}
public void jjtAddChild(Node n) {
if (this.children == null) {
this.children = new java.util.Vector<Node>();
}
this.children.addElement(n);
}
public Node jjtGetChild(int i) {
return this.children.elementAt(i);
}
public int jjtGetNumChildren() {
return (this.children == null) ? 0 : this.children.size();
}
/*
* These two methods provide a very simple mechanism for attaching arbitrary
* data to the node.
*/
public void setInfo(Object i) {
this.info = i;
}
public Object getInfo() {
return this.info;
}
/*
* You can override these two methods in subclasses of SimpleNode to
* customize the way the node appears when the tree is dumped. If your
* output uses more than one line you should override toString(String),
* otherwise overriding toString() is probably all you need to do.
*/
public String toString() {
Class<?> c = getNodeClass();
if (c == null) {
return this.identifier;
}
return this.identifier + " [" + c.toString() + "]";
}
public String toString(String prefix) {
return prefix + toString();
}
/*
* Override this method if you want to customize how the node dumps out its
* children.
*/
public void dump(String prefix) {
// System.out.println( toString(prefix) );
AttrSession.logPrintln(VerboseControl.logJexParser, toString(prefix));
if (this.children != null) {
for (java.util.Enumeration<Node> e = this.children.elements(); e
.hasMoreElements();) {
SimpleNode n = (SimpleNode) e.nextElement();
n.dump(prefix + " ");
}
}
}
/** *********************** Added by Sreeni. ****************** */
/** Stack for calculations. */
// protected static Object[] stack = new Object[2048]; //[1024];
protected static ArrayList<Object> stack = new ArrayList<Object>();
protected static int top = -1;
/**
* This method must be overridden from all its subclasses.
*/
public void interpret() {
// throw new Error(); /* It better not come here. */
this.error = "SimpleNode.interpret: FAILED!";
}
public String getError() {
return this.error;
}
/** *********************** Added by BM. ****************** */
/** Initialization flag */
static protected boolean neverCalled = true;
/** Symbol table */
static protected SymbolTable symtab = null;
/** Widening order for numeric types */
protected static java.util.Hashtable<Class<?>, Integer> numberTypes = new java.util.Hashtable<Class<?>, Integer>();
// /** Constructors */
// protected static java.util.Hashtable constructors = new java.util.Hashtable();
// /** Referencing methods for Operands */
// protected static java.util.Hashtable refMethods = new java.util.Hashtable();
/** String class handle for frequent comparison */
static protected Class<?> stringClass;
/** Object class handle for frequent comparison */
static protected Class<?> objectClass;
static protected void typeInit() {
if (neverCalled) {
neverCalled = false;
int codeNr = 0;
codeNr = 0;
numberTypes.put(Byte.TYPE, new Integer(codeNr++));
numberTypes.put(Short.TYPE, new Integer(codeNr++));
numberTypes.put(Long.TYPE, new Integer(codeNr++));
numberTypes.put(Integer.TYPE, new Integer(codeNr++));
numberTypes.put(Float.TYPE, new Integer(codeNr++));
numberTypes.put(Double.TYPE, new Integer(codeNr++));
try {
stringClass = Class.forName("java.lang.String");
objectClass = Class.forName("java.lang.Object");
} catch (Exception e) {
throw (RuntimeException) e;
}
}
}
/** The class handle */
private Class<?> nodeClass = null;
/** Getting the node class. */
// protected Class<?> getNodeClass(){
public Class<?> getNodeClass() {
return this.nodeClass;
}
/** Setting the node class. */
protected void setNodeClass(Class<?> nodeClass) {
this.nodeClass = nodeClass;
}
/** Setting the node class to that of the parameter node. */
protected void takeNodeClassFrom(SimpleNode node) {
setNodeClass(node.getNodeClass());
}
/** Checking if the node represents a member (method or field). */
public boolean isAction() {
return (this.identifier.equals("Action"));
}
/** Checking if the node represents a member (method or field). */
public boolean isMember() {
return (this.identifier.equals("Method") || this.identifier.equals("Action") || this.identifier
.equals("Field"));
}
/** Checking if the node represents an array index). */
public boolean isArrayIndex() {
return (this.identifier.equals("ArrayIndex"));
}
/** Checking if node's type is a number type. */
public boolean hasStringType() {
return (getNodeClass() == stringClass);
}
/** Checking if node's type is a number type. */
public boolean hasNumberType() {
return (numberTypes.containsKey(this.nodeClass));
}
/** Getting the number type code of this node object */
protected int typeCode() {
return typeCode(getNodeClass());
}
/** Getting the number type code of a primitive number type */
protected static int typeCode(Class<?> cls) {
return numberTypes.get(cls).intValue();
}
/** Widening a number type as necessary. */
protected Class<?> commonNumberType(SimpleNode n1, SimpleNode n2) {
int numType1 = numberTypes.get(n1.getNodeClass()).intValue();
int numType2 = numberTypes.get(n2.getNodeClass()).intValue();
return (numType1 > numType2 ? n1.getNodeClass() : n2.getNodeClass());
}
protected boolean isConstantExpr() {
int nChildren = jjtGetNumChildren();
SimpleNode child;
for (int i = 0; i < nChildren; i++) {
child = (SimpleNode) jjtGetChild(i);
if (!child.isConstantExpr()) {
return false;
}
}
return true;
}
/***************************************************************************
* Public Methods
**************************************************************************/
/** Obtaining the node type and checking for consistency. */
public void checkContext() {
/* It better not come here. */
// throw new Error();
this.error = "SimpleNode.checkContext FAILED!";
}
static public void setSymbolTable(SymbolTable st) {
symtab = st;
}
static public SymbolTable getSymbolTable() {
return symtab;
}
static protected ClassResolver classResolver = null;
static public void setClassResolver(ClassResolver cr) {
classResolver = cr;
}
public Object getRootResult() {
// return stack[top];
return stack.get(top);
}
/**
* returns this node as a string with all children. Subclasses must override
* this.
*/
public String getString() {
return toString();
}
/**
* Rewrites all children. This method must be overridden if any special
* handling is needed.
*
* @see ASTId#rewrite special rewriting at class ASTId
*/
public void rewrite() {
for (int i = 0; i < jjtGetNumChildren(); i++) {
this.error = "";
try {
jjtGetChild(i).interpret();
if (jjtGetChild(i).getError().length() != 0) {
// AttrSession.logPrintln(VerboseControl.logJexParser,
// " SimpleNode.rewrite : interpret FAILED!");
this.error = jjtGetChild(i).getError();
break;
}
} catch (ASTMissingValueException amve) {
jjtGetChild(i).rewrite();
}
}
}
/** Replaces a child */
public void replaceChild(Node oldChild, Node newChild) {
int pos = this.children.indexOf(oldChild);
this.children.insertElementAt(newChild, pos);
this.children.removeElement(oldChild);
}
/**
* fills the vector with the names of all variables which occur in this
* abstract syntax tree
*/
public void getAllVariablesinExpression(Vector<String> v) {
for (int i = 0; i < jjtGetNumChildren(); i++) {
jjtGetChild(i).getAllVariablesinExpression(v);
}
}
public String getIdentifier() {
return this.identifier;
}
/**
* Copys the abstract syntax tree. The information object won't be copied.
*/
public Node copy() {
Node copy = null;
/*
* Class<?> clazze = getClass(); boolean found = false; Constructor[]
* construct = clazze.getDeclaredConstructors(); int i=0; for(;i<construct.length
* &&!found; ){ Class<?>[] parameters = construct[i].getParameterTypes();
* if(parameters.length == 1){
*//*
* gesucht wir der Constructor der als Parameter nur String
* enthaelt. Die Laenge ist daher 1
*//*
* String s = parameters[0].getName(); found = (s.equals(
* "java.lang.String")); } if(!found) i++; } Object[]
* constructorParameter = new Object[1]; constructorParameter[0] =
* identifier; try{ copy =
* (Node)construct[i].newInstance(constructorParameter); }
* catch(InvocationTargetException ite){}
* catch(IllegalAccessException iae){} catch(InstantiationException
* ie){} copy.jjtSetParent(parent); ((SimpleNode) copy).info= info;
* ((SimpleNode)copy).setNodeClass( nodeClass); for(int c = 0; c<jjtGetNumChildren();
* c++){ Node child = jjtGetChild(c); Node childCopy = child.copy();
* copy.jjtAddChild(childCopy); childCopy.jjtSetParent(copy); }
*/
try {
/*
* Diese Copy-Methode sei Yang Xiang <xiang@uni-hamburg.de>
* gewidmet, der unerschrocken ueber meine Anfrage in
* de.comp.lang.java eine Stunde spaeter diese Loesung parat hatte
*/
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(out);
oos.writeObject(this);
oos.flush();
ByteArrayInputStream in = new ByteArrayInputStream(out
.toByteArray());
ObjectInputStream ois = new ObjectInputStream(in);
copy = (Node) ois.readObject();
oos.close();
ois.close();
} catch (IOException ioe) {
} catch (ClassNotFoundException cnfe) {
}
return copy;
}
}
/*
* $Log: SimpleNode.java,v $
* Revision 1.10 2010/09/23 08:15:01 olga
* tuning
*
* Revision 1.9 2010/07/29 10:09:23 olga
* Array stack changed to Vector stack
*
* Revision 1.8 2010/03/31 21:10:49 olga
* tuning
*
* Revision 1.7 2010/03/08 15:38:38 olga
* code optimizing
*
* Revision 1.6 2009/10/26 10:04:58 olga
* tuning and tests
*
* Revision 1.5 2007/11/01 09:58:17 olga
* Code refactoring: generic types- done
*
* Revision 1.4 2007/09/10 13:05:49 olga
* In this update:
* - package xerces2.5.0 is not used anymore;
* - class com.objectspace.jgl.Pair is replaced by the agg own generic class agg.util.Pair;
* - bugs fixed in: usage of PACs in rules; match completion;
* usage of static method calls in attr. conditions
* - graph editing: added some new features
* Revision 1.3 2006/12/13 13:32:58 enrico
* reimplemented code
*
* Revision 1.2 2006/01/16 09:37:01 olga Extended attr. setting
*
* Revision 1.1 2005/08/25 11:56:51 enrico *** empty log message ***
*
* Revision 1.1 2005/05/30 12:58:01 olga Version with Eclipse
*
* Revision 1.8 2005/01/28 14:02:32 olga -Fehlerbehandlung beim Typgraph check
* -Erweiterung CP GUI / CP Menu -Fehlerbehandlung mit identification option
* -Fehlerbehandlung bei Rule PAC
*
* Revision 1.7 2004/09/23 08:26:43 olga Fehler bei CPs weg, Debug output in
* file
*
* Revision 1.6 2003/10/16 08:21:13 olga Nur Tests
*
* Revision 1.5 2003/09/25 09:38:07 olga stack groesse erhoet wegen ueberlauf
*
* Revision 1.4 2003/07/21 13:18:10 olga Attrs testen
*
* Revision 1.3 2003/03/05 18:24:14 komm sorted/optimized import statements
*
* Revision 1.2 2003/01/15 11:36:00 olga Neue VerboseControl Konstante
* :logJexParser zum Testen
*
* Revision 1.1.1.1 2002/07/11 12:17:04 olga Imported sources
*
* Revision 1.8 2000/04/05 12:11:11 shultzke serialVersionUID aus V1.0.0
* generiert
*
* Revision 1.7 2000/03/14 10:59:59 shultzke Transformieren von Variablen auf
* Variablen sollte jetzt funktionieren Ueber das Design der Copy-Methode des
* abstrakten Syntaxbaumes sollte unbedingt diskutiert werden.
*
* Revision 1.6 2000/03/14 10:01:32 shultzke erste version des kopierens
*
* Revision 1.5 2000/03/03 11:32:50 shultzke Alphaversion von Variablen auf
* Variablen matchen
*/