Return-Path: Delivered-To: apmail-db-jdo-commits-archive@www.apache.org Received: (qmail 46420 invoked from network); 22 May 2005 18:09:26 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 22 May 2005 18:09:26 -0000 Received: (qmail 22565 invoked by uid 500); 22 May 2005 18:09:25 -0000 Mailing-List: contact jdo-commits-help@db.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: jdo-dev@db.apache.org Delivered-To: mailing list jdo-commits@db.apache.org Received: (qmail 22475 invoked by uid 99); 22 May 2005 18:09:24 -0000 X-ASF-Spam-Status: No, hits=-9.8 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from minotaur.apache.org (HELO minotaur.apache.org) (209.237.227.194) by apache.org (qpsmtpd/0.28) with SMTP; Sun, 22 May 2005 11:09:20 -0700 Received: (qmail 46347 invoked by uid 65534); 22 May 2005 18:09:18 -0000 Message-ID: <20050522180918.46346.qmail@minotaur.apache.org> Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Subject: svn commit: r171353 [2/13] - in /incubator/jdo/trunk/query20: ./ src/ src/conf/ src/java/ src/java/org/ src/java/org/apache/ src/java/org/apache/jdo/ src/java/org/apache/jdo/impl/ src/java/org/apache/jdo/impl/jdoql/ src/java/org/apache/jdo/impl/jdoql/jdoqlc/ src/java/org/apache/jdo/impl/jdoql/scope/ src/java/org/apache/jdo/impl/jdoql/tree/ src/java/org/apache/jdo/jdoql/ src/java/org/apache/jdo/jdoql/tree/ Date: Sun, 22 May 2005 18:09:00 -0000 To: jdo-commits@db.apache.org From: mbo@apache.org X-Mailer: svnmailer-1.0.0-dev X-Virus-Checked: Checked X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N Added: incubator/jdo/trunk/query20/src/java/org/apache/jdo/impl/jdoql/Memor= yQuery.java URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/query20/src/java/org= /apache/jdo/impl/jdoql/MemoryQuery.java?rev=3D171353&view=3Dauto =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/jdo/trunk/query20/src/java/org/apache/jdo/impl/jdoql/MemoryQu= ery.java (added) +++ incubator/jdo/trunk/query20/src/java/org/apache/jdo/impl/jdoql/MemoryQu= ery.java Sun May 22 11:08:57 2005 @@ -0,0 +1,1484 @@ +/* + * Copyright 2005 The Apache Software Foundation. + *=20 + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at=20 + *=20 + * http://www.apache.org/licenses/LICENSE-2.0 + *=20 + * Unless required by applicable law or agreed to in writing, software=20 + * distributed under the License is distributed on an "AS IS" BASIS,=20 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied= .=20 + * See the License for the specific language governing permissions and=20 + * limitations under the License. + */ + +package org.apache.jdo.impl.jdoql; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.Iterator; +import java.util.List; +import java.util.Collections; + +import javax.jdo.JDOHelper; +import javax.jdo.PersistenceManager; + +import org.apache.jdo.impl.jdoql.scope.ParameterTable; +import org.apache.jdo.impl.jdoql.scope.UNDEFINED; +import org.apache.jdo.impl.jdoql.scope.VariableTable; +import org.apache.jdo.jdoql.JDOQueryException; +import org.apache.jdo.jdoql.tree.AbstractNodeVisitor; +import org.apache.jdo.jdoql.tree.AndExpression; +import org.apache.jdo.jdoql.tree.CastExpression; +import org.apache.jdo.jdoql.tree.ComplementExpression; +import org.apache.jdo.jdoql.tree.ConditionalAndExpression; +import org.apache.jdo.jdoql.tree.ConditionalOrExpression; +import org.apache.jdo.jdoql.tree.ConstantExpression; +import org.apache.jdo.jdoql.tree.ContainsCallExpression; +import org.apache.jdo.jdoql.tree.DivideExpression; +import org.apache.jdo.jdoql.tree.EndsWithCallExpression; +import org.apache.jdo.jdoql.tree.EqualsExpression; +import org.apache.jdo.jdoql.tree.Expression; +import org.apache.jdo.jdoql.tree.FieldAccessExpression; +import org.apache.jdo.jdoql.tree.GreaterThanEqualsExpression; +import org.apache.jdo.jdoql.tree.GreaterThanExpression; +import org.apache.jdo.jdoql.tree.IsEmptyCallExpression; +import org.apache.jdo.jdoql.tree.LessThanEqualsExpression; +import org.apache.jdo.jdoql.tree.LessThanExpression; +import org.apache.jdo.jdoql.tree.MinusExpression; +import org.apache.jdo.jdoql.tree.NotEqualsExpression; +import org.apache.jdo.jdoql.tree.NotExpression; +import org.apache.jdo.jdoql.tree.OrExpression; +import org.apache.jdo.jdoql.tree.OrderingExpression; +import org.apache.jdo.jdoql.tree.ParameterAccessExpression; +import org.apache.jdo.jdoql.tree.PlusExpression; +import org.apache.jdo.jdoql.tree.StartsWithCallExpression; +import org.apache.jdo.jdoql.tree.StaticFieldAccessExpression; +import org.apache.jdo.jdoql.tree.ThisExpression; +import org.apache.jdo.jdoql.tree.TimesExpression; +import org.apache.jdo.jdoql.tree.TreeWalker; +import org.apache.jdo.jdoql.tree.UnaryMinusExpression; +import org.apache.jdo.jdoql.tree.UnaryPlusExpression; +import org.apache.jdo.jdoql.tree.VariableAccessExpression; +import org.apache.jdo.pm.PersistenceManagerInternal; +import org.apache.jdo.util.I18NHelper; + +/** + * An instance of this class is used to evaluate a + * query tree in memory. For this purpose this class keeps references + * to a parameter/variable table and to the current object corresponding + * with a ThisExpression. + * It extends AbstractNodeVisitor. + * To evaluate a query tree, you need to pass the query tree instance and + * an instance of this class to method walk of a tree walker + * instance. + * + * @author Michael Watzek + */ +public class MemoryQuery extends AbstractNodeVisitor +{ + /** I18N support */ + final static I18NHelper msg =3D I18NHelper.getInstance(MemoryQuery.cla= ss); + final static UNDEFINED undefined =3D UNDEFINED.getInstance(); + + final TreeWalker walker =3D new TreeWalker(); + final List boundVariables =3D new ArrayList(); + VariableAccessExpression unboundVariableAccess =3D null; + BoundVariable removedBoundVariable =3D null; + + final PersistenceManagerInternal pm; + final ParameterTable parameters; + final VariableTable variables; + Object current; + + /** + * Constructs an instance of this class for the specified paramter tab= le + * and variable table. This query evaluator uses reflection for + * field accesses. + * @param parameters the parameter table + * @param variables the variable table + */ + public MemoryQuery(ParameterTable parameters, VariableTable variables) + { this( null, parameters, variables ); + } + + /** + * Constructs an instance of this class for the specified paramter tab= le + * and variable table. + * @param pm the persistence manager + * @param parameters the parameter table + * @param variables the variable table + */ + public MemoryQuery(PersistenceManagerInternal pm, ParameterTable param= eters, VariableTable variables) + { this.pm =3D pm; + this.parameters =3D parameters; + this.variables =3D variables; + } + + /** + * Sets the instance returned by leaving an instance if + * ThisExpression. + * @param current the instance to set + */ + public void setCurrent(Object current) + { this.current =3D current; + } + + //public methods of NodeVisitor + + /** + * Returns the result evaluated for the argument node. + * The argument results contains the results evaluated + * by the children of the argument node. The result + * returned by this method is based on the results evaluated by the ch= ildren + * of the argument node. + * @param node the node to be evaluated + * @param results the results evaluated by children of node + * @return the result evaluated for node + * @exception JDOQueryException if the results evaluated by the node's + * children are non boolean types + */ + public Object leave(AndExpression node, Object[] results) + { Class clazz =3D node.getJavaClass(); + if( clazz=3D=3DBoolean.class || clazz=3D=3Dboolean.class ) + return logicalAnd( results[0], results[1] ); + throw new JDOQueryException( msg.msg("EXC_IllegalResultTypeForExpr= ession", "&", clazz.getName()) ); //NOI18N + } + + /** + * Returns the result evaluated for the argument node. + * The argument results contains the result evaluated + * by the child of the argument node. The result + * returned by this method is the same as the result evaluated by the = child + * of the argument node. + * @param node the node to be evaluated + * @param results the result evaluated by the node's child + * @return the result evaluated for node + * @exception JDOQueryException if the result evaluated by the node's + * child is not an instance of the type to cast to + */ + public Object leave(CastExpression node, Object[] results) + { Object value =3D results[1]; + if( value=3D=3Dundefined ) + return undefined; + Class clazz =3D node.getJavaClass(); + if( value!=3Dnull && + !clazz.isInstance(value) ) + { =20 + if( clazz=3D=3DByte.class || clazz=3D=3Dbyte.class ) { + if( value instanceof Character ) + return new Byte( (byte)((Character)value).charValue() = ); + else + return new Byte( ((Number)value).byteValue() ); + } + else if( clazz=3D=3DDouble.class || clazz=3D=3Ddouble.class ) { + if( value instanceof Character ) + return new Double( ((Character)value).charValue() ); + else + return new Double( ((Number)value).doubleValue() ); + } + else if( clazz=3D=3DFloat.class || clazz=3D=3Dfloat.class ) { + if( value instanceof Character ) + return new Float( ((Character)value).charValue() ); + else + return new Float( ((Number)value).floatValue() ); + } + else if( clazz=3D=3DInteger.class || clazz=3D=3Dint.class ) { + if( value instanceof Character ) + return new Integer( ((Character)value).charValue() ); + else + return new Integer( ((Number)value).intValue() ); + } + else if( clazz=3D=3DLong.class || clazz=3D=3Dlong.class ) { + if( value instanceof Character ) + return new Long( ((Character)value).charValue() ); + else + return new Long( ((Number)value).longValue() ); + } + else if( clazz=3D=3DShort.class || clazz=3D=3Dshort.class ) { + if( value instanceof Character ) + return new Short( (short) ((Character)value).charValue= () ); + else + return new Short( ((Number)value).shortValue() ); + } + else if( clazz=3D=3DBigInteger.class ) { + if( value instanceof Character ) + return BigInteger.valueOf( (long) ((Character)value).ch= arValue() ); + else + return BigInteger.valueOf( ((Number)value).longValue()= ); + } + else if( clazz=3D=3DBigDecimal.class ) { + if( value instanceof Character ) + return new BigDecimal( (double) ((Character)value).cha= rValue() ); + else + return new BigDecimal( ((Number)value).doubleValue() ); + } + else if( clazz=3D=3DCharacter.class || clazz=3D=3Dchar.class )= { + if (value instanceof Number ) + return new Character((char)((Number)value).intValue()); + else + return value; + } + // value is not null and is not an instance of the type + // specified in the cast expression =3D> return undefined + return undefined; + } + return value; + } + + /** + * Returns the result evaluated for the argument node. + * The argument results contains the result evaluated + * by the child of the argument node. The result + * returned by this method is based on the result evaluated by the chi= ld + * of the argument node. + * @param node the node to be evaluated + * @param results the result evaluated by the node's child + * @return the result evaluated for node + * @exception JDOQueryException if the result evaluated by the node's + * child is not a boolean or integral type. + */ + public Object leave(ComplementExpression node, Object[] results) + { if( results[0]=3D=3Dnull || + results[0]=3D=3Dundefined ) + return undefined; + Class clazz =3D node.getJavaClass(); + if( clazz=3D=3DInteger.class || clazz=3D=3Dint.class ) + return new Integer( ~((Number)results[0]).intValue() ); + else if( clazz=3D=3DLong.class || clazz=3D=3Dlong.class ) + return new Long( ~((Number)results[0]).longValue() ); + else if( clazz=3D=3DBigInteger.class ) + return ((BigInteger)results[0]).not(); + else if( clazz=3D=3DByte.class || clazz=3D=3Dbyte.class ) + return new Byte( (byte) ~((Number)results[0]).byteValue() ); + else if( clazz=3D=3DCharacter.class || clazz=3D=3Dchar.class ) + return new Character( (char) ~((Character)results[0]).charValu= e() ); + else if( clazz=3D=3DShort.class || clazz=3D=3Dshort.class ) + return new Short( (short) ~((Number)results[0]).shortValue() ); + throw new JDOQueryException( msg.msg("EXC_IllegalResultTypeForExpr= ession", "~", clazz.getName()) ); //NOI18N + } + + /** + * Returns the result evaluated for the argument node. + * The argument results contains the results evaluated + * by the children of the argument node. The result + * returned by this method is based on the results evaluated by the ch= ildren + * of the argument node. + * @param node the node to be evaluated + * @param results the results evaluated by children of node + * @return the result evaluated for node + * @exception JDOQueryException if the results evaluated by the node's + * children are non boolean types + */ + public Object leave(ConditionalAndExpression node, Object[] results) + { Class clazz =3D node.getJavaClass(); + if( clazz=3D=3DBoolean.class || clazz=3D=3Dboolean.class ) + return logicalAnd( results[0], results[1] ); + throw new JDOQueryException( msg.msg("EXC_IllegalResultTypeForExpr= ession", "&&", clazz.getName()) ); //NOI18N + } + + /** + * Returns the result evaluated for the argument node. + * The argument results contains the results evaluated + * by the children of the argument node. The result + * returned by this method is based on the results evaluated by the ch= ildren + * of the argument node. + * @param node the node to be evaluated + * @param results the results evaluated by children of node + * @return the result evaluated for node + * @exception JDOQueryException if the results evaluated by the node's + * children are non boolean types + */ + public Object leave(ConditionalOrExpression node, Object[] results) + { Class clazz =3D node.getJavaClass(); + if( clazz=3D=3DBoolean.class || clazz=3D=3Dboolean.class ) + return logicalOr( results[0], results[1] ); + throw new JDOQueryException( msg.msg("EXC_IllegalResultTypeForExpr= ession", "||", clazz.getName()) ); //NOI18N + } + + /** + * Returns the result evaluated for the argument node. + * The argument results is null as the argum= ent + * node does not have any children. The result + * returned by this method is the object wrapped by the argument node. + * @param node the node to be evaluated + * @param results null + * @return the object wrapped by node + */ + public Object leave(ConstantExpression node, Object[] results) + { return node.getValue(); + } + + /** + * Returns the result evaluated for the argument node. + * The argument results contains the results evaluated + * by the children of the argument node. The result + * returned by this method is based on the results evaluated by the ch= ildren + * of the argument node. + * @param node the node to be evaluated + * @param results the results evaluated by children of node + * @return the result evaluated for node + */ + public Object leave(ContainsCallExpression node, Object[] results) + { if( results[0]=3D=3Dnull || + results[0]=3D=3Dundefined ) + { // bind an empty set to the variable, if collection evaluates + // to null or undefined, otherwise the variable access results + // in an exception that unbound variables are not supported. + if( this.unboundVariableAccess!=3Dnull ) + { this.boundVariables.add( new BoundVariable(this.unboundVa= riableAccess.getName(), this.unboundVariableAccess.getJavaClass(), Collecti= ons.EMPTY_SET) ); + } + this.unboundVariableAccess =3D null; + return undefined; + } + Collection collection =3D (Collection) results[0]; + boolean result; + if( this.unboundVariableAccess!=3Dnull ) + { this.boundVariables.add( new BoundVariable(this.unboundVariab= leAccess.getName(), this.unboundVariableAccess.getJavaClass(), collection) = ); + result =3D !collection.isEmpty(); + } + else + result =3D ((Collection)results[0]).contains( results[1] ); + this.unboundVariableAccess =3D null; + return result ? Boolean.TRUE : Boolean.FALSE; + } + + /** + * Returns the result evaluated for the argument node. + * The argument results contains the results evaluated + * by the children of the argument node. The result + * returned by this method is based on the results evaluated by the ch= ildren + * of the argument node. + * @param node the node to be evaluated + * @param results the results evaluated by children of node + * @return the result evaluated for node + * @exception JDOQueryException if the results evaluated by the node's + * children are non integral types + */ + public Object leave(DivideExpression node, Object[] results) + { if( results[0]=3D=3Dnull || results[1]=3D=3Dnull || + results[0]=3D=3Dundefined || results[1]=3D=3Dundefined ) + return undefined; + Class clazz =3D node.getJavaClass(); + if( clazz=3D=3DInteger.class || clazz=3D=3Dint.class ) + return new Integer( ((Number)results[0]).intValue() / ((Number= )results[1]).intValue() ); + else if( clazz=3D=3DLong.class || clazz=3D=3Dlong.class ) + return new Long( ((Number)results[0]).longValue() / ((Number)r= esults[1]).longValue() ); + else if( clazz=3D=3DDouble.class || clazz=3D=3Ddouble.class ) + return new Double( ((Number)results[0]).doubleValue() / ((Numb= er)results[1]).doubleValue() ); + else if( clazz=3D=3DFloat.class || clazz=3D=3Dfloat.class ) + return new Float( ((Number)results[0]).floatValue() / ((Number= )results[1]).floatValue() ); + else if( clazz=3D=3DBigDecimal.class ) + { BigDecimal left, right; + if( results[0] instanceof BigDecimal ) + left =3D (BigDecimal) results[0]; + else + left =3D new BigDecimal( results[0].toString() ); + if( results[1] instanceof BigDecimal ) + right =3D (BigDecimal) results[1]; + else + right =3D new BigDecimal( results[1].toString() ); + return left.divide( right, BigDecimal.ROUND_HALF_UP ); + } + else if( clazz=3D=3DBigInteger.class ) + { BigInteger left, right; + if( results[0] instanceof BigInteger ) + left =3D (BigInteger) results[0]; + else + left =3D new BigInteger( results[0].toString() ); + if( results[1] instanceof BigInteger ) + right =3D (BigInteger) results[1]; + else + right =3D new BigInteger( results[1].toString() ); + return left.divide( right ); + } + else if( clazz=3D=3DByte.class || clazz=3D=3Dbyte.class ) + return new Byte( (byte) (((Number)results[0]).byteValue() / ((= Number)results[1]).byteValue()) ); + else if( clazz=3D=3DCharacter.class || clazz=3D=3Dchar.class ) + return new Character( (char) (((Character)results[0]).charValu= e() / ((Character)results[1]).charValue()) ); + else if( clazz=3D=3DShort.class || clazz=3D=3Dshort.class ) + return new Short( (short) (((Number)results[0]).shortValue() /= ((Number)results[1]).shortValue()) ); + throw new JDOQueryException( msg.msg("EXC_IllegalResultTypeForExpr= ession", "/", clazz.getName()) ); //NOI18N + } + + /** + * Returns the result evaluated for the argument node. + * The argument results contains the results evaluated + * by the children of the argument node. The result + * returned by this method is based on the results evaluated by the ch= ildren + * of the argument node. + * @param node the node to be evaluated + * @param results the results evaluated by children of node + * @return the result evaluated for node + */ + public Object leave(EndsWithCallExpression node, Object[] results) + { if( results[0]=3D=3Dnull || + results[0]=3D=3Dundefined ) + return undefined; + boolean result =3D ((String)results[0]).endsWith( (String)results[= 1] ); + return result ? Boolean.TRUE : Boolean.FALSE; + } + + /** + * Returns the result evaluated for the argument node. + * The argument results contains the results evaluated + * by the children of the argument node. The result + * returned by this method is based on the results evaluated by the ch= ildren + * of the argument node. + * @param node the node to be evaluated + * @param results the results evaluated by children of node + * @return the result evaluated for node + */ + public Object leave(EqualsExpression node, Object[] results) + { if( results[0]=3D=3Dundefined || results[1]=3D=3Dundefined ) + return undefined; + boolean result; + if( results[0]=3D=3Dnull && results[1]=3D=3Dnull ) + result =3D true; + else if( results[0]=3D=3Dnull || results[1]=3D=3Dnull ) + result =3D false; + else + { Class clazz =3D node.getCommonOperandType(); + if( clazz=3D=3DInteger.class || clazz=3D=3Dint.class ) + result =3D ((Number)results[0]).intValue() =3D=3D ((Number= )results[1]).intValue(); + else if( clazz=3D=3DLong.class || clazz=3D=3Dlong.class ) + result =3D ((Number)results[0]).longValue() =3D=3D ((Numbe= r)results[1]).longValue(); + else if( clazz=3D=3DDouble.class || clazz=3D=3Ddouble.class ) + result =3D ((Number)results[0]).doubleValue() =3D=3D ((Num= ber)results[1]).doubleValue(); + else if( clazz=3D=3DFloat.class || clazz=3D=3Dfloat.class ) + result =3D ((Number)results[0]).floatValue() =3D=3D ((Numb= er)results[1]).floatValue(); + else if( clazz=3D=3DBigDecimal.class ) + { BigDecimal left, right; + if( results[0] instanceof BigDecimal ) + left =3D (BigDecimal) results[0]; + else + left =3D new BigDecimal( results[0].toString() ); + if( results[1] instanceof BigDecimal ) + right =3D (BigDecimal) results[1]; + else + right =3D new BigDecimal( results[1].toString() ); + result =3D left.compareTo( right ) =3D=3D 0; + } + else if( clazz=3D=3DBigInteger.class ) + { BigInteger left, right; + if( results[0] instanceof BigInteger ) + left =3D (BigInteger) results[0]; + else + left =3D new BigInteger( results[0].toString() ); + if( results[1] instanceof BigInteger ) + right =3D (BigInteger) results[1]; + else + right =3D new BigInteger( results[1].toString() ); + result =3D left.compareTo( right ) =3D=3D 0; + } + else if( Date.class.isAssignableFrom(clazz) ) + result =3D ((Date)results[0]).getTime() =3D=3D ((Date)resu= lts[1]).getTime(); + else if( clazz=3D=3DByte.class || clazz=3D=3Dbyte.class ) + result =3D ((Number)results[0]).byteValue() =3D=3D ((Numbe= r)results[1]).byteValue(); + else if( clazz=3D=3DCharacter.class || clazz=3D=3Dchar.class ) + result =3D ((Character)results[0]).charValue() =3D=3D ((Ch= aracter)results[1]).charValue(); + else if( clazz=3D=3DShort.class || clazz=3D=3Dshort.class ) + result =3D ((Number)results[0]).shortValue() =3D=3D ((Numb= er)results[1]).shortValue(); + else=20 + { PersistenceManager leftPM =3D JDOHelper.getPersistenceMana= ger(results[0]); + PersistenceManager rightPM =3D JDOHelper.getPersistenceMan= ager(results[1]); + if( leftPM!=3Dnull && rightPM!=3Dnull ) + // use =3D=3D for persistence instances + result =3D results[0] =3D=3D results[1]; + else if( leftPM=3D=3Dnull && rightPM=3D=3Dnull ) + // use equals for non persistent instances + result =3D results[0].equals( results[1] ); + else=20 + // comparing persistent with non persistent instance + result =3D false; + } + } + return result ? Boolean.TRUE : Boolean.FALSE; + } + + /** + * Returns the result evaluated for the argument node. + * The argument results contains the results evaluated + * by the children of the argument node. The result + * returned by this method is based on the results evaluated by the ch= ildren + * of the argument node. + * @param node the node to be evaluated + * @param results the results evaluated by children of node + * @return the result evaluated for node + * @exception JDOQueryException if the results evaluated by the node's + * children is undefined + */ + public Object leave(FieldAccessExpression node, Object[] results) + { if( results[0]=3D=3Dnull || + results[0]=3D=3Dundefined ) + return undefined; + return node.getFieldValue( pm, results[0] ); + } + + /** + * Returns the result evaluated for the argument node. + * The argument results contains the results evaluated + * by the children of the argument node. The result + * returned by this method is based on the results evaluated by the ch= ildren + * of the argument node. + * @param node the node to be evaluated + * @param results the results evaluated by children of node + * @return the result evaluated for node + * @exception JDOQueryException if the results evaluated by the node's + * children are non integral types + */ + public Object leave(GreaterThanEqualsExpression node, Object[] results) + { if( results[0]=3D=3Dnull || results[1]=3D=3Dnull || + results[0]=3D=3Dundefined || results[1]=3D=3Dundefined ) + return undefined; + boolean result; + Class clazz =3D node.getCommonOperandType(); + if( clazz=3D=3DInteger.class || clazz=3D=3Dint.class ) + result =3D ((Number)results[0]).intValue() >=3D ((Number)resul= ts[1]).intValue(); + else if( clazz=3D=3DLong.class || clazz=3D=3Dlong.class ) + result =3D ((Number)results[0]).longValue() >=3D ((Number)resu= lts[1]).longValue(); + else if( clazz=3D=3DDouble.class || clazz=3D=3Ddouble.class ) + result =3D ((Number)results[0]).doubleValue() >=3D ((Number)re= sults[1]).doubleValue(); + else if( clazz=3D=3DFloat.class || clazz=3D=3Dfloat.class ) + result =3D ((Number)results[0]).floatValue() >=3D ((Number)res= ults[1]).floatValue(); + else if( clazz=3D=3DBigDecimal.class ) + { BigDecimal left, right; + if( results[0] instanceof BigDecimal ) + left =3D (BigDecimal) results[0]; + else + left =3D new BigDecimal( results[0].toString() ); + if( results[1] instanceof BigDecimal ) + right =3D (BigDecimal) results[1]; + else + right =3D new BigDecimal( results[1].toString() ); + result =3D left.compareTo(right) >=3D 0; + } + else if( clazz=3D=3DBigInteger.class ) + { BigInteger left, right; + if( results[0] instanceof BigInteger ) + left =3D (BigInteger) results[0]; + else + left =3D new BigInteger( results[0].toString() ); + if( results[1] instanceof BigInteger ) + right =3D (BigInteger) results[1]; + else + right =3D new BigInteger( results[1].toString() ); + result =3D left.compareTo(right) >=3D 0; + } + // Comparable covers Date and String + else if( Comparable.class.isAssignableFrom(clazz) ) + result =3D ((Comparable)results[0]).compareTo((Comparable)resu= lts[1]) >=3D 0; + else if( clazz=3D=3DByte.class || clazz=3D=3Dbyte.class ) + result =3D ((Number)results[0]).byteValue() >=3D ((Number)resu= lts[1]).byteValue(); + else if( clazz=3D=3DCharacter.class || clazz=3D=3Dchar.class ) + result =3D ((Character)results[0]).charValue() >=3D ((Characte= r)results[1]).charValue(); + else if( clazz=3D=3DShort.class || clazz=3D=3Dshort.class ) + result =3D ((Number)results[0]).shortValue() >=3D ((Number)res= ults[1]).shortValue(); + else + throw new JDOQueryException( msg.msg("EXC_IllegalResultTypeFor= Expression", ">=3D", clazz.getName()) ); //NOI18N + return result ? Boolean.TRUE : Boolean.FALSE; + } + + /** + * Returns the result evaluated for the argument node. + * The argument results contains the results evaluated + * by the children of the argument node. The result + * returned by this method is based on the results evaluated by the ch= ildren + * of the argument node. + * @param node the node to be evaluated + * @param results the results evaluated by children of node + * @return the result evaluated for node + * @exception JDOQueryException if the results evaluated by the node's + * children are non integral types + */ + public Object leave(GreaterThanExpression node, Object[] results) + { if( results[0]=3D=3Dnull || results[1]=3D=3Dnull || + results[0]=3D=3Dundefined || results[1]=3D=3Dundefined ) + return undefined; + boolean result; + Class clazz =3D node.getCommonOperandType(); + if( clazz=3D=3DInteger.class || clazz=3D=3Dint.class ) + result =3D ((Number)results[0]).intValue() > ((Number)results[= 1]).intValue(); + else if( clazz=3D=3DLong.class || clazz=3D=3Dlong.class ) + result =3D ((Number)results[0]).longValue() > ((Number)results= [1]).longValue(); + else if( clazz=3D=3DDouble.class || clazz=3D=3Ddouble.class ) + result =3D ((Number)results[0]).doubleValue() > ((Number)resul= ts[1]).doubleValue(); + else if( clazz=3D=3DFloat.class || clazz=3D=3Dfloat.class ) + result =3D ((Number)results[0]).floatValue() > ((Number)result= s[1]).floatValue(); + else if( clazz=3D=3DBigDecimal.class ) + { BigDecimal left, right; + if( results[0] instanceof BigDecimal ) + left =3D (BigDecimal) results[0]; + else + left =3D new BigDecimal( results[0].toString() ); + if( results[1] instanceof BigDecimal ) + right =3D (BigDecimal) results[1]; + else + right =3D new BigDecimal( results[1].toString() ); + result =3D left.compareTo(right) > 0; + } + else if( clazz=3D=3DBigInteger.class ) + { BigInteger left, right; + if( results[0] instanceof BigInteger ) + left =3D (BigInteger) results[0]; + else + left =3D new BigInteger( results[0].toString() ); + if( results[1] instanceof BigInteger ) + right =3D (BigInteger) results[1]; + else + right =3D new BigInteger( results[1].toString() ); + result =3D left.compareTo(right) > 0; + } + // Comparable covers Date and String + else if( Comparable.class.isAssignableFrom(clazz) ) + result =3D ((Comparable)results[0]).compareTo((Comparable)resu= lts[1]) > 0; + else if( clazz=3D=3DByte.class || clazz=3D=3Dbyte.class ) + result =3D ((Number)results[0]).byteValue() > ((Number)results= [1]).byteValue(); + else if( clazz=3D=3DCharacter.class || clazz=3D=3Dchar.class ) + result =3D ((Character)results[0]).charValue() > ((Character)r= esults[1]).charValue(); + else if( clazz=3D=3DShort.class || clazz=3D=3Dshort.class ) + result =3D ((Number)results[0]).shortValue() > ((Number)result= s[1]).shortValue(); + else + throw new JDOQueryException( msg.msg("EXC_IllegalResultTypeFor= Expression", ">", clazz.getName()) ); //NOI18N + return result ? Boolean.TRUE : Boolean.FALSE; + } + + /** + * Returns the result evaluated for the argument node. + * The argument results contains the results evaluated + * by the children of the argument node. The result + * returned by this method is based on the results evaluated by the ch= ildren + * of the argument node. + * @param node the node to be evaluated + * @param results the results evaluated by children of node + * @return the result evaluated for node + */ + public Object leave(IsEmptyCallExpression node, Object[] results) + { if( results[0]=3D=3Dnull ) + return Boolean.TRUE; + else if( results[0]=3D=3Dundefined ) + return undefined; + boolean result =3D ((Collection)results[0]).isEmpty(); + return result ? Boolean.TRUE : Boolean.FALSE; + } + + /** + * Returns the result evaluated for the argument node. + * The argument results contains the results evaluated + * by the children of the argument node. The result + * returned by this method is based on the results evaluated by the ch= ildren + * of the argument node. + * @param node the node to be evaluated + * @param results the results evaluated by children of node + * @return the result evaluated for node + * @exception JDOQueryException if the results evaluated by the node's + * children are non integral types + */ + public Object leave(LessThanEqualsExpression node, Object[] results) + { if( results[0]=3D=3Dnull || results[1]=3D=3Dnull || + results[0]=3D=3Dundefined || results[1]=3D=3Dundefined ) + return undefined; + boolean result; + Class clazz =3D node.getCommonOperandType(); + if( clazz=3D=3DInteger.class || clazz=3D=3Dint.class ) + result =3D ((Number)results[0]).intValue() <=3D ((Number)resul= ts[1]).intValue(); + else if( clazz=3D=3DLong.class || clazz=3D=3Dlong.class ) + result =3D ((Number)results[0]).longValue() <=3D ((Number)resu= lts[1]).longValue(); + else if( clazz=3D=3DDouble.class || clazz=3D=3Ddouble.class ) + result =3D ((Number)results[0]).doubleValue() <=3D ((Number)re= sults[1]).doubleValue(); + else if( clazz=3D=3DFloat.class || clazz=3D=3Dfloat.class ) + result =3D ((Number)results[0]).floatValue() <=3D ((Number)res= ults[1]).floatValue(); + else if( clazz=3D=3DBigDecimal.class ) + { BigDecimal left, right; + if( results[0] instanceof BigDecimal ) + left =3D (BigDecimal) results[0]; + else + left =3D new BigDecimal( results[0].toString() ); + if( results[1] instanceof BigDecimal ) + right =3D (BigDecimal) results[1]; + else + right =3D new BigDecimal( results[1].toString() ); + result =3D left.compareTo(right) <=3D 0; + } + else if( clazz=3D=3DBigInteger.class ) + { BigInteger left, right; + if( results[0] instanceof BigInteger ) + left =3D (BigInteger) results[0]; + else + left =3D new BigInteger( results[0].toString() ); + if( results[1] instanceof BigInteger ) + right =3D (BigInteger) results[1]; + else + right =3D new BigInteger( results[1].toString() ); + result =3D left.compareTo(right) <=3D 0; + } + // Comparable covers Date and String + else if( Comparable.class.isAssignableFrom(clazz) ) + result =3D ((Comparable)results[0]).compareTo((Comparable)resu= lts[1]) <=3D 0; + else if( clazz=3D=3DByte.class || clazz=3D=3Dbyte.class ) + result =3D ((Number)results[0]).byteValue() <=3D ((Number)resu= lts[1]).byteValue(); + else if( clazz=3D=3DCharacter.class || clazz=3D=3Dchar.class ) + result =3D ((Character)results[0]).charValue() <=3D ((Characte= r)results[1]).charValue(); + else if( clazz=3D=3DShort.class || clazz=3D=3Dshort.class ) + result =3D ((Number)results[0]).shortValue() <=3D ((Number)res= ults[1]).shortValue(); + else + throw new JDOQueryException( msg.msg("EXC_IllegalResultTypeFor= Expression", "<=3D", clazz.getName()) ); //NOI18N + return result ? Boolean.TRUE : Boolean.FALSE; + } + + /** + * Returns the result evaluated for the argument node. + * The argument results contains the results evaluated + * by the children of the argument node. The result + * returned by this method is based on the results evaluated by the ch= ildren + * of the argument node. + * @param node the node to be evaluated + * @param results the results evaluated by children of node + * @return the result evaluated for node + * @exception JDOQueryException if the results evaluated by the node's + * children are non integral types + */ + public Object leave(LessThanExpression node, Object[] results) + { if( results[0]=3D=3Dnull || results[1]=3D=3Dnull || + results[0]=3D=3Dundefined || results[1]=3D=3Dundefined ) + return undefined; + boolean result; + Class clazz =3D node.getCommonOperandType(); + if( clazz=3D=3DInteger.class || clazz=3D=3Dint.class ) + result =3D ((Number)results[0]).intValue() < ((Number)results[= 1]).intValue(); + else if( clazz=3D=3DLong.class || clazz=3D=3Dlong.class ) + result =3D ((Number)results[0]).longValue() < ((Number)results= [1]).longValue(); + else if( clazz=3D=3DDouble.class || clazz=3D=3Ddouble.class ) + result =3D ((Number)results[0]).doubleValue() < ((Number)resul= ts[1]).doubleValue(); + else if( clazz=3D=3DFloat.class || clazz=3D=3Dfloat.class ) + result =3D ((Number)results[0]).floatValue() < ((Number)result= s[1]).floatValue(); + else if( clazz=3D=3DBigDecimal.class ) + { BigDecimal left, right; + if( results[0] instanceof BigDecimal ) + left =3D (BigDecimal) results[0]; + else + left =3D new BigDecimal( results[0].toString() ); + if( results[1] instanceof BigDecimal ) + right =3D (BigDecimal) results[1]; + else + right =3D new BigDecimal( results[1].toString() ); + result =3D left.compareTo(right) < 0; + } + else if( clazz=3D=3DBigInteger.class ) + { BigInteger left, right; + if( results[0] instanceof BigInteger ) + left =3D (BigInteger) results[0]; + else + left =3D new BigInteger( results[0].toString() ); + if( results[1] instanceof BigInteger ) + right =3D (BigInteger) results[1]; + else + right =3D new BigInteger( results[1].toString() ); + result =3D left.compareTo(right) < 0; + } + // Comparable covers Date and String + else if( Comparable.class.isAssignableFrom(clazz) ) + result =3D ((Comparable)results[0]).compareTo((Comparable)resu= lts[1]) < 0; + else if( clazz=3D=3DByte.class || clazz=3D=3Dbyte.class ) + result =3D ((Number)results[0]).byteValue() < ((Number)results= [1]).byteValue(); + else if( clazz=3D=3DCharacter.class || clazz=3D=3Dchar.class ) + result =3D ((Character)results[0]).charValue() < ((Character)r= esults[1]).charValue(); + else if( clazz=3D=3DShort.class || clazz=3D=3Dshort.class ) + result =3D ((Number)results[0]).shortValue() < ((Number)result= s[1]).shortValue(); + else + throw new JDOQueryException( msg.msg("EXC_IllegalResultTypeFor= Expression", "<", clazz.getName()) ); //NOI18N + return result ? Boolean.TRUE : Boolean.FALSE; + } + + /** + * Returns the result evaluated for the argument node. + * The argument results contains the results evaluated + * by the children of the argument node. The result + * returned by this method is based on the results evaluated by the ch= ildren + * of the argument node. + * @param node the node to be evaluated + * @param results the results evaluated by children of node + * @return the result evaluated for node + * @exception JDOQueryException if the results evaluated by the node's + * children are non integral types + */ + public Object leave(MinusExpression node, Object[] results) + { if( results[0]=3D=3Dnull || results[1]=3D=3Dnull || + results[0]=3D=3Dundefined || results[1]=3D=3Dundefined ) + return undefined; + Class clazz =3D node.getJavaClass(); + if( clazz=3D=3DInteger.class || clazz=3D=3Dint.class ) + return new Integer( ((Number)results[0]).intValue() - ((Number= )results[1]).intValue() ); + else if( clazz=3D=3DLong.class || clazz=3D=3Dlong.class ) + return new Long( ((Number)results[0]).longValue() - ((Number)r= esults[1]).longValue() ); + else if( clazz=3D=3DDouble.class || clazz=3D=3Ddouble.class ) + return new Double( ((Number)results[0]).doubleValue() - ((Numb= er)results[1]).doubleValue() ); + else if( clazz=3D=3DFloat.class || clazz=3D=3Dfloat.class ) + return new Float( ((Number)results[0]).floatValue() - ((Number= )results[1]).floatValue() ); + else if( clazz=3D=3DBigDecimal.class ) + { BigDecimal left, right; + if( results[0] instanceof BigDecimal ) + left =3D (BigDecimal) results[0]; + else + left =3D new BigDecimal( results[0].toString() ); + if( results[1] instanceof BigDecimal ) + right =3D (BigDecimal) results[1]; + else + right =3D new BigDecimal( results[1].toString() ); + return left.subtract( right ); + } + else if( clazz=3D=3DBigInteger.class ) + { BigInteger left, right; + if( results[0] instanceof BigInteger ) + left =3D (BigInteger) results[0]; + else + left =3D new BigInteger( results[0].toString() ); + if( results[1] instanceof BigInteger ) + right =3D (BigInteger) results[1]; + else + right =3D new BigInteger( results[1].toString() ); + return left.subtract( right ); + } + else if( clazz=3D=3DByte.class || clazz=3D=3Dbyte.class ) + return new Byte( (byte) (((Number)results[0]).byteValue() - ((= Number)results[1]).byteValue()) ); + else if( clazz=3D=3DCharacter.class || clazz=3D=3Dchar.class ) + return new Character( (char) (((Character)results[0]).charValu= e() - ((Character)results[1]).charValue()) ); + else if( clazz=3D=3DShort.class || clazz=3D=3Dshort.class ) + return new Short( (short) (((Number)results[0]).shortValue() -= ((Number)results[1]).shortValue()) ); + throw new JDOQueryException( msg.msg("EXC_IllegalResultTypeForExpr= ession", "-", clazz.getName()) ); //NOI18N + } + + /** + * Returns the result evaluated for the argument node. + * The argument results contains the results evaluated + * by the children of the argument node. The result + * returned by this method is based on the results evaluated by the ch= ildren + * of the argument node. + * @param node the node to be evaluated + * @param results the results evaluated by children of node + * @return the result evaluated for node + * @exception JDOQueryException if the results evaluated by the node's + * children are non integral types + */ + public Object leave(NotEqualsExpression node, Object[] results) + { if( results[0]=3D=3Dundefined || results[1]=3D=3Dundefined ) + return undefined; + boolean result; + if( results[0]=3D=3Dnull && results[1]=3D=3Dnull ) + result =3D false; + else if( results[0]=3D=3Dnull || results[1]=3D=3Dnull ) + result =3D true; + else + { Class clazz =3D node.getCommonOperandType(); + if( clazz=3D=3DInteger.class || clazz=3D=3Dint.class ) + result =3D ((Number)results[0]).intValue() !=3D ((Number)r= esults[1]).intValue(); + else if( clazz=3D=3DLong.class || clazz=3D=3Dlong.class ) + result =3D ((Number)results[0]).longValue() !=3D ((Number)= results[1]).longValue(); + else if( clazz=3D=3DDouble.class || clazz=3D=3Ddouble.class ) + result =3D ((Number)results[0]).doubleValue() !=3D ((Numbe= r)results[1]).doubleValue(); + else if( clazz=3D=3DFloat.class || clazz=3D=3Dfloat.class ) + result =3D ((Number)results[0]).floatValue() !=3D ((Number= )results[1]).floatValue(); + else if( clazz=3D=3DBigDecimal.class ) + { BigDecimal left, right; + if( results[0] instanceof BigDecimal ) + left =3D (BigDecimal) results[0]; + else + left =3D new BigDecimal( results[0].toString() ); + if( results[1] instanceof BigDecimal ) + right =3D (BigDecimal) results[1]; + else + right =3D new BigDecimal( results[1].toString() ); + result =3D left.compareTo( right ) !=3D 0; + } + else if( clazz=3D=3DBigInteger.class ) + { BigInteger left, right; + if( results[0] instanceof BigInteger ) + left =3D (BigInteger) results[0]; + else + left =3D new BigInteger( results[0].toString() ); + if( results[1] instanceof BigInteger ) + right =3D (BigInteger) results[1]; + else + right =3D new BigInteger( results[1].toString() ); + result =3D left.compareTo( right ) !=3D 0; + } + else if( Date.class.isAssignableFrom(clazz) ) + result =3D ((Date)results[0]).getTime() !=3D ((Date)result= s[1]).getTime(); + else if( clazz=3D=3DByte.class || clazz=3D=3Dbyte.class ) + result =3D ((Number)results[0]).byteValue() !=3D ((Number)= results[1]).byteValue(); + else if( clazz=3D=3DCharacter.class || clazz=3D=3Dchar.class ) + result =3D ((Character)results[0]).charValue() !=3D ((Char= acter)results[1]).charValue(); + else if( clazz=3D=3DShort.class || clazz=3D=3Dshort.class ) + result =3D ((Number)results[0]).shortValue() !=3D ((Number= )results[1]).shortValue(); + else=20 + { PersistenceManager leftPM =3D JDOHelper.getPersistenceMana= ger( results[0] ); + PersistenceManager rightPM =3D JDOHelper.getPersistenceMan= ager( results[1] ); + if( leftPM!=3Dnull && rightPM!=3Dnull ) + // use =3D=3D for persistence instances + result =3D results[0] !=3D results[1]; + else if( leftPM=3D=3Dnull && rightPM=3D=3Dnull ) + // use equals for non persistent instances + result =3D !results[0].equals( results[1] ); + else + // comparing persistent with non persistent instance + result =3D true; + } + } + return result ? Boolean.TRUE : Boolean.FALSE; + } + + /** + * Returns the result evaluated for the argument node. + * The argument results contains the result evaluated + * by the child of the argument node. The result + * returned by this method is based on the result evaluated by the chi= ld + * of the argument node. + * @param node the node to be evaluated + * @param results the result evaluated by child of node + * @return the result evaluated for node + */ + public Object leave(NotExpression node, Object[] results) + { if( results[0]=3D=3Dnull || + results[0]=3D=3Dundefined ) + return undefined; + boolean result =3D !((Boolean)results[0]).booleanValue(); + return result ? Boolean.TRUE : Boolean.FALSE; + } + + /** + * Returns the result evaluated for the argument node. + * The argument results contains the result evaluated + * by the child of the argument node. The result + * returned by this method is based on the result evaluated by the chi= ld + * of the argument node. + * @param node the node to be evaluated + * @param results the result evaluated by child of node + * @return the result evaluated for node + */ + public Object leave(OrderingExpression node, Object[] results) + { if( results[0]=3D=3Dnull || + results[0]=3D=3Dundefined ) + return undefined; + return results[0]; + } + + /** + * Returns the result evaluated for the argument node. + * The argument results contains the results evaluated + * by the children of the argument node. The result + * returned by this method is based on the results evaluated by the ch= ildren + * of the argument node. + * @param node the node to be evaluated + * @param results the results evaluated by children of node + * @return the result evaluated for node + * @exception JDOQueryException if the results evaluated by the node's + * children are non boolean types + */ + public Object leave(OrExpression node, Object[] results) + { Class clazz =3D node.getJavaClass(); + if( clazz=3D=3DBoolean.class || clazz=3D=3Dboolean.class ) + return logicalOr( results[0], results[1] ); + throw new JDOQueryException( msg.msg("EXC_IllegalResultTypeForExpr= ession", "|", clazz.getName()) ); //NOI18N + } + + /** + * Returns the result evaluated for the argument node. + * The argument results is null as the argum= ent + * node does not have any children. The result + * returned by this method is the instance obtained by the parameter t= able + * for for the argument node. + * @param node the node to be evaluated + * @param results null + * @return the instance obtained by the parameter table for node + */ + public Object leave(ParameterAccessExpression node, Object[] results) + { return this.parameters.getValue( node.getName() ); + } + + /** + * Returns the result evaluated for the argument node. + * The argument results contains the results evaluated + * by the children of the argument node. The result + * returned by this method is based on the results evaluated by the ch= ildren + * of the argument node. + * @param node the node to be evaluated + * @param results the results evaluated by children of node + * @return the result evaluated for node + * @exception JDOQueryException if the results evaluated by the node's + * children are non integral types + */ + public Object leave(PlusExpression node, Object[] results) + { if( results[0]=3D=3Dnull || results[1]=3D=3Dnull || + results[0]=3D=3Dundefined || results[1]=3D=3Dundefined ) + return undefined; + Class clazz =3D node.getJavaClass(); + if( clazz=3D=3DInteger.class || clazz=3D=3Dint.class ) + return new Integer( ((Number)results[0]).intValue() + ((Number= )results[1]).intValue() ); + else if( clazz=3D=3DLong.class || clazz=3D=3Dlong.class ) + return new Long( ((Number)results[0]).longValue() + ((Number)r= esults[1]).longValue() ); + else if( clazz=3D=3DDouble.class || clazz=3D=3Ddouble.class ) + return new Double( ((Number)results[0]).doubleValue() + ((Numb= er)results[1]).doubleValue() ); + else if( clazz=3D=3DFloat.class || clazz=3D=3Dfloat.class ) + return new Float( ((Number)results[0]).floatValue() + ((Number= )results[1]).floatValue() ); + else if( clazz=3D=3DBigDecimal.class ) + { BigDecimal left, right; + if( results[0] instanceof BigDecimal ) + left =3D (BigDecimal) results[0]; + else + left =3D new BigDecimal( results[0].toString() ); + if( results[1] instanceof BigDecimal ) + right =3D (BigDecimal) results[1]; + else + right =3D new BigDecimal( results[1].toString() ); + return left.add( right ); + } + else if( clazz=3D=3DBigInteger.class ) + { BigInteger left, right; + if( results[0] instanceof BigInteger ) + left =3D (BigInteger) results[0]; + else + left =3D new BigInteger( results[0].toString() ); + if( results[1] instanceof BigInteger ) + right =3D (BigInteger) results[1]; + else + right =3D new BigInteger( results[1].toString() ); + return left.add( right ); + } + else if( clazz=3D=3DString.class ) + return (String)results[0] + (String)results[1]; + else if( clazz=3D=3DByte.class || clazz=3D=3Dbyte.class ) + return new Byte( (byte) (((Number)results[0]).byteValue() + ((= Number)results[1]).byteValue()) ); + else if( clazz=3D=3DCharacter.class || clazz=3D=3Dchar.class ) + return new Character( (char) (((Character)results[0]).charValu= e() + ((Character)results[1]).charValue()) ); + else if( clazz=3D=3DShort.class || clazz=3D=3Dshort.class ) + return new Short( (short) (((Number)results[0]).shortValue() += ((Number)results[1]).shortValue()) ); + throw new JDOQueryException( msg.msg("EXC_IllegalResultTypeForExpr= ession", "+", clazz.getName()) ); //NOI18N + } + + /** + * Returns the result evaluated for the argument node. + * The argument results contains the results evaluated + * by the children of the argument node. The result + * returned by this method is based on the results evaluated by the ch= ildren + * of the argument node. + * @param node the node to be evaluated + * @param results the results evaluated by children of node + * @return the result evaluated for node + */ + public Object leave(StartsWithCallExpression node, Object[] results) + { if( results[0]=3D=3Dnull || + results[0]=3D=3Dundefined ) + return undefined; + boolean result =3D ((String)results[0]).startsWith( (String)result= s[1] ); + return result ? Boolean.TRUE : Boolean.FALSE; + } + + /** + * Returns the result evaluated for the argument node. + * The argument results contains the results evaluated + * by the children of the argument node. The result + * returned by this method is based on the results evaluated by the ch= ildren + * of the argument node. + * @param node the node to be evaluated + * @param results the results evaluated by children of node + * @return the result evaluated for node + */ + public Object leave(StaticFieldAccessExpression node, Object[] results) + { return node.getFieldValue( pm ); + } + + /** + * Returns the result evaluated for the argument node. + * The argument results is null as the argum= ent + * node does not have any children. The result + * returned by this method is the current instance stored in this node= visitor + * by method setCurrent. + * @param node the node to be evaluated + * @param results null + * @return the current instance stored in this node visitor + * by method setCurrent + */ + public Object leave(ThisExpression node, Object[] results) + { return this.current; + } + + /** + * Returns the result evaluated for the argument node. + * The argument results contains the results evaluated + * by the children of the argument node. The result + * returned by this method is based on the results evaluated by the ch= ildren + * of the argument node. + * @param node the node to be evaluated + * @param results the results evaluated by children of node + * @return the result evaluated for node + * @exception JDOQueryException if the results evaluated by the node's + * children are non integral types + */ + public Object leave(TimesExpression node, Object[] results) + { if( results[0]=3D=3Dnull || results[1]=3D=3Dnull || + results[0]=3D=3Dundefined || results[1]=3D=3Dundefined ) + return undefined; + Class clazz =3D node.getJavaClass(); + if( clazz=3D=3DInteger.class || clazz=3D=3Dint.class ) + return new Integer( ((Number)results[0]).intValue() * ((Number= )results[1]).intValue() ); + else if( clazz=3D=3DLong.class || clazz=3D=3Dlong.class ) + return new Long( ((Number)results[0]).longValue() * ((Number)r= esults[1]).longValue() ); + else if( clazz=3D=3DDouble.class || clazz=3D=3Ddouble.class ) + return new Double( ((Number)results[0]).doubleValue() * ((Numb= er)results[1]).doubleValue() ); + else if( clazz=3D=3DFloat.class || clazz=3D=3Dfloat.class ) + return new Float( ((Number)results[0]).floatValue() * ((Number= )results[1]).floatValue() ); + else if( clazz=3D=3DBigDecimal.class ) + { BigDecimal left, right; + if( results[0] instanceof BigDecimal ) + left =3D (BigDecimal) results[0]; + else + left =3D new BigDecimal( results[0].toString() ); + if( results[1] instanceof BigDecimal ) + right =3D (BigDecimal) results[1]; + else + right =3D new BigDecimal( results[1].toString() ); + return left.multiply( right ); + } + else if( clazz=3D=3DBigInteger.class ) + { BigInteger left, right; + if( results[0] instanceof BigInteger ) + left =3D (BigInteger) results[0]; + else + left =3D new BigInteger( results[0].toString() ); + if( results[1] instanceof BigInteger ) + right =3D (BigInteger) results[1]; + else + right =3D new BigInteger( results[1].toString() ); + return left.multiply( right ); + } + else if( clazz=3D=3DByte.class || clazz=3D=3Dbyte.class ) + return new Byte( (byte) (((Number)results[0]).byteValue() * ((= Number)results[1]).byteValue()) ); + else if( clazz=3D=3DCharacter.class || clazz=3D=3Dchar.class ) + return new Character( (char) (((Character)results[0]).charValu= e() * ((Character)results[1]).charValue()) ); + else if( clazz=3D=3DShort.class || clazz=3D=3Dshort.class ) + return new Short( (short) (((Number)results[0]).shortValue() *= ((Number)results[1]).shortValue()) ); + throw new JDOQueryException( msg.msg("EXC_IllegalResultTypeForExpr= ession", "*", clazz.getName()) ); //NOI18N + } + + /** + * Returns the result evaluated for the argument node. + * The argument results contains the result evaluated + * by the child of the argument node. The result + * returned by this method is based on the result evaluated by the chi= ld + * of the argument node. + * @param node the node to be evaluated + * @param results the result evaluated by the node's child + * @return the result evaluated for node + * @exception JDOQueryException if the result evaluated by the node's + * child is not an integral type. + */ + public Object leave(UnaryMinusExpression node, Object[] results) + { if( results[0]=3D=3Dnull || + results[0]=3D=3Dundefined ) + return undefined; + Class clazz =3D node.getJavaClass(); + if( clazz=3D=3DInteger.class || clazz=3D=3Dint.class ) + return new Integer( -((Number)results[0]).intValue() ); + else if( clazz=3D=3DLong.class || clazz=3D=3Dlong.class ) + return new Long( -((Number)results[0]).longValue() ); + else if( clazz=3D=3DDouble.class || clazz=3D=3Ddouble.class ) + return new Double( -((Number)results[0]).doubleValue() ); + else if( clazz=3D=3DFloat.class || clazz=3D=3Dfloat.class ) + return new Float( -((Number)results[0]).floatValue() ); + else if( clazz=3D=3DBigInteger.class ) + return ((BigInteger)results[0]).negate(); + else if( clazz=3D=3DBigDecimal.class ) + return ((BigDecimal)results[0]).negate(); + else if( clazz=3D=3DByte.class || clazz=3D=3Dbyte.class ) + return new Byte( (byte) -((Number)results[0]).byteValue() ); + else if( clazz=3D=3DCharacter.class || clazz=3D=3Dchar.class ) + return new Character( (char) -((Character)results[0]).charValu= e() ); + else if( clazz=3D=3DShort.class || clazz=3D=3Dshort.class ) + return new Short( (short) -((Number)results[0]).shortValue() ); + throw new JDOQueryException( msg.msg("EXC_IllegalResultTypeForExpr= ession", "-", clazz.getName()) ); //NOI18N + } + + /** + * Returns the result evaluated for the argument node. + * The argument results contains the result evaluated + * by the child of the argument node. The result + * returned by this method is the same as the result evaluated by the = child + * of the argument node. + * @param node the node to be evaluated + * @param results the result evaluated by the node's child + * @return the result evaluated for node + */ + public Object leave(UnaryPlusExpression node, Object[] results) + { return results[0]; + } + + /** + * Returns the result evaluated for the argument node. + * The argument results is null as the argum= ent + * node does not have any children. The result + * returned by this method is the instance obtained by the variable ta= ble + * for for the argument node. + * @param node the node to be evaluated + * @param results null + * @return the instance obtained by the variable table for node + */ + public Object leave(VariableAccessExpression node, Object[] results) + { Object result =3D this.variables.getValue( node.getName() ); + if( result=3D=3Dundefined ) + this.unboundVariableAccess =3D node; + return result; + } + + /** + * Returns false if the argument resultOfPreviousCh= ild + * is undefined and the argument indexOfNextChild is grea= ter + * than 0. + * @param node the parent node of the children currently evaluated + * @param resultOfPreviousChild an array of null instances + * @param indexOfNextChild the index of the next child to be dumped + * @return false if the argument resultOfPreviousCh= ild + * is undefined and the argument indexOfNextChild is grea= ter + * than 0 + */ + public boolean walkNextChild(AndExpression node, Object resultOfPrevio= usChild, int indexOfNextChild) + { if( indexOfNextChild>0 ) + { BoundVariable boundVariable =3D removeBoundVariable(); + if( isIteration(boundVariable, node.getRightExpression()) ) + return false; + } + return true; + } + + /** + * Returns false if the argument resultOfPreviousCh= ild + * is null, undefined or false and the argum= ent indexOfNextChild is greater + * than 0. + * @param node the parent node of the children currently evaluated + * @param resultOfPreviousChild an array of null instances + * @param indexOfNextChild the index of the next child to be dumped + * @return false if the argument resultOfPreviousCh= ild + * is null, undefined or false and the argum= ent indexOfNextChild is greater + * than 0 + */ + public boolean walkNextChild(ConditionalAndExpression node, Object res= ultOfPreviousChild, int indexOfNextChild) + { if( indexOfNextChild>0 ) + { BoundVariable boundVariable =3D removeBoundVariable(); + if ( isIteration(boundVariable, node.getRightExpression()) ) + return false; + else if ( resultOfPreviousChild=3D=3Dundefined )=20 + // evaluate second operand, if first is undefined + return true; + + Class clazz =3D node.getJavaClass(); + if( ((clazz=3D=3DBoolean.class || clazz=3D=3Dboolean.class) && + resultOfPreviousChild!=3Dnull && + !((Boolean)resultOfPreviousChild).booleanValue()) ) + return false; + } + return true; + } + + /** + * Returns false if the argument resultOfPreviousCh= ild + * is null, undefined or true and the argume= nt indexOfNextChild is greater + * than 0. + * @param node the parent node of the children currently evaluated + * @param resultOfPreviousChild an array of null instances + * @param indexOfNextChild the index of the next child to be dumped + * @return false if the argument resultOfPreviousCh= ild + * is null, undefined or true and the argume= nt indexOfNextChild is greater + * than 0 + */ + public boolean walkNextChild(ConditionalOrExpression node, Object resu= ltOfPreviousChild, int indexOfNextChild) + { if( indexOfNextChild>0 ) + { BoundVariable boundVariable =3D removeBoundVariable(); + if( resultOfPreviousChild=3D=3Dundefined )=20 + // evaluate second operand, if first is undefined + return true; + + Class clazz =3D node.getJavaClass(); + if ( ((clazz=3D=3DBoolean.class || clazz=3D=3Dboolean.class) && + resultOfPreviousChild!=3Dnull && + ((Boolean)resultOfPreviousChild).booleanValue()) ) + return false; + } + return true; + } + + /** + * Returns false if the argument resultOfPreviousCh= ild + * is undefined and the argument indexOfNextChild is grea= ter + * than 0. + * @param node the parent node of the children currently evaluated + * @param resultOfPreviousChild an array of null instances + * @param indexOfNextChild the index of the next child to be dumped + * @return false if the argument resultOfPreviousCh= ild + * is undefined and the argument indexOfNextChild is grea= ter than 0 + */ + public boolean walkNextChild(ContainsCallExpression node, Object resul= tOfPreviousChild, int indexOfNextChild) + { return true; + } + + /** + * Returns false if the argument resultOfPreviousCh= ild + * is undefined and the argument indexOfNextChild is grea= ter + * than 0. + * @param node the parent node of the children currently evaluated + * @param resultOfPreviousChild an array of null instances + * @param indexOfNextChild the index of the next child to be dumped + * @return false if the argument resultOfPreviousCh= ild + * is undefined and the argument indexOfNextChild is grea= ter + * than 0 + */ + public boolean walkNextChild(OrExpression node, Object resultOfPreviou= sChild, int indexOfNextChild) + { if( indexOfNextChild>0 ) + { BoundVariable boundVariable =3D removeBoundVariable(); + } + return true; + } + + //private members + private class BoundVariable + { String name; + Class clazz; + Collection collection; + boolean result =3D false; + + BoundVariable(String name, Class clazz, Collection collection) + { this.name =3D name; + this.clazz =3D clazz; + this.collection =3D collection; + } + public boolean equals(Object obj) + { return name.equals( obj ); + } + public int hashCode() + { return name.hashCode(); + } + public String toString() + { return name.toString(); + } + } + private BoundVariable removeBoundVariable() + { if( this.unboundVariableAccess!=3Dnull ) + throw new JDOQueryException( msg.msg("EXC_CannotAccessUnboundV= ariables", this.unboundVariableAccess.getName()) ); //NOI18N + int nrOfBoundVariables =3D this.boundVariables.size(); + if( nrOfBoundVariables>1 ) + throw new JDOQueryException( msg.msg("EXC_CannotProcessMultipl= eContainsClauses") ); //NOI18N + BoundVariable boundVariable; + if( nrOfBoundVariables>0 ) + boundVariable =3D (BoundVariable) this.boundVariables.remove( = nrOfBoundVariables-1 ); + else + boundVariable =3D null; + return boundVariable; + } + private boolean isIteration(BoundVariable boundVariable, Expression ex= pr) + { boolean result =3D false; + if( boundVariable!=3Dnull ) + { result =3D true; + boundVariable.result =3D false; + int nrOfBoundVariables =3D this.boundVariables.size(); + for( Iterator i=3DboundVariable.collection.iterator(); i.hasNe= xt(); ) + { Object value =3D i.next(); + if( boundVariable.clazz.isInstance(value) ) + { this.variables.setValue( boundVariable.name, value ); + Object object =3D walker.walk( expr, this ); + while( nrOfBoundVariables + // T AND U -> U + // F AND U -> F + // U AND U -> U + if( (left=3D=3Dundefined) || ((Boolean)left).booleanValue() ) + result =3D undefined; + else=20 + result =3D Boolean.FALSE; + } + else if( left=3D=3Dundefined ) + { // left hand side is undefined + // U AND T -> U + // U AND F -> F + // U AND U -> U (handled above) + if( ((Boolean)right).booleanValue() ) + result =3D undefined; + else + result =3D Boolean.FALSE; + } + else=20 + { result =3D ((Boolean)left).booleanValue() && ((Boolean)right).= booleanValue() ? + Boolean.TRUE : Boolean.FALSE; + } + return result; + } + private Object logicalOr(Object left, Object right) + { Object result; + //if the expression has been an iteration then return the iteratio= n result + if( right=3D=3Dnull ) + { if( this.removedBoundVariable!=3Dnull ) + { result =3D this.removedBoundVariable.result ? Boolean.TRUE= : Boolean.FALSE; + this.removedBoundVariable =3D null; + } + else + result =3D left; + } + else if( right=3D=3Dundefined ) + { // right hand side is undefined =3D> + // T OR U -> T + // F OR U -> U + // U OR U -> U + if( (left=3D=3Dundefined) || !((Boolean)left).booleanValue() ) + result =3D undefined; + else + result =3D Boolean.TRUE; + } + else if( left=3D=3Dundefined ) + { // left hand side is undefined + // U OR T -> T + // U OR F -> U + // U OR U -> U (handled above) + if ( ((Boolean)right).booleanValue() ) + result =3D Boolean.TRUE; + else + result =3D undefined;=20 + } + else=20 + { result =3D ((Boolean)left).booleanValue() || ((Boolean)right).= booleanValue() ? + Boolean.TRUE : Boolean.FALSE; + } + return result; + } + private void log(String s) + { System.out.print( s ); + } + private void logln(String s) + { System.out.println( s ); + } +} Added: incubator/jdo/trunk/query20/src/java/org/apache/jdo/impl/jdoql/Order= ingComparator.java URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/query20/src/java/org= /apache/jdo/impl/jdoql/OrderingComparator.java?rev=3D171353&view=3Dauto =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/jdo/trunk/query20/src/java/org/apache/jdo/impl/jdoql/Ordering= Comparator.java (added) +++ incubator/jdo/trunk/query20/src/java/org/apache/jdo/impl/jdoql/Ordering= Comparator.java Sun May 22 11:08:57 2005 @@ -0,0 +1,125 @@ +/* + * Copyright 2005 The Apache Software Foundation. + *=20 + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at=20 + *=20 + * http://www.apache.org/licenses/LICENSE-2.0 + *=20 + * Unless required by applicable law or agreed to in writing, software=20 + * distributed under the License is distributed on an "AS IS" BASIS,=20 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied= .=20 + * See the License for the specific language governing permissions and=20 + * limitations under the License. + */ + +package org.apache.jdo.impl.jdoql; + + +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; + +import org.apache.jdo.impl.jdoql.scope.UNDEFINED; +import org.apache.jdo.jdoql.tree.DescendingOrderingExpression; +import org.apache.jdo.jdoql.tree.OrderingExpression; +import org.apache.jdo.jdoql.tree.QueryTree; +import org.apache.jdo.jdoql.tree.TreeWalker; + +/** + * An instance of this class is used to compare two instances of + * Comparable based on the ordering expressions + * defined by a query tree. This instance holds references to a query tree, + * a tree walker and a memory query instance for this purpose. + * + * @author Michael Watzek + */ +public class OrderingComparator implements Comparator +{ + private static final UNDEFINED undefined =3D UNDEFINED.getInstance(); + + List orderings; + final TreeWalker walker; + final MemoryQuery nodeVisitor; + + /** + * Constructs an ordering comparator for a tree walker and a node visi= tor. + * This comparator is not bound to a query tree. + * It can be bound to a query tree by calling method + * setQueryTree. + * @param walker the tree walker + * @param nodeVisitor the node visitor evaluating the ordering express= ions + */ + public OrderingComparator(TreeWalker walker, MemoryQuery nodeVisitor) + { this( walker, nodeVisitor, null ); + } + + /** + * Constructs an ordering comparator for a tree walker, a node visitor + * and a query tree. This comparator is bound to that query tree. + * @param walker the tree walker + * @param nodeVisitor the node visitor evaluating the ordering express= ions + * @param queryTree the query tree containing the ordering expressions + */ + public OrderingComparator(TreeWalker walker, MemoryQuery nodeVisitor, = QueryTree queryTree) + { this.walker =3D walker; + this.nodeVisitor =3D nodeVisitor; + setQueryTree( queryTree ); + } + + /** + * Sets the query tree for this ordering comparator. Each ordering com= parator + * can be bound to a query tree. The ordering expression list inside + * that query tree determines the ordering semantics of this comparato= r=2E + * @param queryTree the query tree containing the ordering expression = list + */ + public void setQueryTree(QueryTree queryTree) + { if( queryTree!=3Dnull ) + this.orderings =3D queryTree.getOrderingExpressions(); + else + this.orderings =3D null; + } + + /** + * Required method for implementing the interface Comparator. + * This method returns a negative integer, zero, or a positive integer + * as the first argument is less than, equal to, or greater than the s= econd + * argument. + * If this instance is not bound to a query tree or, + * if the query tree bound to this instance + * does not have any ordering expression, then argument o1 + * is less than argument o2 by definition. + * @param o1 the first object to be compared + * @param o2 the second object to be compared + * @return a negative integer, zero, or a positive integer + * as the first argument is less than, equal to, or greater than the s= econd + * @exception ClassCastException if the arguments are not instances of + * Comparable + */ + public int compare(Object o1, Object o2) + { int cmp =3D -1; + if( this.orderings!=3Dnull ) + for( Iterator i=3Dthis.orderings.iterator(); i.hasNext(); ) + { OrderingExpression orderExpr =3D (OrderingExpression) i.ne= xt(); + nodeVisitor.setCurrent( o1 ); + Object result1 =3D walker.walk( orderExpr, nodeVisitor ); + nodeVisitor.setCurrent( o2 ); + Object result2 =3D walker.walk( orderExpr, nodeVisitor ); + if( result1!=3Dnull || + result2!=3Dnull ) + { if( !(result1 instanceof Comparable) ) + break; + else if( !(result2 instanceof Comparable) ) + { cmp =3D 1; + break; + } + cmp =3D ((Comparable)result1).compareTo( result2 ); + if( cmp!=3D0 ) + { if( orderExpr instanceof DescendingOrderingExpress= ion ) + cmp =3D -cmp; + break; + } } } + return cmp; + } +} \ No newline at end of file