openjpa-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From curti...@apache.org
Subject svn commit: r1203337 - in /openjpa/trunk: openjpa-kernel/src/main/java/org/apache/openjpa/meta/ openjpa-persistence/src/main/java/org/apache/openjpa/persistence/
Date Thu, 17 Nov 2011 19:13:08 GMT
Author: curtisr7
Date: Thu Nov 17 19:13:07 2011
New Revision: 1203337

URL: http://svn.apache.org/viewvc?rev=1203337&view=rev
Log:
OPENJPA-2075: Abstract parameter handling from QueryImpl.

Added:
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AbstractQuery.java
Modified:
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/QueryMetaData.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

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/QueryMetaData.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/QueryMetaData.java?rev=1203337&r1=1203336&r2=1203337&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/QueryMetaData.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/QueryMetaData.java Thu Nov 17 19:13:07 2011
@@ -28,6 +28,7 @@ import org.apache.openjpa.kernel.Query;
 import org.apache.openjpa.kernel.QueryLanguages;
 import org.apache.openjpa.kernel.jpql.JPQLParser;
 import org.apache.openjpa.lib.meta.SourceTracker;
+import org.apache.openjpa.lib.util.OrderedMap;
 import org.apache.openjpa.lib.xml.Commentable;
 
 /**
@@ -62,7 +63,8 @@ public class QueryMetaData
     private int _colNum;
     private String _srcName; 
     private boolean _convertPositionalParametersToNamed;
-
+    private OrderedMap<Object,Class<?>> _paramTypes;
+    
     /**
      * Construct with the given name.
      */
@@ -306,4 +308,15 @@ public class QueryMetaData
     public String getSourceName() {
         return _srcName;
     }
+
+    public void setParamTypes(OrderedMap<Object, Class<?>> paramTypes) {
+        _paramTypes = paramTypes;
+    }
+
+    /**
+     * @return a map of parameter name to type for this named query or <b>null if this data hasn't been set.</b>
+     */
+    public OrderedMap<Object, Class<?>> getParamTypes() {
+        return _paramTypes;
+    }
 }

