Expression.java :  » Database-ORM » XORM » org » xorm » query » Java Open Source

Java Open Source » Database ORM » XORM 
XORM » org » xorm » query » Expression.java
/*
    $Header: /cvsroot/xorm/xorm/src/org/xorm/query/Expression.java,v 1.10 2004/05/28 15:38:23 wbiggs Exp $

    This file is part of XORM.

    XORM 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.

    XORM 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 XORM; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
package org.xorm.query;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;

public abstract class Expression {
    public abstract Object evaluate(QueryContext context);
    public abstract String toString();
    public void accept(ExpressionVisitor visitor) {
        // Default implementation, only override where needed
    }
    public abstract Class getType();

    public static abstract class Binary extends Expression {
        protected Expression lhs;
        protected Expression rhs;

        public Binary(Expression lhs, Expression rhs) {
            this.lhs = lhs;
            this.rhs = rhs;
        }

        public Expression getLHS() {
            return lhs;
        }

        public Expression getRHS() {
            return rhs;
        }

        /** Returns a String representation of the operator */
        public abstract Operator operator();

        public String toString() {
            return "(" + lhs + " " + operator() + " " + rhs + ")";
        }
    }

    public static abstract class Comparison extends Binary {
        // Just for declarative purposes, to separate it from Arithmetic
        public Comparison(Expression lhs, Expression rhs) {
            super(lhs,rhs);
        }

        public Class getType() {
            return Boolean.class;
        }

        public void accept(ExpressionVisitor visitor) {
            if (!visitor.visitComparison(this))
                super.accept(visitor);
        }
    }

    public static class ConditionalOr extends Comparison {
        public ConditionalOr(Expression lhs, Expression rhs) {
            super(lhs, rhs);
        }

        public Object evaluate(QueryContext context) {
            Boolean lhv = (Boolean) lhs.evaluate(context);
            if (lhv.booleanValue()) return lhv;
            return (Boolean) rhs.evaluate(context);
        }

        public void accept(ExpressionVisitor visitor) {
            if (!visitor.visitConditionalOr(this))
                super.accept(visitor);
        }

        public Operator operator() { return Operator.ORC; }
    }

    public static class ConditionalAnd extends Comparison {
        public ConditionalAnd(Expression lhs, Expression rhs) {
            super(lhs, rhs);
        }

        public Object evaluate(QueryContext context) {
            Boolean lhv = (Boolean) lhs.evaluate(context);
            if (lhv.booleanValue()) {
                return (Boolean) rhs.evaluate(context);
            }
            return lhv;
        }

        public void accept(ExpressionVisitor visitor) {
            if (!visitor.visitConditionalAnd(this)) {
                super.accept(visitor);
            }
        }

        public Operator operator() { return Operator.ANDC; }
    }

    public static class InclusiveOr extends Comparison {
        public InclusiveOr(Expression lhs, Expression rhs) {
            super(lhs, rhs);
        }

        public Object evaluate(QueryContext context) {
            Boolean lhv = (Boolean) lhs.evaluate(context);
            Boolean rhv = (Boolean) rhs.evaluate(context);
            if (lhv.booleanValue() || rhv.booleanValue()) {
                return Boolean.TRUE;
            }
            return Boolean.FALSE;
        }

        public Operator operator() { return Operator.ORL; }
    }

    public static class And extends Comparison {
        public And(Expression lhs, Expression rhs) {
            super(lhs, rhs);
        }

        public Object evaluate(QueryContext context) {
            Boolean lhv = (Boolean) lhs.evaluate(context);
            Boolean rhv = (Boolean) rhs.evaluate(context);
            if (lhv.booleanValue() && rhv.booleanValue()) {
                return Boolean.TRUE;
            }
            return Boolean.FALSE;
        }

        public void accept(ExpressionVisitor visitor) {
            if (!visitor.visitAnd(this)) {
                super.accept(visitor);
            }
        }

        public Operator operator() { return Operator.ANDL; }
    }

    public static class ExclusiveOr extends Comparison {
        public ExclusiveOr(Expression lhs, Expression rhs) {
            super(lhs, rhs);
        }

        public Object evaluate(QueryContext context) {
            Boolean lhv = (Boolean) lhs.evaluate(context);
            Boolean rhv = (Boolean) rhs.evaluate(context);
            if (lhv.booleanValue() ^ rhv.booleanValue()) {
                return Boolean.TRUE;
            }
            return Boolean.FALSE;
        }

        public Operator operator() { return Operator.XOR; }
    }

    public static class Equal extends Comparison {
        public Equal(Expression lhs, Expression rhs) {
            super(lhs, rhs);
        }

        public Object evaluate(QueryContext context) {
            Object lhv = lhs.evaluate(context);
            Object rhv = rhs.evaluate(context);
      
            return (lhv == null) ? 
                Boolean.valueOf(rhv == null) :
                Boolean.valueOf(lhv.equals(rhv));
        }

        public Operator operator() { return Operator.EQUAL; }
    }

    public static class NotEqual extends Equal {
        public NotEqual(Expression lhs, Expression rhs) {
            super(lhs, rhs);
        }

        public Object evaluate(QueryContext context) {
            return Boolean.TRUE.equals(super.evaluate(context)) ?
                Boolean.FALSE :
                Boolean.TRUE;
        }

        public Operator operator() { return Operator.NOT_EQUAL; }
    }

    public static abstract class Numeric extends Comparison {
        public Numeric(Expression lhs, Expression rhs) {
            super(lhs, rhs);
        }

        public abstract boolean evaluateCompared(int compareTo);

        public Object evaluate(QueryContext context) {
            Object lhv = lhs.evaluate(context);
            Object rhv = rhs.evaluate(context);
      
            if (lhv instanceof Long) {
                return evaluateCompared(((Long) lhv).compareTo 
                                        (new Long(((Number) rhv).longValue()))) ?
                    Boolean.TRUE : Boolean.FALSE;
            } else if (lhv instanceof Integer) {
                return evaluateCompared(((Integer) lhv).compareTo
                                        (new Integer(((Number) rhv).intValue()))) ?
                    Boolean.TRUE : Boolean.FALSE;
            } else if (lhv instanceof Short) {
                return evaluateCompared(((Short) lhv).compareTo
                                        (new Short(((Number) rhv).shortValue()))) ?
                    Boolean.TRUE : Boolean.FALSE;
            } else if (lhv instanceof Byte) {
                return evaluateCompared(((Byte) lhv).compareTo
                                        (new Byte(((Number) rhv).byteValue()))) ?
                    Boolean.TRUE : Boolean.FALSE;
            } else if (lhv instanceof Double) {
                return evaluateCompared(((Double) lhv).compareTo
                                        (new Double(((Number) rhv).doubleValue()))) ?
                    Boolean.TRUE : Boolean.FALSE;
            } else if (lhv instanceof Float) {
                return evaluateCompared(((Float) lhv).compareTo
                                        (new Float(((Number) rhv).floatValue()))) ?
                    Boolean.TRUE : Boolean.FALSE;
            } else if (lhv instanceof Character) {
                return evaluateCompared(((Character) lhv).compareTo
                                        ((Character) rhv)) ?
                    Boolean.TRUE : Boolean.FALSE;
            }
            throw new IllegalArgumentException();
        }
    }

    public static class LessThan extends Numeric {
        public LessThan(Expression lhs, Expression rhs) {
            super(lhs, rhs);
        }

        public boolean evaluateCompared(int i) {
            return i < 0;
        }

        public Operator operator() { return Operator.LT; }
    }

    public static class LessThanEqual extends Numeric {
        public LessThanEqual(Expression lhs, Expression rhs) {
            super(lhs, rhs);
        }

        public boolean evaluateCompared(int i) {
            return i <= 0;
        }

        public Operator operator() { return Operator.LTE; }
    }

    public static class GreaterThan extends Numeric {
        public GreaterThan(Expression lhs, Expression rhs) {
            super(lhs, rhs);
        }

        public boolean evaluateCompared(int i) {
            return i > 0;
        }

        public Operator operator() { return Operator.GT; }
    }

    public static class GreaterThanEqual extends Numeric {
        public GreaterThanEqual(Expression lhs, Expression rhs) {
            super(lhs, rhs);
        }

        public boolean evaluateCompared(int i) {
            return i >= 0;
        }

        public Operator operator() { return Operator.GTE; }
    }

    public static class Constant extends Expression {
        public static final Constant TRUE = new Constant(Boolean.TRUE);
        public static final Constant FALSE = new Constant(Boolean.FALSE);
        public static final Constant NULL = new Constant(null);

        protected Object value;

        public Constant(Object value) {
            this.value = value;
        }

        public Object evaluate(QueryContext context) {
            return value;
        }

        public Object getValue() {
            return value;
        }

        public Class getType() {
            if (this == NULL) return null;
            return value.getClass();
        }

        public String toString() {
            if (this == NULL) return "null";
            if (value instanceof String) {
                return escapeString((String) value);
            } else if (value instanceof Character) {
                return escapeChar(((Character) value).charValue());
            }
            return value.toString();
        }

        public void accept(ExpressionVisitor visitor) {
            if (!visitor.visitConstant(this)) {
                super.accept(visitor);
            }
        }
    }

    public abstract static class Symbolic extends Expression {
        protected String name;
        protected Class type;

        public Symbolic(String name, Class type) {
            this.name = name;
            this.type = type;
        }
  
        public String getName() {
            return name;
        }

        public Class getType() {
            return type;
        }
  
        // breaks immutable.. fixme
        public void setType(Class type) {
            this.type = type;
        }
    }

    public static class Parameter extends Symbolic {
        public Parameter(String name, Class type) {
            super(name, type);
        }
  
        public Object evaluate(QueryContext context) {
            return context.resolveParameter(name);
        }

        public void accept(ExpressionVisitor visitor) {
            if (!visitor.visitParameter(this)) {
                super.accept(visitor);
            }
        }

        public String toString() {
            return name;
        }
    }

    public static class Variable extends Symbolic {
        public Variable(String name, Class type) {
            super(name, type);
        }
  
        public Object evaluate(QueryContext context) {
            return context.resolveVariable(name);
        }


        public void accept(ExpressionVisitor visitor) {
            if (!visitor.visitVariable(this)) {
                super.accept(visitor);
            }
        }

        public String toString() {
            return name;
        }
    }

    public abstract static class Member extends Symbolic {
        protected Expression owner;

        public Member(Expression owner, String name, Class type) {
            super(name, type);
            this.owner = owner;
        }

        public Expression getOwner() {
            return owner;
        }

        // This breaks the immutable pattern
        public void setOwner(Expression owner) {
            this.owner = owner;
        }
    }

    public static class FieldAccess extends Member {
        public static final FieldAccess THIS = new FieldAccess(null, "this", null);

        public FieldAccess(Expression owner, String name, Class type) {
            super(owner, name, type);
        }
  
        public Object evaluate(QueryContext context) {
            if (this == THIS) {
                return context.getCandidate();
            }
            // Evaluate using introspection
            Object above = owner.evaluate(context);
            Field f = findField(above.getClass(), name);
            if (f != null) {
                try {
                    return f.get(above);
                } catch (IllegalAccessException e) {
                }
            } else {
                // Then try get() method
                StringBuffer sb = new StringBuffer("get").append(name);
                sb.setCharAt(0, Character.toUpperCase(sb.charAt(3)));
                Method m = findMethod(above.getClass(), sb.toString(), null);
                if (m != null) {
                    try {
                        return m.invoke(above, null);
                    } catch (IllegalAccessException e) {
                    } catch (InvocationTargetException e) {
                    }
                }
            }
            return null;
        }

        public String toString() {
            if (this == THIS) {
                return "this";
            } else {
                return owner + "." + name;
            }
        }

        public void accept(ExpressionVisitor visitor) {
            if (!visitor.visitFieldAccess(this)) {
                super.accept(visitor);
            }
        }
    }

    public static class MethodCall extends Member {
        protected Expression[] parameters;

        public MethodCall(Expression owner, String name, Expression[] parameters, Class type) {
            super(owner, name, type);
            this.parameters = parameters;
        }
  
        public Expression[] getParameters() {
            return parameters;
        }

        public Object evaluate(QueryContext context) {
            // Evaluate using introspection
            Object above = owner.evaluate(context);
            Class[] types = new Class [parameters.length];
            for (int i = 0; i < parameters.length; i++) {
                types[i] = parameters[i].getType();
            }
            Method m = findMethod(above.getClass(), name, types);
            if (m != null) {
                try {
                    return m.invoke(above, parameters);
                } catch (IllegalAccessException e) {
                } catch (InvocationTargetException e) {
                }
            }
            return null;
        }

        public String toString() {
            StringBuffer sb = new StringBuffer(owner.toString())
                .append(".")
                .append(name)
                .append("(");
            for (int i = 0; i < parameters.length; i++) {
                if (i > 0) { sb.append(", "); }
                sb.append(parameters[i].toString());
            }
            return sb.append(")").toString();
        }

        public void accept(ExpressionVisitor visitor) {
            if (!visitor.visitMethodCall(this)) {
                super.accept(visitor);
            }
        }
    }

    public static abstract class Unary extends Expression {
        protected Expression operand;

        public Unary(Expression operand) {
            this.operand = operand;
        }

        public Expression getOperand() {
            return operand;
        }

        // breaks immutable
        public void setOperand(Expression operand) {
            this.operand = operand;
        }

        public Class getType() {
            return operand.getType();
        }

        public void accept(ExpressionVisitor visitor) {
            if (!visitor.visitUnary(this))
                super.accept(visitor);
        }
    }

    public static class UnaryMinus extends Unary {
        public UnaryMinus(Expression operand) {
            super(operand);
        }

        public Object evaluate(QueryContext context) {
            Number value = (Number) operand.evaluate(context);
            if (value instanceof Float) {
                return new Float(-value.floatValue());
            } else if (value instanceof Long) {
                return new Long(-value.longValue());
            } else if (value instanceof Double) {
                return new Double(-value.doubleValue());
            } else {
                return new Integer(-value.intValue());
            }
        }

        public String toString() {
            return "-" + operand;
        }
    }

    public static abstract class Arithmetic extends Binary {
        // For declarative purposes
        public Arithmetic(Expression lhs, Expression rhs) {
            super(lhs,rhs);
        }

        public Object evaluate(QueryContext context) {
            Number lhv = (Number) lhs.evaluate(context);
            Number rhv = (Number) rhs.evaluate(context);
            return evaluateNumeric(lhv, rhv);
        }

        protected abstract Object evaluateNumeric(Number lhs, Number rhs);

        public Class getType() {
            if (Double.class.equals(lhs.getType()) 
                || Double.class.equals(rhs.getType())) {
                return Double.class;
            } else if (Float.class.equals(lhs.getType()) 
                       || Float.class.equals(rhs.getType())) {
                return Float.class;
            } else if (Long.class.equals(lhs.getType()) 
                       || Long.class.equals(rhs.getType())) {
                return Long.class;
            } else {
                return Integer.class;
            }
        }
    }

    public static class Multiply extends Arithmetic {
        public Multiply(Expression lhs, Expression rhs) {
            super(lhs, rhs);
        }
  
        public Object evaluateNumeric(Number lhs, Number rhs) {
            if ((lhs instanceof Double) || (rhs instanceof Double)) {
                // Treat as double
                return new Double(lhs.doubleValue() * rhs.doubleValue());
            } else if ((lhs instanceof Float) || (rhs instanceof Float)) {
                // Treat as float
                return new Float(lhs.floatValue() * rhs.floatValue());
            } else if ((lhs instanceof Long) || (rhs instanceof Long)) {
                // Treat as long
                return new Long(lhs.longValue() * rhs.longValue());
            } else {
                // Treat as int
                return new Integer(lhs.intValue() * rhs.intValue());
            }
        }

        public Operator operator() { return Operator.TIMES; }
    }

    public static class Modulo extends Arithmetic {
        public Modulo(Expression lhs, Expression rhs) {
            super(lhs, rhs);
        }
  
        public Object evaluateNumeric(Number lhs, Number rhs) {
            if ((lhs instanceof Double) || (rhs instanceof Double)) {
                // Treat as double
                return new Double(lhs.doubleValue() % rhs.doubleValue());
            } else if ((lhs instanceof Float) || (rhs instanceof Float)) {
                // Treat as float
                return new Float(lhs.floatValue() % rhs.floatValue());
            } else if ((lhs instanceof Long) || (rhs instanceof Long)) {
                // Treat as long
                return new Long(lhs.longValue() % rhs.longValue());
            } else {
                // Treat as int
                return new Integer(lhs.intValue() % rhs.intValue());
            }
        }

        public Operator operator() { return Operator.MODULO; }
    }

    public static class Divide extends Arithmetic {
        public Divide(Expression lhs, Expression rhs) {
            super(lhs, rhs);
        }
  
        public Object evaluateNumeric(Number lhs, Number rhs) {
            if ((lhs instanceof Double) || (rhs instanceof Double)) {
                // Treat as double
                return new Double(lhs.doubleValue() / rhs.doubleValue());
            } else if ((lhs instanceof Float) || (rhs instanceof Float)) {
                // Treat as float
                return new Float(lhs.floatValue() / rhs.floatValue());
            } else if ((lhs instanceof Long) || (rhs instanceof Long)) {
                // Treat as long
                return new Long(lhs.longValue() / rhs.longValue());
            } else {
                // Treat as int
                return new Integer(lhs.intValue() / rhs.intValue());
            }
        }

        public Operator operator() { return Operator.DIVIDE; }
    }

    public static class Add extends Arithmetic {
        public Add(Expression lhs, Expression rhs) {
            super(lhs, rhs);
        }
  
        public Object evaluate(QueryContext context) {
            Object lhv = lhs.evaluate(context);
            Object rhv = rhs.evaluate(context);
            if (lhv instanceof String) {
                return lhv.toString() + rhv;
            } else if (rhv instanceof String) {
                return lhv + rhv.toString();
            } else {
                return evaluateNumeric((Number) lhv, (Number) rhv);
            }
        }

        public Object evaluateNumeric(Number lhs, Number rhs) {
            if ((lhs instanceof Double) || (rhs instanceof Double)) {
                // Treat as double
                return new Double(lhs.doubleValue() + rhs.doubleValue());
            } else if ((lhs instanceof Float) || (rhs instanceof Float)) {
                // Treat as float
                return new Float(lhs.floatValue() + rhs.floatValue());
            } else if ((lhs instanceof Long) || (rhs instanceof Long)) {
                // Treat as long
                return new Long(lhs.longValue() + rhs.longValue());
            } else {
                // Treat as int
                return new Integer(lhs.intValue() + rhs.intValue());
            }
        }

        public Operator operator() { return Operator.PLUS; }
    }

    public static class Subtract extends Arithmetic {
        public Subtract(Expression lhs, Expression rhs) {
            super(lhs, rhs);
        }
  
        public Object evaluateNumeric(Number lhs, Number rhs) {
            if ((lhs instanceof Double) || (rhs instanceof Double)) {
                // Treat as double
                return new Double(lhs.doubleValue() - rhs.doubleValue());
            } else if ((lhs instanceof Float) || (rhs instanceof Float)) {
                // Treat as float
                return new Float(lhs.floatValue() - rhs.floatValue());
            } else if ((lhs instanceof Long) || (rhs instanceof Long)) {
                // Treat as long
                return new Long(lhs.longValue() - rhs.longValue());
            } else {
                // Treat as int
                return new Integer(lhs.intValue() - rhs.intValue());
            }
        }

        public Operator operator() { return Operator.MINUS; }
    }

    public static class Cast extends Unary {
        protected Class type;
  
        public Cast(Class type, Expression operand) {
            super(operand);
            this.type = type;
        }

        public Object evaluate(QueryContext context) {
            return operand;
        }

        public Class getType() {
            return type;
        }

        public String toString() {
            return "(" + type.getName() + ") " + operand;
        }
    }

    public static class Not extends Unary {
        public Not(Expression operand) {
            super(operand);
        }

        public Object evaluate(QueryContext context) {
            return Boolean.valueOf(!(((Boolean) operand.evaluate(context)).booleanValue()));
        }

        public void accept(ExpressionVisitor visitor) {
            if (!visitor.visitNot(this))
                super.accept(visitor);
        }

        public String toString() {
            return "!" + operand;
        }
    }

    public static class BitwiseComplement extends Unary {
        public BitwiseComplement(Expression operand) {
            super(operand);
        }

        public Object evaluate(QueryContext context) {
            Object value = operand.evaluate(context);
            if (value instanceof Long) {
                return new Long(~((Long) value).longValue());
            } else if (value instanceof Integer) {
                return new Integer(~((Integer) value).intValue());
            } else if (value instanceof Short) {
                return new Integer(~((Short) value).shortValue());
            } else if (value instanceof Byte) {
                return new Integer(~((Byte) value).byteValue());
            }
            throw new IllegalArgumentException();
        }
  
        public Class getType() {
            return (operand.getType().equals(Long.class)) ?
                Long.class : Integer.class;
        }

        public String toString() {
            return "~" + operand;
        }
    }

    /**
     * Converts a String object into its representation in
     * a Java source file by adding double quotes around it
     * and escaping any special characters within.
     */
    public static String escapeString(String input) {
        int len = input.length();
        StringBuffer sb = new StringBuffer(len + 2);
        sb.append('"');
        for (int i = 0; i < len; i++) {
            escapeCharImpl(input.charAt(i), sb);
        }
        sb.append('"');
        return sb.toString();
    }

    /**
     * Converts a character into its representation in a Java
     * source file by adding single quotes around it and
     * escaping it if it's a special character.
     */
    public static String escapeChar(char ch) {
        StringBuffer sb = new StringBuffer(3);
        sb.append('\'');
        escapeCharImpl(ch, sb);
        sb.append('\'');
        return sb.toString();
    }

    /** Escapes the character given and adds it to the StringBuffer. */
    private static void escapeCharImpl(char ch, StringBuffer sb) {
        switch (ch) {
        case '"':
        case '\'':
        case '\\':
            sb.append('\\').append(ch);
            break;
        case '\t':
            sb.append("\\t");
            break;
        case '\n':
            sb.append("\\n");
            break;
        case '\r':
            sb.append("\\r");
            break;
        case '\b':
            sb.append("\\b");
            break;
        case '\f':
            sb.append("\\f");
            break;
        default:
            sb.append(ch);
        }
    }

    /**
     * Locates the field in the class or superclass chain,
     * swallowing all exceptions.
     */
    private static Field findField(Class clazz, String name) {
        while (!Object.class.equals(clazz)) {
            try {
                return clazz.getDeclaredField(name);
            } catch (NoSuchFieldException e) {
                clazz = clazz.getSuperclass();
            }
        }
        return null;
    }

    /** 
     * Locates the method in the class, superclass chain, or interfaces,
     * swallowing all exceptions.
     */
    private static Method findMethod(Class clazz, String name, Class[] paramTypes) {
        try {
            return clazz.getDeclaredMethod(name, paramTypes);
        } catch (NoSuchMethodException e) {
            Method m = null;
            Class superclass = clazz.getSuperclass();
            if (superclass != null) {
                m = findMethod(superclass, name, paramTypes);
            }
            if (m == null) {
                Class[] interfaces = clazz.getInterfaces();
                for (int i = 0; i < interfaces.length; i++) {
                    m = findMethod(interfaces[i], name, paramTypes);
                    if (m != null) {
                        return m;
                    }
                }
            }
        }
        return null;
    }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.