Author: fancy
Date: Thu Jan 22 17:19:47 2009
New Revision: 736881

URL: http://svn.apache.org/viewvc?rev=736881&view=rev
Log:
OPENJPA-856 JPQ2 JPQL add  support for entity type expression

Added:
    
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Type.java
    
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/TypeLit.java
    
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Type.java
    
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/TypeLit.java
    
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jpql/expressions/TestEntityTypeExpression.java
Modified:
    
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/AbstractVal.java
    
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/InExpression.java
    
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/JDBCExpressionFactory.java
    
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java
    
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Param.java
    
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Val.java
    
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldMapping.java
    
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldStrategy.java
    
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/AbstractFieldStrategy.java
    
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ExpressionFactory.java
    
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/InMemoryExpressionFactory.java
    
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Literal.java
    
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java
    
openjpa/trunk/openjpa-kernel/src/main/jjtree/org/apache/openjpa/kernel/jpql/JPQL.jjt
    
openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/jpql/localizer.properties
    
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jpql/expressions/TestJPQLScalarExpressions.java

Modified: 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/AbstractVal.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/AbstractVal.java?rev=736881&r1=736880&r2=736881&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/AbstractVal.java
 (original)
+++ 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/AbstractVal.java
 Thu Jan 22 17:19:47 2009
@@ -79,6 +79,11 @@
         sql.append("1");
     }
 
+    public void appendType(Select sel, ExpContext ctx, ExpState state, 
+        SQLBuffer sql) {
+        sql.append("1");
+    }
+
     public void appendSize(Select sel, ExpContext ctx, ExpState state, 
         SQLBuffer sql) {
         sql.append("1");

Modified: 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/InExpression.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/InExpression.java?rev=736881&r1=736880&r2=736881&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/InExpression.java
 (original)
+++ 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/InExpression.java
 Thu Jan 22 17:19:47 2009
@@ -91,7 +91,11 @@
     public void appendTo(Select sel, ExpContext ctx, ExpState state, 
         SQLBuffer buf) {
         InExpState istate = (InExpState) state; 
-        _const.calculateValue(sel, ctx, istate.constantState, null, null);
+        if (_val instanceof Type)
+            _const.calculateValue(sel, ctx, istate.constantState, _val,
+                istate.valueState);
+        else
+            _const.calculateValue(sel, ctx, istate.constantState, null, null);
         _val.calculateValue(sel, ctx, istate.valueState, null, null);
 
         List list = null;

Modified: 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/JDBCExpressionFactory.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/JDBCExpressionFactory.java?rev=736881&r1=736880&r2=736881&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/JDBCExpressionFactory.java
 (original)
+++ 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/JDBCExpressionFactory.java
 Thu Jan 22 17:19:47 2009
@@ -247,6 +247,10 @@
         return new Lit(val, ptype);
     }
 
+    public Literal newTypeLiteral(Object val, int ptype) {
+        return new TypeLit(val, ptype);
+    }
+
     public Value getThis() {
         return new PCPath(_type);
     }
@@ -396,6 +400,10 @@
         return new Index((Val) val);
     }
 
+    public Value type(Value val) {
+        return new Type((Val) val);
+    }
+
     public Value getObjectId(Value val) {
         if (val instanceof Const)
             return new ConstGetObjectId((Const) val);

Modified: 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java?rev=736881&r1=736880&r2=736881&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java
 (original)
+++ 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java
 Thu Jan 22 17:19:47 2009
@@ -27,6 +27,7 @@
 import org.apache.commons.lang.ObjectUtils;
 import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
 import org.apache.openjpa.jdbc.meta.ClassMapping;
+import org.apache.openjpa.jdbc.meta.Discriminator;
 import org.apache.openjpa.jdbc.meta.FieldMapping;
 import org.apache.openjpa.jdbc.meta.ValueMapping;
 import org.apache.openjpa.jdbc.schema.Column;
@@ -814,6 +815,33 @@
             pstate.field.appendIndex(sql, sel, pstate.joins);;
     }
 
+    public void appendType(Select sel, ExpContext ctx, ExpState state, 
+        SQLBuffer sql) {
+        Discriminator disc = null;
+        ClassMapping sup = _class;
+        while (sup.getMappedPCSuperclassMapping() != null)
+            sup = sup.getMappedPCSuperclassMapping();
+
+        disc = sup.getDiscriminator();
+
+        Column[] cols = null;
+        if (disc != null)
+            cols = disc.getColumns();
+        else
+            cols = getColumns(state);
+
+        if (cols == null) {
+            sql.append("1");
+            return;
+        }
+
+        for (int i = 0; i < cols.length; i++) {
+            if (i > 0)
+                sql.append(", ");
+            sql.append(sel.getColumnAlias(cols[i], state.joins));
+        }
+    }
+
     public void appendSize(Select sel, ExpContext ctx, ExpState state, 
         SQLBuffer sql) {
         PathExpState pstate = (PathExpState) state;

Modified: 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Param.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Param.java?rev=736881&r1=736880&r2=736881&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Param.java
 (original)
+++ 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Param.java
 Thu Jan 22 17:19:47 2009
@@ -22,6 +22,7 @@
 import java.util.Map;
 
 import org.apache.openjpa.jdbc.meta.ClassMapping;
+import org.apache.openjpa.jdbc.meta.Discriminator;
 import org.apache.openjpa.jdbc.sql.SQLBuffer;
 import org.apache.openjpa.jdbc.sql.Select;
 import org.apache.openjpa.kernel.Filters;
@@ -82,6 +83,12 @@
         return Filters.convert(params[_idx], getType());
     }
 
