📄 parser.java
字号:
// If LHS is not a Boolean, then verify it is a comparable // and perform comparison. if (!(Comparable.class.isAssignableFrom(lhsClass))) { String opName = null; switch (operator) { case EQUAL : opName = "="; case GREATER_EQUAL : opName = ">="; case LESS_EQUAL : opName = "<="; case APPROX: opName = "~="; default: opName = "UNKNOWN OP"; } unsupportedType(opName, lhsClass); } // We will try to create a comparable object from the // RHS string. Comparable rhsComparable = null; try { // We are expecting to be able to construct a comparable // instance from the RHS string by passing it into the // constructor of the corresponing comparable class. The // Character class is a special case, since its constructor // does not take a string, so handle it separately. if (lhsClass == Character.class) { rhsComparable = new Character(rhs.charAt(0)); } else { rhsComparable = (Comparable) lhsClass .getConstructor(new Class[] { String.class }) .newInstance(new Object[] { rhs }); } } catch (Exception ex) { String msg = (ex.getCause() == null) ? ex.toString() : ex.getCause().toString(); throw new EvaluationException( "Could not instantiate class " + lhsClass.getName() + " with constructor String parameter " + rhs + " " + msg); } Comparable lhsComparable = (Comparable) lhs; switch (operator) { case EQUAL : return (lhsComparable.compareTo(rhsComparable) == 0); case GREATER_EQUAL : return (lhsComparable.compareTo(rhsComparable) >= 0); case LESS_EQUAL : return (lhsComparable.compareTo(rhsComparable) <= 0); case APPROX: return compareToApprox(lhsComparable, rhsComparable); default: throw new EvaluationException("Unknown comparison operator..." + operator); } } return false; } /** * This is an ugly utility method to convert an array of primitives * to an array of primitive wrapper objects. This method simplifies * processing LDAP filters since the special case of primitive arrays * can be ignored. * @param array * @return **/ private static Object[] convertPrimitiveArray(Object array) { Class clazz = array.getClass().getComponentType(); if (clazz == Boolean.TYPE) { boolean[] src = (boolean[]) array; array = new Boolean[src.length]; for (int i = 0; i < src.length; i++) { ((Object[]) array)[i] = new Boolean(src[i]); } } else if (clazz == Character.TYPE) { char[] src = (char[]) array; array = new Character[src.length]; for (int i = 0; i < src.length; i++) { ((Object[]) array)[i] = new Character(src[i]); } } else if (clazz == Byte.TYPE) { byte[] src = (byte[]) array; array = new Byte[src.length]; for (int i = 0; i < src.length; i++) { ((Object[]) array)[i] = new Byte(src[i]); } } else if (clazz == Short.TYPE) { byte[] src = (byte[]) array; array = new Byte[src.length]; for (int i = 0; i < src.length; i++) { ((Object[]) array)[i] = new Byte(src[i]); } } else if (clazz == Integer.TYPE) { int[] src = (int[]) array; array = new Integer[src.length]; for (int i = 0; i < src.length; i++) { ((Object[]) array)[i] = new Integer(src[i]); } } else if (clazz == Long.TYPE) { long[] src = (long[]) array; array = new Long[src.length]; for (int i = 0; i < src.length; i++) { ((Object[]) array)[i] = new Long(src[i]); } } else if (clazz == Float.TYPE) { float[] src = (float[]) array; array = new Float[src.length]; for (int i = 0; i < src.length; i++) { ((Object[]) array)[i] = new Float(src[i]); } } else if (clazz == Double.TYPE) { double[] src = (double[]) array; array = new Double[src.length]; for (int i = 0; i < src.length; i++) { ((Object[]) array)[i] = new Double(src[i]); } } return (Object[]) array; } private static boolean compareBoolean(Object lhs, String rhs, int operator) throws EvaluationException { Boolean rhsBoolean = new Boolean(rhs); if (lhs.getClass().isArray()) { Object[] objs = (Object[]) lhs; for (int i = 0; i < objs.length; i++) { switch (operator) { case EQUAL : case GREATER_EQUAL : case LESS_EQUAL : case APPROX: if (objs[i].equals(rhsBoolean)) { return true; } break; default: throw new EvaluationException( "Unknown comparison operator: " + operator); } } return false; } else { switch (operator) { case EQUAL : case GREATER_EQUAL : case LESS_EQUAL : case APPROX: return (lhs.equals(rhsBoolean)); default: throw new EvaluationException("Unknown comparison operator..." + operator); } } } /** * Test if two objects are approximate. The two objects that are passed must * have the same type. * * Approximate for numerical values involves a difference of less than APPROX_CRITERIA * Approximate for string values is calculated by using the Levenshtein distance * between strings. Less than APPROX_CRITERIA of difference is considered as approximate. * * Supported types only include the following subclasses of Number: * - Byte * - Double * - Float * - Int * - Long * - Short * - BigInteger * - BigDecimal * As subclasses of Number must provide methods to convert the represented numeric value * to byte, double, float, int, long, and short. (see API) * * @param obj1 * @param obj2 * @return true if they are approximate * @throws EvaluationException if it the two objects cannot be approximated **/ private static boolean compareToApprox(Object obj1, Object obj2) throws EvaluationException { if (obj1 instanceof Byte) { byte value1 = ((Byte)obj1).byteValue(); byte value2 = ((Byte)obj2).byteValue(); return (value2 >= (value1-((Math.abs(value1)*(byte)APPROX_CRITERIA)/(byte)100)) && value2 <= (value1+((Math.abs(value1)*(byte)APPROX_CRITERIA)/(byte)100))); } else if (obj1 instanceof Character) { char value1 = ((Character)obj1).charValue(); char value2 = ((Character)obj2).charValue(); return (value2 >= (value1-((Math.abs(value1)*(char)APPROX_CRITERIA)/(char)100)) && value2 <= (value1+((Math.abs(value1)*(char)APPROX_CRITERIA)/(char)100))); } else if (obj1 instanceof Double) { double value1 = ((Double)obj1).doubleValue(); double value2 = ((Double)obj2).doubleValue(); return (value2 >= (value1-((Math.abs(value1)*(double)APPROX_CRITERIA)/(double)100)) && value2 <= (value1+((Math.abs(value1)*(double)APPROX_CRITERIA)/(double)100))); } else if (obj1 instanceof Float) { float value1 = ((Float)obj1).floatValue(); float value2 = ((Float)obj2).floatValue(); return (value2 >= (value1-((Math.abs(value1)*(float)APPROX_CRITERIA)/(float)100)) && value2 <= (value1+((Math.abs(value1)*(float)APPROX_CRITERIA)/(float)100))); } else if (obj1 instanceof Integer) { int value1 = ((Integer)obj1).intValue(); int value2 = ((Integer)obj2).intValue(); return (value2 >= (value1-((Math.abs(value1)*(int)APPROX_CRITERIA)/(int)100)) && value2 <= (value1+((Math.abs(value1)*(int)APPROX_CRITERIA)/(int)100))); } else if (obj1 instanceof Long) { long value1 = ((Long)obj1).longValue(); long value2 = ((Long)obj2).longValue(); return (value2 >= (value1-((Math.abs(value1)*(long)APPROX_CRITERIA)/(long)100)) && value2 <= (value1+((Math.abs(value1)*(long)APPROX_CRITERIA)/(long)100))); } else if (obj1 instanceof Short) { short value1 = ((Short)obj1).shortValue(); short value2 = ((Short)obj2).shortValue(); return (value2 >= (value1-((Math.abs(value1)*(short)APPROX_CRITERIA)/(short)100)) && value2 <= (value1+((Math.abs(value1)*(short)APPROX_CRITERIA)/(short)100))); } else if (obj1 instanceof String) { int distance = getDistance(obj1.toString(),obj2.toString()); int size = ((String)obj1).length(); return (distance <= ((size*APPROX_CRITERIA)/100)); } else if (m_hasBigNumbers && (obj1 instanceof BigInteger)) { BigInteger value1 = (BigInteger)obj1; BigInteger value2 = (BigInteger)obj2; BigInteger delta = value1.abs().multiply( BigInteger.valueOf(APPROX_CRITERIA) .divide(BigInteger.valueOf(100))); BigInteger low = value1.subtract(delta); BigInteger high = value1.add(delta); return (value2.compareTo(low) >= 0) && (value2.compareTo(high) <= 0); } else if (m_hasBigNumbers && (obj1 instanceof BigDecimal)) { BigDecimal value1 = (BigDecimal)obj1; BigDecimal value2 = (BigDecimal)obj2; BigDecimal delta = value1.abs().multiply( BigDecimal.valueOf(APPROX_CRITERIA) .divide(BigDecimal.valueOf(100), BigDecimal.ROUND_HALF_DOWN)); BigDecimal low = value1.subtract(delta); BigDecimal high = value1.add(delta); return (value2.compareTo(low) >= 0) && (value2.compareTo(high) <= 0); } throw new EvaluationException( "Approximate operator not supported for type " + obj1.getClass().getName()); } /** * Calculate the Levenshtein distance (LD) between two strings. * The Levenshteing distance is a measure of the similarity between * two strings, which we will refer to as the source string (s) and * the target string (t). The distance is the number of deletions, * insertions, or substitutions required to transform s into t. * * Algorithm from: http://www.merriampark.com/ld.htm * * @param s the first string * @param t the second string * @return */ private static int getDistance(String s, String t) { int d[][]; // matrix int n; // length of s int m; // length of t int i; // iterates through s int j; // iterates through t char s_i; // ith character of s char t_j; // jth character of t int cost; // cost // Step 1 n = s.length(); m = t.length(); if (n == 0) { return m; } if (m == 0) { return n; } d = new int[n + 1][m + 1]; // Step 2 for (i = 0; i <= n; i++) { d[i][0] = i; } for (j = 0; j <= m; j++) { d[0][j] = j; } // Step 3 for (i = 1; i <= n; i++) { s_i = s.charAt(i - 1); // Step 4 for (j = 1; j <= m; j++) { t_j = t.charAt(j - 1); // Step 5 if (s_i == t_j) { cost = 0; } else { cost = 1; } // Step 6 d[i][j] = Minimum( d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + cost); } } // Step 7 return d[n][m]; } /** * Calculate the minimum between three values * * @param a * @param b * @param c * @return */ private static int Minimum(int a, int b, int c) { int mi; mi = a; if (b < mi) { mi = b; } if (c < mi) { mi = c; } return mi; } private static void fewOperands(String op) throws EvaluationException { throw new EvaluationException(op + ": too few operands"); } private static void unsupportedType(String opStr, Class clazz) throws EvaluationException { throw new EvaluationException( opStr + ": unsupported type " + clazz.getName(), clazz); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -