cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From serg...@apache.org
Subject svn commit: r1406135 - in /cxf/branches/2.6.x-fixes: ./ rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/ rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/ rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/se...
Date Tue, 06 Nov 2012 13:42:43 GMT
Author: sergeyb
Date: Tue Nov  6 13:42:42 2012
New Revision: 1406135

URL: http://svn.apache.org/viewvc?rev=1406135&view=rev
Log:
Merged revisions 1400692,1401212,1401216,1401256,1401772 via svnmerge from 
https://svn.apache.org/repos/asf/cxf/trunk

........
  r1400692 | sergeyb | 2012-10-21 19:41:23 +0100 (Sun, 21 Oct 2012) | 1 line
  
  Support for nested properties with mappings at different levels
........
  r1401212 | sergeyb | 2012-10-23 10:16:08 +0100 (Tue, 23 Oct 2012) | 1 line
  
  Trying to fix test failures with IBM JDK
........
  r1401216 | sergeyb | 2012-10-23 10:21:59 +0100 (Tue, 23 Oct 2012) | 1 line
  
  Trying to fix test failures with IBM JDK, the actual update
........
  r1401256 | sergeyb | 2012-10-23 12:50:07 +0100 (Tue, 23 Oct 2012) | 1 line
  
  Making it simpler to use the dates in queries
........
  r1401772 | sergeyb | 2012-10-24 17:40:03 +0100 (Wed, 24 Oct 2012) | 1 line
  
  More JPA2 support, making CriteriaQuery visitor more useful, support for joins to be added at some later stage
........

Added:
    cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/PropertyNotFoundException.java
      - copied unchanged from r1400692, cxf/trunk/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/PropertyNotFoundException.java
    cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/test/java/org/apache/cxf/jaxrs/ext/search/jpa/Book_.java
      - copied unchanged from r1401772, cxf/trunk/rt/rs/extensions/search/src/test/java/org/apache/cxf/jaxrs/ext/search/jpa/Book_.java
    cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/test/java/org/apache/cxf/jaxrs/ext/search/jpa/Name.java
      - copied unchanged from r1400692, cxf/trunk/rt/rs/extensions/search/src/test/java/org/apache/cxf/jaxrs/ext/search/jpa/Name.java
    cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/test/java/org/apache/cxf/jaxrs/ext/search/jpa/OwnerAddress.java
      - copied unchanged from r1400692, cxf/trunk/rt/rs/extensions/search/src/test/java/org/apache/cxf/jaxrs/ext/search/jpa/OwnerAddress.java
    cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/test/java/org/apache/cxf/jaxrs/ext/search/jpa/OwnerInfo.java
      - copied unchanged from r1401256, cxf/trunk/rt/rs/extensions/search/src/test/java/org/apache/cxf/jaxrs/ext/search/jpa/OwnerInfo.java
Modified:
    cxf/branches/2.6.x-fixes/   (props changed)
    cxf/branches/2.6.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java
    cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/AbstractSearchConditionVisitor.java
    cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/PrimitiveSearchCondition.java
    cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/SearchContextImpl.java
    cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/SearchUtils.java
    cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/SimpleSearchCondition.java
    cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/client/FiqlSearchConditionBuilder.java
    cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/fiql/FiqlParser.java
    cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/jpa/AbstractJPATypedQueryVisitor.java
    cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/jpa/JPACriteriaQueryVisitor.java
    cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/jpa/JPATypedQueryVisitor.java
    cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/test/java/org/apache/cxf/jaxrs/ext/search/client/FiqlSearchConditionBuilderTest.java
    cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/test/java/org/apache/cxf/jaxrs/ext/search/fiql/FiqlParserTest.java
    cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/test/java/org/apache/cxf/jaxrs/ext/search/jpa/Book.java
    cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/test/java/org/apache/cxf/jaxrs/ext/search/jpa/JPATypedQueryVisitorTest.java

Propchange: cxf/branches/2.6.x-fixes/
------------------------------------------------------------------------------
  Merged /cxf/trunk:r1400692,1401212-1401216,1401256,1401772

Propchange: cxf/branches/2.6.x-fixes/
------------------------------------------------------------------------------
Binary property 'svnmerge-blocked' - no diff available.

Propchange: cxf/branches/2.6.x-fixes/
------------------------------------------------------------------------------
Binary property 'svnmerge-integrated' - no diff available.