+    public Object getValue(ExpContext ctx, ExpState state) {
+        ParamExpState pstate = (ParamExpState) state;
+        return (pstate.discValue != null) ? pstate.discValue :
+            getValue(ctx.params);
+    }
+
     public Object getSQLValue(Select sel, ExpContext ctx, ExpState state) {
         return ((ParamExpState) state).sqlValue;
     }
@@ -97,7 +104,10 @@
         extends ConstExpState {
 
         public Object sqlValue = null;
-        public int otherLength = 1; 
+        public int otherLength = 1;
+        public ClassMapping mapping = null;
+        public Discriminator disc = null;
+        public Object discValue = null;
     } 
 
     public void calculateValue(Select sel, ExpContext ctx, ExpState state, 
@@ -108,6 +118,14 @@
         if (other != null && !_container) {
             pstate.sqlValue = other.toDataStoreValue(sel, ctx, otherState, 
val);
             pstate.otherLength = other.length(sel, ctx, otherState);
+            if (other instanceof Type) {
+                pstate.mapping = ctx.store.getConfiguration().
+                    getMappingRepositoryInstance().getMapping((Class) val,
+                        ctx.store.getContext().getClassLoader(), true);
+                pstate.disc = pstate.mapping.getDiscriminator();
+                pstate.discValue = pstate.disc != null ? pstate.disc.getValue()
+                    : null;
+            }
         } else if (ImplHelper.isManageable(val)) {
             ClassMapping mapping = ctx.store.getConfiguration().
                 getMappingRepositoryInstance().getMapping(val.getClass(),
@@ -125,6 +143,10 @@
         if (pstate.otherLength > 1)
             sql.appendValue(((Object[]) pstate.sqlValue)[index], 
                 pstate.getColumn(index));
+        else if (pstate.cols != null)
+            sql.appendValue(pstate.sqlValue, pstate.getColumn(index));
+        else if (pstate.discValue != null)
+            sql.appendValue(pstate.discValue);
         else
             sql.appendValue(pstate.sqlValue, pstate.getColumn(index));
     }

Added: 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Type.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Type.java?rev=736881&view=auto
==============================================================================
--- 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Type.java
 (added)
+++ 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Type.java
 Thu Jan 22 17:19:47 2009
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+package org.apache.openjpa.jdbc.kernel.exps;
+
+import java.sql.SQLException;
+
+import org.apache.openjpa.jdbc.meta.ClassMapping;
+import org.apache.openjpa.jdbc.meta.Discriminator;
+import org.apache.openjpa.jdbc.sql.Result;
+import org.apache.openjpa.jdbc.sql.SQLBuffer;
+import org.apache.openjpa.jdbc.sql.Select;
+import org.apache.openjpa.util.InternalException;
+
+/**
+ * Entity Type expression.
+ *
+ * @author Catalina Wei
+ */
+class Type
+    extends UnaryOp {
+    
+    Discriminator _disc = null;
+
+    public Type(Val val) {
+        super(val);
+        setMetaData(val.getMetaData());
+        _disc = ((ClassMapping) getMetaData()).getDiscriminator();
+    }
+
+    public ExpState initialize(Select sel, ExpContext ctx, int flags) {
+        // initialize the value with a null test
+        return initializeValue(sel, ctx, NULL_CMP);
+    }
+
+    public Object load(ExpContext ctx, ExpState state, Result res)
+        throws SQLException {
+        Object type = getValue().load(ctx, state, res);
+        return type.getClass();
+    }
+
+    public void calculateValue(Select sel, ExpContext ctx, ExpState state, 
+        Val other, ExpState otherState) {
+        super.calculateValue(sel, ctx, state, null, null);
+        if (_disc != null)
+            _disc.select(sel, (ClassMapping) getMetaData()); 
+    }
+
+    public void select(Select sel, ExpContext ctx, ExpState state, 
+        boolean pks) {
+        getValue().select(sel, ctx, state, pks);
+    }
+
+    public void appendTo(Select sel, ExpContext ctx, ExpState state, 
+        SQLBuffer sql, int index) {
+        getValue().calculateValue(sel, ctx, state, null, null);
+        getValue().appendType(sel, ctx, state, sql);
+        sel.append(sql, state.joins);
+    }
+
+    protected Class getType(Class c) {
+        return Class.class;
+    }
+
+    protected String getOperator() {
+        // since we override appendTo(), this method should never be called
+        throw new InternalException();
+    }
+}

Added: 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/TypeLit.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/TypeLit.java?rev=736881&view=auto
==============================================================================
--- 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/TypeLit.java
 (added)
+++ 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/TypeLit.java
 Thu Jan 22 17:19:47 2009
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+package org.apache.openjpa.jdbc.kernel.exps;
+
+import org.apache.openjpa.jdbc.meta.ClassMapping;
+import org.apache.openjpa.jdbc.meta.Discriminator;
+import org.apache.openjpa.jdbc.sql.SQLBuffer;
+import org.apache.openjpa.jdbc.sql.Select;
+import org.apache.openjpa.kernel.Filters;
+import org.apache.openjpa.kernel.exps.Literal;
+import org.apache.openjpa.meta.JavaTypes;
+
+/**
+ * A type literal value.
+ *
+ * @author Catalina Wei
+ */
+public class TypeLit
+    extends Const
+    implements Literal {
+
+    private Object _val;
+    private int _ptype;
+
+    /**
+     * Constructor. Supply literal value.
+     */
+    public TypeLit(Object val, int ptype) {
+        _val = val;
+        _ptype = ptype;
+    }
+
+    public Class getType() {
+        return (_val == null) ? Object.class : _val.getClass();
+    }
+
+    public void setImplicitType(Class type) {
+        _val = Filters.convert(_val, type);
+    }
+
+    public int getParseType() {
+        return _ptype;
+    }
+
+    public Object getValue() { 
+        return _val;
+    }
+
+    public void setValue(Object val) {
+        _val = val;
+    }
+
+    public Object getValue(Object[] params) {
+        return getValue();
+    }
+
+    public ExpState initialize(Select sel, ExpContext ctx, int flags) {
+        return new LitExpState();
+    }
+
+    /**
+     * Expression state.
+     */
+    private static class LitExpState
+        extends ConstExpState {
+
+        public Object sqlValue;
+        public int otherLength; 
+        public ClassMapping mapping = null;
+        public Discriminator disc = null;
+        public Object discValue = null;
+    } 
+
+    public void calculateValue(Select sel, ExpContext ctx, ExpState state, 
+        Val other, ExpState otherState) {
+        super.calculateValue(sel, ctx, state, other, otherState);
+        LitExpState lstate = (LitExpState) state;
+        lstate.mapping = (ClassMapping) getMetaData();
+        lstate.disc = lstate.mapping.getDiscriminator();
+        lstate.discValue = lstate.disc != null ? lstate.disc.getValue() :
+            null;
+        sel.select(((ClassMapping) getMetaData()).getPrimaryKeyColumns(),
+            lstate.joins);
+    }
+
+    public void appendTo(Select sel, ExpContext ctx, ExpState state, 
+        SQLBuffer sql, int index) {
+        LitExpState lstate = (LitExpState) state;
+        if (lstate.otherLength > 1)
+            sql.appendValue(((Object[]) lstate.sqlValue)[index], 
+                lstate.getColumn(index));
+        else {
+            if (lstate.discValue != null)                
+                sql.append(getDiscriminator(lstate));
+            else
+                sql.append("1");
+        }
+    }
+
+    private String getDiscriminator(LitExpState lstate) {
+        StringBuffer disc = new StringBuffer(lstate.discValue.toString());
+        switch(lstate.disc.getJavaType()) {
+        case JavaTypes.INT:
+            return disc.toString();
+        case JavaTypes.CHAR:
+        case JavaTypes.STRING:
+        default:
+            return disc.insert(0, "'").append("'").toString();
+        }        
+    }
+}

Modified: 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Val.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Val.java?rev=736881&r1=736880&r2=736881&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Val.java
 (original)
+++ 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Val.java
 Thu Jan 22 17:19:47 2009
@@ -153,6 +153,12 @@
         SQLBuffer sql);
 
     /**
+     * Append the SQL checking the type of this value.
+     */
+    public void appendType(Select sel, ExpContext ctx, ExpState state, 
+        SQLBuffer sql);
+
+    /**
      * Append the SQL checking the size of this value.
      */
     public void appendSize(Select sel, ExpContext ctx, ExpState state, 

Modified: 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldMapping.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldMapping.java?rev=736881&r1=736880&r2=736881&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldMapping.java
 (original)
+++ 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldMapping.java
 Thu Jan 22 17:19:47 2009
@@ -862,6 +862,10 @@
         assertStrategy().appendIndex(sql, sel, joins);
     }
 
+    public void appendType(SQLBuffer sql, Select sel, Joins joins) {
+        assertStrategy().appendType(sql, sel, joins);
+    }
+
     public Joins join(Joins joins, boolean forceOuter) {
         return assertStrategy().join(joins, forceOuter);
     }

Modified: 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldStrategy.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldStrategy.java?rev=736881&r1=736880&r2=736881&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldStrategy.java
 (original)
+++ 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldStrategy.java
 Thu Jan 22 17:19:47 2009
@@ -186,6 +186,11 @@
     public void appendIndex(SQLBuffer sql, Select sel, Joins joins);
 
     /**
+     * Append the entity discriminator value to the given statement.
+     */
+    public void appendType(SQLBuffer sql, Select sel, Joins joins);
+
+    /**
      * Join this value to the class table. Does nothing by default.
      */
     public Joins join(Joins joins, boolean forceOuter);

Modified: 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/AbstractFieldStrategy.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/AbstractFieldStrategy.java?rev=736881&r1=736880&r2=736881&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/AbstractFieldStrategy.java
 (original)
+++ 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/AbstractFieldStrategy.java
 Thu Jan 22 17:19:47 2009
@@ -139,6 +139,10 @@
         sql.append("1");
     }
 
+    public void appendType(SQLBuffer sql, Select sel, Joins joins) {
+        sql.append("1");
+    }
+
     public Joins join(Joins joins, boolean forceOuter) {
         return joins;
     }

Modified: 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ExpressionFactory.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ExpressionFactory.java?rev=736881&r1=736880&r2=736881&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ExpressionFactory.java
 (original)
+++ 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ExpressionFactory.java
 Thu Jan 22 17:19:47 2009
@@ -403,6 +403,13 @@
     public Value index(Value target);
 
     /**
+     * Return the type/class of the given value.
+     *
+     * @since 2.0.0
+     */
+    public Value type(Value target);
+
+    /**
      * Return distinct values of the given value. This is typically used
      * within aggregates, for example: max(distinct(path))
         *
@@ -445,4 +452,10 @@
      * Return a nullif expression
      */
     public Value nullIfExpression(Value val1, Value val2);
+
+    /**
+     * Return a value representing the given constant, which will be
+     * a {...@link Number}, {...@link String}, or {...@link Boolean} instance.
+     */
+    public Literal newTypeLiteral(Object val, int parseType);
 }

Modified: 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/InMemoryExpressionFactory.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/InMemoryExpressionFactory.java?rev=736881&r1=736880&r2=736881&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/InMemoryExpressionFactory.java
 (original)
+++ 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/InMemoryExpressionFactory.java
 Thu Jan 22 17:19:47 2009
@@ -480,6 +480,10 @@
         return new Lit(val, parseType);
     }
 
+    public Literal newTypeLiteral(Object val, int parseType) {
+        return new TypeLit(val, parseType);
+    }
+
     public Value getThis() {
         return new This();
     }
@@ -635,6 +639,10 @@
         return new Index((Val) val);
     }
 
+    public Value type(Value val) {
+        return new Type((Val) val);
+    }
+
     public Value getObjectId(Value val) {
         return new GetObjectId((Val) val);
     }

Modified: 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Literal.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Literal.java?rev=736881&r1=736880&r2=736881&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Literal.java
 (original)
+++ 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Literal.java
 Thu Jan 22 17:19:47 2009
@@ -32,6 +32,7 @@
     public static final int TYPE_BOOLEAN = 2;
     public static final int TYPE_STRING = 3;
     public static final int TYPE_SQ_STRING = 4; // single-quoted string
+    public static final int TYPE_CLASS = 5;
 
     /**
      * The value of this literal.

Added: 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Type.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Type.java?rev=736881&view=auto
==============================================================================
--- 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Type.java
 (added)
+++ 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Type.java
 Thu Jan 22 17:19:47 2009
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+package org.apache.openjpa.kernel.exps;
+
+import java.util.Collection;
+import java.util.Map;
+
+import org.apache.openjpa.kernel.StoreContext;
+
+import serp.util.Numbers;
+
+/**
+ * Returns the entity type.
+ *
+ * @author Catalina Wei
+ */
+class Type extends Val {
+
+    private final Val _val;
+
+    /**
+     * Constructor. Provide target string and the arguments to the
+     * indexOf method.
+     */
+    public Type(Val val) {
+        _val = val;
+    }
+
+    public Class getType() {
+        return Class.class;
+    }
+
+    public void setImplicitType(Class type) {
+    }
+
+    protected Object eval(Object candidate, Object orig,
+        StoreContext ctx, Object[] params) {
+        _val.eval(candidate, orig, ctx, params);
+        return _val.getType();
+    }
+
+    public void acceptVisit(ExpressionVisitor visitor) {
+        visitor.enter(this);
+        _val.acceptVisit(visitor);
+        visitor.exit(this);
+    }
+}

Added: 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/TypeLit.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/TypeLit.java?rev=736881&view=auto
==============================================================================
--- 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/TypeLit.java
 (added)
+++ 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/TypeLit.java
 Thu Jan 22 17:19:47 2009
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+package org.apache.openjpa.kernel.exps;
+
+import org.apache.openjpa.kernel.Filters;
+import org.apache.openjpa.kernel.StoreContext;
+
+/**
+ * Represents a type literal.
+ *
+ * @author Catalina Wei
+ */
+class TypeLit
+    extends Val
+    implements Literal {
+
+    private Object _val;
+    private final int _ptype;
+
+    /**
+     * Constructor. Provide constant value.
+     */
+    public TypeLit(Object val, int ptype) {
+        _val = val;
+        _ptype = ptype;
+    }
+
+    public Object getValue() {
+        return _val;
+    }
+
+    public void setValue(Object val) {
+        _val = val;
+    }
+
+    public int getParseType() {
+        return _ptype;
+    }
+
+    public Object getValue(Object[] parameters) {
+        return _val;
+    }
+
+    public Class getType() {
+        return (_val == null) ? Object.class : _val.getClass();
+    }
+
+    public void setImplicitType(Class type) {
+        _val = Filters.convert(_val, type);
+    }
+
+    protected Object eval(Object candidate, Object orig,
+        StoreContext ctx, Object[] params) {
+        return _val;
+    }
+}

Modified: 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java?rev=736881&r1=736880&r2=736881&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java
 (original)
+++ 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java
 Thu Jan 22 17:19:47 2009
@@ -330,14 +330,23 @@
             if (aliasNode != null)
                 proj.setAlias(alias);
             exps.projections[i] = proj;
-            exps.projectionClauses[i] = aliasNode == null ?
-                assemble(node.id == JJTSCALAREXPRESSION ? firstChild(node)
-                    : node) : alias;
+            exps.projectionClauses[i] = aliasNode != null ? alias :
+                projectionClause(node.id == JJTSCALAREXPRESSION ?
+                    firstChild(node) : node);
             exps.projectionAliases[i] = alias;
         }
         return exp;
     }
 
