📄 simpletest.java
字号:
/* * WebWork, Web Application Framework * * Distributable under Apache license. * See terms of license at opensource.org */package webwork.util;import java.util.Map;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;/** * This class is used to handle test expressions in an efficient way. * It is more than 5 times faster than the javacc generated Parser.java * Instances of the class are retrieved through the static method * getSimpleTest. If the method returns null it means the expression was * too complex for this class too handle. Complex expressions are * those using parenthesis to control the order of evaluation. * Those expressions will instead be handled by the old * javacc Parser.java class. * * @see webwork.util.ValueStack * @see webwork.util.ComplexException * @see webwork.expr.Parser * @author Dick Zetterberg (dick@transitor.se) * @version $Revision: 1.2 $ */public class SimpleTest{ private static final Log log = LogFactory.getLog(SimpleTest.class); private static Map simpleTestMap = new ConcurrentReaderHashMap(); /** * This marker object is stored in the simpleTestMap to show * that the expression has been found to be too complex for * this class to handle */ private static final SimpleTest COMPLEX_TEST = new SimpleTest(); private static final Object NO_CONSTANT = new Object(); // The possible values for the operator protected static final int NONE = 0; protected static final int AND = 1; protected static final int OR = 2; // The condition characters used protected static final char AND_CHAR = '&'; protected static final char OR_CHAR = '|'; protected static final char QUOTE_CHAR = '\''; protected static final char EQUAL_CHAR = '='; protected static final char NOT_CHAR = '!'; protected static final char GREATER_CHAR = '>'; protected static final char LESS_CHAR = '<'; // The possible values for the condition protected static final int CHECK_NULL = 0; protected static final int EQUAL = 1; protected static final int NOT_EQUAL = 2; protected static final int GREATER = 3; protected static final int GREATER_EQUAL = 4; protected static final int LESS = 5; protected static final int LESS_EQUAL = 6; protected int condition; protected boolean neg1; protected boolean neg2; protected Query q1; protected Query q2; protected String exp1; protected String exp2; protected Object value1; protected Object value2; protected SimpleTest nextTest; protected int operator = NONE; protected int sameVal1; protected int sameVal2; /** * Get a SimpleTest object for the expression. * If the expression is too complex then null is returned * If the expression has been handled before then a cached SimpleTest * object is returned. Otherwise a new one is created */ public static SimpleTest getSimpleTest(String expression) { SimpleTest test = (SimpleTest) simpleTestMap.get(expression); if (test != null) { if (test != COMPLEX_TEST) return test; else return null; } // The expression has not been handled before, try creating a SimpleTest now try {// log.debug("Creating SimpleTest for expression: " + expression); test = new SimpleTest(expression); // Put the expression in the map simpleTestMap.put(expression, test); return test; } catch(ComplexException e) {// log.debug("SimpleTest not created because expression is too complex: " + expression, e); // Put the expression in the map so we do not try to handle it again simpleTestMap.put(expression, COMPLEX_TEST); // Return null to show that no SimpleTest could be created return null; } // Consider catching throwable to give better error message/* catch(Throwable t) { log.error("SimpleTest not created because unexpected throwable, expression: " + expression, t); // Put the expression in the map so we do not try to handle it again simpleTestMap.put(expression, COMPLEX_TEST); // Return null to show that no SimpleTest could be created return null; }*/ } public SimpleTest() {} /** * Create a SimpleTest for the expression exp, and make use of the values * found in the previously evaluated expression prevText if possible */ public SimpleTest(SimpleTest prevTest, String exp) throws ComplexException { // First evaluate the expression exp this(exp); // If the first expression is not a constant then // check if it already exists in the previous test if (value1 == NO_CONSTANT) { if (exp1.equals(prevTest.exp1)) sameVal1 = 1; else if (exp1.equals(prevTest.exp2)) sameVal1 = 2; } // If we have a second non constant expression check if it exists in the previous test if (exp2 != null && value2 == NO_CONSTANT) { if (exp2.equals(prevTest.exp1)) sameVal2 = 1; else if (exp2.equals(prevTest.exp2)) sameVal2 = 2; } } public SimpleTest(String exp) throws ComplexException { exp = exp.trim(); String nextExp = null; // Get the index of any && or || operators // The method also check for conditions like == and != and // if found, sets the exp1 and exp2 variables int opIndex = checkOperator(exp); // If there is an operator it means that the expression consists of // several expressions. Get the index of the next one if (operator != NONE) { nextExp = exp.substring(opIndex+2).trim(); exp = exp.substring(0, opIndex).trim(); } if (condition == CHECK_NULL) { // The expression is only to check for null value if (exp.charAt(0)=='!') { neg1 = true; exp1 = exp.substring(1).trim(); } else exp1 = exp; // Check that expression does not start with ( if (exp1.charAt(0) == '(') throw new ComplexException("Expression too complex because it starts with ( : " + exp); value1 = getConstant(exp1); } else { // The expression consists of 2 parts with a condition: ==, !=, <, > etc // Check that the expressions do not start with negation, in that case it is an // illegal expression if (exp1.charAt(0)=='!' || exp2.charAt(0)=='!') throw new IllegalArgumentException("Invalid expression, misplaced \'!\' : " + exp); // Check that expression does not start with ( if (exp1.charAt(0) == '(' || exp2.charAt(0) == '(') throw new ComplexException("Expression too complex because it starts with ( : " + exp); value1 = getConstant(exp1); value2 = getConstant(exp2); } if (value1 == NO_CONSTANT) q1 = Query.getQuery(exp1); if (condition != CHECK_NULL && value2 == NO_CONSTANT) q2 = Query.getQuery(exp2); if (nextExp != null) nextTest = new SimpleTest(this, nextExp); } /** * Look through the expression to find any operators like && or ||, <, > etc. * If found then the operator variable is updated. */ protected int checkOperator(String str) throws ComplexException { int length = str.length(); int i = 0; int exp2Index = -1; while(i < length) { char c = str.charAt(i++); // Check if the current characters is the && expression if (c == AND_CHAR && i < length && str.charAt(i) == AND_CHAR) { operator = AND; // If exp2Index is set we must truncate the exp2 expression now if (exp2Index >= 0) { exp2 = exp2.substring(0, i-exp2Index-1).trim(); } return i-1; } // Check if the current characters is the || expression if (c == OR_CHAR && i < length && str.charAt(i) == OR_CHAR) { operator = OR; if (exp2Index >= 0) { exp2 = exp2.substring(0, i-exp2Index-1).trim(); } return i-1; } // Check if the current character starts a quote if (c == QUOTE_CHAR && i < length) { // Find the next quote character and skip forward to it i = str.indexOf(QUOTE_CHAR, i); // If no other quote found do not handle it if (i < 0) throw new IllegalArgumentException("Invalid expression, no matching quote found: " + str); // Set i to the next character i++; continue; } // Perhaps add check if condition is already set and in that case throw exception if (c == EQUAL_CHAR && i < length && str.charAt(i) == EQUAL_CHAR) { condition = EQUAL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -