You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pp...@apache.org on 2009/08/01 14:03:09 UTC

svn commit: r799848 - in /openjpa/trunk: openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/que...

Author: ppoddar
Date: Sat Aug  1 12:03:09 2009
New Revision: 799848

URL: http://svn.apache.org/viewvc?rev=799848&view=rev
Log:
OPENJPA-1180: Parameter processing for JPA 2.0. Query now distinguishes between bound and declared parameters. Holds all bound parameters in a single data structure instead of named/positional parameters in separate maps.

Removed:
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryParameter.java
Modified:
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/TestNativeQueryParameterBinding.java
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/TestQueryParameters.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/ParameterImpl.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaQueryImpl.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ParameterExpressionImpl.java

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java?rev=799848&r1=799847&r2=799848&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java Sat Aug  1 12:03:09 2009
@@ -465,6 +465,13 @@
             unlock();
         }
     }
+    
+    /**
+     * Affirms if this query has originated by parsing a string-based query.
+     */
+    public boolean isParsedQuery() {
+        return getQueryString() != null;
+    }
 
     public void setUnique(boolean unique) {
         lock();
@@ -622,7 +629,7 @@
     protected Compilation compilationFromCache() {
         Map compCache =
             _broker.getConfiguration().getQueryCompilationCacheInstance();
-        if (compCache == null || getQueryString() == null) {
+        if (compCache == null || !isParsedQuery()) {
             return newCompilation();
         } else {
             CompilationKey key = new CompilationKey();
@@ -1684,7 +1691,7 @@
      */
     protected void assertParameters(StoreQuery q, StoreQuery.Executor ex, 
         Object[] params) {
-        if (!q.requiresParameterDeclarations())
+        if (!q.requiresParameterDeclarations() || !isParsedQuery())
             return;
 
         LinkedMap paramTypes = ex.getParameterTypes(q);

Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/TestNativeQueryParameterBinding.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/TestNativeQueryParameterBinding.java?rev=799848&r1=799847&r2=799848&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/TestNativeQueryParameterBinding.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/query/TestNativeQueryParameterBinding.java Sat Aug  1 12:03:09 2009
@@ -56,6 +56,14 @@
 		verifyParams(sql, IllegalArgumentException.class, 0, 10);
 	}
 	
+	public void testNativeQueryDeclaredParameters() {
+        String sql = "SELECT * FROM Application WHERE id=?1 AND name=?2";
+        EntityManager em = emf.createEntityManager();
+        em.getTransaction().begin();
+        Query query = em.createNativeQuery(sql);
+        assertTrue(query.getParameters().isEmpty());
+	}
+	
 	void verifyParams(String jpql, Class<? extends Exception> error,
         Object... params) {
         EntityManager em = emf.createEntityManager();

Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/TestQueryParameters.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/TestQueryParameters.java?rev=799848&r1=799847&r2=799848&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/TestQueryParameters.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/TestQueryParameters.java Sat Aug  1 12:03:09 2009
@@ -8,7 +8,6 @@
 import javax.persistence.criteria.Predicate;
 import javax.persistence.criteria.QueryBuilder;
 import javax.persistence.criteria.Root;
-import javax.persistence.metamodel.Attribute;
 import javax.persistence.metamodel.EntityType;
 import javax.persistence.metamodel.Metamodel;
 import javax.persistence.metamodel.SingularAttribute;
@@ -18,7 +17,6 @@
 import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI;
 import org.apache.openjpa.persistence.OpenJPAPersistence;
 import org.apache.openjpa.persistence.ParameterImpl;
-import org.apache.openjpa.persistence.QueryParameter;
 import org.apache.openjpa.persistence.test.SingleEMFTestCase;
 
 /**
@@ -125,11 +123,11 @@
         
         Parameter<?> param1 = q.getParameter(1);
         assertTrue(param1 instanceof ParameterImpl);
-        assertEquals(long.class, ((QueryParameter<?>)param1).getExpectedValueType());
+        assertEquals(long.class, param1.getJavaType());
         
         Parameter<?> param2 = q.getParameter(2);
         assertTrue(param2 instanceof ParameterImpl);
-        assertEquals(String.class, ((QueryParameter<?>)param2).getExpectedValueType());
+        assertEquals(String.class, param2.getJavaType());
     }
     
     public void testNamedParameterValueTypeInJPQLQuery() {
@@ -140,11 +138,11 @@
         
         Parameter<?> param1 = q.getParameter("id");
         assertTrue(param1 instanceof ParameterImpl);
-        assertEquals(long.class, ((QueryParameter<?>)param1).getExpectedValueType());
+        assertEquals(long.class, param1.getJavaType());
         
         Parameter<?> param2 = q.getParameter("name");
         assertTrue(param2 instanceof ParameterImpl);
-        assertEquals(String.class, ((QueryParameter<?>)param2).getExpectedValueType());
+        assertEquals(String.class, param2.getJavaType());
     }
     
     public void testNamedParameterInPreparedQuery() {
@@ -242,11 +240,11 @@
         
         Parameter<?> param1 = q.getParameter(1);
         assertTrue(param1 instanceof ParameterImpl);
-        assertEquals(long.class, ((QueryParameter<?>)param1).getExpectedValueType());
+        assertEquals(long.class, param1.getJavaType());
         
         Parameter<?> param2 = q.getParameter(2);
         assertTrue(param2 instanceof ParameterImpl);
-        assertEquals(String.class, ((QueryParameter<?>)param2).getExpectedValueType());
+        assertEquals(String.class, param2.getJavaType());
     }
     
     public void testNamedParameterValueTypeInNamedQuery() {
@@ -256,11 +254,11 @@
         
         Parameter<?> param1 = q.getParameter("id");
         assertTrue(param1 instanceof ParameterImpl);
-        assertEquals(long.class, ((QueryParameter<?>)param1).getExpectedValueType());
+        assertEquals(long.class, param1.getJavaType());
         
         Parameter<?> param2 = q.getParameter("name");
         assertTrue(param2 instanceof ParameterImpl);
-        assertEquals(String.class, ((QueryParameter<?>)param2).getExpectedValueType());
+        assertEquals(String.class, param2.getJavaType());
     }
     
     public void testCriteriaQueryWithNamedParameter() {
@@ -284,6 +282,8 @@
         assertEquals(2, q.getParameters().size());
         assertTrue(q.getParameters().contains(param1));
         assertTrue(q.getParameters().contains(param2));
+        assertNotNull(q.getParameter("id"));
+        assertNotNull(q.getParameter("name"));
     }
     
     public void testCriteriaQueryWithUnnamedParameter() {

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java?rev=799848&r1=799847&r2=799848&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java Sat Aug  1 12:03:09 2009
@@ -1540,7 +1540,7 @@
         Set<ParameterExpression<?>> params = ((CriteriaQueryImpl<T>)criteriaQuery).getParameters();
         
         for (ParameterExpression<?> param : params) {
-            facadeQuery.registerParameter((QueryParameter<?>)param);
+            facadeQuery.declareParameter(param, param);
         }
         return facadeQuery;
     }

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/ParameterImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/ParameterImpl.java?rev=799848&r1=799847&r2=799848&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/ParameterImpl.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/ParameterImpl.java Sat Aug  1 12:03:09 2009
@@ -20,9 +20,6 @@
 
 import javax.persistence.Parameter;
 
-import org.apache.openjpa.kernel.Filters;
-import org.apache.openjpa.lib.util.Localizer;
-
 /**
  * A user-defined parameter of a query.
  * 
@@ -42,28 +39,16 @@
  * @param <T> type of value carried by this parameter.
  * 
  */
-public class ParameterImpl<T> implements QueryParameter<T> {
-    private static final Localizer _loc = Localizer.forPackage(ParameterImpl.class);
-    
+public class ParameterImpl<T> implements Parameter<T> {
     private final String _name;
     private final Integer _position;
-    private final Class<?> _expectedValueType;
-    private T _value;
-    private boolean _bound; 
-    
-    /**
-     * Construct a positional parameter with the given position as key and
-     * no expected value type.
-     */
-    public ParameterImpl(int position) {
-        this(position, null);
-    }
+    private final Class<T> _expectedValueType;
     
     /**
      * Construct a positional parameter with the given position as key and
      * given expected value type.
      */
-    public ParameterImpl(int position, Class<?> expectedValueType) {
+    public ParameterImpl(int position, Class<T> expectedValueType) {
         _name = null;
         _position = position;
         _expectedValueType = expectedValueType;
@@ -71,17 +56,9 @@
     
     /**
      * Construct a named parameter with the given name as key and
-     * no expected value type.
-     */
-    public ParameterImpl(String name) {
-        this(name, null);
-    }
-    
-    /**
-     * Construct a named parameter with the given name as key and
      * given expected value type.
      */
-    public ParameterImpl(String name, Class<?> expectedValueType) {
+    public ParameterImpl(String name, Class<T> expectedValueType) {
         _name = name;
         _position = null;
         _expectedValueType = expectedValueType;
@@ -95,81 +72,8 @@
         return _position;
     }
     
-    public final boolean isNamed() {
-        return _name != null;
-    }
-    
-    public final boolean isPositional() {
-        return _position != null;
-    }
-    
-    /**
-     * Affirms if the given value can be assigned to this parameter.
-     * 
-     * If no expected value type is set, then always returns true.
-     */
-    public boolean isValueAssignable(Object v) {
-        if (_expectedValueType == null)
-            return true;
-        if (v == null)
-            return !_expectedValueType.isPrimitive();
-        return Filters.canConvert(v.getClass(), _expectedValueType, true);
-    }
-    
-    /**
-     * Affirms if this parameter has been bound to a value.
-     */
-    public boolean isBound() {
-        return _bound;
-    }
-    
-    /**
-     * Binds the given value to this parameter.
-     * 
-     * @exception if the given value is not permissible for this parameter.
-     */
-    public QueryParameter<T> bindValue(T v) {
-        if (!isValueAssignable(v)) {
-            if (v == null)
-                throw new IllegalArgumentException(_loc.get("param-null-not-assignable", this).getMessage());
-            else
-                throw new IllegalArgumentException(_loc.get("param-value-not-assignable", this, v, v.getClass())
-                        .getMessage());
-        }
-        _value = v;
-        _bound = true;
-        return this;
-    }
-    
-    /**
-     * Gets the current value irrespective of whether a value has been bound or not.
-     */
-    public Object getValue() {
-        return getValue(false);
-    }
-    
-    /**
-     * Gets the current value only if a value has been bound or not.
-     */
-    public Object getValue(boolean mustBeBound) {
-        if (mustBeBound && !isBound())
-            throw new IllegalStateException(_loc.get("param-not-bound", this).getMessage());
-        return _value;
-    }
-    
-    /**
-     * Clears bound value.
-     */
-    public void clearBinding() {
-        _bound = false;
-        _value = null;
-    }
-    
-    /**
-     * Gets (immutable) type of expected value of this parameter. 
-     */
-    public Class<?> getExpectedValueType() {
-        return _expectedValueType;
+    public Class<T> getJavaType() {
+      return _expectedValueType;
     }
     
     /**
@@ -182,28 +86,25 @@
         if (!(other instanceof Parameter))
             return false;
         Parameter<?> that = (Parameter<?>)other;
-        if (isNamed())
-            return this.getName().equals(that.getName());
-        if (isPositional())
-            return getPosition().equals(that.getPosition());
+        if (_name != null)
+            return _name.equals(that.getName());
+        if (_position != null)
+            return _position.equals(that.getPosition());
         return false;
     }
     
     public String toString() {
         StringBuilder buf = new StringBuilder("Parameter");
-        buf.append("<" + (getExpectedValueType() == null ? "?" : getExpectedValueType().getName()) + ">");
-        if (isNamed()) {
-            buf.append("('" + getName() + "':");
-        } else if (isPositional()) {
-            buf.append("(" + getPosition() + ":");
+        buf.append("<" + getJavaType().getSimpleName() + ">");
+        if (_name != null) {
+            buf.append("('" + _name + "')");
+        } else if (_position != null) {
+            buf.append("(" + _position + ")");
+        } else {
+            buf.append("(?)");
         }
-        buf.append((isBound() ? getValue() : "UNBOUND") + ")");
 
         return buf.toString();
     }
 
-    public Class<T> getJavaType() {
-        Class<?> cls = _value.getClass();
-        return (Class<T>) cls;
-    }
 }

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java?rev=799848&r1=799847&r2=799848&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java Sat Aug  1 12:03:09 2009
@@ -46,12 +46,15 @@
 import javax.persistence.ResultItem;
 import javax.persistence.TemporalType;
 import javax.persistence.TypedQuery;
+import javax.persistence.criteria.ParameterExpression;
 
+import org.apache.commons.collections.map.LinkedMap;
 import org.apache.openjpa.conf.OpenJPAConfiguration;
 import org.apache.openjpa.kernel.Broker;
 import org.apache.openjpa.kernel.DelegatingQuery;
 import org.apache.openjpa.kernel.DelegatingResultList;
 import org.apache.openjpa.kernel.FetchConfiguration;
+import org.apache.openjpa.kernel.Filters;
 import org.apache.openjpa.kernel.PreparedQuery;
 import org.apache.openjpa.kernel.PreparedQueryCache;
 import org.apache.openjpa.kernel.QueryLanguages;
@@ -84,14 +87,13 @@
 	private transient EntityManagerImpl _em;
 	private transient FetchPlan _fetch;
 
-	private Map<String, QueryParameter<?>> _named;
-	private Map<Integer, QueryParameter<?>> _positional;
+    private Map<Parameter<?>, Object> _boundParams;
+    private Map<Object, Parameter<?>> _declaredParams;
+    private Class<?> _paramKeyType;
 	private String _id;
     private transient ReentrantLock _lock = null;
 	private final HintHandler _hintHandler;
 
-	private Map<Parameter<?>, Object> parmatersToValues = new HashMap<Parameter<?>, Object>();
-
 	/**
 	 * Constructor; supply factory exception translator and delegate.
 	 * 
@@ -263,16 +265,18 @@
 	}
 	
 	/**
-	 * Gets a map of values of each parameter indexed by their original key.
+	 * Gets a map of values of each parameter indexed by their <em>original</em> key.
 	 * 
-	 * @return an empty map if no parameter is registered for this query.
+	 * @return an empty map if no parameter is declared for this query.
+     * The unbound parameters has a value of null which is indistinguishable
+     * from the value being bound to null.
 	 */
-	Map<?,?> getParameterValues() {
-	    Map<?,QueryParameter<?>> params = _positional != null ? _positional 
-                : _named != null ? _named : new HashMap();
-	    Map result = new LinkedHashMap();
-	    for (Map.Entry<?,QueryParameter<?>> entry : params.entrySet()) {
-	        result.put(entry.getKey(), entry.getValue().getValue());
+	Map<Object,Object> getParameterValues() {
+	    Map<Object,Object> result = new HashMap<Object,Object>();
+	    for (Map.Entry<Object,Parameter<?>> entry : getDeclaredParameters().entrySet()) {
+	        Object paramKey = entry.getKey();
+	        Parameter<?> param = entry.getValue();
+	        result.put(paramKey, _boundParams.get(param));
 	    }
 	    return result;
 	}
@@ -365,243 +369,10 @@
 		return this;
 	}
 
-	public OpenJPAQuery<X> setParameter(int position, Calendar value,
-			TemporalType t) {
-		return setParameter(position, convertTemporalType(value, t));
-	}
-
-    public OpenJPAQuery<X> setParameter(int position, Date value,
-            TemporalType type) {
-		return setParameter(position, convertTemporalType(value, type));
-	}
-    
-	/**
-     * Converts the given Date to a value corresponding to given temporal type.
-	 */
-	Object convertTemporalType(Date value, TemporalType type) {
-		switch (type) {
-		case DATE:
-			return value;
-		case TIME:
-			return new Time(value.getTime());
-		case TIMESTAMP:
-			return new Timestamp(value.getTime());
-		default:
-			return null;
-		}
-	}
-
-	Object convertTemporalType(Calendar value, TemporalType type) {
-		return convertTemporalType(value.getTime(), type);
-	}
-
-    /**
-     * Bind an argument to a positional parameter.
-     * @param position
-     * @param value
-     * @return the same query instance
-     * @throws IllegalArgumentException if position does not correspond to a positional 
-     * parameter of the query or if the argument is of incorrect type
-     */    
-	public OpenJPAQuery<X> setParameter(int position, Object value) {
-		_query.assertOpen();
-		_em.assertNotCloseInvoked();
-		_query.lock();
-		try {
-		    // native queries are not parsed and hence their parameter types are not known
-            if (!isNative() && !getDeclaredParameterKeys().contains(position)) {
-                throw new IllegalArgumentException(_loc.get("param-missing-pos", 
-                    position, getQueryString(), getDeclaredParameterKeys()).getMessage());
-            }
-			if (isNative() && position < 1) {
-                throw new IllegalArgumentException(_loc.get("bad-pos-params",
-                        position, getQueryString()).toString());
-			}
-
-			if (position < 1)
-                throw new InvalidStateException(_loc.get("illegal-index",
-                        position), null, null, false);
-
-			Class<?> valueType = (Class<?>)_query.getParameterTypes().get((Object)position);
-			ParameterImpl<Object> param = new ParameterImpl<Object>(position, valueType);
-			registerParameter(param);
-			param.bindValue(value);
-
-			return this;
-		} finally {
-			_query.unlock();
-		}
-	}
-
-	public OpenJPAQuery<X> setParameter(String name, Calendar value,
-			TemporalType type) {
-		return setParameter(name, convertTemporalType(value, type));
-	}
-
-    public OpenJPAQuery<X> setParameter(String name, Date value, TemporalType type) {
-		return setParameter(name, convertTemporalType(value, type));
-	}
-
-    /**
-     * Sets the parameter of the given name to the given value.
-     */
-	public OpenJPAQuery<X> setParameter(String name, Object value) {
-		_query.assertOpen();
-		_em.assertNotCloseInvoked();
-		_query.lock();
-		try {
-            // native queries are not parsed and hence their parameter types are not known
-            if (!isNative() && !getDeclaredParameterKeys().contains(name)) {
-                throw new IllegalArgumentException(_loc.get("param-missing-name", 
-                    name, getQueryString(), getDeclaredParameterKeys()).getMessage());
-            }
-			if (isNative()) {
-                throw new IllegalArgumentException(_loc.get("no-named-params",
-                        name, getQueryString()).toString());
-			}
-			
-			Class<?> valueType = (Class<?>)_query.getParameterTypes().get(name);
-			ParameterImpl<Object> param = new ParameterImpl<Object>(name, valueType);
-			registerParameter(param);
-			param.bindValue(value);
-			
-			return this;
-		} finally {
-			_query.unlock();
-		}
-	}
-
-	/**
-	 * Registers a parameter by creating an entry in the named or positional parameter map.
-	 * The named or positional parameter map may be created if this is the first parameter
-	 * to be registered.
-	 * It is not permitted to mix named and positional parameter. So one of them is always
-	 * null.
-	 * 
-	 * @exception IllegalStateException if a positional parameter is given when named parameters 
-	 * had been registered or vice versa.
-	 */
-	QueryImpl<X> registerParameter(QueryParameter<?> param) {
-	    if (param.isNamed()) {
-	        if (_positional != null)
-                throw new IllegalStateException(_loc.get("param-pos-named-mix", param, _query.getQueryString(), 
-                        _positional.keySet()).getMessage());
-	        if (_named == null) {
-	            _named = new HashMap<String, QueryParameter<?>>();
-	        }
-	        _named.put(param.getName(), param);
-	    } else if (param.isPositional()) {
-            if (_named != null)
-                throw new IllegalStateException(_loc.get("param-pos-named-mix", param, _query.getQueryString(), 
-                        _named.keySet()).getMessage());
-	        if (_positional == null) {
-	            _positional = new TreeMap<Integer, QueryParameter<?>>();
-	        }
-	        _positional.put(param.getPosition(), param);
-	    } else {
-	        throw new IllegalStateException(_loc.get("param-no-key", param).getMessage());
-	    }
-
-	    return this;   
-	}
-	
 	public boolean isNative() {
 		return QueryLanguages.LANG_SQL.equals(getLanguage());
 	}
 
-	public boolean hasPositionalParameters() {
-		return _positional != null;
-	}
-
-    /**
-     * Gets the array of positional parameter values.
-     * The n-th array element represents (n+1)-th positional parameter.  
-     * If a parameter has been declared but not bound to a value then
-     * the value is null and hence is indistinguishable from the value
-     * being actually null.
-     * If the parameter indexing is not contiguous then the unspecified
-     * parameters are considered as null.
-     */
-    public Object[] getPositionalParameters() {
-        _query.lock();
-        try {
-            if (_positional == null) 
-                return EMPTY_ARRAY;
-            Object[] result = new Object[calculateMaxKey(_positional.keySet())];
-            for (Map.Entry<Integer, QueryParameter<?>> e : _positional.entrySet()) {
-                result[e.getKey().intValue()-1] = e.getValue().getValue();
-            }
-            return result;
-        } finally {
-            _query.unlock();
-        }
-    }
-    
-    /**
-     * Calculate the maximum value of the given set.
-     */
-    int calculateMaxKey(Set<Integer> p) {
-        if (p == null)
-            return 0;
-        int max = Integer.MIN_VALUE;
-        for (Integer i : p)
-            max = Math.max(max, i);
-        return max;
-    }
-
-	public OpenJPAQuery<X> setParameters(Object... params) {
-		_query.assertOpen();
-		_em.assertNotCloseInvoked();
-		_query.lock();
-		try {
-			_positional = null;
-			_named = null;
-			if (params != null)
-				for (int i = 0; i < params.length; i++)
-					setParameter(i + 1, params[i]);
-			return this;
-		} finally {
-			_query.unlock();
-		}
-	}
-
-	/**
-	 * Gets the value of all the named parameters.
-	 * If a parameter has been declared but not bound to a value then
-	 * the value is null and hence is indistinguishable from the value
-	 * being actually null.
-	 */
-	public Map<String, Object> getNamedParameters() {
-		_query.lock();
-		try {
-            if (_named == null) 
-                return Collections.EMPTY_MAP;
-            Map<String, Object> result = new HashMap<String, Object>();
-            for (Map.Entry<String, QueryParameter<?>> e : _named.entrySet()) {
-                result.put(e.getKey(), e.getValue().getValue());
-            }
-            return result;
-		} finally {
-			_query.unlock();
-		}
-	}
-
-	public OpenJPAQuery<X> setParameters(Map params) {
-		_query.assertOpen();
-		_em.assertNotCloseInvoked();
-		_query.lock();
-		try {
-			_positional = null;
-			_named = null;
-			if (params != null)
-                for (Map.Entry e : (Set<Map.Entry>) params.entrySet())
-                    setParameter((String) e.getKey(), e.getValue());
-			return this;
-		} finally {
-			_query.unlock();
-		}
-	}
-
 	public OpenJPAQuery<X> closeAll() {
 		_query.closeAll();
 		return this;
@@ -671,9 +442,9 @@
             .toString(), null, this, false);
     }
     
-    //
+    // =======================================================================
     // Prepared Query Cache related methods
-    //
+    // =======================================================================
     
     /**
      * Invoked before a query is executed.
@@ -772,6 +543,7 @@
         _id = id;
         return this;
     }
+    // ================ End of Prepared Query related methods =====================
     
     void lock() {
         if (_lock != null) 
@@ -783,72 +555,254 @@
             _lock.unlock();
     }
 
-    public <T> Parameter<T> getParameter(String name, Class<T> arg1) {
-        return (Parameter<T>)_named.get(name);
+    
+    // =================================================================================
+    //   Parameter processing routines
+    // =================================================================================
+
+    /**
+     * Binds the parameter identified by the given position to the given value.
+     * The parameter are bound to a value in the context of this query. 
+     * The same parameter may be bound to a different value in the context of 
+     * another query.
+     * <br>
+     * For non-native queries, the given position must be a valid position in
+     * the declared parameters.
+     * <br>
+     * As native queries may not be parsed and hence their declared parameters
+     * may not be known, setting an positional parameter has the side-effect
+     * of a positional parameter being declared.
+     *   
+     * @param position positive, integer position of the parameter
+     * @param value an assignment compatible value
+     * @return the same query instance
+     * @throws IllegalArgumentException if position does not correspond to a positional 
+     * parameter of the query or if the argument is of incorrect type
+     */    
+    public OpenJPAQuery<X> setParameter(int pos, Object value) {
+        _query.assertOpen();
+        _em.assertNotCloseInvoked();
+        _query.lock();
+        try {
+            if (pos < 1) {
+                throw new IllegalArgumentException(_loc.get("illegal-index", pos).getMessage());
+            }
+            Parameter<?> param = null;
+            if (isNative()) {
+                param = new ParameterImpl<Object>(pos, Object.class);
+                declareParameter(pos, param);
+            } else {
+                param = getParameter(pos);
+            }
+            bindValue(param, value);
+
+            return this;
+        } finally {
+            _query.unlock();
+        }
+    }
+    
+    /**
+     * Sets the value of the given positional parameter after conversion of the
+     * given value to the given Temporal Type.
+     */
+    public OpenJPAQuery<X> setParameter(int position, Calendar value, TemporalType t) {
+        return setParameter(position, convertTemporalType(value, t));
+    }
+
+    /**
+     * Sets the value of the given named parameter after conversion of the
+     * given value to the given Temporal Type.
+     */
+    public OpenJPAQuery<X> setParameter(int position, Date value, TemporalType type) {
+        return setParameter(position, convertTemporalType(value, type));
+    }
+    
+    /**
+     * Converts the given Date to a value corresponding to given temporal type.
+     */
+    Object convertTemporalType(Date value, TemporalType type) {
+        switch (type) {
+        case DATE:
+            return value;
+        case TIME:
+            return new Time(value.getTime());
+        case TIMESTAMP:
+            return new Timestamp(value.getTime());
+        default:
+            return null;
+        }
     }
 
-    public <T> Parameter<T> getParameter(int pos, Class<T> arg1) {
-        return (Parameter<T>)_positional.get(pos);
+    Object convertTemporalType(Calendar value, TemporalType type) {
+        return convertTemporalType(value.getTime(), type);
     }
 
     /**
-     * Return the value bound to the parameter.
-     * @param param parameter object
-     * @return parameter value
-     * @throws IllegalStateException if the parameter has not been been bound
-     * @throws IllegalArgumentException if the parameter does not belong to this query
+     * Affirms if declared parameters use position identifier.
      */
-    public <T> T getParameterValue(Parameter<T> p) {
-        if ((_named == null || !_named.containsValue(p)) 
-         && (_positional == null || !_positional.containsValue(p))) {
-           throw new IllegalArgumentException(_loc.get("param-missing", p, getQueryString(), 
-               getBoundParameterKeys()).getMessage());
+    public boolean hasPositionalParameters() {
+        return !getDeclaredParameterKeys(Integer.class).isEmpty();
+    }
+
+    /**
+     * Gets the array of positional parameter values.
+     * The n-th array element represents (n+1)-th positional parameter.  
+     * If a parameter has been declared but not bound to a value then
+     * the value is null and hence is indistinguishable from the value
+     * being actually null.
+     * If the parameter indexing is not contiguous then the unspecified
+     * parameters are considered as null.
+     */
+    public Object[] getPositionalParameters() {
+        _query.lock();
+        try {
+            Set<Integer> positionalKeys = getDeclaredParameterKeys(Integer.class);
+            Object[] result = new Object[calculateMaxKey(positionalKeys)];
+            for (Integer pos : positionalKeys) {
+                Parameter<?> param = getParameter(pos);
+                result[pos.intValue()-1] = isBound(param) ? getParameterValue(pos) : null;
+            }
+            return result;
+        } finally {
+            _query.unlock();
         }
-        QueryParameter<T> param = (QueryParameter<T>)p;
-        return (T)param.getValue(true);
+    }
+    
+    /**
+     * Calculate the maximum value of the given set.
+     */
+    int calculateMaxKey(Set<Integer> p) {
+        if (p == null)
+            return 0;
+        int max = Integer.MIN_VALUE;
+        for (Integer i : p)
+            max = Math.max(max, i);
+        return max;
     }
 
     /**
-     * Gets the parameters registered for this query.
+     * Binds the given values as positional parameters. 
+     * The n-th array element value is set to a Parameter with (n+1)-th positional identifier.  
      */
-    public Set<Parameter<?>> getParameters() {
-        Set<Parameter<?>> result = new HashSet<Parameter<?>>();
-        if (_named != null) {
-            result.addAll(_named.values());
-        } else if (_positional != null) {
-            result.addAll(_positional.values());
+    public OpenJPAQuery<X> setParameters(Object... params) {
+        _query.assertOpen();
+        _em.assertNotCloseInvoked();
+        _query.lock();
+        try {
+            clearBinding();
+            for (int i = 0; params != null && i < params.length; i++) {
+                setParameter(i + 1, params[i]);
+            }
+            return this;
+        } finally {
+            _query.unlock();
         }
-        return result;
+    }
+    
+    void clearBinding() {
+        if (_boundParams != null)
+            _boundParams.clear();
     }
 
-    public <T> ResultItem<T> getResultItem(String arg0, Class<T> arg1) {
-        throw new UnsupportedOperationException(
-            "JPA 2.0 - Method not yet implemented");
+    /**
+     * Gets the value of all the named parameters.  
+     * 
+     * If a parameter has been declared but not bound to a value then
+     * the value is null and hence is indistinguishable from the value
+     * being actually null.
+     */
+    public Map<String, Object> getNamedParameters() {
+        _query.lock();
+        try {
+            Map<String, Object> result = new HashMap<String, Object>();
+            Set<String> namedKeys = getDeclaredParameterKeys(String.class);
+            for (String name : namedKeys) {
+                Parameter<?> param = getParameter(name);
+                result.put(name, isBound(param) ? getParameterValue(name) : null);
+            }
+            return result;
+        } finally {
+            _query.unlock();
+        }
+    }
+
+    /**
+     * Sets the values of the parameters from the given Map.
+     * The keys of the given map designate the name of the declared parameter.
+      
+     */
+    public OpenJPAQuery<X> setParameters(Map params) {
+        _query.assertOpen();
+        _em.assertNotCloseInvoked();
+        _query.lock();
+        try {
+            clearBinding();
+            if (params != null)
+                for (Map.Entry e : (Set<Map.Entry>) params.entrySet())
+                    setParameter((String) e.getKey(), e.getValue());
+            return this;
+        } finally {
+            _query.unlock();
+        }
     }
 
-    public <T> ResultItem<T> getResultItem(int arg0, Class<T> arg1) {
-        throw new UnsupportedOperationException(
-            "JPA 2.0 - Method not yet implemented");
+    /**
+     * Get the parameter of the given name and type.
+     * 
+     * @throws IllegalArgumentException if the parameter of the
+     *         specified name does not exist or is not assignable
+     *         to the type
+     * @throws IllegalStateException if invoked on a native query 
+     */
+    public <T> Parameter<T> getParameter(String name, Class<T> type) {
+        Parameter<?> param = getParameter(name);
+        if (param.getJavaType().isAssignableFrom(type))
+            throw new IllegalArgumentException(param + " does not match the requested type " + type);
+        return (Parameter<T>)param;
     }
 
-    public List<ResultItem<?>> getResultItems() {
-        throw new UnsupportedOperationException(
-            "JPA 2.0 - Method not yet implemented");
+    /**
+     * Get the positional parameter with the given position and type.
+     * @throws IllegalArgumentException if the parameter with the
+     *         specified position does not exist or is not assignable
+     *         to the type
+     * @throws IllegalStateException if invoked on a native query unless
+     * the same parameter position is bound already.
+     */
+    public <T> Parameter<T> getParameter(int pos, Class<T> type) {
+        Parameter<?> param = getParameter(pos);
+        if (param.getJavaType().isAssignableFrom(type))
+            throw new IllegalArgumentException(param + " does not match the requested type " + type);
+        return (Parameter<T>)param;
     }
 
-    public List<Result> getTypedResultList() {
-        throw new UnsupportedOperationException(
-            "JPA 2.0 - Method not yet implemented");
+    /**
+     * Return the value bound to the parameter.
+     * @param param parameter object
+     * @return parameter value
+     * @throws IllegalStateException if the parameter has not been been bound
+     * @throws IllegalArgumentException if the parameter does not belong to this query
+     */
+    public <T> T getParameterValue(Parameter<T> p) {
+        if (!isBound(p)) {
+           throw new IllegalArgumentException(_loc.get("param-missing", p, getQueryString(), 
+               getBoundParameterKeys()).getMessage());
+        }
+        return (T)_boundParams.get(p);
     }
 
-    public Result getTypedSingleResult() {
-        throw new UnsupportedOperationException(
-            "JPA 2.0 - Method not yet implemented");
+    /**
+     * Gets the parameters declared in this query.
+     */
+    public Set<Parameter<?>> getParameters() {
+        Set<Parameter<?>> result = new HashSet<Parameter<?>>();
+        result.addAll(getDeclaredParameters().values());
+        return result;
     }
 
     public <T> OpenJPAQuery<X> setParameter(Parameter<T> p, T arg1) {
-        QueryParameter<T> param = (QueryParameter<T>)p;
-        param.bindValue(arg1);
+        bindValue((Parameter<T>)p, arg1);
         return this;
     }
 
@@ -860,25 +814,44 @@
         return setParameter(p, (Calendar)convertTemporalType(cal, type));
     }
 
-    public QueryParameter<?> getParameter(String name) {
-        if (_named == null || !_named.containsKey(name))
+    /**
+     * Get the parameter object corresponding to the declared parameter of the given name.
+     * This method is not required to be supported for native queries.
+     * 
+     * @throws IllegalArgumentException if the parameter of the specified name does not exist
+     * @throws IllegalStateException if invoked on a native query
+     */
+    public Parameter<?> getParameter(String name) {
+        if (isNative()) {
+            throw new IllegalStateException(_loc.get("param-named-non-native", name).getMessage());
+        }
+        Parameter<?> param = getDeclaredParameters().get(name);
+        if (param == null) {
+            Set<ParameterExpression> exps = getDeclaredParameterKeys(ParameterExpression.class);
+            for (ParameterExpression e : exps) {
+                if (name.equals(e.getName()))
+                    return e;
+            }
             throw new IllegalArgumentException(_loc.get("param-missing-name", 
-                name, getQueryString(), getBoundParameterKeys()).getMessage());
-        return _named.get(name);
+                name, getQueryString(), getDeclaredParameterKeys()).getMessage());
+        }
+        return param;
     }
 
     /**
      * Get the positional parameter with the given position.
+     * The parameter may just have been declared and not bound to a value.
      * 
      * @param position specified in the user query.
      * @return parameter object
      * @throws IllegalArgumentException if the parameter with the given position does not exist
      */
-    public QueryParameter<?> getParameter(int pos) {
-        if (_positional == null || !_positional.containsKey(pos))
+    public Parameter<?> getParameter(int pos) {
+        Parameter<?> param = getDeclaredParameters().get(pos);
+        if (param == null)
             throw new IllegalArgumentException(_loc.get("param-missing-pos", 
-                pos, getQueryString(), getBoundParameterKeys()).getMessage());
-        return _positional.get(pos);
+                pos, getQueryString(), getDeclaredParameterKeys()).getMessage());
+        return param;
     }
 
     /**
@@ -890,7 +863,7 @@
      * @throws IllegalStateException if this parameter has not been bound
      */
     public Object getParameterValue(String name) {
-        return getParameter(name).getValue(true);
+        return _boundParams.get(getParameter(name));
     }
 
     /**
@@ -902,18 +875,27 @@
      * @throws IllegalStateException if this parameter has not been bound
      */
     public Object getParameterValue(int pos) {
-        return getParameter(pos).getValue(true);
+        Parameter<?> param = getParameter(pos);
+        assertBound(param);
+        return _boundParams.get(param);
     }
     
     /**
      * Gets the parameter keys bound with this query.
+     * Parameter key can be Integer, String or a ParameterExpression itself
+     * but all parameters keys of a particular query are of the same type.
      */
     public Set<?> getBoundParameterKeys() {
-        if (_named != null)
-            return _named.keySet();
-        if (_positional != null)
-            return _positional.keySet();
-        return Collections.EMPTY_SET;
+        if (_boundParams == null)
+            return Collections.EMPTY_SET;
+        getDeclaredParameters();
+        Set<Object> result = new HashSet<Object>();
+        for (Map.Entry<Object, Parameter<?>> entry : _declaredParams.entrySet()) {
+            if (isBound(entry.getValue())) {
+                result.add(entry.getKey());
+            }
+        }
+        return result;
     }
     
     /**
@@ -924,11 +906,136 @@
      * @return set of parameter identifiers in a parsed query
      */
     public Set<?> getDeclaredParameterKeys() {
-        return _query.getParameterTypes().keySet();
+        return getDeclaredParameters().keySet();
+    }
+    
+    public <T> Set<T> getDeclaredParameterKeys(Class<T> keyType) {
+        Set<T> result = new HashSet<T>();
+        for (Object key : getDeclaredParameterKeys()) {
+            if (keyType.isInstance(key))
+                result.add((T)key);
+        }
+        return result;
+    }
+    
+    /**
+     * Gets the parameter instances declared in this query.
+     * All parameter keys are of the same type. It is not allowed to mix keys of different type
+     * such as named and positional keys. 
+     * 
+     * For string-based queries, the parser supplies the information about the declared parameters
+     * as a LinkedMap of expected parameter value type indexed by parameter identifier.
+     * For non string-based queries that a facade itself may construct (e.g. CriteriaQuery),
+     * the parameters must be declared by the caller.
+     * This receiver constructs concrete Parameter instances from the given parameter identifiers.
+     * 
+     * @return a Map where the key represents the original identifier of the parameter (can be a String,
+     * Integer or a ParameterExpression itself) and the value is the concrete Parameter instance
+     * either constructed as a result of this call or supplied by declaring the parameter explicitly
+     * via {@linkplain #declareParameter(Parameter)}.
+     */
+    public Map<Object, Parameter<?>> getDeclaredParameters() {
+        if (_declaredParams == null) {
+            _declaredParams = new HashMap<Object, Parameter<?>>();
+            LinkedMap paramTypes = _query.getParameterTypes();
+            for (Object key : paramTypes.keySet()) {
+                Parameter<?> param = null;
+                Class<?> expectedValueType = (Class<?>)paramTypes.get(key);
+                if (key instanceof Integer) {
+                    param = new ParameterImpl((Integer)key, expectedValueType);
+                } else if (key instanceof String) {
+                    param = new ParameterImpl((String)key, expectedValueType);
+                } else if (key instanceof Parameter) {
+                    param = (Parameter<?>)key;
+                } else {
+                    throw new IllegalArgumentException("parameter identifier " + key + " unrecognized");
+                }
+                declareParameter(key, param);
+            }
+        }
+        return _declaredParams;
+    }
+    
+    /**
+     * Declares the given parameter for this query. 
+     * Used by non-string based queries that are constructed by the facade itself rather than
+     * OpenJPA parsing the query to detect the declared parameters.
+     * 
+     * @param key this is the key to identify the parameter later in the context of this query.
+     * Valid key types are Integer, String or ParameterExpression itself.
+     * @param the parameter instance to be declared
+     */
+    public void declareParameter(Object key, Parameter<?> param) {
+        if (_declaredParams == null) {
+            _declaredParams = new HashMap<Object, Parameter<?>>();
+        }
+        _declaredParams.put(key, param);
     }
 
+    /**
+     * Affirms if the given parameter is bound to a value for this query.
+     */
     public boolean isBound(Parameter<?> param) {
-        return parmatersToValues.keySet().contains(param);
+        return _boundParams != null && _boundParams.containsKey(param);
+    }
+    
+    void assertBound(Parameter<?> param) {
+        if (!isBound(param)) {
+            throw new IllegalStateException(_loc.get("param-not-bound", param, getQueryString(), 
+                    getBoundParameterKeys()).getMessage());
+        }
+    }
+    /**
+     * Binds the given value to the given parameter.
+     * Validates if the parameter can accept the value by its type.
+     */
+    void bindValue(Parameter<?> param, Object value) {
+        assertValueAssignable(param, value);
+        if (_boundParams == null)
+            _boundParams = new HashMap<Parameter<?>, Object>();
+        _boundParams.put(param, value);
+    }
+
+    public OpenJPAQuery<X> setParameter(String name, Calendar value, TemporalType type) {
+        return setParameter(name, convertTemporalType(value, type));
     }
 
+    public OpenJPAQuery<X> setParameter(String name, Date value, TemporalType type) {
+        return setParameter(name, convertTemporalType(value, type));
+    }
+
+    /**
+     * Sets the parameter of the given name to the given value.
+     */
+    public OpenJPAQuery<X> setParameter(String name, Object value) {
+        _query.assertOpen();
+        _em.assertNotCloseInvoked();
+        _query.lock();
+        try {
+            // native queries can not have named parameters
+            if (isNative()) {
+                throw new IllegalArgumentException(_loc.get("no-named-params",
+                        name, getQueryString()).toString());
+            } else {
+                bindValue(getParameter(name), value);
+            }
+            
+            return this;
+        } finally {
+            _query.unlock();
+        }
+    }
+
+    void assertValueAssignable(Parameter<?> param, Object v) {
+        if (v == null) {
+            if (param.getJavaType().isPrimitive())
+                throw new IllegalArgumentException(_loc.get("param-null-primitive", param).getMessage());
+            return;
+        }
+        if (!Filters.canConvert(v.getClass(), param.getJavaType(), true)) {
+            throw new IllegalArgumentException(_loc.get("param-no-convert", param, v).getMessage());
+        }
+    }
+    
+    // ================== End of Parameter Processing routines ================================
 }

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaQueryImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaQueryImpl.java?rev=799848&r1=799847&r2=799848&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaQueryImpl.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaQueryImpl.java Sat Aug  1 12:03:09 2009
@@ -22,6 +22,7 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.List;
@@ -69,7 +70,7 @@
     private Set<Root<?>>        _roots;
     private PredicateImpl       _where;
     private List<Order>         _orders;
-    private LinkedHashMap<ParameterExpression<?>, Class<?>> _paramTypes;
+    private Set<ParameterExpression<?>> _params;
     private List<Selection<?>>  _selections;
     private List<Expression<?>> _groups;
     private PredicateImpl       _having;
@@ -83,9 +84,6 @@
     private int aliasCount = 0;
     private static String ALIAS_BASE = "autoAlias";
     
-    // Auto-generated Parameter name 
-    private static String PARAM_BASE = "*autoParam";
-    
     private Map<Selection<?>,Value> _variables = new HashMap<Selection<?>, Value>();
     private Map<Selection<?>,Value> _values    = new HashMap<Selection<?>, Value>();
     private Map<Selection<?>,String> _aliases  = null;
@@ -196,20 +194,15 @@
      * 
      */
     public void registerParameter(ParameterExpressionImpl<?> p) {
-        if (_paramTypes == null) {
-            _paramTypes = new LinkedHashMap<ParameterExpression<?>, Class<?>>();
-        }
-        if (_paramTypes.containsKey(p)) {
-            return;
+        if (_params == null)
+            _params = new HashSet<ParameterExpression<?>>();
+        if (_params.add(p)) {
+            p.setIndex(_params.size());
         }
-        p.setIndex(_paramTypes.size());
-        _paramTypes.put(p, p.getJavaType());
-        if (p.getName() == null)
-            p.assignAutoName(PARAM_BASE + p.getIndex());
     }
     
     public Set<ParameterExpression<?>> getParameters() {
-        return _paramTypes == null ? Collections.EMPTY_SET : _paramTypes.keySet();
+        return _params == null ? Collections.EMPTY_SET : Collections.unmodifiableSet(_params);
     }
 
     /**
@@ -331,19 +324,15 @@
     }
     
     /**
-     * Return map of <String, Class> where key is the name of the parameter
-     * and value is the expected type. 
+     * Return map where key is the parameter expression itself and value is the expected type.
+     * Empty map if no parameter has been declared. 
      */
     public LinkedMap getParameterTypes() {
-        if (_paramTypes == null)
+        if (_params == null)
             return StoreQuery.EMPTY_PARAMS;
         LinkedMap  parameterTypes = new LinkedMap();
-        for (ParameterExpression<?> p : _paramTypes.keySet()) {
-            if (p.getName() == null && p.getPosition() == null)
-                throw new RuntimeException(p + " is not set");
-            Object paramKey = p.getName() == null 
-               ? p.getPosition() : p.getName();
-            parameterTypes.put(paramKey, p.getJavaType());
+        for (ParameterExpression<?> p : _params) {
+            parameterTypes.put(p, p.getJavaType());
         }
         return parameterTypes;
     }

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ParameterExpressionImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ParameterExpressionImpl.java?rev=799848&r1=799847&r2=799848&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ParameterExpressionImpl.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ParameterExpressionImpl.java Sat Aug  1 12:03:09 2009
@@ -24,23 +24,15 @@
 
 import org.apache.openjpa.kernel.exps.ExpressionFactory;
 import org.apache.openjpa.kernel.exps.Value;
-import org.apache.openjpa.meta.ClassMetaData;
-import org.apache.openjpa.persistence.ParameterImpl;
-import org.apache.openjpa.persistence.QueryParameter;
 import org.apache.openjpa.persistence.meta.MetamodelImpl;
 import org.apache.openjpa.util.InternalException;
 
 /**
  * Parameter of a criteria query.
  * <br>
- * A parameter in CriteriaQuery is always a named parameter but
- * can be constructed without a name.
+ * A parameter in CriteriaQuery is always a named parameter but can be constructed with a null name.
  * Positional parameters are not allowed in CriteraQuery.
- * The unnamed Parameter will be assigned a name automatically
- * when they are registered to a CriteriaQuery.
  * <br> 
- * This expression uses a delegate Parameter implementation because
- * multiple inheritance is not allowed in Java language. 
  * 
  * @author Pinaki Poddar
  * @author Fay wang
@@ -48,11 +40,9 @@
  * @param <T> the type of value held by this parameter.
  */
 public class ParameterExpressionImpl<T> extends ExpressionImpl<T> 
-    implements ParameterExpression<T>, QueryParameter<T> {
-    
-    private String _autoName = null;
-    private int _index = 0; // index of the parameter as seen by the kernel
-	private final ParameterImpl<T> _delegate;
+    implements ParameterExpression<T> {
+    private String _name;
+    private int _index = 0; // index of the parameter as seen by the kernel, not position
 	
 	/**
 	 * Construct a Parameter of given expected value type and name.
@@ -62,40 +52,18 @@
 	 */
     public ParameterExpressionImpl(Class<T> cls, String name) {
         super(cls);
-        _delegate = new ParameterImpl<T>(name, cls);
+        _name = name;
     }
 
     /**
      * Gets the name of this parameter.
-     * The name can either be assigned by the user or automatically
-     * generated by the implementation.
-     * 
-     * @see #assignAutoName(String)
+     * The name can be null.
      */
     public final String getName() {
-        return _autoName != null ? _autoName : _delegate.getName();
+        return _name;
     }
     
     /**
-     * Assigns an automatically generated name to this parameter.
-     * Package protected for internal use only.
-     *  
-     * @exception if this parameter has been given a non-null
-     * name at construction.
-     */
-    final void assignAutoName(String auto) {
-        if (_delegate.getName() != null)
-            throw new InternalException("Can not assign name [" + auto + "] to " + this);
-        _autoName = auto;
-    }
-    
-    public ParameterExpression<T> alias(String alias) {
-        assignAutoName(alias);
-        super.alias(alias);
-        return this;
-    }
-	
-    /**
      * Raises an internal exception because parameters of CriteriaQuery
      * are not positional. 
      */
@@ -103,55 +71,15 @@
         throw new InternalException(this + " must not be asked for its position");
     }
     
-    public final void clearBinding() {
-        _delegate.clearBinding();
-    }
-    
-    public final QueryParameter<T> bindValue(T v) {
-        return _delegate.bindValue(v);
-    }
-
-    public Class<?> getExpectedValueType() {
-        return _delegate.getExpectedValueType();
-    }
-
-    public final T getValue() {
-        return (T)_delegate.getValue();
-    }
-
-    public final Object getValue(boolean mustBeBound) {
-        return _delegate.getValue(mustBeBound);
-    }
-
-    public final boolean isBound() {
-        return _delegate.isBound();
-    }
-
-    public final boolean isNamed() {
-        return true;
-    }
-
-    public final boolean isPositional() {
-        return false;
-    }
-    
     void setIndex(int index) {
         _index = index;
     }
     
-    public int getIndex() {
-        return _index;
-    }
-
-    public final boolean isValueAssignable(Object v) {
-        return _delegate.isValueAssignable(v);
-    }
-    
     public String toString() {
         StringBuilder buf = new StringBuilder("ParameterExpression");
-        buf.append("<" + (getExpectedValueType() == null ? "?" : getExpectedValueType().getName()) + ">");
-        buf.append("("+getName()+":"); 
-        buf.append((isBound() ? getValue() : "UNBOUND") + ")");
+        buf.append("<" + getJavaType().getSimpleName() + ">");
+        if (_name != null)
+            buf.append("('"+ _name +"')"); 
 
         return buf.toString();
     }
@@ -160,16 +88,12 @@
     public Value toValue(ExpressionFactory factory, MetamodelImpl model, CriteriaQueryImpl<?> q) {
         q.registerParameter(this);
         
-        ClassMetaData meta = null;
         Class<?> clzz = getJavaType();
-        Object paramKey = getName();
-        if (paramKey == null)
-            throw new InternalException(this + " should have been assigned a name");
+        Object paramKey = _name == null ? _index : _name;
         boolean isCollectionValued  = Collection.class.isAssignableFrom(clzz);
         org.apache.openjpa.kernel.exps.Parameter param = isCollectionValued 
             ? factory.newCollectionValuedParameter(paramKey, clzz) 
             : factory.newParameter(paramKey, clzz);
-        param.setMetaData(meta);
         param.setIndex(_index);
         
         return param;