+    private String projectionClause(JPQLNode node) {
+        switch (node.id) {
+        case JJTTYPE:
+            return projectionClause(firstChild(node));
+        default:
+            return assemble(node);
+        }
+    }
+    
     private void evalQueryOperation(QueryExpressions exps) {
         // determine whether we want to select, delete, or update
         if (root().id == JJTSELECT || root().id == JJTSUBSELECT)
@@ -746,7 +755,10 @@
                 return eval(onlyChild(node));
 
             case JJTTYPE:
-                return eval(onlyChild(node));
+                return getType(onlyChild(node));
+
+            case JJTTYPELITERAL:
+                return getTypeLiteral(node);
 
             case JJTCLASSNAME:
                 return getPathOrConstant(node);
@@ -754,10 +766,10 @@
             case JJTCASE:
                 return eval(onlyChild(node));
 
-            case JJTSCASE:
+            case JJTSIMPLECASE:
                 return getSimpleCaseExpression(node);
 
-            case JJTGCASE:
+            case JJTGENERALCASE:
                 return getGeneralCaseExpression(node);
 
             case JJTWHEN:
@@ -814,6 +826,10 @@
             case JJTPOSITIONALINPUTPARAMETER:
                 return getParameter(node.text, true);
 
+            case JJTCOLLECTIONPARAMETER:
+                // TODO: support collection valued parameters
+                return getParameter(onlyChild(node).text, true);
+
             case JJTOR: // x OR y
                 return factory.or(getExpression(left(node)),
                     getExpression(right(node)));
@@ -892,14 +908,19 @@
                     factory.lessThanEqual(val1, val3)));
 
             case JJTIN: // x.field [NOT] IN ('a', 'b', 'c')
-
+                        // TYPE(x...) [NOT] IN (entityTypeLiteral1,...)
                 Expression inExp = null;
                 Iterator inIterator = node.iterator();
                 // the first child is the path
-                val1 = getValue((JPQLNode) inIterator.next());
+                JPQLNode first = (JPQLNode) inIterator.next();
+                val1 = getValue(first);
 
                 while (inIterator.hasNext()) {
-                    val2 = getValue((JPQLNode) inIterator.next());
+                    JPQLNode next = (JPQLNode) inIterator.next();
+                    if (first.id == JJTTYPE && next.id == JJTTYPELITERAL)
+                        val2 = getTypeLiteral(next);
+                    else
+                        val2 = getValue(next);
 
                     // special case for <value> IN (<subquery>) or
                     // <value> IN (<single value>)
@@ -1360,6 +1381,21 @@
         } else if (val instanceof Path) {
             return (Path) val;
         } else if (val instanceof Value) {
+            if (val.isVariable()) {
+                // can be an entity type literal
+                Class c = resolver.classForName(name, null);
+                if (c != null) {
+                    Value lit = factory.newTypeLiteral(c, Literal.TYPE_CLASS);
+                    Class<?> candidate = getCandidateType();
+                    ClassMetaData can = getClassMetaData(candidate.getName(), 
false);
+                    ClassMetaData meta = getClassMetaData(name, false);
+                    if (candidate.isAssignableFrom(c))
+                        lit.setMetaData(meta);
+                    else
+                        lit.setMetaData(can);
+                    return lit;
+                }
+            }
             return (Value) val;
         }
 
@@ -1367,6 +1403,24 @@
             new Object[]{ name }, null);
     }
 
+    private Value getTypeLiteral(JPQLNode node) {
+        JPQLNode type = onlyChild(node);
+        final String name = type.text;
+        final Value val = getVariable(name, false);
+
+        if (val instanceof Value && val.isVariable()) {
+            Class c = resolver.classForName(name, null);
+            if (c != null) {
+                Value typeLit = factory.newTypeLiteral(c, Literal.TYPE_CLASS);
+                typeLit.setMetaData(getClassMetaData(name, false));
+                return typeLit;
+            }
+        }
+
+        throw parseException(EX_USER, "not-type-literal",
+            new Object[]{ name }, null);
+    }
+
     private Value getPathOrConstant(JPQLNode node) {
         // first check to see if the path is an enum or static field, and
         // if so, load it
@@ -1394,6 +1448,36 @@
         }
     }
 
+    /**
+     * Process type_discriminator
+     *     type_discriminator ::=
+     *         TYPE(identification_variable |
+     *         single_valued_object_path_expression |
+     *         input_parameter )
+     */
+    private Value getType(JPQLNode node) {
+        switch (node.id) {
+        case JJTIDENTIFIER:
+            return factory.type(getValue(node));
+
+        case JJTNAMEDINPUTPARAMETER:
+            return factory.type(getParameter(node.text, false));
+
+        case JJTPOSITIONALINPUTPARAMETER:
+            return factory.type(getParameter(node.text, true));
+
+        default:
+            // TODO: enforce jpa2.0 spec rules.
+            // A single_valued_object_field is designated by the name of
+            // an association field in a one-to-one or many-to-one relationship
+            // or a field of embeddable class type.
+            // The type of a single_valued_object_field is the abstract schema
+            // type of the related entity or embeddable class
+            Value path = getPath(node, false, true);
+            return factory.type(path);
+        }
+    }
+
     private Path getPath(JPQLNode node) {
         return getPath(node, false, true);
     }

Modified: 
openjpa/trunk/openjpa-kernel/src/main/jjtree/org/apache/openjpa/kernel/jpql/JPQL.jjt
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/jjtree/org/apache/openjpa/kernel/jpql/JPQL.jjt?rev=736881&r1=736880&r2=736881&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-kernel/src/main/jjtree/org/apache/openjpa/kernel/jpql/JPQL.jjt
 (original)
+++ 
openjpa/trunk/openjpa-kernel/src/main/jjtree/org/apache/openjpa/kernel/jpql/JPQL.jjt
 Thu Jan 22 17:19:47 2009
