You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by cu...@apache.org on 2011/11/17 20:17:37 UTC

svn commit: r1203338 - /openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AbstractQuery.java

Author: curtisr7
Date: Thu Nov 17 19:17:37 2011
New Revision: 1203338

URL: http://svn.apache.org/viewvc?rev=1203338&view=rev
Log:
OPENJPA-2075: Update eol prop.

Modified:
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AbstractQuery.java   (contents, props changed)

Modified: 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=1203338&r1=1203337&r2=1203338&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AbstractQuery.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AbstractQuery.java Thu Nov 17 19:17:37 2011
@@ -1,641 +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();
-            }
-        }
-    }
-}
+/*
+ * 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();
+            }
+        }
+    }
+}

Propchange: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AbstractQuery.java
------------------------------------------------------------------------------
    svn:eol-style = native