Author: ppoddar
Date: Wed Nov 17 00:38:17 2010
New Revision: 1035884

URL: http://svn.apache.org/viewvc?rev=1035884&view=rev
Log:
OPENJPA-1889: Relax binding query parameter type checks for enums

Modified:
    
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Filters.java
    
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryHints.java
    
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/HintHandler.java
    
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAQuery.java
    
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java

Modified: 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Filters.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Filters.java?rev=1035884&r1=1035883&r2=1035884&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Filters.java
 (original)
+++ 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Filters.java
 Wed Nov 17 00:38:17 2010
@@ -328,6 +328,8 @@ public class Filters {
                 } catch (IllegalArgumentException e) {
                     
                 }
+            } else if (o instanceof String && type.isEnum()) {
+                return Enum.valueOf((Class<Enum>)type, o.toString());
             }
         }
         if (!num)

Modified: 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryHints.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryHints.java?rev=1035884&r1=1035883&r2=1035884&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryHints.java
 (original)
+++ 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryHints.java
 Wed Nov 17 00:38:17 2010
@@ -43,8 +43,7 @@ public interface QueryHints {
      * to count number of parameters assuming that all <code>?</code> 
characters
      * designate a bind parameter. This assumption makes the parse faster.
      */
-    public static final String HINT_PARAM_MARKER_IN_QUERY =
-        "openjpa.hint.ParameterMarkerInQuery";
+    public static final String HINT_PARAM_MARKER_IN_QUERY = 
"openjpa.hint.ParameterMarkerInQuery";
     
     /**
      * A directive to invalidate any prepared SQL that might have been cached
@@ -61,8 +60,7 @@ public interface QueryHints {
      * 
      * @see #HINT_IGNORE_PREPARED_QUERY
      */
-    public static final String HINT_INVALIDATE_PREPARED_QUERY =
-        "openjpa.hint.InvalidatePreparedQuery";
+    public static final String HINT_INVALIDATE_PREPARED_QUERY = 
"openjpa.hint.InvalidatePreparedQuery";
     
     /**
      * A directive to ignore any prepared SQL that might have been cached
@@ -80,8 +78,7 @@ public interface QueryHints {
      * 
      * @see #HINT_INVALIDATE_PREPARED_QUERY
      */
-    public static final String HINT_IGNORE_PREPARED_QUERY =
-        "openjpa.hint.IgnorePreparedQuery";
+    public static final String HINT_IGNORE_PREPARED_QUERY = 
"openjpa.hint.IgnorePreparedQuery";
 
     /**
      * A directive to ignore any cached finder query for find() operation.
@@ -92,12 +89,17 @@ public interface QueryHints {
     /**
      * A directive to invalidate any cached finder query.
      */
-    public static final String HINT_INVALIDATE_FINDER = 
-        "openjpa.hint.InvalidateFinder";
+    public static final String HINT_INVALIDATE_FINDER = 
"openjpa.hint.InvalidateFinder";
     
     /**
      * A directive to overwrite a cached finder query by a new query. 
      */
     public static final String HINT_RECACHE_FINDER = 
         "openjpa.hint.RecacheFinder";
+    
+    /**
+     * A boolean directive to relax checking of binding parameter value and 
the predicate
+     * it binds to.
+     */
+    public static final String HINT_RELAX_BIND_PARAM_TYPE_CHECK = 
"openjpa.hint.RelaxParameterTypeChecking";
 }

Modified: 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/HintHandler.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/HintHandler.java?rev=1035884&r1=1035883&r2=1035884&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/HintHandler.java
 (original)
+++ 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/HintHandler.java
 Wed Nov 17 00:38:17 2010
