From commits-return-9211-apmail-openjpa-commits-archive=openjpa.apache.org@openjpa.apache.org Thu Nov 17 19:18:01 2011 Return-Path: X-Original-To: apmail-openjpa-commits-archive@www.apache.org Delivered-To: apmail-openjpa-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 508697A44 for ; Thu, 17 Nov 2011 19:18:01 +0000 (UTC) Received: (qmail 62719 invoked by uid 500); 17 Nov 2011 19:18:01 -0000 Delivered-To: apmail-openjpa-commits-archive@openjpa.apache.org Received: (qmail 62701 invoked by uid 500); 17 Nov 2011 19:18:01 -0000 Mailing-List: contact commits-help@openjpa.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@openjpa.apache.org Delivered-To: mailing list commits@openjpa.apache.org Received: (qmail 62694 invoked by uid 99); 17 Nov 2011 19:18:01 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 17 Nov 2011 19:18:01 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 17 Nov 2011 19:17:58 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 058F623889D7 for ; Thu, 17 Nov 2011 19:17:38 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1203338 - /openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AbstractQuery.java Date: Thu, 17 Nov 2011 19:17:37 -0000 To: commits@openjpa.apache.org From: curtisr7@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20111117191738.058F623889D7@eris.apache.org> 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 implements OpenJPAQuerySPI { - 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, Object> _boundParams; - protected Map> _declaredParams; - - public AbstractQuery(QueryMetaData qmd, EntityManagerImpl em) { - _qmd = qmd; - _em = em; - - _boundParams = new HashMap, Object>(); - } - - /** - * Gets a map of values of each parameter indexed by their original 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 getParameterValues() { - Map result = new HashMap(); - if (_boundParams == null) - return result; - for (Map.Entry> 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> 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.
- * For non-native queries, the given position must be a valid position in the declared parameters.
- * 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 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(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 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 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 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 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 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 getNamedParameters() { - lock(); - try { - Map result = new HashMap(); - Set 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 setParameters(Map params) { - assertOpen(); - _em.assertNotCloseInvoked(); - lock(); - try { - clearBinding(); - if (params != null) - for (Map.Entry e : (Set) 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 Parameter getParameter(String name, Class type) { - Parameter param = getParameter(name); - if (param.getParameterType().isAssignableFrom(type)) - throw new IllegalArgumentException(param + " does not match the requested type " + type); - return (Parameter) 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 Parameter getParameter(int pos, Class 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) 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 getParameterValue(Parameter 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> getParameters() { - Set> result = new HashSet>(); - result.addAll(getDeclaredParameters().values()); - return result; - } - - public OpenJPAQuery setParameter(Parameter p, T arg1) { - bindValue((Parameter) p, arg1); - return this; - } - - public OpenJPAQuery setParameter(Parameter p, Date date, TemporalType type) { - return setParameter(p, (Date) convertTemporalType(date, type)); - } - - public TypedQuery setParameter(Parameter 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 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 result = new HashSet(); - for (Map.Entry> 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 Set getDeclaredParameterKeys(Class keyType) { - Set result = new HashSet(); - 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> getDeclaredParameters() { - if (_declaredParams == null) { - _declaredParams = new HashMap>(); - - OrderedMap> 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> 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>(); - } - _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 setParameter(String name, Calendar value, TemporalType type) { - return setParameter(name, convertTemporalType(value, type)); - } - - public OpenJPAQuery 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 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 implements OpenJPAQuerySPI { + 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, Object> _boundParams; + protected Map> _declaredParams; + + public AbstractQuery(QueryMetaData qmd, EntityManagerImpl em) { + _qmd = qmd; + _em = em; + + _boundParams = new HashMap, Object>(); + } + + /** + * Gets a map of values of each parameter indexed by their original 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 getParameterValues() { + Map result = new HashMap(); + if (_boundParams == null) + return result; + for (Map.Entry> 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> 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.
+ * For non-native queries, the given position must be a valid position in the declared parameters.
+ * 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 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(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 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 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 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 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 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 getNamedParameters() { + lock(); + try { + Map result = new HashMap(); + Set 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 setParameters(Map params) { + assertOpen(); + _em.assertNotCloseInvoked(); + lock(); + try { + clearBinding(); + if (params != null) + for (Map.Entry e : (Set) 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 Parameter getParameter(String name, Class type) { + Parameter param = getParameter(name); + if (param.getParameterType().isAssignableFrom(type)) + throw new IllegalArgumentException(param + " does not match the requested type " + type); + return (Parameter) 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 Parameter getParameter(int pos, Class 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) 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 getParameterValue(Parameter 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> getParameters() { + Set> result = new HashSet>(); + result.addAll(getDeclaredParameters().values()); + return result; + } + + public OpenJPAQuery setParameter(Parameter p, T arg1) { + bindValue((Parameter) p, arg1); + return this; + } + + public OpenJPAQuery setParameter(Parameter p, Date date, TemporalType type) { + return setParameter(p, (Date) convertTemporalType(date, type)); + } + + public TypedQuery setParameter(Parameter 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 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 result = new HashSet(); + for (Map.Entry> 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 Set getDeclaredParameterKeys(Class keyType) { + Set result = new HashSet(); + 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> getDeclaredParameters() { + if (_declaredParams == null) { + _declaredParams = new HashMap>(); + + OrderedMap> 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> 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>(); + } + _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 setParameter(String name, Calendar value, TemporalType type) { + return setParameter(name, convertTemporalType(value, type)); + } + + public OpenJPAQuery 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 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