Added: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AbstractQuery.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AbstractQuery.java?rev=1203337&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AbstractQuery.java (added)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AbstractQuery.java Thu Nov 17 19:13:07 2011
@@ -0,0 +1,641 @@
+/*
+ * 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;
+
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import javax.persistence.Parameter;
+import javax.persistence.TemporalType;
+import javax.persistence.TypedQuery;
+import javax.persistence.criteria.ParameterExpression;
+
+import org.apache.openjpa.kernel.Filters;
+import org.apache.openjpa.kernel.QueryLanguages;
+import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.lib.util.OrderedMap;
+import org.apache.openjpa.meta.QueryMetaData;
+
+/**
+ * An abstract implementation of the Query interface.
+ */
+public abstract class AbstractQuery<X> implements OpenJPAQuerySPI<X> {
+    private static final Localizer _loc = Localizer.forPackage(AbstractQuery.class);
+
+    protected boolean _relaxBindParameterTypeChecking;
+    protected boolean _convertPositionalParams;
+
+    // Will be null if this isn't a NamedQuery
+    protected final QueryMetaData _qmd;
+
+    protected transient EntityManagerImpl _em;
+
+    protected Map<Parameter<?>, Object> _boundParams;
+    protected Map<Object, Parameter<?>> _declaredParams;
+
+    public AbstractQuery(QueryMetaData qmd, EntityManagerImpl em) {
+        _qmd = qmd;
+        _em = em;
+
+        _boundParams = new HashMap<Parameter<?>, Object>();
+    }
+
+    /**
+     * Gets a map of values of each parameter indexed by their <em>original</em> key.
+     * 
+     * @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<Object, Object> getParameterValues() {
+        Map<Object, Object> result = new HashMap<Object, Object>();
+        if (_boundParams == null)
+            return result;
+        for (Map.Entry<Object, Parameter<?>> entry : getDeclaredParameters().entrySet()) {
+            Object paramKey = entry.getKey();
+            Parameter<?> param = entry.getValue();
+            result.put(paramKey, _boundParams.get(param));
+        }
+        return result;
+    }
+
+    public boolean isNative() {
+        return QueryLanguages.LANG_SQL.equals(getLanguage());
+    }
+
+    protected abstract void assertOpen();
+
+    protected abstract void lock();
+
+    protected abstract void unlock();
+
+   /**
+    * @return a map of parameter name to type for this query.
+    */
+    protected abstract OrderedMap<Object, Class<?>> getParamTypes();
+
+    // =================================================================================
+    // 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) {
+        if (_convertPositionalParams == true) {
+            return setParameter("_" + String.valueOf(pos), value);
+        }
+
+        assertOpen();
+        _em.assertNotCloseInvoked();
+        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 {
+            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;
+        }
+    }
+
+    Object convertTemporalType(Calendar value, TemporalType type) {
+        return convertTemporalType(value.getTime(), type);
+    }
+
+    /**
+     * Affirms if declared parameters use position identifier.
+     */
+    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() {
+        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 {
+            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;
+    }
+
+    /**
+     * 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 OpenJPAQuery<X> setParameters(Object... params) {
+        assertOpen();
+        _em.assertNotCloseInvoked();
+        lock();
+        try {
+            clearBinding();
+            for (int i = 0; params != null && i < params.length; i++) {
+                setParameter(i + 1, params[i]);
+            }
+            return this;
+        } finally {
+            unlock();
+        }
+    }
+
+    void clearBinding() {
+        if (_boundParams != null)
+            _boundParams.clear();
+    }
+
+    /**
+     * 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() {
+        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 {
+            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) {
+        assertOpen();
+        _em.assertNotCloseInvoked();
+        lock();
+        try {
+            clearBinding();
+            if (params != null)
+                for (Map.Entry e : (Set<Map.Entry>) params.entrySet())
+                    setParameter((String) e.getKey(), e.getValue());
+            return this;
+        } finally {
+            unlock();
+        }
+    }
+
+    /**
+     * 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.getParameterType().isAssignableFrom(type))
+            throw new IllegalArgumentException(param + " does not match the requested type " + type);
+        return (Parameter<T>) param;
+    }
+
+    /**
+     * 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) {
+        if (_convertPositionalParams == true) {
+            return getParameter("_" + String.valueOf(pos), type);
+        }
+        Parameter<?> param = getParameter(pos);
+        if (param.getParameterType().isAssignableFrom(type))
+            throw new IllegalArgumentException(param + " does not match the requested type " + type);
+        return (Parameter<T>) param;
+    }
+
+    /**
+     * 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);
+    }
+
+    /**
+     * 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) {
+        bindValue((Parameter<T>) p, arg1);
+        return this;
+    }
+
+    public OpenJPAQuery<X> setParameter(Parameter<Date> p, Date date, TemporalType type) {
+        return setParameter(p, (Date) convertTemporalType(date, type));
+    }
+
+    public TypedQuery<X> setParameter(Parameter<Calendar> p, Calendar cal, TemporalType type) {
+        return setParameter(p, (Calendar) convertTemporalType(cal, type));
+    }
+
+    /**
+     * 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(),
+                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 Parameter<?> getParameter(int pos) {
+        if (_convertPositionalParams == true) {
+            return getParameter("_" + String.valueOf(pos));
+        }
+        Parameter<?> param = getDeclaredParameters().get(pos);
+        if (param == null)
+            throw new IllegalArgumentException(_loc.get("param-missing-pos", pos, getQueryString(),
+                getDeclaredParameterKeys()).getMessage());
+        return param;
+    }
+
+    /**
+     * Return the value bound to the parameter.
+     * 
+     * @param name
+     *            name of the parameter
+     * @return parameter value
+     * 
+     * @throws IllegalStateException
+     *             if this parameter has not been bound
+     */
+    public Object getParameterValue(String name) {
+        return _boundParams.get(getParameter(name));
+    }
+
+    /**
+     * Return the value bound to the parameter.
+     * 
+     * @param pos
+     *            position of the parameter
+     * @return parameter value
+     * 
+     * @throws IllegalStateException
+     *             if this parameter has not been bound
+     */
+    public Object getParameterValue(int pos) {
+        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 (_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;
+    }
+
+    /**
+     * Gets the declared parameter keys in the given query. This information is only available after the query has been
+     * parsed. As native language queries are not parsed, this information is not available for them.
+     * 
+     * @return set of parameter identifiers in a parsed query
+     */
+    public Set<?> getDeclaredParameterKeys() {
+        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<?>>();
+
+            OrderedMap<Object, Class<?>> paramTypes = null;
+            // Check to see if we have a cached version of the paramTypes in QueryMetaData.
+            if (_qmd != null) {
+                paramTypes = _qmd.getParamTypes();
+            }
+            if (paramTypes == null) {
+                paramTypes = getParamTypes();
+                // Cache the param types as they haven't been set yet.
+                if (_qmd != null) {
+                    _qmd.setParamTypes(paramTypes);
+                }
+            }
+            for (Entry<Object, Class<?>> entry : paramTypes.entrySet()) {
+                Object key = entry.getKey();
+                Class<?> expectedValueType = entry.getValue();
+                Parameter<?> param;
+
+                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 _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) {
+        Object bindVal = assertValueAssignable(param, value);
+        _boundParams.put(param, bindVal);
+    }
+
+    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) {
+        assertOpen();
+        _em.assertNotCloseInvoked();
+        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 {
+            unlock();
+        }
+    }
+
+    /**
+     * Convert the given value to match the given parameter type, if possible.
+     * 
+     * @param param
+     *            a query parameter
+     * @param v
+     *            a user-supplied value for the parameter
+     */
+    Object assertValueAssignable(Parameter<?> param, Object v) {
+        Class<?> expectedType = param.getParameterType();
+        if (v == null) {
+            if (expectedType.isPrimitive())
+                throw new IllegalArgumentException(_loc.get("param-null-primitive", param).getMessage());
+            return v;
+        }
+        if (getRelaxBindParameterTypeChecking()) {
+            try {
+                return Filters.convert(v, expectedType);
+            } catch (Exception e) {
+                throw new IllegalArgumentException(_loc.get("param-type-mismatch",
+                    new Object[] { param, getQueryString(), v, v.getClass().getName(), expectedType.getName() })
+                    .getMessage());
+            }
+        } else {
+            if (!Filters.canConvert(v.getClass(), expectedType, true)) {
+                throw new IllegalArgumentException(_loc.get("param-type-mismatch",
+                    new Object[] { param, getQueryString(), v, v.getClass().getName(), expectedType.getName() })
+                    .getMessage());
+            } else {
+                return v;
+            }
+        }
+    }
+
+    // ================== End of Parameter Processing routines ================================
+
+    @Override
+    public boolean getRelaxBindParameterTypeChecking() {
+        return _relaxBindParameterTypeChecking;
+    }
+
+    public void setRelaxBindParameterTypeChecking(Object value) {
+        if (value != null) {
+            if (value instanceof String) {
+                _relaxBindParameterTypeChecking = "true".equalsIgnoreCase(value.toString());
+            } else if (value instanceof Boolean) {
+                _relaxBindParameterTypeChecking = ((Boolean) value).booleanValue();
+            }
+        }
+    }
+}

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=1203337&r1=1203336&r2=1203337&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 Thu Nov 17 19:13:07 2011
@@ -998,7 +998,7 @@ public class EntityManagerImpl
             if (pq != null) {
                 pq.setInto(q);
             }
-            return newQueryImpl(q).setId(qid);
+            return newQueryImpl(q, null).setId(qid);
         } catch (RuntimeException re) {
             throw PersistenceExceptions.toPersistenceException(re);
         }