@@ -745,19 +745,26 @@
 
 void in_expression() #IN : { }
 {
-       (path() | scalar_function()) [ LOOKAHEAD(1) <NOT> { jjtThis.not = true; 
}] <IN>
-               "(" (literal_or_param()
+       (path() | scalar_function() | type_discriminator()) [ LOOKAHEAD(1) 
<NOT> { jjtThis.not = true; }] <IN>
+               ("(" (literal_or_param()
                        (<COMMA> (literal_or_param()))* | subquery())
-               ")" 
+                ")"  
+               | collection_valued_input_parameter()
+               )
 }
 
+void entity_type_literal() #TYPELITERAL : { }
+{
+    identification_variable()
+}
 
 void literal_or_param() : { }
 {
        (numeric_literal()
        | string_literal()
        | boolean_literal()
-       | input_parameter())
+       | input_parameter()
+       | entity_type_literal())
 }
 
 
@@ -941,46 +948,51 @@
        LOOKAHEAD(2) "(" arithmetic_expression() ")" | 
        functions_returning_numerics() | 
        aggregate_select_expression() | 
+       LOOKAHEAD(case_expression()) case_expression() |
        subquery()
 }
 
 
-void qualified_path() #QPATH : { }
+void qualified_path() #QUALIFIEDPATH : { }
 {
     general_identification_variable() (LOOKAHEAD(2) <DOT> path_component())+
 }
 