Modified: cxf/branches/2.6.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.6.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java?rev=1406135&r1=1406134&r2=1406135&view=diff
==============================================================================
--- cxf/branches/2.6.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java (original)
+++ cxf/branches/2.6.x-fixes/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java Tue Nov  6 13:42:42 2012
@@ -1136,6 +1136,12 @@ public final class InjectionUtils {
             return PrimitiveUtils.read(value, cls);
         } else {
             try {
+                Constructor<?> c = cls.getConstructor(new Class<?>[]{String.class});
+                return c.newInstance(new Object[]{value});
+            } catch (Throwable ex) {
+                // try valueOf
+            }
+            try {
                 Method m = cls.getMethod("valueOf", new Class[]{String.class});
                 return cls.cast(m.invoke(null, value));
             } catch (Exception ex) {

Modified: cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/AbstractSearchConditionVisitor.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/AbstractSearchConditionVisitor.java?rev=1406135&r1=1406134&r2=1406135&view=diff
==============================================================================
--- cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/AbstractSearchConditionVisitor.java (original)
+++ cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/AbstractSearchConditionVisitor.java Tue Nov  6 13:42:42 2012
@@ -18,15 +18,13 @@
  */
 package org.apache.cxf.jaxrs.ext.search;
 
+import java.lang.reflect.Method;
 import java.util.Map;
-import java.util.logging.Logger;
 
-import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.jaxrs.utils.InjectionUtils;
 
 
 public abstract class AbstractSearchConditionVisitor <T, E> implements SearchConditionVisitor<T, E> {
-
-    private static final Logger LOG = LogUtils.getL7dLogger(AbstractSearchConditionVisitor.class);
     
     private Map<String, String> fieldMap;
     private Map<String, Class<?>> primitiveFieldTypeMap;
@@ -36,25 +34,50 @@ public abstract class AbstractSearchCond
     }
     
     protected String getRealPropertyName(String name) {
-        if (fieldMap != null && !fieldMap.isEmpty()) {
-            if (fieldMap.containsKey(name)) {
-                return fieldMap.get(name);
-            } else {
-                LOG.warning("Unrecognized field alias : " + name);
-            }
+        if (fieldMap != null && fieldMap.containsKey(name)) {
+            return fieldMap.get(name);
         }
         return name;
     }
 
-    protected Class<?> getPrimitiveFieldClass(String name, Class<?> defaultCls) {
+    protected Class<?> getPrimitiveFieldClass(String name, Class<?> valueCls) {
+        return getPrimitiveFieldClass(name, valueCls, null).getCls(); 
+    }    
+    
+    protected ClassValue getPrimitiveFieldClass(String name, Class<?> valueCls, Object value) {
+        
+        int index = name.indexOf(".");
+        if (index != -1) {
+            String[] names = name.split("\\.");
+            name = name.substring(index + 1);
+            if (value != null && !InjectionUtils.isPrimitive(valueCls)) {
+                try {
+                    String nextPart = names[1];
+                    if (nextPart.length() == 1) {
+                        nextPart = nextPart.toUpperCase();
+                    } else {
+                        nextPart = Character.toUpperCase(nextPart.charAt(0)) + nextPart.substring(1);
+                    }
+                    Method m = valueCls.getMethod("get" + nextPart, new Class[]{});
+                    value = m.invoke(value, new Object[]{});
+                    valueCls = value.getClass();
+                    
+                } catch (Throwable ex) {
+                    throw new RuntimeException();
+                }
+                return getPrimitiveFieldClass(name, valueCls, value);
+            }
+            
+        }
+        
         Class<?> cls = null;
         if (primitiveFieldTypeMap != null) {
             cls = primitiveFieldTypeMap.get(name);
         }
         if (cls == null) {  
-            cls = defaultCls;
+            cls = valueCls;
         }
-        return cls;
+        return new ClassValue(cls, value);
     }
 
     public void setPrimitiveFieldTypeMap(Map<String, Class<?>> primitiveFieldTypeMap) {
@@ -64,4 +87,26 @@ public abstract class AbstractSearchCond
     public SearchConditionVisitor<T, E> visitor() {
         return this;
     }
+    
+    protected class ClassValue {
+        private Class<?> cls;
+        private Object value;
+        public ClassValue(Class<?> cls, Object value) {
+            this.cls = cls;
+            this.value = value;
+                
+        }
+        public Class<?> getCls() {
+            return cls;
+        }
+        public void setCls(Class<?> cls) {
+            this.cls = cls;
+        }
+        public Object getValue() {
+            return value;
+        }
+        public void setValue(Object value) {
+            this.value = value;
+        }
+    }
 }

Modified: cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/PrimitiveSearchCondition.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/PrimitiveSearchCondition.java?rev=1406135&r1=1406134&r2=1406135&view=diff
==============================================================================
--- cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/PrimitiveSearchCondition.java (original)
+++ cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/PrimitiveSearchCondition.java Tue Nov  6 13:42:42 2012
@@ -18,10 +18,13 @@
  */
 package org.apache.cxf.jaxrs.ext.search;
 
+import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 
+import org.apache.cxf.jaxrs.utils.InjectionUtils;
+
 public class PrimitiveSearchCondition<T> implements SearchCondition<T> {
     
     private String propertyName;
@@ -75,17 +78,28 @@ public class PrimitiveSearchCondition<T>
             return compare(pojo, cType, propertyValue);
         } else {
             Object lValue = getValue(propertyName, pojo);
-            return lValue == null ? false : compare(lValue, cType, propertyValue);
+            Object rValue = getPrimitiveValue(propertyName, propertyValue);
+            return lValue == null ? false : compare(lValue, cType, rValue);
         }
     }
 
     private Object getValue(String getter, T pojo) {
+        String thePropertyName;
+        int index = getter.indexOf(".");
+        if (index != -1) {
+            thePropertyName = getter.substring(0, index).toLowerCase();
+        } else {
+            thePropertyName = getter;
+        }
+        
+        Object value;
         try {
             if (beanspector != null) {
-                return beanspector.swap(pojo).getValue(getter);
+                value = beanspector.swap(pojo).getValue(thePropertyName);
             } else {
-                return ((SearchBean)pojo).get(getter);
+                value = ((SearchBean)pojo).get(getter);
             }
+            return getPrimitiveValue(getter, value);
         } catch (Throwable e) {
             return null;
         }
@@ -174,4 +188,30 @@ public class PrimitiveSearchCondition<T>
             return lval.equals(rval);
         }
     }
+    
+    protected static Object getPrimitiveValue(String name, Object value) {
+        
+        int index = name.indexOf(".");
+        if (index != -1) {
+            String[] names = name.split("\\.");
+            name = name.substring(index + 1);
+            if (value != null && !InjectionUtils.isPrimitive(value.getClass())) {
+                try {
+                    String nextPart = names[1];
+                    if (nextPart.length() == 1) {
+                        nextPart = nextPart.toUpperCase();
+                    } else {
+                        nextPart = Character.toUpperCase(nextPart.charAt(0)) + nextPart.substring(1);
+                    }
+                    Method m = value.getClass().getMethod("get" + nextPart, new Class[]{});
+                    value = m.invoke(value, new Object[]{});
+                } catch (Throwable ex) {
+                    throw new RuntimeException();
+                }
+            }
+            return getPrimitiveValue(name, value);
+        } 
+        return value;
+        
+    }
 }

Modified: cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/SearchContextImpl.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/SearchContextImpl.java?rev=1406135&r1=1406134&r2=1406135&view=diff
==============================================================================
--- cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/SearchContextImpl.java (original)
+++ cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/SearchContextImpl.java Tue Nov  6 13:42:42 2012
@@ -26,6 +26,7 @@ import java.util.logging.Logger;
 import javax.ws.rs.core.MultivaluedMap;
 
 import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.helpers.CastUtils;
 import org.apache.cxf.jaxrs.ext.search.fiql.FiqlParser;
 import org.apache.cxf.jaxrs.utils.InjectionUtils;
 import org.apache.cxf.jaxrs.utils.JAXRSUtils;
@@ -91,11 +92,17 @@ public class SearchContextImpl implement
         // we can use this method as a parser factory, ex
         // we can get parsers capable of parsing XQuery and other languages
         // depending on the properties set by a user
-        Map<String, String> props = new LinkedHashMap<String, String>(2);
+        Map<String, String> props = new LinkedHashMap<String, String>(4);
         props.put(SearchUtils.DATE_FORMAT_PROPERTY, 
                   (String)message.getContextualProperty(SearchUtils.DATE_FORMAT_PROPERTY));
         props.put(SearchUtils.TIMEZONE_SUPPORT_PROPERTY, 
                   (String)message.getContextualProperty(SearchUtils.TIMEZONE_SUPPORT_PROPERTY));
-        return new FiqlParser<T>(cls, props); 
+        props.put(SearchUtils.LAX_PROPERTY_MATCH, 
+                  (String)message.getContextualProperty(SearchUtils.LAX_PROPERTY_MATCH));
+        
+        Map<String, String> beanProps = 
+            CastUtils.cast((Map<?, ?>)message.getContextualProperty(SearchUtils.BEAN_PROPERTY_MAP));
+        
+        return new FiqlParser<T>(cls, props, beanProps); 
     }
 }

Modified: cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/SearchUtils.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/SearchUtils.java?rev=1406135&r1=1406134&r2=1406135&view=diff
==============================================================================
--- cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/SearchUtils.java (original)
+++ cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/SearchUtils.java Tue Nov  6 13:42:42 2012
@@ -25,17 +25,20 @@ import java.util.Map;
 import org.apache.cxf.jaxrs.ext.search.sql.SQLPrinterVisitor;
 
 public final class SearchUtils {
-    
+    public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
+    //public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
     public static final String DATE_FORMAT_PROPERTY = "search.date-format";
     public static final String TIMEZONE_SUPPORT_PROPERTY = "search.timezone.support";
+    public static final String LAX_PROPERTY_MATCH = "search.lax.property.match";
+    public static final String BEAN_PROPERTY_MAP = "search.lax.property.match";
     
     private SearchUtils() {
         
     }
     
-    public static SimpleDateFormat getDateFormat(Map<String, String> properties, String defaultFormat) {
+    public static SimpleDateFormat getDateFormat(Map<String, String> properties) {
         String dfProperty = properties.get(DATE_FORMAT_PROPERTY);
-        return new SimpleDateFormat(dfProperty == null ? defaultFormat : dfProperty);    
+        return new SimpleDateFormat(dfProperty == null ? DEFAULT_DATE_FORMAT : dfProperty);    
     }
     
     public static boolean isTimeZoneSupported(Map<String, String> properties, Boolean defaultValue) {

Modified: cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/SimpleSearchCondition.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/SimpleSearchCondition.java?rev=1406135&r1=1406134&r2=1406135&view=diff
==============================================================================
--- cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/SimpleSearchCondition.java (original)
+++ cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/SimpleSearchCondition.java Tue Nov  6 13:42:42 2012
@@ -68,7 +68,7 @@ public class SimpleSearchCondition<T> im
             throw new IllegalArgumentException("unsupported condition type: " + cType.name());
         }
         this.condition = condition;
-        scts = createConditions(null, cType);
+        scts = createConditions(null, null, cType);
                 
     }
 
@@ -80,7 +80,9 @@ public class SimpleSearchCondition<T> im
      * @param getters2operators getters names and operators to be used with them during comparison
      * @param condition template object
      */
-    public SimpleSearchCondition(Map<String, ConditionType> getters2operators, T condition) {
+    public SimpleSearchCondition(Map<String, ConditionType> getters2operators, 
+                                 Map<String, String> realGetters,
+                                 T condition) {
         if (getters2operators == null) {
             throw new IllegalArgumentException("getters2operators is null");
         }
@@ -98,9 +100,14 @@ public class SimpleSearchCondition<T> im
                 throw new IllegalArgumentException("unsupported condition type: " + ct.name());
             }
         }
-        scts = createConditions(getters2operators, null);
+        scts = createConditions(getters2operators, realGetters, null);
     }
 
