package jadex.javaparser.javaccimpl;
import jadex.commons.SReflect;
import jadex.javaparser.IValueFetcher;
import java.lang.reflect.Array;
/**
* A node representing an array to create.
*/
public class ArrayNode extends ExpressionNode
{
//-------- constants --------
/** The array with content constructor. */
public static final int ARRAY = 1;
/** The empty array constructor. */
public static final int ARRAY_DIMENSION = 2;
//-------- attributes --------
/** The node type. */
protected int type;
//-------- constructors --------
/**
* Create an expression node.
* @param p The parser.
* @param id The id.
*/
public ArrayNode(ParserImpl p, int id)
{
super(p, id);
}
//-------- attribute accessors --------
/**
* Set the node type.
* @param type The node type.
*/
public void setType(int type)
{
this.type = type;
}
/**
* Get the node type.
* @return The node type.
*/
public int getType()
{
return this.type;
}
//-------- evaluation --------
/**
* Precompute type, and perform checks.
*/
public void precompile()
{
// Check number of children and node type.
if( !(jjtGetNumChildren()==2))
{
throw new ParseException("Wrong number of child nodes: "+this);
}
else if(type!=ARRAY && type!=ARRAY_DIMENSION)
{
throw new ParseException("Unknown node type "+type+": "+this);
}
// Get child nodes.
ExpressionNode typenode = (ExpressionNode)jjtGetChild(0);
ExpressionNode argsnode = (ExpressionNode)jjtGetChild(1);
// Precompute type.
Class clazz = null;
if(typenode.isConstant())
{
try
{
clazz = (Class)typenode.getValue(null);
setStaticType(clazz);
}
catch(Exception e)
{
}
}
// Array: Check content types.
if(type==ARRAY && clazz!=null)
{
// Check for array type.
if(clazz.getComponentType()==null)
{
throw new ParseException("Type not array: "+this);
}
for(int i=0; i<argsnode.jjtGetNumChildren(); i++)
{
ExpressionNode node = (ExpressionNode)argsnode.jjtGetChild(i);
if(node.getStaticType()!=null && !SReflect.isSupertype(
clazz.getComponentType(), node.getStaticType()))
{
throw new ParseException("Content does not match array type: "+this);
}
}
}
// Array Dimension: Check for integer.
else if(type==ARRAY_DIMENSION)
{
for(int i=0; i<argsnode.jjtGetNumChildren(); i++)
{
ExpressionNode node = (ExpressionNode)argsnode.jjtGetChild(i);
if(node.getStaticType()!=null && !SReflect
.isSupertype(Integer.class, node.getStaticType()))
{
throw new ParseException("Dimension specification must be int: "+this);
}
}
}
}
/**
* Evaluate the expression in the given state
* with respect to given parameters.
* @param params The parameters (string, value pairs), if any.
* @return The value of the term.
*/
public Object getValue(IValueFetcher fetcher) //throws Exception
{
// Get child nodes.
ExpressionNode typenode = (ExpressionNode)jjtGetChild(0);
ExpressionNode argsnode = (ExpressionNode)jjtGetChild(1);
Class clazz = (Class)typenode.getValue(fetcher);
Object value = null;
// Array with content.
if(type==ARRAY)
{
// Check for array type.
if(clazz.getComponentType()==null)
{
throw new RuntimeException("Type not array: "+this);
}
value = Array.newInstance(clazz.getComponentType(), argsnode.jjtGetNumChildren());
for(int i=0; i<argsnode.jjtGetNumChildren(); i++)
{
ExpressionNode node = (ExpressionNode)argsnode.jjtGetChild(i);
Object val = node.getValue(fetcher);
if(val!=null && !SReflect.isSupertype(
clazz.getComponentType(), val.getClass()))
{
throw new RuntimeException("Content does not match array type: "+this);
}
else if(val==null && clazz.getComponentType().isPrimitive())
{
throw new RuntimeException("Cannot put null into basic type array: "+this);
}
Array.set(value, i, val);
}
}
// Array Dimension: Check for integer.
else if(type==ARRAY_DIMENSION)
{
int[] dims = new int[argsnode.jjtGetNumChildren()];
for(int i=0; i<argsnode.jjtGetNumChildren(); i++)
{
clazz = clazz.getComponentType();
ExpressionNode node = (ExpressionNode)argsnode.jjtGetChild(i);
Object val = node.getValue(fetcher);
if(!(val instanceof Number))
{
throw new ParseException("Dimension specification must be int: "+this);
}
dims[i] = ((Number)val).intValue();
}
value = Array.newInstance(clazz, dims);
}
return value;
}
/**
* Create a string representation of this node and its subnodes.
* @return A string representation of this node.
*/
public String toPlainString()
{
String ret = "new " + jjtGetChild(0).toPlainString();
Node argsnode = jjtGetChild(1);
if(type==ARRAY)
{
// Append array content.
ret += "{";
for(int i=0; i<argsnode.jjtGetNumChildren(); i++)
{
ret += argsnode.jjtGetChild(i).toPlainString();
if(i<argsnode.jjtGetNumChildren()-1)
{
ret += ", ";
}
}
ret += "}";
}
else // if(type==ARRAY_DIMENSION)
{
// Fill in dimension specifications.
int idx = ret.indexOf("[");
int dims = ret.substring(idx).length()/2;
ret = ret.substring(0, idx);
for(int i=0; i<dims; i++)
{
ret += "[";
if(i<argsnode.jjtGetNumChildren())
{
ret += argsnode.jjtGetChild(i).toPlainString();
}
ret += "]";
}
}
return ret;
}
}