/*
* $Id$
*
* Copyright (c) 2009-2013 Brent Easton
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License (LGPL) as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, copies are available
* at http://www.opensource.org.
*/
package VASSAL.script.expression;
import java.util.Map;
import VASSAL.build.BadDataReport;
import VASSAL.build.module.properties.PropertySource;
import VASSAL.counters.GamePiece;
import VASSAL.counters.PieceFilter;
import VASSAL.i18n.Resources;
import VASSAL.script.ExpressionInterpreter;
import VASSAL.tools.ErrorDialog;
/**
* A basic beanShell expression
*/
public class BeanShellExpression extends Expression {
protected ExpressionInterpreter interpreter;
public BeanShellExpression (String s) {
setExpression("{" + s + "}");
}
/**
* Evaluate this expression using a BeanShell Interpreter
*/
public String evaluate(PropertySource ps, Map<String, String> properties,
boolean localized) throws ExpressionException {
if (interpreter == null) {
interpreter = ExpressionInterpreter.createInterpreter(strip(getExpression()));
}
return interpreter.evaluate(ps, localized);
}
public String toBeanShellString() {
return strip(getExpression());
}
protected static String strip(String expr) {
final String s = expr.trim();
if (s.startsWith("{") && s.endsWith("}")) {
return s.substring(1, s.length()-1);
}
return expr;
}
/**
* Return a PieceFilter that selects GamePieces that cause
* this expression to evaluate to true
*/
public PieceFilter getFilter(final PropertySource ps) {
return new PieceFilter() {
public boolean accept(GamePiece piece) {
String result = null;
try {
result = evaluate(piece);
}
catch (ExpressionException e) {
ErrorDialog.dataError(new BadDataReport(Resources.getString("Error.expression_error"), "Expression="+getExpression()+", Error="+e.getError(), e));
}
return "true".equals(result);
}
};
}
/**
* Convert a Property name to it's BeanShell equivalent.
*
* @param property name
* @return beanshell equivalent
*/
public static String convertProperty (String prop) {
// Null Expression
if (prop == null || prop.length() == 0) {
return "";
}
// Already a bsh exopression?
if (isBeanShellExpression(prop)) {
return strip(prop);
}
// Check it follows Java variable rules
boolean ok = Character.isJavaIdentifierStart(prop.charAt(0));
if (ok) {
for (int i=1; i < prop.length() && ok; i++) {
ok = Character.isJavaIdentifierPart(prop.charAt(i));
}
}
// If not a Java variable, wrap it in GetProperty()
return ok ? prop : "GetProperty(\""+prop+"\")";
}
public static boolean isBeanShellExpression(String expr) {
return expr.startsWith("{") && expr.endsWith("}");
}
public static boolean isJavaIdentifier(String s) {
if (s == null || s.length() == 0) {
return false;
}
if (!Character.isJavaIdentifierStart(s.charAt(0))) {
return false;
}
for (int i = 1; i < s.length(); ++i) {
if (!Character.isJavaIdentifierPart(s.charAt(i))) {
return false;
}
}
return true;
}
/**
* Create a BeanShellExpression.
*
* The expression may or may not be surrounded by {}.
*
* Create null, integer and simple Expressions as their basic type to
* ensure efficient evaluation.
*/
public static Expression createExpression(String s) {
String expr;
final String t = s.trim();
if (t.startsWith("{") && t.endsWith("}")) {
expr = t.substring(1, t.length() - 1).trim();
}
else {
expr = t;
}
if (expr.trim().length() == 0) {
return new NullExpression();
}
try {
return new IntExpression(Integer.parseInt(expr));
}
catch (NumberFormatException e) {
// Not an error
}
// Return a single String as a string without quotes
if (expr.length() > 1 && expr.startsWith("\"") && expr.endsWith("\"")
&& expr.indexOf('"', 1) == expr.length() - 1) {
return new StringExpression(expr.substring(1, expr.length() - 1));
}
// Return a generalised Beanshell expression
return new BeanShellExpression(expr);
}
@Override
public boolean equals(Object bse) {
return super.equals(bse);
}
}