+    public SimpleSearchCondition(Map<String, ConditionType> getters2operators, 
+                                 T condition) {
+        this(getters2operators, null, condition);
+    }
+    
     public T getCondition() {
         return condition;
     }
@@ -126,7 +133,8 @@ public class SimpleSearchCondition<T> im
         }
     }
 
-    private List<SearchCondition<T>> createConditions(Map<String, ConditionType> getters2operators, 
+    private List<SearchCondition<T>> createConditions(Map<String, ConditionType> getters2operators,
+                                                      Map<String, String> realGetters,
                                                       ConditionType sharedType) {
         if (isBuiltIn(condition)) {
             return Collections.singletonList(
@@ -148,7 +156,10 @@ public class SimpleSearchCondition<T> im
                 if (rval == null) {
                     continue;
                 }
-                list.add(new PrimitiveSearchCondition<T>(getter, rval, ct, condition));
+                String realGetter = realGetters != null && realGetters.containsKey(getter) 
+                    ? realGetters.get(getter) : getter;
+                
+                list.add(new PrimitiveSearchCondition<T>(realGetter, rval, ct, condition));
                 
             }
             if (list.isEmpty()) {

Modified: cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/client/FiqlSearchConditionBuilder.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/client/FiqlSearchConditionBuilder.java?rev=1406135&r1=1406134&r2=1406135&view=diff
==============================================================================
--- cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/client/FiqlSearchConditionBuilder.java (original)
+++ cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/client/FiqlSearchConditionBuilder.java Tue Nov  6 13:42:42 2012
@@ -89,8 +89,8 @@ public class FiqlSearchConditionBuilder 
 
         public Builder(Map<String, String> properties) {
             parent = null;
-            df = SearchUtils.getDateFormat(properties, FiqlParser.DEFAULT_DATE_FORMAT);
-            timeZoneSupported = SearchUtils.isTimeZoneSupported(properties, Boolean.TRUE);
+            df = SearchUtils.getDateFormat(properties);
+            timeZoneSupported = SearchUtils.isTimeZoneSupported(properties, Boolean.FALSE);
         }
 
         public Builder(Builder parent) {

Modified: cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/fiql/FiqlParser.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/fiql/FiqlParser.java?rev=1406135&r1=1406134&r2=1406135&view=diff
==============================================================================
--- cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/fiql/FiqlParser.java (original)
+++ cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/fiql/FiqlParser.java Tue Nov  6 13:42:42 2012
@@ -17,13 +17,13 @@
  * under the License.
  */
 package org.apache.cxf.jaxrs.ext.search.fiql;
+import java.lang.reflect.Method;
 import java.text.DateFormat;
 import java.text.ParseException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
-import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.regex.Matcher;
@@ -36,6 +36,7 @@ import org.apache.cxf.jaxrs.ext.search.A
 import org.apache.cxf.jaxrs.ext.search.Beanspector;
 import org.apache.cxf.jaxrs.ext.search.ConditionType;
 import org.apache.cxf.jaxrs.ext.search.OrSearchCondition;
+import org.apache.cxf.jaxrs.ext.search.PropertyNotFoundException;
 import org.apache.cxf.jaxrs.ext.search.SearchBean;
 import org.apache.cxf.jaxrs.ext.search.SearchCondition;
 import org.apache.cxf.jaxrs.ext.search.SearchConditionParser;
@@ -43,6 +44,7 @@ import org.apache.cxf.jaxrs.ext.search.S
 import org.apache.cxf.jaxrs.ext.search.SearchUtils;
 import org.apache.cxf.jaxrs.ext.search.SimpleSearchCondition;
 import org.apache.cxf.jaxrs.utils.InjectionUtils;
+import org.apache.cxf.message.MessageUtils;
 
 
 /**
@@ -65,8 +67,6 @@ public class FiqlParser<T> implements Se
     public static final String EQ = "==";
     public static final String NEQ = "!=";
     
-    public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
-
     private static final Pattern COMPARATORS_PATTERN; 
     private static final Map<String, ConditionType> OPERATORS_MAP;
 
@@ -88,7 +88,8 @@ public class FiqlParser<T> implements Se
 
     private Beanspector<T> beanspector;
     private Class<T> conditionClass;
-    private Map<String, String> properties;
+    private Map<String, String> contextProperties;
+    private Map<String, String> beanPropertiesMap;
     /**
      * Creates FIQL parser.
      * 
@@ -107,12 +108,27 @@ public class FiqlParser<T> implements Se
      * @param contextProperties            
      */
     public FiqlParser(Class<T> tclass, Map<String, String> contextProperties) {
+        this(tclass, contextProperties, null);
+    }
+    
+    /**
+     * Creates FIQL parser.
+     * 
+     * @param tclass - class of T used to create condition objects in built syntax tree. Class T must have
+     *            accessible no-arg constructor and complementary setters to these used in FIQL expressions.
+     * @param contextProperties            
+     */
+    public FiqlParser(Class<T> tclass, 
+                      Map<String, String> contextProperties,
+                      Map<String, String> beanProperties) {
         beanspector = SearchBean.class.isAssignableFrom(tclass) 
             ? null : new Beanspector<T>(tclass);
         conditionClass = tclass;
-        properties = contextProperties;
+        this.contextProperties = contextProperties == null 
+            ? Collections.<String, String>emptyMap() : contextProperties;
+        this.beanPropertiesMap = beanProperties;
     }
-
+    
     /**
      * Parses expression and builds search filter. Names used in FIQL expression are names of getters/setters
      * in type T.
@@ -203,7 +219,9 @@ public class FiqlParser<T> implements Se
                 } else {
                     node = parseComparison(subex);
                 }
-                ands.add(node);
+                if (node != null) {
+                    ands.add(node);
+                }
             }
             to = from;
             if (ands.getSubnodes().size() == 1) {
@@ -228,56 +246,149 @@ public class FiqlParser<T> implements Se
             if ("".equals(value)) {
                 throw new SearchParseException("Not a comparison expression: " + expr);
             }
-            Object castedValue = parseDatatype(name, value);
-            return new Comparison(name, operator, castedValue);
+            
+            String beanPropertyName = beanPropertiesMap == null ? null : beanPropertiesMap.get(name);
+            if (beanPropertyName != null) {
+                name = beanPropertyName;
+            }
+            
+            Object castedValue = parseType(name, value);
+            if (castedValue != null) {
+                return new Comparison(name, operator, castedValue);
+            } else if (MessageUtils.isTrue(contextProperties.get(SearchUtils.LAX_PROPERTY_MATCH))) {
+                return null;
+            } else {
+                throw new PropertyNotFoundException(name, value);
+            }
         } else {
             throw new SearchParseException("Not a comparison expression: " + expr);
         }
     }
 
-    private Object parseDatatype(String setter, String value) throws SearchParseException {
-        Object castedValue = value;
-        Class<?> valueType;
+    
+    private Object parseType(String setter, String value) throws SearchParseException {
+        String name = getSetter(setter);
+        
         try {
-            valueType = beanspector != null ? beanspector.getAccessorType(setter) : String.class;
+            Class<?> valueType = 
+                beanspector != null ? beanspector.getAccessorType(name) : String.class;
+            return parseType(null, null, setter, valueType, value);
         } catch (Exception e) {
-            throw new SearchParseException(e);
+            return null;
         }
-        if (Date.class.isAssignableFrom(valueType)) {
-            try {
-                DateFormat df = SearchUtils.getDateFormat(properties, DEFAULT_DATE_FORMAT);
-                String dateValue = value;
-                if (SearchUtils.isTimeZoneSupported(properties, Boolean.TRUE)) {
-                    // zone in XML is "+01:00" in Java is "+0100"; stripping semicolon
-                    int idx = value.lastIndexOf(':');
-                    if (idx != -1) {
-                        dateValue = value.substring(0, idx) + value.substring(idx + 1);
-                    }
-                }
-                castedValue = df.parse(dateValue);
-            } catch (ParseException e) {
-                // is that duration?
+        
+    }
+
+    private Object parseType(Object ownerBean, Object lastCastedValue, String setter, 
+                             Class<?> valueType, String value) throws SearchParseException {
+        int index = setter.indexOf(".");
+        if (index == -1) {
+            Object castedValue = value;
+            if (Date.class.isAssignableFrom(valueType)) {
+                castedValue = convertToDate(value);
+            } else {
                 try {
-                    Date now = new Date();
-                    DatatypeFactory.newInstance().newDuration(value).addTo(now);
-                    castedValue = now;
-                } catch (DatatypeConfigurationException e1) {
-                    throw new SearchParseException(e1);
-                } catch (IllegalArgumentException e1) {
-                    throw new SearchParseException("Can parse " + value + " neither as date nor duration", e);
+                    castedValue = InjectionUtils.convertStringToPrimitive(value, valueType);
+                } catch (Exception e) {
+                    boolean throwEx = true;
+                    if (!valueType.isPrimitive()) {
+                        try {
+                            Method setterM = valueType.getMethod("set" + getMethodNameSuffix(setter),
+                                                                 new Class[]{String.class});
+                            setterM.invoke(ownerBean, new Object[]{value});
+                            castedValue = lastCastedValue;
+                            throwEx = false;
+                        } catch (Throwable ex) {
+                            // continue
+                        }
+                    }
+                    if (throwEx) {
+                        throw new SearchParseException("Cannot convert String value \"" + value
+                                                 + "\" to a value of class " + valueType.getName(), e);
+                    }
                 }
             }
+            return castedValue;
         } else {
+            String[] names = setter.split("\\.");
             try {
-                castedValue = InjectionUtils.convertStringToPrimitive(value, valueType);
-            } catch (Exception e) {
+                String nextPart = getMethodNameSuffix(names[1]);
+                Method getterM = valueType.getMethod("get" + nextPart, new Class[]{});   
+                Class<?> returnType = getterM.getReturnType();
+                
+                boolean isPrimitive = InjectionUtils.isPrimitive(returnType);
+                boolean lastTry = names.length == 2 && (isPrimitive || returnType == Date.class);
+                
+                Object valueObject = lastTry && ownerBean != null ? ownerBean : valueType.newInstance();
+                Object nextObject;
+                
+                if (lastTry) {
+                    nextObject = isPrimitive ? InjectionUtils.convertStringToPrimitive(value, returnType) 
+                        : convertToDate(value); 
+                } else {
+                    nextObject = returnType.newInstance();
+                }
+                
+                Method setterM = valueType.getMethod("set" + nextPart, new Class[]{getterM.getReturnType()});
+                setterM.invoke(valueObject, new Object[]{nextObject});
+                
+                lastCastedValue = lastCastedValue == null ? valueObject : lastCastedValue;
+                if (lastTry) {
+                    return lastCastedValue;
+                } 
+                
+                return parseType(nextObject, lastCastedValue, setter.substring(index + 1), 
+                                 nextObject.getClass(), value);
+            } catch (Throwable e) {
                 throw new SearchParseException("Cannot convert String value \"" + value
-                                             + "\" to a value of class " + valueType.getName(), e);
+                                               + "\" to a value of class " + valueType.getName(), e);
             }
         }
-        return castedValue;
     }
-
+    
+    private Object convertToDate(String value) throws SearchParseException {
+        try {
+            DateFormat df = SearchUtils.getDateFormat(contextProperties);
+            String dateValue = value;
+            if (SearchUtils.isTimeZoneSupported(contextProperties, Boolean.FALSE)) {
+                // zone in XML is "+01:00" in Java is "+0100"; stripping semicolon
+                int idx = value.lastIndexOf(':');
+                if (idx != -1) {
+                    dateValue = value.substring(0, idx) + value.substring(idx + 1);
+                }
+            }
+            return df.parse(dateValue);
+        } catch (ParseException e) {
+            // is that duration?
+            try {
+                Date now = new Date();
+                DatatypeFactory.newInstance().newDuration(value).addTo(now);
+                return now;
+            } catch (DatatypeConfigurationException e1) {
+                throw new SearchParseException(e1);
+            } catch (IllegalArgumentException e1) {
+                throw new SearchParseException("Can parse " + value + " neither as date nor duration", e);
+            }
+        }
+    }
+    
+    private String getSetter(String setter) {
+        int index = setter.indexOf(".");
+        if (index != -1) {
+            return setter.substring(0, index).toLowerCase();
+        } else {
+            return setter;
+        }
+    }
+    
+    private String getMethodNameSuffix(String name) {
+        if (name.length() == 1) {
+            return name.toUpperCase();
+        } else {
+            return Character.toUpperCase(name.charAt(0)) + name.substring(1);
+        }
+    }
+    
     // node of abstract syntax tree
     private interface ASTNode<T> {
         SearchCondition<T> build() throws SearchParseException;
@@ -314,38 +425,16 @@ public class FiqlParser<T> implements Se
         }
 
         public SearchCondition<T> build() throws SearchParseException {
-            boolean hasSubtree = false;
+            List<SearchCondition<T>> scNodes = new ArrayList<SearchCondition<T>>();
             for (ASTNode<T> node : subnodes) {
-                if (node instanceof FiqlParser.SubExpression) {
-                    hasSubtree = true;
-                    break;
-                }
+                scNodes.add(node.build());
             }
-            if (!hasSubtree && AND.equals(operator) && beanspector != null) {
-                try {
-                    // Optimization: single SimpleSearchCondition for 'AND' conditions
-                    Map<String, ConditionType> map = new LinkedHashMap<String, ConditionType>();
-                    beanspector.instantiate();
-                    for (ASTNode<T> node : subnodes) {
-                        FiqlParser<T>.Comparison comp = (Comparison)node;
-                        map.put(comp.getName(), OPERATORS_MAP.get(comp.getOperator()));
-                        beanspector.setValue(comp.getName(), comp.getValue());
-                    }
-                    return new SimpleSearchCondition<T>(map, beanspector.getBean());
-                } catch (Throwable e) {
-                    throw new RuntimeException(e);
-                }
+            if (OR.equals(operator)) {
+                return new OrSearchCondition<T>(scNodes);
             } else {
-                List<SearchCondition<T>> scNodes = new ArrayList<SearchCondition<T>>();
-                for (ASTNode<T> node : subnodes) {
-                    scNodes.add(node.build());
-                }
-                if (OR.equals(operator)) {
-                    return new OrSearchCondition<T>(scNodes);
-                } else {
-                    return new AndSearchCondition<T>(scNodes);
-                }
+                return new AndSearchCondition<T>(scNodes);
             }
+            
         }
     }
 
@@ -360,31 +449,21 @@ public class FiqlParser<T> implements Se
             this.value = value;
         }
 
-        public String getName() {
-            return name;
-        }
-
-        public String getOperator() {
-            return operator;
-        }
-
-        public Object getValue() {
-            return value;
-        }
-
         @Override
         public String toString() {
             return name + " " + operator + " " + value + " (" + value.getClass().getSimpleName() + ")";
         }
 
         public SearchCondition<T> build() throws SearchParseException {
-            T cond = createTemplate(name, value);
+            String templateName = getSetter(name);
+            T cond = createTemplate(templateName, value);
             ConditionType ct = OPERATORS_MAP.get(operator);
             
             if (isPrimitive(cond)) {
                 return new SimpleSearchCondition<T>(ct, cond); 
             } else {
-                return new SimpleSearchCondition<T>(Collections.singletonMap(name, ct), 
+                return new SimpleSearchCondition<T>(Collections.singletonMap(templateName, ct),
+                                                    Collections.singletonMap(templateName, name),
                                                    cond);
             }
         }

Modified: cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/jpa/AbstractJPATypedQueryVisitor.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/jpa/AbstractJPATypedQueryVisitor.java?rev=1406135&r1=1406134&r2=1406135&view=diff
==============================================================================
--- cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/jpa/AbstractJPATypedQueryVisitor.java (original)
+++ cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/jpa/AbstractJPATypedQueryVisitor.java Tue Nov  6 13:42:42 2012
@@ -36,25 +36,45 @@ import org.apache.cxf.jaxrs.ext.search.O
 import org.apache.cxf.jaxrs.ext.search.PrimitiveStatement;
 import org.apache.cxf.jaxrs.ext.search.SearchCondition;
 
-public abstract class AbstractJPATypedQueryVisitor<T, E> 
+public abstract class AbstractJPATypedQueryVisitor<T, T1, E> 
     extends AbstractSearchConditionVisitor<T, E> {
 
     private EntityManager em;
     private Class<T> tClass;
+    private Class<T1> queryClass;
     private Root<T> root;
     private CriteriaBuilder builder;
-    private CriteriaQuery<T> cq;
+    private CriteriaQuery<T1> cq;
     private Stack<List<Predicate>> predStack = new Stack<List<Predicate>>();
     private boolean criteriaFinalized;
     
-    public AbstractJPATypedQueryVisitor(EntityManager em, Class<T> tClass) {
-        this(em, tClass, null);
+    protected AbstractJPATypedQueryVisitor(EntityManager em, Class<T> tClass) {
+        this(em, tClass, null, null);
     }
     
-    public AbstractJPATypedQueryVisitor(EntityManager em, Class<T> tClass, Map<String, String> fieldMap) {
+    protected AbstractJPATypedQueryVisitor(EntityManager em, Class<T> tClass, Class<T1> queryClass) {
+        this(em, tClass, queryClass, null);
+    }
+    
+    protected AbstractJPATypedQueryVisitor(EntityManager em, 
+                                        Class<T> tClass, 
+                                        Map<String, String> fieldMap) {
+        this(em, tClass, null, fieldMap);
+    }
+    
+    protected AbstractJPATypedQueryVisitor(EntityManager em, 
+                                        Class<T> tClass, 
+                                        Class<T1> queryClass,
+                                        Map<String, String> fieldMap) {
         super(fieldMap);
         this.em = em;
         this.tClass = tClass;
+        this.queryClass = toQueryClass(queryClass, tClass);
+    }
+    
+    @SuppressWarnings("unchecked")
+    private static <E> Class<E> toQueryClass(Class<E> queryClass, Class<?> tClass) {
+        return queryClass != null ? queryClass : (Class<E>)tClass;
     }
     
     protected EntityManager getEntityManager() {
@@ -64,7 +84,7 @@ public abstract class AbstractJPATypedQu
     public void visit(SearchCondition<T> sc) {
         if (builder == null) {
             builder = em.getCriteriaBuilder();
-            cq = builder.createQuery(tClass);
+            cq = builder.createQuery(queryClass);
             root = cq.from(tClass);
             predStack.push(new ArrayList<Predicate>());
         }
@@ -92,7 +112,19 @@ public abstract class AbstractJPATypedQu
         }
     }
 
-    public CriteriaQuery<T> getCriteriaQuery() {
+    protected CriteriaBuilder getCriteriaBuilder() {
+        return builder;
+    }
+    
+    protected Class<T1> getQueryClass() {
+        return queryClass;
+    }
+    
+    public Root<T> getRoot() {
+        return root;
+    }
+    
+    public CriteriaQuery<T1> getCriteriaQuery() {
         if (!criteriaFinalized) {
             List<Predicate> predsList = predStack.pop();
             cq.where(predsList.toArray(new Predicate[predsList.size()]));
@@ -106,11 +138,15 @@ public abstract class AbstractJPATypedQu
     private Predicate buildPredicate(ConditionType ct, String name, Object value) {
 
         name = super.getRealPropertyName(name);
-        Class<? extends Comparable> clazz = (Class<? extends Comparable>)
-            getPrimitiveFieldClass(name, value.getClass());
+        ClassValue cv = getPrimitiveFieldClass(name, value.getClass(), value); 
         
+        Class<? extends Comparable> clazz = (Class<? extends Comparable>)cv.getCls();
+        value = cv.getValue();    
         
         Path<?> path = getPath(root, name);
+        if (tClass != queryClass) {
+            path.alias(name);
+        }
         
         Predicate pred = null;
         switch (ct) {
@@ -119,7 +155,7 @@ public abstract class AbstractJPATypedQu
             break;
         case EQUALS:
             if (clazz.equals(String.class)) {
-                String theValue = (String)value;
+                String theValue = value.toString();
                 if (theValue.contains("*")) {
                     theValue = ((String)value).replaceAll("\\*", "");
                 }

Modified: cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/jpa/JPACriteriaQueryVisitor.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/jpa/JPACriteriaQueryVisitor.java?rev=1406135&r1=1406134&r2=1406135&view=diff
==============================================================================
--- cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/jpa/JPACriteriaQueryVisitor.java (original)
+++ cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/jpa/JPACriteriaQueryVisitor.java Tue Nov  6 13:42:42 2012
@@ -18,23 +18,77 @@
  */
 package org.apache.cxf.jaxrs.ext.search.jpa;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Map;
 
 import javax.persistence.EntityManager;
+import javax.persistence.criteria.CompoundSelection;
 import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Selection;
+import javax.persistence.metamodel.SingularAttribute;
 
-public class JPACriteriaQueryVisitor<T> extends AbstractJPATypedQueryVisitor<T, CriteriaQuery<T>> {
+public class JPACriteriaQueryVisitor<T, E> extends AbstractJPATypedQueryVisitor<T, E, CriteriaQuery<E>> {
 
-    public JPACriteriaQueryVisitor(EntityManager em, Class<T> tClass) {
-        this(em, tClass, null);
+    public JPACriteriaQueryVisitor(EntityManager em, 
+                                   Class<T> tClass,
+                                   Class<E> queryClass) {
+        this(em, tClass, queryClass, null);
     }
     
-    public JPACriteriaQueryVisitor(EntityManager em, Class<T> tClass, Map<String, String> fieldMap) {
-        super(em, tClass, fieldMap);
+    public JPACriteriaQueryVisitor(EntityManager em, 
+                                   Class<T> tClass,
+                                   Class<E> queryClass,
+                                   Map<String, String> fieldMap) {
+        super(em, tClass, queryClass, fieldMap);
     }
     
-    public CriteriaQuery<T> getQuery() {
+    public CriteriaQuery<E> getQuery() {
         return getCriteriaQuery();
     }
         
+    public CriteriaQuery<E> selectArray(List<SingularAttribute<T, ?>> attributes) {
+        return selectArraySelections(toSelectionsArray(toSelectionsList(attributes)));
+    }
+    
+    private CriteriaQuery<E> selectArraySelections(Selection<?>... selections) {
+        @SuppressWarnings("unchecked")
+        CompoundSelection<E> selection = (CompoundSelection<E>)getCriteriaBuilder().array(selections);
+        getQuery().select(selection);
+        return getQuery();
+    }
+    
+    public CriteriaQuery<E> selectConstruct(List<SingularAttribute<T, ?>> attributes) {
+        return selectConstructSelections(toSelectionsArray(toSelectionsList(attributes)));
+    }
+    
+    private CriteriaQuery<E> selectConstructSelections(Selection<?>... selections) {
+        getQuery().select(getCriteriaBuilder().construct(getQueryClass(), selections));
+        return getQuery();
+    }
+    
+    public CriteriaQuery<E> selectTuple(List<SingularAttribute<T, ?>> attributes) {
+        return selectTupleSelections(toSelectionsArray(toSelectionsList(attributes)));
+    }
+    
+    private CriteriaQuery<E> selectTupleSelections(Selection<?>... selections) {
+        @SuppressWarnings("unchecked")
+        CompoundSelection<E> selection = 
+            (CompoundSelection<E>)getCriteriaBuilder().tuple(selections);
+        getQuery().select(selection);
+        return getQuery();
+    }
+    
+    private List<Selection<?>> toSelectionsList(List<SingularAttribute<T, ?>> attributes) {
+        List<Selection<?>> selections = new ArrayList<Selection<?>>(attributes.size());
+        for (SingularAttribute<T, ?> attr : attributes) {
+            selections.add(getRoot().get(attr));
+        }
+        return selections;
+    }
+    
+    private static Selection<?>[] toSelectionsArray(List<Selection<?>> selections) {
+        return selections.toArray(new Selection[]{});
+    }
+    
 }

Modified: cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/jpa/JPATypedQueryVisitor.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/jpa/JPATypedQueryVisitor.java?rev=1406135&r1=1406134&r2=1406135&view=diff
==============================================================================
--- cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/jpa/JPATypedQueryVisitor.java (original)
+++ cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/jpa/JPATypedQueryVisitor.java Tue Nov  6 13:42:42 2012
@@ -18,146 +18,23 @@
  */
 package org.apache.cxf.jaxrs.ext.search.jpa;
 
-import java.util.ArrayList;
-import java.util.List;
 import java.util.Map;
-import java.util.Stack;
 
 import javax.persistence.EntityManager;
 import javax.persistence.TypedQuery;
-import javax.persistence.criteria.CriteriaBuilder;
-import javax.persistence.criteria.CriteriaQuery;
-import javax.persistence.criteria.Path;
-import javax.persistence.criteria.Predicate;
-import javax.persistence.criteria.Root;
 
-import org.apache.cxf.jaxrs.ext.search.AbstractSearchConditionVisitor;
-import org.apache.cxf.jaxrs.ext.search.ConditionType;
-import org.apache.cxf.jaxrs.ext.search.OrSearchCondition;
-import org.apache.cxf.jaxrs.ext.search.PrimitiveStatement;
-import org.apache.cxf.jaxrs.ext.search.SearchCondition;
+public class JPATypedQueryVisitor<T> extends AbstractJPATypedQueryVisitor<T, T, TypedQuery<T>> {
 
-public class JPATypedQueryVisitor<T> extends AbstractSearchConditionVisitor<T, TypedQuery<T>> {
-
-    private EntityManager em;
-    private Class<T> tClass;
-    private Root<T> root;
-    private CriteriaBuilder builder;
-    private CriteriaQuery<T> cq;
-    private Stack<List<Predicate>> predStack = new Stack<List<Predicate>>();
-    private boolean criteriaFinalized;
-    
     public JPATypedQueryVisitor(EntityManager em, Class<T> tClass) {
         this(em, tClass, null);
     }
     
     public JPATypedQueryVisitor(EntityManager em, Class<T> tClass, Map<String, String> fieldMap) {
-        super(fieldMap);
-        this.em = em;
-        this.tClass = tClass;
+        super(em, tClass, fieldMap);
     }
     
-    public void visit(SearchCondition<T> sc) {
-        if (builder == null) {
-            builder = em.getCriteriaBuilder();
-            cq = builder.createQuery(tClass);
-            root = cq.from(tClass);
-            predStack.push(new ArrayList<Predicate>());
-        }
-        PrimitiveStatement statement = sc.getStatement();
-        if (statement != null) {
-            if (statement.getProperty() != null) {
-                predStack.peek().add(buildPredicate(sc.getConditionType(), 
-                                                    statement.getProperty(), 
-                                                    statement.getValue()));
-            }
-        } else {
-            predStack.push(new ArrayList<Predicate>());
-            for (SearchCondition<T> condition : sc.getSearchConditions()) {
-                condition.accept(this);
-            }
-            Predicate[] preds = predStack.pop().toArray(new Predicate[0]);
-            Predicate newPred;
-            if (sc instanceof OrSearchCondition) {
-                newPred = builder.or(preds);
-            } else {
-                newPred = builder.and(preds);
-            }
-            predStack.peek().add(newPred);
-        }
-    }
-
     public TypedQuery<T> getQuery() {
-        return em.createQuery(getCriteriaQuery());
-    }
-    
-    public CriteriaQuery<T> getCriteriaQuery() {
-        if (!criteriaFinalized) {
-            cq.where(predStack.pop().toArray(new Predicate[0]));
-            criteriaFinalized = true;
-        }
-        return cq;
-    }
-    
-    
-    @SuppressWarnings({ "unchecked", "rawtypes" })
-    private Predicate buildPredicate(ConditionType ct, String name, Object value) {
-
-        name = super.getRealPropertyName(name);
-        Class<? extends Comparable> clazz = (Class<? extends Comparable>)
-            getPrimitiveFieldClass(name, value.getClass());
-        
-        
-        Path<?> path = getPath(root, name);
-        
-        Predicate pred = null;
-        switch (ct) {
-        case GREATER_THAN:
-            pred = builder.greaterThan(path.as(clazz), clazz.cast(value));
-            break;
-        case EQUALS:
-            if (clazz.equals(String.class)) {
-                String theValue = (String)value;
-                if (theValue.contains("*")) {
-                    theValue = ((String)value).replaceAll("\\*", "");
-                }
-                pred = builder.like(path.as(String.class), "%" + theValue + "%");
-            } else {
-                pred = builder.equal(path.as(clazz), clazz.cast(value));
-            }
-            break;
-        case NOT_EQUALS:
-            pred = builder.notEqual(path.as(clazz), 
-                                    clazz.cast(value));
-            break;
-        case LESS_THAN:
-            pred = builder.lessThan(path.as(clazz), 
-                                    clazz.cast(value));
-            break;
-        case LESS_OR_EQUALS:
-            pred = builder.lessThanOrEqualTo(path.as(clazz), 
-                                             clazz.cast(value));
-            break;
-        case GREATER_OR_EQUALS:
-            pred = builder.greaterThanOrEqualTo(path.as(clazz), 
-                                                clazz.cast(value));
-            break;
-        default: 
-            break;
-        }
-        return pred;
+        return getEntityManager().createQuery(getCriteriaQuery());
     }
-
-    private Path<?> getPath(Path<?> element, String name) {
-        if (name.contains(".")) {
-            String pre = name.substring(0, name.indexOf('.'));
-            String post = name.substring(name.indexOf('.') + 1);
-            Path<?> newPath = element.get(pre);
-            return getPath(newPath, post);
-        } else {
-            return element.get(name);
-        }
-    }
-    
-    
+     
 }

Modified: cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/test/java/org/apache/cxf/jaxrs/ext/search/client/FiqlSearchConditionBuilderTest.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/test/java/org/apache/cxf/jaxrs/ext/search/client/FiqlSearchConditionBuilderTest.java?rev=1406135&r1=1406134&r2=1406135&view=diff
==============================================================================
--- cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/test/java/org/apache/cxf/jaxrs/ext/search/client/FiqlSearchConditionBuilderTest.java (original)
+++ cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/test/java/org/apache/cxf/jaxrs/ext/search/client/FiqlSearchConditionBuilderTest.java Tue Nov  6 13:42:42 2012
@@ -18,7 +18,6 @@
  */
 package org.apache.cxf.jaxrs.ext.search.client;
 
-import java.text.DateFormat;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.Date;
@@ -30,18 +29,16 @@ import javax.xml.datatype.DatatypeConfig
 import javax.xml.datatype.DatatypeFactory;
 import javax.xml.datatype.Duration;
 
-import static junit.framework.Assert.assertEquals;
-
 import org.apache.cxf.jaxrs.ext.search.SearchUtils;
 
 import org.junit.AfterClass;
+import org.junit.Assert;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
-public class FiqlSearchConditionBuilderTest {
+public class FiqlSearchConditionBuilderTest extends Assert {
     private static FiqlSearchConditionBuilder b = new FiqlSearchConditionBuilder();
     private static TimeZone tz;
-    private DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm Z");
     
     @BeforeClass
     public static void beforeClass() {
@@ -73,11 +70,15 @@ public class FiqlSearchConditionBuilderT
         assertEquals("foo==123.5", ret);
     }
 
+    private Date parseDate(String format, String value) throws ParseException {
+        return new SimpleDateFormat(format).parse(value);
+    }
+    
     @Test
-    public void testEqualToDate() throws ParseException {
-        Date d = df.parse("2011-03-01 12:34 +0000");
+    public void testEqualToDateDefault() throws ParseException {
+        Date d = parseDate(SearchUtils.DEFAULT_DATE_FORMAT, "2011-03-01");
         String ret = b.is("foo").equalTo(d).query();
-        assertEquals("foo==2011-03-01T12:34:00.000+00:00", ret);
+        assertEquals("foo==2011-03-01", ret);
     }
     
     @Test
@@ -87,7 +88,7 @@ public class FiqlSearchConditionBuilderT
         props.put(SearchUtils.DATE_FORMAT_PROPERTY, "yyyy-MM-dd'T'HH:mm:ss");
         props.put(SearchUtils.TIMEZONE_SUPPORT_PROPERTY, "false");
         
-        Date d = df.parse("2011-03-01 12:34 +0000");
+        Date d = parseDate("yyyy-MM-dd HH:mm Z", "2011-03-01 12:34 +0000");
         
         FiqlSearchConditionBuilder bCustom = new FiqlSearchConditionBuilder(props);
         
@@ -115,10 +116,10 @@ public class FiqlSearchConditionBuilderT
     }
 
     @Test
-    public void testNotEqualToDate() throws ParseException {
-        Date d = df.parse("2011-03-01 12:34 +0000");
+    public void testNotEqualToDateDefault() throws ParseException {
+        Date d = parseDate(SearchUtils.DEFAULT_DATE_FORMAT, "2011-03-01");
         String ret = b.is("foo").notEqualTo(d).query();
-        assertEquals("foo!=2011-03-01T12:34:00.000+00:00", ret);
+        assertEquals("foo!=2011-03-01", ret);
     }
 
     @Test
@@ -196,30 +197,30 @@ public class FiqlSearchConditionBuilderT
 
     @Test
     public void testGreaterThanDate() throws ParseException {
-        Date d = df.parse("2011-03-02 22:33 +0000");
+        Date d = parseDate(SearchUtils.DEFAULT_DATE_FORMAT, "2011-03-02");
         String ret = b.is("foo").after(d).query();
-        assertEquals("foo=gt=2011-03-02T22:33:00.000+00:00", ret);
+        assertEquals("foo=gt=2011-03-02", ret);
     }
 
     @Test
     public void testLessThanDate() throws ParseException {
-        Date d = df.parse("2011-03-02 22:33 +0000");
+        Date d = parseDate(SearchUtils.DEFAULT_DATE_FORMAT, "2011-03-02");
         String ret = b.is("foo").before(d).query();
-        assertEquals("foo=lt=2011-03-02T22:33:00.000+00:00", ret);
+        assertEquals("foo=lt=2011-03-02", ret);
     }
 
     @Test
     public void testLessOrEqualToDate() throws ParseException {
-        Date d = df.parse("2011-03-02 22:33 +0000");
+        Date d = parseDate(SearchUtils.DEFAULT_DATE_FORMAT, "2011-03-02");
         String ret = b.is("foo").notAfter(d).query();
-        assertEquals("foo=le=2011-03-02T22:33:00.000+00:00", ret);
+        assertEquals("foo=le=2011-03-02", ret);
     }
 
     @Test
     public void testGreaterOrEqualToDate() throws ParseException {
-        Date d = df.parse("2011-03-02 22:33 +0000");
+        Date d = parseDate(SearchUtils.DEFAULT_DATE_FORMAT, "2011-03-02");
         String ret = b.is("foo").notBefore(d).query();
-        assertEquals("foo=ge=2011-03-02T22:33:00.000+00:00", ret);
+        assertEquals("foo=ge=2011-03-02", ret);
     }
 
     @Test

Modified: cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/test/java/org/apache/cxf/jaxrs/ext/search/fiql/FiqlParserTest.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/test/java/org/apache/cxf/jaxrs/ext/search/fiql/FiqlParserTest.java?rev=1406135&r1=1406134&r2=1406135&view=diff
==============================================================================
--- cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/test/java/org/apache/cxf/jaxrs/ext/search/fiql/FiqlParserTest.java (original)
+++ cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/test/java/org/apache/cxf/jaxrs/ext/search/fiql/FiqlParserTest.java Tue Nov  6 13:42:42 2012
@@ -147,7 +147,7 @@ public class FiqlParserTest extends Asse
     @Test
     public void testParseDateWithDefaultFormat() throws SearchParseException, ParseException {
         SearchCondition<Condition> filter = parser.parse("time=le=2010-03-11T18:00:00.000+00:00");
-        DateFormat df = new SimpleDateFormat(FiqlParser.DEFAULT_DATE_FORMAT);
+        DateFormat df = new SimpleDateFormat(SearchUtils.DEFAULT_DATE_FORMAT);
         assertTrue(filter.isMet(new Condition("whatever", 15, df.parse("2010-03-11T18:00:00.000+0000"))));
         assertTrue(filter.isMet(new Condition(null, null, df.parse("2010-03-10T22:22:00.000+0000"))));
         assertFalse(filter.isMet(new Condition("blah", null, df.parse("2010-03-12T00:00:00.000+0000"))));

Modified: cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/test/java/org/apache/cxf/jaxrs/ext/search/jpa/Book.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/test/java/org/apache/cxf/jaxrs/ext/search/jpa/Book.java?rev=1406135&r1=1406134&r2=1406135&view=diff
==============================================================================
--- cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/test/java/org/apache/cxf/jaxrs/ext/search/jpa/Book.java (original)
+++ cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/test/java/org/apache/cxf/jaxrs/ext/search/jpa/Book.java Tue Nov  6 13:42:42 2012
@@ -18,6 +18,7 @@
  */
 package org.apache.cxf.jaxrs.ext.search.jpa;
 
+import javax.persistence.Embedded;
 import javax.persistence.Entity;
 import javax.persistence.Id;
 
@@ -25,8 +26,9 @@ import javax.persistence.Id;
 public class Book {
     @Id
     private int id;
-    private String name;
-    
+    private String title;
+    private OwnerAddress address;
+    private OwnerInfo ownerInfo;
     
     public int getId() {
         return id;
@@ -36,11 +38,28 @@ public class Book {
         this.id = id;
     }
 
-    public String getName() {
-        return name;
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String name) {
+        this.title = name;
+    }
+
+    @Embedded
+    public OwnerAddress getAddress() {
+        return address;
+    }
+
+    public void setAddress(OwnerAddress address) {
+        this.address = address;
+    }
+
+    public OwnerInfo getOwnerInfo() {
+        return ownerInfo;
     }
 
-    public void setName(String name) {
-        this.name = name;
+    public void setOwnerInfo(OwnerInfo ownerInfo) {
+        this.ownerInfo = ownerInfo;
     }
 }

Modified: cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/test/java/org/apache/cxf/jaxrs/ext/search/jpa/JPATypedQueryVisitorTest.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/test/java/org/apache/cxf/jaxrs/ext/search/jpa/JPATypedQueryVisitorTest.java?rev=1406135&r1=1406134&r2=1406135&view=diff
==============================================================================
--- cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/test/java/org/apache/cxf/jaxrs/ext/search/jpa/JPATypedQueryVisitorTest.java (original)
+++ cxf/branches/2.6.x-fixes/rt/rs/extensions/search/src/test/java/org/apache/cxf/jaxrs/ext/search/jpa/JPATypedQueryVisitorTest.java Tue Nov  6 13:42:42 2012
@@ -20,15 +20,25 @@ package org.apache.cxf.jaxrs.ext.search.
 
 import java.sql.Connection;
 import java.sql.DriverManager;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import javax.persistence.EntityManager;
 import javax.persistence.EntityManagerFactory;
 import javax.persistence.Persistence;
+import javax.persistence.Tuple;
 import javax.persistence.TypedQuery;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.metamodel.SingularAttribute;
 
 import org.apache.cxf.jaxrs.ext.search.SearchCondition;
 import org.apache.cxf.jaxrs.ext.search.SearchConditionVisitor;
+import org.apache.cxf.jaxrs.ext.search.SearchUtils;
 import org.apache.cxf.jaxrs.ext.search.fiql.FiqlParser;
 
 import org.junit.After;
@@ -60,17 +70,32 @@ public class JPATypedQueryVisitorTest ex
             em.getTransaction().begin();
             Book b1 = new Book();
             b1.setId(9);
-            b1.setName("num9");
+            b1.setTitle("num9");
+            b1.setAddress(new OwnerAddress("Street1"));
+            OwnerInfo info1 = new OwnerInfo();
+            info1.setName(new Name("Fred"));
+            info1.setDateOfBirth(parseDate("2000-01-01"));
+            b1.setOwnerInfo(info1);
             em.persist(b1);
             assertTrue(em.contains(b1));
             Book b2 = new Book();
             b2.setId(10);
-            b2.setName("num10");
+            b2.setTitle("num10");
+            b2.setAddress(new OwnerAddress("Street2"));
+            OwnerInfo info2 = new OwnerInfo();
+            info2.setName(new Name("Barry"));
+            info2.setDateOfBirth(parseDate("2001-01-01"));
+            b2.setOwnerInfo(info2);
             em.persist(b2);
             assertTrue(em.contains(b2));
             Book b3 = new Book();
             b3.setId(11);
-            b3.setName("num11");
+            b3.setTitle("num11");
+            b3.setAddress(new OwnerAddress("Street3"));
+            OwnerInfo info3 = new OwnerInfo();
+            info3.setName(new Name("Bill"));
+            info3.setDateOfBirth(parseDate("2002-01-01"));
+            b3.setOwnerInfo(info3);
             em.persist(b3);
             assertTrue(em.contains(b3));
             
@@ -91,10 +116,12 @@ public class JPATypedQueryVisitorTest ex
             if (emFactory != null) {
                 emFactory.close();
             }
+        } catch (Throwable ex) {
+            ex.printStackTrace();    
         } finally {    
             try {
                 connection.createStatement().execute("SHUTDOWN");
-            } catch (Exception ex) {
+            } catch (Throwable ex) {
                 ex.printStackTrace();
             }
         }
@@ -116,14 +143,14 @@ public class JPATypedQueryVisitorTest ex
     
     @Test
     public void testAndQuery() throws Exception {
-        List<Book> books = queryBooks("id==10;name==num10");
+        List<Book> books = queryBooks("id==10;title==num10");
         assertEquals(1, books.size());
-        assertTrue(10 == books.get(0).getId() && "num10".equals(books.get(0).getName()));
+        assertTrue(10 == books.get(0).getId() && "num10".equals(books.get(0).getTitle()));
     }
     
     @Test
     public void testAndQueryNoMatch() throws Exception {
-        List<Book> books = queryBooks("id==10;name==num9");
+        List<Book> books = queryBooks("id==10;title==num9");
         assertEquals(0, books.size());
     }
     
@@ -135,8 +162,110 @@ public class JPATypedQueryVisitorTest ex
     }
     
     @Test
+    public void testEqualsCriteriaQueryTuple() throws Exception {
+        List<Tuple> books = criteriaQueryBooks("id==10");
+        assertEquals(1, books.size());
+        Tuple tuple = books.get(0);
+        int tupleId = tuple.get("id", Integer.class);
+        assertEquals(10, tupleId);
+    }
+    
+    @Test
+    public void testEqualsAddressQuery() throws Exception {
+        List<Book> books = queryBooks("address==Street1",
+            Collections.singletonMap("address", "address.street"));
+        assertEquals(1, books.size());
+        Book book = books.get(0);
+        assertTrue(9 == book.getId());
+        assertEquals("Street1", book.getAddress().getStreet());
+    }
+    
+    @Test
+    public void testIsMet() throws Exception {
+        SearchCondition<Book> filter = 
+            new FiqlParser<Book>(Book.class,
+                null,                          
+                Collections.singletonMap("address", "address.street")).parse("address==Street1");
+        
+        Book b = new Book();
+        b.setAddress(new OwnerAddress("Street1"));
+        assertTrue(filter.isMet(b));
+        
+        b.setAddress(new OwnerAddress("Street2"));
+        assertFalse(filter.isMet(b));
+    }
+    
+    @Test
+    public void testEqualsAddressQuery2() throws Exception {
+        List<Book> books = queryBooks("street==Street1",
+            null,                          
+            Collections.singletonMap("street", "address.street"));
+        assertEquals(1, books.size());
+        Book book = books.get(0);
+        assertTrue(9 == book.getId());
+        assertEquals("Street1", book.getAddress().getStreet());
+    }
+    
+    @Test
+    public void testEqualsAddressQuery3() throws Exception {
+        Map<String, String> beanPropertiesMap = new HashMap<String, String>();
+        beanPropertiesMap.put("street", "address.street");
+        beanPropertiesMap.put("housenum", "address.houseNumber");
+        List<Book> books = 
+            queryBooks("street==Street2;housenum=lt=5", null, beanPropertiesMap);
+        assertEquals(1, books.size());
+        Book book = books.get(0);
+        assertTrue(10 == book.getId());
+        assertEquals("Street2", book.getAddress().getStreet());
+        
+    }
+
+    @Test
+    public void testEqualsOwnerNameQuery() throws Exception {
+        List<Book> books = queryBooks("ownerInfo.name.name==Fred");
+        assertEquals(1, books.size());
+        Book book = books.get(0);
+        assertEquals("Fred", book.getOwnerInfo().getName().getName());
+    }
+    
+    @Test
+    public void testEqualsOwnerNameQuery2() throws Exception {
+        List<Book> books = queryBooks("ownerInfo.name==Fred");
+        assertEquals(1, books.size());
+        Book book = books.get(0);
+        assertEquals("Fred", book.getOwnerInfo().getName().getName());
+    }
+    
+    @Test
+    public void testEqualsOwnerNameQuery3() throws Exception {
+        List<Book> books = queryBooks("ownerName==Fred", null,
+            Collections.singletonMap("ownerName", "ownerInfo.name.name"));
+        assertEquals(1, books.size());
+        Book book = books.get(0);
+        assertEquals("Fred", book.getOwnerInfo().getName().getName());
+    }
+    
+    @Test
+    public void testEqualsOwnerBirthDate() throws Exception {
+        List<Book> books = queryBooks("ownerbdate==2000-01-01", null,
+            Collections.singletonMap("ownerbdate", "ownerInfo.dateOfBirth"));
+        assertEquals(1, books.size());
+        Book book = books.get(0);
+        assertEquals("Fred", book.getOwnerInfo().getName().getName());
+        
+        Date d = parseDate("2000-01-01");
+        
+        assertEquals("Fred", book.getOwnerInfo().getName().getName());
+        assertEquals(d, book.getOwnerInfo().getDateOfBirth());
+    }
+    
+    private Date parseDate(String value) throws Exception {
+        return new SimpleDateFormat(SearchUtils.DEFAULT_DATE_FORMAT).parse(value);
+    }
+    
+    @Test
     public void testEqualsWildcard() throws Exception {
-        List<Book> books = queryBooks("name==num1*");
+        List<Book> books = queryBooks("title==num1*");
         assertEquals(2, books.size());
         assertTrue(10 == books.get(0).getId() && 11 == books.get(1).getId()
             || 11 == books.get(0).getId() && 10 == books.get(1).getId());
@@ -174,10 +303,42 @@ public class JPATypedQueryVisitorTest ex
     }
     
     private List<Book> queryBooks(String expression) throws Exception {
-        SearchCondition<Book> filter = new FiqlParser<Book>(Book.class).parse(expression);
-        SearchConditionVisitor<Book, TypedQuery<Book>> jpa = new JPATypedQueryVisitor<Book>(em, Book.class);
+        return queryBooks(expression, null);
+    }
+    
+    private List<Book> queryBooks(String expression, 
+                                  Map<String, String> visitorProps) throws Exception {
+        return queryBooks(expression, visitorProps, null);
+    }
+    
+    private List<Book> queryBooks(String expression, 
+                                  Map<String, String> visitorProps,
+                                  Map<String, String> parserBinProps) throws Exception {
+        SearchCondition<Book> filter = 
+            new FiqlParser<Book>(Book.class,
+                                 visitorProps,
+                                 parserBinProps).parse(expression);
+        SearchConditionVisitor<Book, TypedQuery<Book>> jpa = 
+            new JPATypedQueryVisitor<Book>(em, Book.class, visitorProps);
         filter.accept(jpa);
         TypedQuery<Book> query = jpa.getQuery();
         return query.getResultList();
     }
+    
+    private List<Tuple> criteriaQueryBooks(String expression) throws Exception {
+        SearchCondition<Book> filter = 
+            new FiqlParser<Book>(Book.class).parse(expression);
+        JPACriteriaQueryVisitor<Book, Tuple> jpa = 
+            new JPACriteriaQueryVisitor<Book, Tuple>(em, Book.class, Tuple.class);
+        filter.accept(jpa);
+        
+        List<SingularAttribute<Book, ?>> selections = 
+            new ArrayList<SingularAttribute<Book, ?>>();
+        selections.add(Book_.id);
+        
+        jpa.selectTuple(selections);
+        
+        CriteriaQuery<Tuple> cquery = jpa.getQuery();
+        return em.createQuery(cquery).getResultList();
+    }
 }



Mime
View raw message