@@ -1009,7 +1009,7 @@ public class EntityManagerImpl
             return createQuery((String) null);
         assertNotCloseInvoked();
         org.apache.openjpa.kernel.Query q = ((QueryImpl) query).getDelegate();
-        return newQueryImpl(_broker.newQuery(q.getLanguage(), q));
+        return newQueryImpl(_broker.newQuery(q.getLanguage(), q), null);
     }
     
     @SuppressWarnings("unchecked")
@@ -1038,7 +1038,7 @@ public class EntityManagerImpl
                 del.compile();
             }
             
-            OpenJPAQuery q = newQueryImpl(del).setId(qid);
+            OpenJPAQuery q = newQueryImpl(del, meta).setId(qid);
             String[] hints = meta.getHintKeys();
             Object[] values = meta.getHintValues();
             for (int i = 0; i < hints.length; i++)
@@ -1064,11 +1064,22 @@ public class EntityManagerImpl
         org.apache.openjpa.kernel.Query kernelQuery = _broker.newQuery(
             QueryLanguages.LANG_SQL, query);
         kernelQuery.setResultMapping(null, mappingName);
-        return newQueryImpl(kernelQuery);
+        return newQueryImpl(kernelQuery, null);
     }
 
+    protected <T> QueryImpl<T> newQueryImpl(org.apache.openjpa.kernel.Query kernelQuery, QueryMetaData qmd) {
+        return new QueryImpl<T>(this, _ret, kernelQuery, qmd);
+    }
+    
+    /**
+     * @Deprecated -- Use org.apache.openjpa.persistence.EntityManagerImpl.newQueryImpl(Query kernelQuery, QueryMetaData
+     *             qmd)
+     * <br>
+     *             Leave this method here as extenders of OpenJPA might depend on this hook to allow interception of
+     *             query creation
+     */
     protected <T> QueryImpl<T> newQueryImpl(org.apache.openjpa.kernel.Query kernelQuery) {
-        return new QueryImpl<T>(this, _ret, kernelQuery);
+        return new QueryImpl<T>(this, _ret, kernelQuery, null);
     }
 
     /**
@@ -1597,7 +1608,7 @@ public class EntityManagerImpl
         
         org.apache.openjpa.kernel.Query kernelQuery =_broker.newQuery(CriteriaBuilderImpl.LANG_CRITERIA, criteriaQuery);
         
-        QueryImpl<T> facadeQuery = newQueryImpl(kernelQuery).setId(criteriaQuery.toString());
+        QueryImpl<T> facadeQuery = newQueryImpl(kernelQuery, null).setId(criteriaQuery.toString());
         Set<ParameterExpression<?>> params = criteriaQuery.getParameters();
         
         for (ParameterExpression<?> param : params) {

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=1203337&r1=1203336&r2=1203337&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 Thu Nov 17 19:13:07 2011
@@ -48,7 +48,7 @@ public class ParameterImpl<T> implements
      * Construct a positional parameter with the given position as key and
      * given expected value type.
      */
