/******************************************************************************* * Copyright (C) 2009-2011 Amir Hassan <amir@viel-zu.org> * * This program 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 2 of the License, or * (at your option) any later version. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ******************************************************************************/ package org.wooden.util; import java.io.PrintStream; import java.text.ParseException; import java.util.*; public class BooleanExpression { public BooleanExpression(String expression) throws ParseException { booleanValue = false; rawExpression = expression; booleanValue = parseExpression(expression); } private boolean parseExpression(String expression) throws ParseException { if(expression == null) throw new IllegalArgumentException("The boolean expression can't be null"); String arrExpression[] = getBooleanTokens(expression); String exp = null; String operator = null; Boolean result = null; Boolean lastResult = null; Boolean paritialResult = null; for(int i = 0; i < arrExpression.length; i++) { exp = arrExpression[i]; if(exp.equals("||") || exp.equals("&&")) { operator = exp; } else { paritialResult = new Boolean(resolveValue(exp)); if(lastResult == null || operator == null) { result = lastResult = paritialResult; } else { if(operator.equals("&&")) result = and(lastResult, paritialResult); else if(operator.equals("||")) result = or(lastResult, paritialResult); else throw new ParseException((new StringBuilder("Unknown operator: ")).append(operator).toString(), rawExpression.indexOf(operator)); lastResult = result; } } } return result.booleanValue(); } private Boolean and(Boolean b1, Boolean b2) { return new Boolean(b1.booleanValue() && b2.booleanValue()); } private Boolean or(Boolean b1, Boolean b2) { return new Boolean(b1.booleanValue() || b2.booleanValue()); } private boolean resolveValue(String expression) throws ParseException { boolean r = false; if(expression.indexOf("==") > 0) r = resolveValue(expression, 0); else if(expression.indexOf("=") > 0) r = resolveValue(expression, 1); else if(expression.indexOf(">>") > 0) r = resolveValue(expression, 3); else r = resolveValue(expression, 2); return r; } private Collection findOperator(String expression, String operator) throws ParseException { Vector indeces = new Vector(); int operatorOff = 0; try { int operatorIndex; while((operatorIndex = expression.indexOf(operator, operatorOff)) > -1) { operatorOff = operatorIndex + 2; indeces.add(new Integer(operatorIndex)); } return indeces; } catch(Exception ex) { throw new ParseException(ex.getMessage(), operatorOff); } } private String[] getBooleanTokens(String expression) throws ParseException { Vector indeces = new Vector(); Vector t = new Vector(); int operatorOff = 0; try { indeces.addAll(findOperator(expression, "&&")); indeces.addAll(findOperator(expression, "||")); int arrOperatorIndeces[] = new int[indeces.size()]; for(int i = 0; i < arrOperatorIndeces.length; i++) arrOperatorIndeces[i] = ((Integer)indeces.get(i)).intValue(); Arrays.sort(arrOperatorIndeces); operatorOff = 0; for(int i = 0; i < arrOperatorIndeces.length; i++) { t.add(expression.substring(operatorOff, arrOperatorIndeces[i])); t.add(expression.substring(arrOperatorIndeces[i], arrOperatorIndeces[i] + 2)); operatorOff = arrOperatorIndeces[i] + 2; } String rest = expression.substring(operatorOff); if(rest.trim().length() > 0) t.add(rest); return (String[])t.toArray(new String[0]); } catch(ParseException ex) { throw ex; } catch(Exception ex) { throw new ParseException(ex.getMessage(), operatorOff); } } private boolean resolveValue(String expression, int mode) throws ParseException { boolean result = false; switch(mode) { case 0: // '\0' result = resolveExact(expression); break; case 1: // '\001' result = resolveEquals(expression); break; case 2: // '\002' result = resolveMath(expression); break; case 3: // '\003' result = resolveContains(expression); break; } return result; } private boolean resolveMath(String expression) throws ParseException { try { return (new MathExpression(expression)).booleanValue(); } catch(Exception ex) { throw new ParseException(ex.getMessage(), rawExpression.indexOf(expression)); } } private boolean resolveEquals(String expression) throws ParseException { boolean res; MathExpression lastexp; res = true; lastexp = null; try { StringTokenizer st = new StringTokenizer(expression, "="); if(st.countTokens() < 2) return false; while(st.hasMoreTokens()) { MathExpression exp = new MathExpression(st.nextToken()); if(lastexp != null) res = res && lastexp.value() == exp.value(); lastexp = exp; } return res; } catch(Exception ex) { throw new ParseException(ex.getMessage(), rawExpression.indexOf(expression)); } } private boolean resolveContains(String expression) throws ParseException { boolean res; String lasttoken; res = true; lasttoken = null; try { StringTokenizer st = new StringTokenizer(expression, ">>"); if(st.countTokens() < 2) return false; while(st.hasMoreTokens()) { String token = st.nextToken(); if(lasttoken != null) res = res && token.indexOf(lasttoken.trim()) > -1; lasttoken = token; } return res; } catch(Exception ex) { throw new ParseException(ex.getMessage(), rawExpression.indexOf(expression)); } } private boolean resolveExact(String expression) throws ParseException { boolean res; String lasttoken; res = true; lasttoken = null; try { StringTokenizer st = new StringTokenizer(expression, "=="); if(st.countTokens() < 2) return false; while(st.hasMoreTokens()) { String token = st.nextToken().trim(); if(lasttoken != null) res = res && lasttoken.equals(token); lasttoken = token; } return res; } catch(Exception ex) { throw new ParseException(ex.getMessage(), rawExpression.indexOf(expression)); } } public boolean booleanValue() { return booleanValue; } public static void main(String args[]) { try { BooleanExpression le = new BooleanExpression("Amir==Amir && (10*a)+24=104 && AMIR >> hasAMIRsan || 0"); System.out.println((new StringBuilder(String.valueOf(le.booleanValue()))).append("\n").toString()); le = new BooleanExpression("1*5=5"); System.out.println((new StringBuilder(String.valueOf(le.booleanValue()))).append("\n").toString()); le = new BooleanExpression("8-9"); System.out.println((new StringBuilder(String.valueOf(le.booleanValue()))).append("\n").toString()); } catch(ParseException ex) { ex.printStackTrace(); } } private static final int RESOLVE_EXACT = 0; private static final int RESOLVE_EQUALS = 1; private static final int RESOLVE_MATH = 2; private static final int RESOLVE_CONTAINS = 3; private static final String OPERATOR_EXACT = "=="; private static final String OPERATOR_EQUALS = "="; private static final String OPERATOR_CONTAINS = ">>"; private static final String OPERATOR_AND = "&&"; private static final String OPERATOR_OR = "||"; private boolean booleanValue; private String rawExpression; }