/* * (c) Copyright 2010-2011 AgileBirds * * This file is part of OpenFlexo. * * OpenFlexo is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * OpenFlexo 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>. * */ package org.openflexo.antar.expr; import java.util.Hashtable; import java.util.Iterator; import java.util.Vector; import java.util.logging.Logger; import org.openflexo.antar.expr.parser.ExpressionParser; import org.openflexo.antar.expr.parser.ParseException; /** * Represents a symbolic expression * * @author sylvain * */ public abstract class Expression { private static final Logger logger = Logger.getLogger(Expression.class.getPackage().getName()); public abstract Expression transform(ExpressionTransformer transformer) throws TransformException; public final Expression evaluate() throws TypeMismatchException, NullReferenceException { try { return transform(new ExpressionEvaluator()); } catch (TypeMismatchException e) { throw e; } catch (NullReferenceException e) { throw e; } catch (TransformException e) { logger.warning("Unexpected exception occured during evaluation " + e); e.printStackTrace(); return null; } } public abstract int getDepth(); @Override public String toString() { return debugPP.getStringRepresentation(this); } private static final DefaultExpressionPrettyPrinter debugPP = new DefaultExpressionPrettyPrinter(); @Override public boolean equals(Object obj) { if (obj == null) { return false; } else if (obj instanceof Expression) { return getClass().equals(obj.getClass()) && toString().equalsIgnoreCase(((Expression) obj).toString()); } return super.equals(obj); } public abstract EvaluationType getEvaluationType() throws TypeMismatchException; public boolean isSemanticallyAcceptable() { try { getEvaluationType(); return true; } catch (TypeMismatchException e) { return false; } } protected void _checkSemanticallyAcceptable() throws TypeMismatchException { getEvaluationType(); } /** * Returns an iterator on atomic expressions */ public Iterator<Expression> atomicExpressions() { return getAllAtomicExpressions().iterator(); } public Vector<Expression> getAllAtomicExpressions() { Vector<Expression> returned = new Vector<Expression>(); appendAllAtomicExpressions(returned, this); return returned; } private static void appendAllAtomicExpressions(Vector<Expression> buildVector, Expression current) { if (current.getChilds() == null) { buildVector.add(current); } else { for (Expression e : current.getChilds()) { appendAllAtomicExpressions(buildVector, e); } } } protected abstract Vector<Expression> getChilds(); /** * Evaluate expression considering some declared variables * * @param variables * @return * @throws TypeMismatchException */ public Expression evaluate(final Hashtable<String, ?> variables) throws TypeMismatchException { try { Expression resolvedExpression = transform(new ExpressionTransformer() { @Override public Expression performTransformation(Expression e) throws TransformException { if (e instanceof BindingValueAsExpression) { BindingValueAsExpression bv = (BindingValueAsExpression) e; if (bv.isSimpleVariable() && variables.get(bv.toString()) != null) { return Constant.makeConstant(variables.get(bv.toString())); } } return e; } }); return resolvedExpression.evaluate(); } catch (TransformException e) { e.printStackTrace(); return null; } /*return evaluate(new EvaluationContext(new ExpressionParser.DefaultConstantFactory(), new VariableFactory() { @Override public Expression makeVariable(Word value, Bindable bindable) { Object valueObject = variables.get(value.getValue()); if (valueObject == null) { return ObjectSymbolicConstant.NULL; } if (valueObject instanceof String) { return new Constant.StringConstant((String) valueObject); } else if (valueObject instanceof Enum) { return new Constant.EnumConstant(((Enum) valueObject).name()); } else if (valueObject instanceof Integer) { return new Constant.IntegerConstant((Integer) valueObject); } else if (valueObject instanceof Long) { return new Constant.IntegerConstant((Long) valueObject); } else if (valueObject instanceof Short) { return new Constant.IntegerConstant((Short) valueObject); } else if (valueObject instanceof Float) { return new Constant.FloatConstant((Float) valueObject); } else if (valueObject instanceof Double) { return new Constant.FloatConstant((Double) valueObject); } else if (valueObject instanceof Boolean) { return (Boolean) valueObject ? Constant.BooleanConstant.TRUE : Constant.BooleanConstant.FALSE; } // TODO Handle others // return new Variable(value.getValue()); return new Constant.StringConstant(value.getValue()); } }, new ExpressionParser.DefaultFunctionFactory()), bindable);*/ } public boolean evaluateCondition(final Hashtable<String, ?> variables) throws TypeMismatchException, UnresolvedExpressionException { // logger.info("evaluate "+this); // logger.info("variables "+variables); Expression evaluation = evaluate(variables); // logger.info("evaluation "+evaluation); if (evaluation == Constant.BooleanConstant.TRUE) { return true; } if (evaluation == Constant.BooleanConstant.FALSE) { return false; } logger.warning("Unresolved expression: " + evaluation); throw new UnresolvedExpressionException(); } public static Vector<Variable> extractVariables(String anExpression) throws ParseException, TypeMismatchException { final Hashtable<String, Variable> returnedHash = new Hashtable<String, Variable>(); try { Expression e = ExpressionParser.parse(anExpression); e.transform(new ExpressionTransformer() { @Override public Expression performTransformation(Expression e) throws TransformException { if (e instanceof BindingValueAsExpression) { String variableName = ((BindingValueAsExpression) e).toString(); Variable returned = returnedHash.get(variableName); if (returned == null) { returned = new Variable(variableName); returnedHash.put(variableName, returned); } return returned; } return e; } }); } catch (ParseException e1) { throw e1; } catch (TransformException e) { e.printStackTrace(); } /*DefaultExpressionParser parser = new DefaultExpressionParser(); Expression expression = parser.parse(anExpression, bindable); expression.evaluate(new EvaluationContext(new ExpressionParser.DefaultConstantFactory(), new VariableFactory() { @Override public Expression makeVariable(Word value, Bindable bindable) { Variable returned = returnedHash.get(value.getValue()); if (returned == null) { returned = new Variable(value.getValue()); returnedHash.put(value.getValue(), returned); } return returned; } }, new ExpressionParser.DefaultFunctionFactory()), bindable);*/ Vector<Variable> returned = new Vector<Variable>(); for (String v : returnedHash.keySet()) { returned.add(returnedHash.get(v)); } return returned; } public static Vector<Expression> extractPrimitives(String anExpression) throws ParseException, TypeMismatchException { final Hashtable<String, Expression> returnedHash = new Hashtable<String, Expression>(); try { Expression e = ExpressionParser.parse(anExpression); e.transform(new ExpressionTransformer() { @Override public Expression performTransformation(Expression e) throws TransformException { if (e instanceof BindingValueAsExpression) { String variableName = ((BindingValueAsExpression) e).toString(); Expression returned = returnedHash.get(variableName); if (returned == null) { returned = new Variable(variableName); returnedHash.put(variableName, returned); } return returned; } return e; } }); } catch (org.openflexo.antar.expr.parser.ParseException e1) { e1.printStackTrace(); } catch (TransformException e) { e.printStackTrace(); } /*DefaultExpressionParser parser = new DefaultExpressionParser(); Expression expression = parser.parse(anExpression, bindable); expression.evaluate(new EvaluationContext(new ExpressionParser.DefaultConstantFactory(), new VariableFactory() { @Override public Expression makeVariable(Word value, Bindable bindable) { Expression returned = returnedHash.get(value.getValue()); if (returned == null) { returned = new Variable(value.getValue()); returnedHash.put(value.getValue(), returned); } return returned; } }, new FunctionFactory() { @Override public Expression makeFunction(String functionName, List<Expression> args, Bindable bindable) { StringBuffer key = new StringBuffer(); key.append(functionName + "("); for (int i = 0; i < args.size(); i++) { key.append((i > 0 ? "," : "") + "arg" + i); } key.append(")"); Expression returned = returnedHash.get(key); if (returned == null) { returned = new Function(functionName, args); returnedHash.put(key.toString(), returned); } return returned; } }), bindable); */ Vector<Expression> returned = new Vector<Expression>(); for (String v : returnedHash.keySet()) { returned.add(returnedHash.get(v)); } return returned; } @Override public int hashCode() { return (getClass().getName() + "@[" + toString() + "]").hashCode(); } }