@@ -150,6 +150,8 @@ public class HintHandler  {
             if (value instanceof String)
                 value = Boolean.valueOf((String) value);
             owner.setSubclasses(((Boolean) value).booleanValue());
+        } else if (QueryHints.HINT_RELAX_BIND_PARAM_TYPE_CHECK.equals(key)) {
+            owner.setRelaxBindParameterTypeChecking(value);
         } else if (QueryHints.HINT_FILTER_LISTENER.equals(key)) {
             owner.addFilterListener(Filters.hintToFilterListener(value, 
loader));
         } else if (QueryHints.HINT_FILTER_LISTENERS.equals(key)) {

Modified: 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAQuery.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAQuery.java?rev=1035884&r1=1035883&r2=1035884&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAQuery.java
 (original)
+++ 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAQuery.java
 Wed Nov 17 00:38:17 2010
@@ -25,9 +25,11 @@ import java.util.Map;
 import java.util.Set;
 
 import javax.persistence.FlushModeType;
+import javax.persistence.Query;
 import javax.persistence.TemporalType;
 import javax.persistence.TypedQuery;
 
+import org.apache.openjpa.kernel.Filters;
 import org.apache.openjpa.kernel.QueryFlushModes;
 import org.apache.openjpa.kernel.QueryHints;
 import org.apache.openjpa.kernel.QueryOperations;
@@ -177,19 +179,39 @@ public interface OpenJPAQuery<X> extends
 
     public OpenJPAQuery<X> setParameter(String name, Object value);
 
-    public OpenJPAQuery<X> setParameter(String name, Date value,
-        TemporalType temporalType);
+    public OpenJPAQuery<X> setParameter(String name, Date value, TemporalType 
temporalType);
 
-    public OpenJPAQuery<X> setParameter(String name, Calendar value,
-        TemporalType temporalType);
+    public OpenJPAQuery<X> setParameter(String name, Calendar value, 
TemporalType temporalType);
 
     public OpenJPAQuery<X> setParameter(int position, Object value);
 
-    public OpenJPAQuery<X> setParameter(int position, Date value,
-        TemporalType temporalType);
+    public OpenJPAQuery<X> setParameter(int position, Date value, TemporalType 
temporalType);
 
-    public OpenJPAQuery<X> setParameter(int position, Calendar value,
-        TemporalType temporalType);
+    public OpenJPAQuery<X> setParameter(int position, Calendar value, 
TemporalType temporalType);
+    
+    /**
+     * Sets whether the type of user-supplied bind parameter value and the 
type of target persistent 
+     * property they bind to are checked with strong or weak constraint.
+     * <br>
+     * The same can be set via {...@link Query#setHint(String, Object) hint} 
without puncturing standard
+     * JPA API.
+     * 
+     * @see Filters#canConvert(Class, Class, boolean)
+     * @see Filters#convert(Object, Class, boolean)
+     * 
+     * @param hint a String or Boolean value.
+     */
+    public void setRelaxBindParameterTypeChecking(Object hint);
+    
+    /**
+     * Gets whether the type of user-supplied bind parameter value and the 
type of target persistent 
+     * property they bind to are checked with strong or weak constraint.
+     * 
+     * @return the booelan state. False by default, i.e. the type of a bind 
parameter value is checked
+     * strongly against the target property type.  
+     */
+    public boolean getRelaxBindParameterTypeChecking();
+    
 
     public OpenJPAQuery<X> setFlushMode(FlushModeType flushMode);
 
@@ -233,29 +255,25 @@ public interface OpenJPAQuery<X> extends
      * @deprecated cast to {...@link QueryImpl} instead. This
      * method pierces the published-API boundary, as does the SPI cast.
      */
-    public OpenJPAQuery<X> addFilterListener(
-        org.apache.openjpa.kernel.exps.FilterListener listener);
+    public OpenJPAQuery<X> 
addFilterListener(org.apache.openjpa.kernel.exps.FilterListener listener);
 
     /**
      * @deprecated cast to {...@link QueryImpl} instead. This
      * method pierces the published-API boundary, as does the SPI cast.
      */
-    public OpenJPAQuery<X> removeFilterListener(
-        org.apache.openjpa.kernel.exps.FilterListener listener);
+    public OpenJPAQuery<X> 
removeFilterListener(org.apache.openjpa.kernel.exps.FilterListener listener);
 
     /**
      * @deprecated cast to {...@link QueryImpl} instead. This
      * method pierces the published-API boundary, as does the SPI cast.
      */
-    public OpenJPAQuery<X> addAggregateListener(
-        org.apache.openjpa.kernel.exps.AggregateListener listener);
+    public OpenJPAQuery<X> 
addAggregateListener(org.apache.openjpa.kernel.exps.AggregateListener listener);
 
     /**
      * @deprecated cast to {...@link QueryImpl} instead. This
      * method pierces the published-API boundary, as does the SPI cast.
      */
-    public OpenJPAQuery<X> removeAggregateListener(
-        org.apache.openjpa.kernel.exps.AggregateListener listener);
+    public OpenJPAQuery<X> 
removeAggregateListener(org.apache.openjpa.kernel.exps.AggregateListener 
listener);
     
     /**
      * Gets hints supported by this query.

Modified: 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java?rev=1035884&r1=1035883&r2=1035884&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java
 (original)
+++ 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java
 Wed Nov 17 00:38:17 2010
@@ -54,6 +54,7 @@ import org.apache.openjpa.kernel.FetchCo
 import org.apache.openjpa.kernel.Filters;
 import org.apache.openjpa.kernel.PreparedQuery;
 import org.apache.openjpa.kernel.PreparedQueryCache;
+import org.apache.openjpa.kernel.QueryHints;
 import org.apache.openjpa.kernel.QueryLanguages;
 import org.apache.openjpa.kernel.QueryOperations;
 import org.apache.openjpa.kernel.QueryStatistics;
@@ -91,7 +92,8 @@ public class QueryImpl<X> implements Ope
        private String _id;
     private transient ReentrantLock _lock = null;
        private HintHandler _hintHandler;
-
+       private boolean _relaxBindParameterTypeChecking;
+       
        /**
         * Constructor; supply factory exception translator and delegate.
         * 
@@ -253,6 +255,20 @@ public class QueryImpl<X> implements Ope
                        _query.setRange(start, start + max);
                return this;
        }
+       
+       public boolean getRelaxBindParameterTypeChecking() {
+           return _relaxBindParameterTypeChecking;
+       }
+       
+       public void setRelaxBindParameterTypeChecking(Object value) {
+           if (value != null) {
+               if (value instanceof String) {
+                   _relaxBindParameterTypeChecking = 
"true".equalsIgnoreCase(value.toString());
+               } else if (value instanceof Boolean) {
+                _relaxBindParameterTypeChecking = 
((Boolean)value).booleanValue();
+               }
+           }
+       }
 
        public OpenJPAQuery<X> compile() {
                _em.assertNotCloseInvoked();
@@ -323,7 +339,7 @@ public class QueryImpl<X> implements Ope
         */
        public X getSingleResult() {
                _em.assertNotCloseInvoked();
-        setHint("openjpa.hint.OptimizeResultCount", 1); // for DB2 optimization
+        setHint(QueryHints.HINT_RESULT_COUNT, 1); // for DB2 optimization
                List result = getResultList();
                if (result == null || result.isEmpty())
             throw new NoResultException(_loc.get("no-result", getQueryString())
@@ -1042,10 +1058,10 @@ public class QueryImpl<X> implements Ope
      * Validates if the parameter can accept the value by its type.
      */
     void bindValue(Parameter<?> param, Object value) {
-        assertValueAssignable(param, value);
+        Object bindVal = assertValueAssignable(param, value);
         if (_boundParams == null)
             _boundParams = new HashMap<Parameter<?>, Object>();
-        _boundParams.put(param, value);
+        _boundParams.put(param, bindVal);
     }
 
     public OpenJPAQuery<X> setParameter(String name, Calendar value, 
TemporalType type) {
@@ -1078,15 +1094,33 @@ public class QueryImpl<X> implements Ope
         }
     }
 
-    void assertValueAssignable(Parameter<?> param, Object v) {
+    /**
+     * 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 (param.getParameterType().isPrimitive())
+            if (expectedType.isPrimitive())
                 throw new 
IllegalArgumentException(_loc.get("param-null-primitive", param).getMessage());
-            return;
+            return v;
         }
-        if (!Filters.canConvert(v.getClass(), param.getParameterType(), true)) 
{
-            throw new IllegalArgumentException(_loc.get("param-type-mismatch", 
new Object[]{
-                param, getQueryString(), v, v.getClass().getName(), 
param.getParameterType().getName()}).getMessage());
+        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;
+            }
         }
     }
     


Reply via email to