if (expression == null)
throw new EngineException("ExpressionIsNull", "Cannot evaluate null expression");
Object value = null;
StringParser sp = new StringParser(expression);
try
{
char c;
String ident;
sp.skipSpace();
if (base != null)
{
value = base;
}
else
{
// First symbol must be an identifier denoting the object in the list
ident = sp.getIdentifier();
if (ident == null)
throw newError("Expression.IdentifierExpected", "Identifier expected in expression", sp);
// Check if this ident is continued using the "ident1\.ident2" syntax
ident = collectIdent(sp, ident);
// Get the first object
value = getBaseObject(ident);
if (value == null)
{
// Object not found in list
if ((mode & OBJECT_MUST_EXIST) != 0)
{
throw newError("Expression.ObjectNotFound", "Object '" + ident + "' does not exist", sp);
}
return null;
}
}
// Now look for member specs
for (;;)
{
// Need '.', '[' or end of string
c = sp.getChar();
if (base != null)
{
// A base object has been provided, continue with accessing its property
if (c != '-')
{
c = ExpressionConstants.MEMBER_OPERATOR_CHAR;
}
base = null;
}
else
{
if (c == 0)
break;
sp.nextChar();
}
sp.skipSpace();
if (c == '[')
{
// Index specification
ident = "[...]"; // For debug msg below only
if (value.getClass().isArray())
{
// Get the text between '[' and ']'
String indexExpr = collectIndexExpr(sp);
int pos = Integer.parseInt(indexExpr);
if (pos >= 0 && pos < Array.getLength(value))
{
return Array.get(value, pos);
}
return null;
}
else if (value instanceof List)
{
String indexExpr = collectIndexExpr(sp);
int pos = Integer.parseInt(indexExpr);
List list = (List) value;
try
{
value = list.get(pos);
}
catch (IndexOutOfBoundsException e)
{
throw newError("Expression.IndexOutOfBounds", "Collection index '" + pos + "' is out of bounds", sp);
}
}
else if (value instanceof Collection)
{
String indexExpr = collectIndexExpr(sp);
int pos = Integer.parseInt(indexExpr);
Collection coll = (Collection) value;
Iterator it = coll.iterator();
for (int i = 0; i < pos; ++i)
{
if (!it.hasNext())
{
throw newError("Expression.IndexOutOfBounds", "Collection index '" + pos + "' is out of bounds", sp);
}
value = it.next();
}
}
else if (value instanceof Map)
{
String indexExpr = collectIndexExpr(sp);
Map map = (Map) value;
// First, try to get the value directly from the map
value = map.get(indexExpr);
if (value == null)
{
// Didn't work, iterate the map and compare the map element specifiers
Iterator it = map.keySet().iterator();
for (int i = 0; it.hasNext(); i++)
{
Object key = it.next();
String name = ScriptUtil.createMapElementName(key, false);
if (name != null && name.equals(indexExpr))
{
value = map.get(key);
break;
}
}
}
}
} // End index spec
else if (c == ExpressionConstants.REFERENCE_KEY_OPERATOR_CHAR && sp.getChar() == ExpressionConstants.REFERENCE_KEY_OPERATOR_CHAR)
{
sp.nextChar(); // Consume
if (!(context instanceof TokenContext))
{
throw newError("Expression.EvaluationContextMissing", "Invalid context for '" + ExpressionConstants.REFERENCE_KEY_OPERATOR + "' operation", sp);
}
Model model = ((TokenContext) context).getExecutingModel();
if (persistenceContextProvider == null)
{
throw newError("Expression.EvaluationContextMissing", "Invalid context for '" + ExpressionConstants.REFERENCE_KEY_OPERATOR + "' operation", sp);
}
ident = collectDataTypeName(sp);
try
{
DataTypeItem targetType = (DataTypeItem) model.resolveItemRef(ident, ItemTypes.TYPE);
if (targetType.isSimpleType())
{
throw newError("Expression.EvaluationContextMissing", "Data type '" + ident + "' in '" + ExpressionConstants.REFERENCE_KEY_OPERATOR + "' expression may not be a primitive type.", sp);
}
try
{
// Retrieve the bean according to the given id value
PersistenceContext pc = persistenceContextProvider.obtainPersistenceContext();
value = pc.findById(value, targetType.getJavaClass());
}
catch (Exception e)
{
throw newError("AutoRetrieval", "Auto-retrieval of bean of expression '" + ExpressionConstants.REFERENCE_KEY_OPERATOR + "" + ident + "' by id value '" + value + "' failed.", e, sp);
}
}
catch (OpenBPException e)
{
throw newError("Expression.EvaluationContextMissing", "Data type '" + ident + "' in '" + ExpressionConstants.REFERENCE_KEY_OPERATOR + "' expression could not be found in the executing model or its imported models.", sp);
}
}
else
{
// Regular member spec
if (c != ExpressionConstants.MEMBER_OPERATOR_CHAR)
{
throw newError("Expression.Syntax", "'" + ExpressionConstants.MEMBER_OPERATOR_CHAR + "' or end of expression expected", sp);
}
// Need identifier
ident = sp.getIdentifier();
if (ident == null)
throw newError("Expression.IdentifierExpected", "Identifier expected in expression", sp);
// Access the property
try
{
value = PropertyAccessUtil.getProperty(value, ident);
}
catch (PropertyException e)
{
throw newError("Expression.PropertyAccessFailed", e.getMessage(), e.getCause(), sp);
}
}
sp.skipSpace();
c = sp.getChar();
if (c == 0)
break;
if (value == null)
{