-void qualified_identification_variable() #QIDENTIFIER : { }
+void qualified_identification_variable() #QUALIFIEDIDENTIFIER : { }
 {
-    ( <KEY> "(" identification_variable() ")" #KEY
-    | <VALUE> "(" identification_variable() ")" #VALUE
-    | <ENTRY> "(" identification_variable() ")" #ENTRY
+    ( <KEY> "(" identification_variable() ")" #KEY(1)
+    | <VALUE> "(" identification_variable() ")" #VALUE(1)
+    | <ENTRY> "(" identification_variable() ")" #ENTRY(1)
     )
 }
 
-void general_identification_variable() #GIDENTIFIER : { }
+void general_identification_variable() #GENERALIDENTIFIER : { }
 {
-    ( <KEY> "(" identification_variable() ")" #KEY
-    | <VALUE> "(" identification_variable() ")" #VALUE
+    ( <KEY> "(" identification_variable() ")" #KEY(1)
+    | <VALUE> "(" identification_variable() ")" #VALUE(1)
     )
 }
 
 void entity_type_comp() : { }
 {
-    entity_type_expression()
-       ( <EQ> entity_type_expression() #EQUALS(2)
-       | <NE> entity_type_expression() #NOTEQUALS(2)
+    (entity_type_expression() | entity_type_literal())
+       ( <EQ> (entity_type_expression() | entity_type_literal()) #EQUALS(2)
+       | <NE> (entity_type_expression() | entity_type_literal()) #NOTEQUALS(2)
        )
 }
 
-void entity_type_expression() #TYPE : { }
+void type_discriminator() #TYPE : { }
 {
-    <TYPE> "(" (LOOKAHEAD(identification_variable()) identification_variable()
-               | LOOKAHEAD(path()) path()
+    <TYPE> "(" (LOOKAHEAD(path()) path()
                | LOOKAHEAD(general_identification_variable()) 
general_identification_variable()
+               | LOOKAHEAD(identification_variable()) identification_variable()
                | LOOKAHEAD(input_parameter()) input_parameter())
-            ")" |
-    classname() #TYPE_LITERAL |
+            ")"
+}
+
+void entity_type_expression(): { }
+{
+    type_discriminator() |
     input_parameter()
 }
 
@@ -990,7 +1002,7 @@
     LOOKAHEAD(case_expression()) case_expression() |
     LOOKAHEAD(string_primary()) string_primary() |
     LOOKAHEAD(datetime_primary()) datetime_primary() |
-    LOOKAHEAD(enum_primary()) enum_primary()
+    LOOKAHEAD(enum_primary()) enum_primary() |
     LOOKAHEAD(entity_type_expression()) entity_type_expression()
 }
 
@@ -1004,29 +1016,31 @@
     <NULLIF> nullif_expression()
 }
 
-void general_case_expression() #GCASE : { }
+void general_case_expression() #GENERALCASE : { }
 {
     (when_clause())+
-    <ELSE> scalar_expression()
+    <ELSE> (LOOKAHEAD(2) scalar_expression() | entity_type_literal())
     <END>
 }
 
 void when_clause() #WHEN : { }
 {
-    <WHEN> conditional_expression() <THEN> scalar_expression()
+    <WHEN> conditional_expression()
+    <THEN> (LOOKAHEAD(2) scalar_expression() | entity_type_literal())
 }
 
-void simple_case_expression() #SCASE : { }
+void simple_case_expression() #SIMPLECASE : { }
 {
-    (LOOKAHEAD(2) path() | entity_type_expression())
+    (LOOKAHEAD(type_discriminator()) type_discriminator() | LOOKAHEAD(path()) 
path())
     (simple_when_clause())+
-    <ELSE> scalar_expression()
+    <ELSE> (LOOKAHEAD(2) scalar_expression() | entity_type_literal())
     <END>
 }
 
 void simple_when_clause() #WHENSCALAR : { }
 {
-    <WHEN> scalar_expression() <THEN> scalar_expression()
+    <WHEN> (LOOKAHEAD(2) scalar_expression() | entity_type_literal())
+    <THEN> (LOOKAHEAD(2) scalar_expression() | entity_type_literal())
 }
 
 void coalesce_expression() #COALESCE : { }
@@ -1409,6 +1423,12 @@
 }
 
 
+void collection_valued_input_parameter() #COLLECTIONPARAMETER: { }
+{
+       named_input_parameter() | positional_input_parameter()
+}
+
+
 void named_input_parameter() #NAMEDINPUTPARAMETER :
 { Token t; }
 {

Modified: 
openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/jpql/localizer.properties
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/jpql/localizer.properties?rev=736881&r1=736880&r2=736881&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/jpql/localizer.properties
 (original)
+++ 
openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/jpql/localizer.properties
 Thu Jan 22 17:19:47 2009
@@ -71,4 +71,5 @@
     openjpa.Compatibility configuration setting is configured to disallow \
     JPQL extensions.
 jpql-parse-error: "{1}" while parsing JPQL "{0}". See nested stack trace for \
-       original parse error.
\ No newline at end of file
+       original parse error.
+not-type-literal: The specified node ("{0}") is not a valid entity type 
literal.

Added: 
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jpql/expressions/TestEntityTypeExpression.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jpql/expressions/TestEntityTypeExpression.java?rev=736881&view=auto
==============================================================================
--- 
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jpql/expressions/TestEntityTypeExpression.java
 (added)
+++ 
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jpql/expressions/TestEntityTypeExpression.java
 Thu Jan 22 17:19:47 2009
@@ -0,0 +1,192 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+package org.apache.openjpa.persistence.jpql.expressions;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import javax.persistence.EntityManager;
+
+import org.apache.openjpa.persistence.common.apps.*;
+import org.apache.openjpa.persistence.common.utils.AbstractTestCase;
+
+public class TestEntityTypeExpression extends AbstractTestCase {
+
+    private int userid1, userid2, userid3, userid4, userid5, userid6;
+
+    public TestEntityTypeExpression(String name) {
+        super(name, "jpqlclausescactusapp");
+    }
+
+    public void setUp() {
+        deleteAll(CompUser.class);
+        EntityManager em = currentEntityManager();
+        startTx(em);
+
+        Address[] add = new Address[]{
+            new Address("43 Sansome", "SF", "United-Kingdom", "94104"),
+            new Address("24 Mink", "ANTIOCH", "USA", "94513"),
+            new Address("23 Ogbete", "CoalCamp", "NIGERIA", "00000"),
+            new Address("10 Wilshire", "Worcester", "CANADA", "80080"),
+            new Address("23 Bellflower", "Ogui", null, "02000"),
+            new Address("22 Montgomery", "SF", null, "50054") };
+
+        CompUser user1 = createUser("Seetha", "MAC", add[0], 36, true);
+        CompUser user2 = createUser("Shannon ", "PC", add[1], 36, false);
+        CompUser user3 = createUser("Ugo", "PC", add[2], 19, true);
+        CompUser user4 = createUser("_Jacob", "LINUX", add[3], 10, true);
+        CompUser user5 = createUser("Famzy", "UNIX", add[4], 29, false);
+        CompUser user6 = createUser("Shade", "UNIX", add[5], 23, false);
+
+        em.persist(user1);
+        userid1 = user1.getUserid();
+        em.persist(user2);
+        userid2 = user2.getUserid();
+        em.persist(user3);
+        userid3 = user3.getUserid();
+        em.persist(user4);
+        userid4 = user4.getUserid();
+        em.persist(user5);
+        userid5 = user5.getUserid();
+        em.persist(user6);
+        userid6 = user6.getUserid();
+
+        endTx(em);
+        endEm(em);
+    }
+
+    @SuppressWarnings("unchecked")
+    public void testTypeExpression() {
+        EntityManager em = currentEntityManager();
+
+        String query = null;
+        List<CompUser> rs = null;
+        CompUser user = null;
+
+//      TODO: test when support for collection valued parameters is available
+//        Collection params = new ArrayList();
+//        params.add(FemaleUser.class);
+//        params.add(MaleUser.class);
+//        query = "SELECT e FROM CompUser e where TYPE(e) = :params";
+//        rs =  em.createQuery(query).
+//            setParameter("params", params).getResultList();
+//        user = rs.get(0);
+//        assertEquals("the name is not shannon", "Shannon ", user.getName());
+        
+        query = "SELECT TYPE(e) FROM MaleUser e where TYPE(e) = MaleUser";
+        rs = em.createQuery(query).getResultList();
+        Object type = rs.get(0);
+        assertEquals(type, MaleUser.class);
+        
+        query = "SELECT TYPE(e) FROM CompUser e where TYPE(e) = ?1";
+        rs = em.createQuery(query).
+            setParameter(1, FemaleUser.class).getResultList();
+        type = rs.get(0);
+        assertEquals(type, FemaleUser.class);
+
+        query = "SELECT TYPE(e) FROM MaleUser e where TYPE(e) = ?1";
+        rs = em.createQuery(query).
+            setParameter(1, MaleUser.class).getResultList();
+        type = rs.get(0);
+        assertEquals(type, MaleUser.class);
+
+        query = "SELECT e, FemaleUser, a FROM Address a, FemaleUser e " +
+            " where e.address IS NOT NULL";
+        List<Object> rs2 = em.createQuery(query).getResultList();
+        type = ((Object[]) rs2.get(0))[1];
+        assertEquals(type, FemaleUser.class);
+        
+        query = "SELECT e FROM CompUser e where TYPE(e) = :typeName";
+        rs =  em.createQuery(query).
+            setParameter("typeName", FemaleUser.class).getResultList();
+        user = rs.get(0);
+        assertEquals("the name is not shannon", "Shannon ", user.getName());
+
+        query = "SELECT e FROM CompUser e where TYPE(e) = ?1";
+        rs = em.createQuery(query).
+            setParameter(1, FemaleUser.class).getResultList();
+        user = rs.get(0);
+        assertEquals("the name is not shannon", "Shannon ", user.getName());
+        
+        query = "SELECT e FROM CompUser e where TYPE(e) in (?1)";
+        rs = em.createQuery(query).
+            setParameter(1, MaleUser.class).getResultList();
+        user = rs.get(0);
+        assertEquals(user.getName(), "Seetha");
+        
+        query = "SELECT e FROM CompUser e where TYPE(e) in (?1, ?2)";
+        rs = em.createQuery(query).
+            setParameter(1, FemaleUser.class).setParameter(2, MaleUser.class).
+            getResultList();
+        user = rs.get(0);
+        assertEquals("the name is not shannon", "Shannon ", user.getName());
+
+        query = "select sum(e.age) FROM CompUser e GROUP BY e.age" +
+            " HAVING ABS(e.age) = :param";
+        Long sum = (Long) em.createQuery(query).
+            setParameter("param",  new Double(36)).getSingleResult();
+        assertEquals(sum.intValue(), 72);
+
+        String[] queries = {
+            "SELECT e FROM CompUser e where TYPE(e) = MaleUser",
+            "SELECT e from CompUser e where TYPE(e) in (FemaleUser)",
+            "SELECT e from CompUser e where TYPE(e) not in (FemaleUser)",
+            "SELECT e from CompUser e where TYPE(e) in (MaleUser, FemaleUser)",
+            "SELECT TYPE(e) FROM CompUser e where TYPE(e) = MaleUser",
+            "SELECT TYPE(e) FROM CompUser e",
+            "SELECT TYPE(a.user) FROM Address a",
+            "SELECT MaleUser FROM CompUser e", 
+            "SELECT MaleUser FROM Address a",
+            "SELECT " +
+                " CASE TYPE(e) WHEN FemaleUser THEN 'Female' " +
+                " ELSE 'Male' " +
+                " END " +
+                " FROM CompUser e",
+        };
+        
+        for (int i = 0; i < queries.length; i++) {
+            query = queries[i];
+            List<Object> rs1 = em.createQuery(query).getResultList();
+            Object obj = rs1.get(0);
+            obj.toString();
+            System.err.println(obj+" rs size="+rs1.size());
+        }
+
+        endEm(em);
+    }
+
+    public CompUser createUser(String name, String cName, Address add, int age,
+        boolean isMale) {
+        CompUser user = null;
+        if (isMale) {
+            user = new MaleUser();
+            user.setName(name);
+            user.setComputerName(cName);
+            user.setAddress(add);
+            user.setAge(age);
+        } else {
+            user = new FemaleUser();
+            user.setName(name);
+            user.setComputerName(cName);
+            user.setAddress(add);
+            user.setAge(age);
+        }
+        return user;
+    }
+}

Modified: 
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jpql/expressions/TestJPQLScalarExpressions.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jpql/expressions/TestJPQLScalarExpressions.java?rev=736881&r1=736880&r2=736881&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jpql/expressions/TestJPQLScalarExpressions.java
 (original)
+++ 
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jpql/expressions/TestJPQLScalarExpressions.java
 Thu Jan 22 17:19:47 2009
@@ -69,11 +69,11 @@
         endEm(em);
     }
 
+    @SuppressWarnings("unchecked")
     public void testCoalesceExpressions() {
         EntityManager em = currentEntityManager();
         startTx(em);
 
-
         String query = "SELECT e.name, " +
             "COALESCE (e.address.country, 'Unknown')" +
             " FROM CompUser e";
@@ -86,6 +86,7 @@
         endEm(em);
     }
 
+    @SuppressWarnings("unchecked")
     public void testNullIfExpressions() {
         EntityManager em = currentEntityManager();
         startTx(em);
@@ -103,6 +104,7 @@
         endEm(em);
     }
 
+    @SuppressWarnings("unchecked")
     public void testSimpleCaseExpressions() {
         EntityManager em = currentEntityManager();
 
@@ -129,15 +131,23 @@
         Object[] result2 = (Object[]) rs2.get(rs2.size()-1);
         assertEquals("the name is not seetha", "Seetha", result2[0]);
 
-        // TODO: needs entity-type-expression
         String query3 = "SELECT e.name, " +
             " CASE TYPE(e) WHEN FemaleUser THEN 'Female' " +
             " ELSE 'Male' " +
-            " END " +
+            " END as result" +
             " FROM CompUser e";
+        List rs3 = em.createQuery(query3).getResultList();
+        Object[] result3 = (Object[]) rs3.get(rs3.size()-1);
+        assertEquals("the result is not female", "Female", result3[1]);
+        assertEquals("the name is not shade", "Shade", result3[0]);
+        result3 = (Object[]) rs3.get(0);
+        assertEquals("the result is not male", "Male", result3[1]);
+        assertEquals("the name is not seetha", "Seetha", result3[0]);
+
         endEm(em);
     }
 
+    @SuppressWarnings("unchecked")
     public void testGeneralCaseExpressions() {
         EntityManager em = currentEntityManager();
         startTx(em);
@@ -154,7 +164,6 @@
             " FROM CompUser e ORDER BY cage";
         
         List rs = em.createQuery(query).getResultList();
-       
 
         String update = "UPDATE CompUser e SET e.age = " +
             "CASE WHEN e.age > 30 THEN e.age - 1 " +
@@ -169,6 +178,7 @@
         endEm(em);
     }
 
+    @SuppressWarnings("unchecked")
     public void testMathFuncOrderByAlias() {
         EntityManager em = currentEntityManager();
 


Reply via email to