ref #10373 remove all datePublished is null or-restriction and do some refactoring...
[cdm-vaadin.git] / src / main / java / eu / etaxonomy / cdm / service / CdmFilterablePagingProvider.java
index 07050ce1e0b60ee4f49955f9df5ca6eea0ed1a38..e166d5390b883b0cc781030b2e1274bc28f827eb 100644 (file)
@@ -12,7 +12,9 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.hibernate.Session;
 import org.hibernate.criterion.Criterion;
 import org.vaadin.viritin.fields.LazyComboBox.FilterableCountProvider;
 import org.vaadin.viritin.fields.LazyComboBox.FilterablePagingProvider;
@@ -27,14 +29,15 @@ import eu.etaxonomy.cdm.persistence.query.OrderHint;
 /**
  * @author a.kohlbecker
  * @since Jun 7, 2017
- *
  */
-public class CdmFilterablePagingProvider<T extends IdentifiableEntity, V extends T> implements FilterablePagingProvider<V>, FilterableCountProvider {
+public class CdmFilterablePagingProvider<T extends IdentifiableEntity, V extends T>
+        implements FilterablePagingProvider<V>, FilterableCountProvider {
 
+    private static final Logger logger = LogManager.getLogger();
 
     private static final List<String> DEFAULT_INIT_STRATEGY = Arrays.asList("$");
 
-    private static final Logger logger = Logger.getLogger(CdmFilterablePagingProvider.class);
+    public static final String QUERY_STRING_PLACEHOLDER = "{query-string}";
 
     private int pageSize = 20;
 
@@ -46,44 +49,28 @@ public class CdmFilterablePagingProvider<T extends IdentifiableEntity, V extends
 
     private List<OrderHint> orderHints = OrderHint.ORDER_BY_TITLE_CACHE.asList();
 
-    List<String> initStrategy = DEFAULT_INIT_STRATEGY;
+    private List<String> initStrategy = DEFAULT_INIT_STRATEGY;
 
     private List<Criterion> criteria = new ArrayList<>();
 
     private List<Restriction<?>> restrictions = new ArrayList<>();
 
-
-    /**
-     * @return the matchMode
-     */
     protected MatchMode getMatchMode() {
         return matchMode;
     }
-
-    /**
-     * @param matchMode the matchMode to set
-     */
     protected void setMatchMode(MatchMode matchMode) {
         this.matchMode = matchMode;
     }
 
-    /**
-     * @return the orderHints
-     */
     protected List<OrderHint> getOrderHints() {
         return orderHints;
     }
-
-    /**
-     * @param orderHints the orderHints to set
-     */
     protected void setOrderHints(List<OrderHint> orderHints) {
         this.orderHints = orderHints;
     }
 
     /**
      * With defaults for matchMode = MatchMode.ANYWHERE and orderHints = OrderHint.ORDER_BY_TITLE_CACHE
-     *
      */
     public CdmFilterablePagingProvider(IIdentifiableEntityService<T> service) {
         this(service, null);
@@ -91,52 +78,50 @@ public class CdmFilterablePagingProvider<T extends IdentifiableEntity, V extends
 
     /**
      * With defaults for matchMode = MatchMode.ANYWHERE and orderHints = OrderHint.ORDER_BY_TITLE_CACHE
-     *
      */
     public CdmFilterablePagingProvider(IIdentifiableEntityService<T> service, Class<V> type) {
         super();
         this.type = type;
         this.service = service;
 
-        // Logger.getLogger("org.hibernate.SQL").setLevel(Level.TRACE);
+        // LogUtils.setLevel("org.hibernate.SQL", Level.TRACE);
     }
 
-
     public CdmFilterablePagingProvider(IIdentifiableEntityService<T> service, MatchMode matchMode, List<OrderHint> orderHints) {
         this(service, null, matchMode, orderHints);
     }
 
     public <S extends T> CdmFilterablePagingProvider(IIdentifiableEntityService<T> service, Class<V> type, MatchMode matchMode, List<OrderHint> orderHints) {
-        super();
         this.type = type;
         this.service = service;
         this.matchMode = matchMode;
         this.orderHints = orderHints;
 
-        // Logger.getLogger("org.hibernate.SQL").setLevel(Level.TRACE);
+        // LogUtils.setLevel("org.hibernate.SQL", Level.TRACE);
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public List<V> findEntities(int firstRow, String filter) {
 
+        checkNotMixed();
+
         Integer pageIndex = firstRow / pageSize;
         Pager<V> page;
-        if(!restrictions.isEmpty() && criteria.isEmpty()){
-            page = (Pager<V>) service.findByTitleWithRestrictions(
+        clearSession(); // clear the session from remains of previous service calls, see issue #7559
+        if(!restrictions.isEmpty()){
+            List<Restriction<?>> preparedRestrictions = prepareRestrictions(filter, matchMode);
+            page = service.findByTitleWithRestrictions(
                     type,
                     filter,
                     matchMode,
-                    restrictions,
+                    preparedRestrictions,
                     pageSize,
                     pageIndex ,
                     orderHints,
                     initStrategy
                     );
-        } else if(restrictions.isEmpty() && !criteria.isEmpty()){
-            page = (Pager<V>) service.findByTitle(
+        } else {
+            page = service.findByTitle(
                     type,
                     filter,
                     matchMode,
@@ -146,79 +131,83 @@ public class CdmFilterablePagingProvider<T extends IdentifiableEntity, V extends
                     orderHints,
                     initStrategy
                     );
-        } else {
-            // this will never be reaced sind the size() method is always called before.
-            throw new RuntimeException("Citeria and Restrictions must not be used at the same time");
         }
+
         if(logger.isTraceEnabled()){
             logger.trace("findEntities() - page: " + page.getCurrentIndex() + "/" + page.getPagesAvailable() + " totalRecords: " + page.getCount() + "\n" + page.getRecords());
         }
+
+        // LogUtils.setLevel("org.hibernate.SQL", Level.TRACE);
         return page.getRecords();
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public int size(String filter) {
 
-        Pager<V> page;
-        if(!restrictions.isEmpty() && criteria.isEmpty()){
-            page = (Pager<V>) service.findByTitleWithRestrictions(
-                    type,
-                    filter,
-                    matchMode,
-                    restrictions,
-                    1,
-                    0,
-                    null,
-                    null
-                  );
-        } else if(restrictions.isEmpty() && !criteria.isEmpty()){
-            page = (Pager<V>) service.findByTitle(
-                    type,
-                    filter,
-                    matchMode,
-                    criteria,
-                    1,
-                    0,
-                    null,
-                    null
-                  );
+        checkNotMixed();
+
+        clearSession(); // clear the session from remains of previous service calls, see issue #7559
+        long count = 0;
+        if(!restrictions.isEmpty()){
+            // LogUtils.setLevel("org.hibernate.SQL", Level.TRACE);
+            List<Restriction<?>> preparedRestrictions = prepareRestrictions(filter, matchMode);
+            count = service.countByTitleWithRestrictions(type, filter, matchMode, preparedRestrictions);
         } else {
-            throw new RuntimeException("Citeria and Restrictions must not be used at the same time");
+            count = service.countByTitle(type, filter, matchMode, criteria);
         }
 
+
         if(logger.isTraceEnabled()){
-            logger.trace("size() -  count: " + page.getCount().intValue());
+            logger.trace("size() -  count: " + count);
         }
-        return page.getCount().intValue();
+        return Long.valueOf(count).intValue();
     }
 
     /**
-     * @return the pageSize
+     * see issue #7559
      */
+    public void clearSession() {
+        Session session = service.getSession();
+        if(session.isOpen()){
+            session.clear();
+        }
+    }
+
+    private List<Restriction<?>> prepareRestrictions(String filter, MatchMode matchMode) {
+        List<Restriction<?>> prepared = new ArrayList<>(restrictions.size());
+        for(Restriction<?> r : restrictions) {
+            List<Object> values = new ArrayList<>(r.getValues().size());
+            for(Object v : r.getValues()){
+                if(v instanceof String){
+                    String expandedValue = ((String)v).replace(QUERY_STRING_PLACEHOLDER, matchMode.queryStringFrom(filter));
+                    values.add(expandedValue);
+                } else {
+                    values.add(v);
+                }
+            }
+            prepared.add(new Restriction<>(r.getPropertyName(), r.getOperator(), r.getMatchMode(), values.toArray(new Object[values.size()])));
+        }
+        return prepared;
+    }
+
+    protected void checkNotMixed() {
+        if(!restrictions.isEmpty() && !criteria.isEmpty()){
+            throw new RuntimeException("Citeria and Restrictions must not be used at the same time");
+        }
+    }
+
     public int getPageSize() {
         return pageSize;
     }
 
-    /**
-     * @param pageSize the pageSize to set
-     */
     public void setPageSize(int pageSize) {
         this.pageSize = pageSize;
     }
 
-    /**
-     * @return the initStrategy
-     */
     public List<String> getInitStrategy() {
         return initStrategy;
     }
 
-    /**
-     * @param initStrategy the initStrategy to set
-     */
     public void setInitStrategy(List<String> initStrategy) {
         this.initStrategy = initStrategy;
     }
@@ -238,6 +227,10 @@ public class CdmFilterablePagingProvider<T extends IdentifiableEntity, V extends
 
     /**
      * The list of restrictions is initially empty.
+     * <p>
+     * Occurrences of the {@link QUERY_STRING_PLACEHOLDER} in the value
+     * of String type Restrictions will be replaced by the <code>filter</code> parameter passed to the paging provider.
+     *
      *
      * @return the restrictions
      */
@@ -245,7 +238,13 @@ public class CdmFilterablePagingProvider<T extends IdentifiableEntity, V extends
         return restrictions;
     }
 
+    /**
+     * Occurrences of the {@link QUERY_STRING_PLACEHOLDER} in the value
+     * of String type Restrictions will be replaced by the <code>filter</code> parameter passed to the paging provider.
+     *
+     * @param restriction
+     */
     public void addRestriction(Restriction<?> restriction){
         restrictions.add(restriction);
     }
-}
+}
\ No newline at end of file