-    public ParameterImpl(int position, Class<T> expectedValueType) {
+    public ParameterImpl(Integer position, Class<T> expectedValueType) {
         _name = null;
         _position = position;
         _expectedValueType = expectedValueType;
@@ -92,6 +92,12 @@ public class ParameterImpl<T> implements
             return _position.equals(that.getPosition());
         return false;
     }
+
+    @Override
+    public int hashCode() {
+        return _expectedValueType.hashCode() ^ ((_name != null) ? _name.hashCode() : 0)
+            ^ ((_position != null) ? _position.hashCode() : 0); 
+    }
     
     public String toString() {
         StringBuilder buf = new StringBuilder("Parameter");

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=1203337&r1=1203336&r2=1203337&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 Thu Nov 17 19:13:07 2011
@@ -31,8 +31,8 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 import java.util.Map.Entry;
+import java.util.Set;
 import java.util.concurrent.locks.ReentrantLock;
 
 import javax.persistence.FlushModeType;
@@ -66,6 +66,7 @@ import org.apache.openjpa.lib.log.Log;
 import org.apache.openjpa.lib.rop.ResultList;
 import org.apache.openjpa.lib.util.Localizer;
 import org.apache.openjpa.lib.util.OrderedMap;
+import org.apache.openjpa.meta.QueryMetaData;
 import org.apache.openjpa.persistence.criteria.CriteriaBuilderImpl;
 import org.apache.openjpa.util.ImplHelper;
 import org.apache.openjpa.util.RuntimeExceptionTranslator;
@@ -80,22 +81,15 @@ import org.apache.openjpa.util.UserExcep
  * @nojavadoc
  */
 @SuppressWarnings("serial")
-public class QueryImpl<X> implements OpenJPAQuerySPI<X>, Serializable {
+public class QueryImpl<X> extends AbstractQuery<X> implements Serializable {
 
     private static final Localizer _loc = Localizer.forPackage(QueryImpl.class);
-
-	private DelegatingQuery _query;
-	private transient EntityManagerImpl _em;
 	private transient FetchPlan _fetch;
 
-    private Map<Parameter<?>, Object> _boundParams;
-    private Map<Object, Parameter<?>> _declaredParams;
 	private String _id;
     private transient ReentrantLock _lock = null;
 	private HintHandler _hintHandler;
-	private boolean _relaxBindParameterTypeChecking;
-	private boolean _convertPositionalParams;
-	
+    private DelegatingQuery _query;
 	/**
 	 * Constructor; supply factory exception translator and delegate.
 	 * 
@@ -103,8 +97,9 @@ public class QueryImpl<X> implements Ope
 	 * @param ret Exception translator for this query
 	 * @param query The underlying "kernel" query.
 	 */
-	public QueryImpl(EntityManagerImpl em, RuntimeExceptionTranslator ret, org.apache.openjpa.kernel.Query query) {
-        _em = em;
+    public QueryImpl(EntityManagerImpl em, RuntimeExceptionTranslator ret, org.apache.openjpa.kernel.Query query,
+        QueryMetaData qmd) {
+        super(qmd, em);
         _query = new DelegatingQuery(query, ret);
         _lock = new ReentrantLock();
         if(query.getLanguage() == QueryLanguages.LANG_SQL) { 
@@ -123,7 +118,7 @@ public class QueryImpl<X> implements Ope
 	 * @deprecated
 	 */
 	public QueryImpl(EntityManagerImpl em, org.apache.openjpa.kernel.Query query) {
-		this(em, null, query);
+		this(em, null, query, null);
 	}
 
 	/**
@@ -266,45 +261,12 @@ public class QueryImpl<X> implements Ope
 		return this;
 	}
 	
-	public boolean getRelaxBindParameterTypeChecking() {
-	    return _relaxBindParameterTypeChecking;
-	}
-	
-	public void setRelaxBindParameterTypeChecking(Object value) {
-	    if (value != null) {
-	        if (value instanceof String) {
-	            _relaxBindParameterTypeChecking = "true".equalsIgnoreCase(value.toString());
-	        } else if (value instanceof Boolean) {
-                _relaxBindParameterTypeChecking = ((Boolean)value).booleanValue();
-	        }
-	    }
-	}
-
 	public OpenJPAQuery<X> compile() {
 		_em.assertNotCloseInvoked();
 		_query.compile();
 		return this;
 	}
 	
-	/**
-	 * Gets a map of values of each parameter indexed by their <em>original</em> key.
-	 * 
-	 * @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<Object,Object> getParameterValues() {
-	    Map<Object,Object> result = new HashMap<Object,Object>();
-	    if (_boundParams == null)
-	        return result;
-	    for (Map.Entry<Object,Parameter<?>> entry : getDeclaredParameters().entrySet()) {
-	        Object paramKey = entry.getKey();
-	        Parameter<?> param = entry.getValue();
-	        result.put(paramKey, _boundParams.get(param));
-	    }
-	    return result;
-	}
-	
 	private Object execute() {
         if (!isNative() && _query.getOperation() != QueryOperations.OP_SELECT)
             throw new InvalidStateException(_loc.get("not-select-query", getQueryString()), null, null, false);
@@ -431,10 +393,6 @@ public class QueryImpl<X> implements Ope
 		return this;
 	}
 
-	public boolean isNative() {
-		return QueryLanguages.LANG_SQL.equals(getLanguage());
-	}
-
 	/**
 	 * Asserts that this query is a JPQL or Criteria Query.
 	 */
@@ -652,531 +610,26 @@ public class QueryImpl<X> implements Ope
     }
     // ================ End of Prepared Query related methods =====================
     
-    void lock() {
+    protected void lock() {
         if (_lock != null) 
             _lock.lock();
     }
 
-    void unlock() {
+    protected void unlock() {
         if (_lock != null)
             _lock.unlock();
     }
 
-    
-    // =================================================================================
-    //   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) {
-        if (_convertPositionalParams == true) {
-            return setParameter("_"+String.valueOf(pos), 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;
-        }
-    }
-
-    Object convertTemporalType(Calendar value, TemporalType type) {
-        return convertTemporalType(value.getTime(), type);
-    }
-
-    /**
-     * Affirms if declared parameters use position identifier.
-     */
-    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();
-        }
-    }
-    
-    /**
-     * 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;
-    }
-
-    /**
-     * 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 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();
-        }
-    }
-    
-    void clearBinding() {
-        if (_boundParams != null)
-            _boundParams.clear();
-    }
-
-    /**
-     * 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) {
+    @Override
+    protected void assertOpen() {
         _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();
-        }
-    }
-
-    /**
-     * 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.getParameterType().isAssignableFrom(type))
-            throw new IllegalArgumentException(param + " does not match the requested type " + type);
-        return (Parameter<T>)param;
-    }
-
-    /**
-     * 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) {
-        if (_convertPositionalParams == true) {
-            return getParameter("_"+String.valueOf(pos), type);
-        }
-        Parameter<?> param = getParameter(pos);
-        if (param.getParameterType().isAssignableFrom(type))
-            throw new IllegalArgumentException(param + " does not match the requested type " + type);
-        return (Parameter<T>)param;
     }
 
-    /**
-     * 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);
+    @Override
+    public OrderedMap<Object, Class<?>> getParamTypes() {
+        return _query.getOrderedParameterTypes();
     }
 
-    /**
-     * 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) {
-        bindValue((Parameter<T>)p, arg1);
-        return this;
-    }
-
-    public OpenJPAQuery<X> setParameter(Parameter<Date> p, Date date, TemporalType type) {
-        return setParameter(p, (Date)convertTemporalType(date, type));
-    }
-
-    public TypedQuery<X> setParameter(Parameter<Calendar> p, Calendar cal, TemporalType type) {
-        return setParameter(p, (Calendar)convertTemporalType(cal, type));
-    }
-
-    /**
-     * 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(), 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 Parameter<?> getParameter(int pos) {
-        if(_convertPositionalParams == true){
-            return getParameter("_"+String.valueOf(pos));
-        }
-        Parameter<?> param = getDeclaredParameters().get(pos);
-        if (param == null)
-            throw new IllegalArgumentException(_loc.get("param-missing-pos", 
-                pos, getQueryString(), getDeclaredParameterKeys()).getMessage());
-        return param;
-    }
-
-    /**
-     * Return the value bound to the parameter.
-     * 
-     * @param name name of the parameter
-     * @return parameter value
-     * 
-     * @throws IllegalStateException if this parameter has not been bound
-     */
-    public Object getParameterValue(String name) {
-        return _boundParams.get(getParameter(name));
-    }
-
-    /**
-     * Return the value bound to the parameter.
-     * 
-     * @param pos position of the parameter
-     * @return parameter value
-     * 
-     * @throws IllegalStateException if this parameter has not been bound
-     */
-    public Object getParameterValue(int pos) {
-        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 (_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;
-    }
-    
-    /**
-     * Gets the declared parameter keys in the given query.
-     * This information is only available after the query has been parsed.
-     * As native language queries are not parsed, this information is not available for them.
-     *   
-     * @return set of parameter identifiers in a parsed query
-     */
-    public Set<?> getDeclaredParameterKeys() {
-        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<?>>();
-            OrderedMap<Object,Class<?>> paramTypes = _query.getOrderedParameterTypes();
-            for(Entry<Object,Class<?>> entry : paramTypes.entrySet()){
-                Object key = entry.getKey();    
-                Class<?> expectedValueType = entry.getValue();
-                Parameter<?> param;
-
-                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 _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) {
-        Object bindVal = assertValueAssignable(param, value);
-        if (_boundParams == null)
-            _boundParams = new HashMap<Parameter<?>, Object>();
-        _boundParams.put(param, bindVal);
-    }
-
-    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();
-        }
-    }
-
-    /**
-     * Convert the given value to match the given parameter type, if possible.
-     * 
-     * @param param a query parameter
-     * @param v a user-supplied value for the parameter
-     */
-    Object assertValueAssignable(Parameter<?> param, Object v) {
-        Class<?> expectedType = param.getParameterType();
-        if (v == null) {
-            if (expectedType.isPrimitive())
-                throw new IllegalArgumentException(_loc.get("param-null-primitive", param).getMessage());
-            return v;
-        }
-        if (getRelaxBindParameterTypeChecking()) {
-            try {
-                return Filters.convert(v, expectedType);
-            } catch (Exception e) {
-                throw new IllegalArgumentException(_loc.get("param-type-mismatch", new Object[]{
-                    param, getQueryString(), v, v.getClass().getName(), expectedType.getName()}).getMessage());
-            }
-        } else {
-            if (!Filters.canConvert(v.getClass(), expectedType, true)) {
-                throw new IllegalArgumentException(_loc.get("param-type-mismatch", new Object[]{
-                    param, getQueryString(), v, v.getClass().getName(), expectedType.getName()}).getMessage());
-            } else {
-                return v;
-            }
-        }
-    }
-    
-    // ================== End of Parameter Processing routines ================================
-    
     public String toString() {
         String result = _query.getQueryString(); 
         return result != null ? result : _id;



Mime
View raw message