generic webservice method for all cdm entitiy list controllers to search by Restriction
authorAndreas Kohlbecker <a.kohlbecker@bgbm.org>
Mon, 3 Jun 2019 15:25:17 +0000 (17:25 +0200)
committerAndreas Kohlbecker <a.kohlbecker@bgbm.org>
Mon, 3 Jun 2019 15:25:23 +0000 (17:25 +0200)
13 files changed:
cdmlib-persistence/src/main/java/eu/etaxonomy/cdm/persistence/dao/common/Restriction.java
cdmlib-persistence/src/main/java/eu/etaxonomy/cdm/persistence/dao/taxon/ITaxonDao.java
cdmlib-remote-webapp/src/main/java/eu/etaxonomy/cdm/remote/config/CdmSpringMVCConfig.java
cdmlib-remote-webapp/src/main/java/eu/etaxonomy/cdm/remote/config/PreloadedBeans.java
cdmlib-remote/src/main/java/eu/etaxonomy/cdm/remote/config/CdmRemoteConfiguration.java [new file with mode: 0644]
cdmlib-remote/src/main/java/eu/etaxonomy/cdm/remote/controller/BaseController.java
cdmlib-remote/src/main/java/eu/etaxonomy/cdm/remote/controller/BaseListController.java
cdmlib-remote/src/main/java/eu/etaxonomy/cdm/remote/converter/RestrictionConverter.java [new file with mode: 0644]
cdmlib-remote/src/main/resources/eu/etaxonomy/cdm/remote.xml
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/IService.java
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/RegistrationServiceImpl.java
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/ServiceBase.java
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/TaxonServiceImpl.java

index 0880423cd7c727a949dcff7bea7006235932dd85..11cd55d8c37d4fd32371141d40fcf2ce6d917f3e 100644 (file)
@@ -41,6 +41,10 @@ public class Restriction<T extends Object> {
 
     private List<T> values = null;
 
+    public Restriction(){
+        super();
+    }
+
     /**
      * @param propertyName
      * @param matchMode is only applied if the <code>value</code> is a <code>String</code> object
index 211ad1eeb93d579ddac932c1e269057fe83096c0..61bda7dff1f91645b3b49430b7b5c4b0056dcb3e 100644 (file)
@@ -91,6 +91,7 @@ public interface ITaxonDao
     /**
      * Returns a list of TaxonBase instances (or Taxon instances, if accepted == true, or Synonym instance, if accepted == false)
      * where the taxonBase.name.nameCache property matches the String queryString.
+     *
      * @param doTaxa
      * @param doSynonyms
      * @param queryString
index 10752591563e3ffbc95c750ff57d5b03232040b8..3790792eaab00c5bf95d3263c1ebd3735e881aa7 100644 (file)
@@ -20,6 +20,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.DependsOn;
 import org.springframework.context.annotation.Import;
+import org.springframework.format.FormatterRegistry;
 import org.springframework.http.MediaType;
 import org.springframework.web.accept.ContentNegotiationManager;
 import org.springframework.web.context.support.ServletContextResource;
@@ -31,7 +32,10 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupp
 import org.springframework.web.servlet.view.ContentNegotiatingViewResolver;
 import org.springframework.web.servlet.view.XmlViewResolver;
 
+import com.fasterxml.jackson.databind.ObjectMapper;
+
 import eu.etaxonomy.cdm.remote.controller.interceptor.LocaleContextHandlerInterceptor;
+import eu.etaxonomy.cdm.remote.converter.RestrictionConverter;
 import eu.etaxonomy.cdm.remote.view.PatternViewResolver;
 
 /**
@@ -64,6 +68,9 @@ public abstract class CdmSpringMVCConfig extends WebMvcConfigurationSupport  {
     @Autowired
     protected ServletContext servletContext;
 
+    @Autowired // is initialized in PreloadedBeans.class
+    private ObjectMapper jsonObjectMapper;
+
     @Autowired // is initialized in PreloadedBeans.class
     private LocaleContextHandlerInterceptor localeContextHandlerInterceptor;
 
@@ -111,6 +118,8 @@ public abstract class CdmSpringMVCConfig extends WebMvcConfigurationSupport  {
     }
 
 
+
+
     /* (non-Javadoc)
      * @see org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration#addInterceptors(org.springframework.web.servlet.config.annotation.InterceptorRegistry)
      */
@@ -121,6 +130,12 @@ public abstract class CdmSpringMVCConfig extends WebMvcConfigurationSupport  {
         logger.debug("addInterceptors");
     }
 
+    @Override
+    public void addFormatters(FormatterRegistry registry) {
+        registry.addConverter(new RestrictionConverter(jsonObjectMapper));
+    }
+
+
     @Override
     protected void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
       // DefaultServletHandlerConfigurer: delegates unhandled requests by forwarding to
index 9a3580b4582c52f6ff36d003a4809d42ed20e788..03e85e5c3700c419237d21f728c20a5d358c8743 100644 (file)
@@ -11,6 +11,10 @@ package eu.etaxonomy.cdm.remote.config;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.MapperFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
 import eu.etaxonomy.cdm.remote.controller.interceptor.LocaleContextHandlerInterceptor;
 
 /**
@@ -26,4 +30,16 @@ public class PreloadedBeans {
         return new LocaleContextHandlerInterceptor();
     }
 
+    /**
+     * This is only uses for Converters so far
+     */
+    @Bean
+    public ObjectMapper objectMapper() {
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+        mapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, true);
+
+        return mapper;
+    }
+
 }
diff --git a/cdmlib-remote/src/main/java/eu/etaxonomy/cdm/remote/config/CdmRemoteConfiguration.java b/cdmlib-remote/src/main/java/eu/etaxonomy/cdm/remote/config/CdmRemoteConfiguration.java
new file mode 100644 (file)
index 0000000..0056fbf
--- /dev/null
@@ -0,0 +1,24 @@
+/**
+* Copyright (C) 2019 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+package eu.etaxonomy.cdm.remote.config;
+
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * This configuration may completely replace the src/main/resources/eu/etaxonomy/cdm/remote.xml in future
+ *
+ * @author a.kohlbecker
+ * @since Jun 3, 2019
+ *
+ */
+@Configuration
+public class CdmRemoteConfiguration {
+
+
+}
index 857024353535bc480c2f6c449aaf9ea2e6956054..96c71a33f7b6857ead8f41bb71c5047f40ad3d59 100644 (file)
@@ -65,11 +65,6 @@ public abstract class BaseController<T extends CdmBase, SERVICE extends IService
 
     private static final Logger logger = Logger.getLogger(BaseController.class);
 
-
-/*     protected SERVICE service;
-
-    public abstract void setService(SERVICE service);*/
-
     protected Class<T> baseClass;
 
     @SuppressWarnings("unchecked")
index ac52d252126f53cf745c39af47f0b5a3ca1ca1cf..0ea0147fe1c0074a1c012c8e337e9d353e03985e 100644 (file)
@@ -11,6 +11,7 @@
 package eu.etaxonomy.cdm.remote.controller;\r
 \r
 import java.io.IOException;\r
+import java.util.ArrayList;\r
 import java.util.List;\r
 import java.util.UUID;\r
 \r
@@ -31,6 +32,7 @@ import eu.etaxonomy.cdm.api.service.pager.Pager;
 import eu.etaxonomy.cdm.model.common.CdmBase;\r
 import eu.etaxonomy.cdm.model.taxon.Classification;\r
 import eu.etaxonomy.cdm.model.taxon.TaxonNode;\r
+import eu.etaxonomy.cdm.persistence.dao.common.Restriction;\r
 import eu.etaxonomy.cdm.remote.controller.util.PagerParameters;\r
 import eu.etaxonomy.cdm.remote.editor.CdmTypePropertyEditor;\r
 import eu.etaxonomy.cdm.remote.editor.UUIDPropertyEditor;\r
@@ -83,8 +85,7 @@ public abstract class BaseListController <T extends CdmBase, SERVICE extends ISe
             {\r
 \r
         logger.info("doPage() " + requestPathAndQuery(request));\r
-        PagerParameters pagerParameters = new PagerParameters(pageSize, pageIndex);\r
-        pagerParameters.normalizeAndValidate(response);\r
+        PagerParameters pagerParameters = new PagerParameters(pageSize, pageIndex).normalizeAndValidate(response);\r
 \r
         if(type != null) {\r
             orderBy = orderBy.checkSuitableFor(type);\r
@@ -93,6 +94,32 @@ public abstract class BaseListController <T extends CdmBase, SERVICE extends ISe
         return service.page(type, pagerParameters.getPageSize(), pagerParameters.getPageIndex(), orderBy.orderHints(), getInitializationStrategy());\r
     }\r
 \r
+    @SuppressWarnings("unchecked")\r
+    @RequestMapping(method = {RequestMethod.GET,RequestMethod.POST}, params={"restriction"})\r
+    public Pager<T> doPageByRestrictions(\r
+            @RequestParam(value = "pageNumber", required = false) Integer pageIndex,\r
+            @RequestParam(value = "pageSize", required = false) Integer pageSize,\r
+            @RequestParam(value = "class", required = false) Class type,\r
+            @RequestParam(value = "restriction", required = false) List<Restriction> restrictions,\r
+            @RequestParam(value = "initStrategy", required = false) List<String> initStrategy,\r
+            @RequestParam(name="orderBy", defaultValue="BY_TITLE_CACHE_ASC", required=true) OrderHintPreset orderBy,\r
+            HttpServletRequest request,\r
+            HttpServletResponse response) throws IOException\r
+            {\r
+\r
+        // NOTE: for testing with httpi and jq:\r
+        // http GET :8080/portal/taxon.json restriction=='{"propertyName":"name.titleCache","matchMode":"EXACT","values":["Eunotia krammeri Metzeltin & Lange-Bert."]}' initStrategy=name.titleCache | jq '.records[].name.titleCache'\r
+        logger.info("doPageByRestrictions() " + requestPathAndQuery(request));\r
+        PagerParameters pagerParameters = new PagerParameters(pageSize, pageIndex).normalizeAndValidate(response);\r
+\r
+        if(type != null) {\r
+            orderBy = orderBy.checkSuitableFor(type);\r
+        }\r
+        ArrayList<Restriction<?>> restrictions2 = new ArrayList<>(restrictions);\r
+        return service.page(type, restrictions2, pagerParameters.getPageSize(), pagerParameters.getPageIndex(), orderBy.orderHints(), initStrategy);\r
+    }\r
+\r
+\r
 //    /**\r
 //     * Parameter less method to be used as default when request without parameter are made. Otherwise\r
 //     * the nameless methods {@link #doPage(Integer, Integer, Class)} and {@link #doList(Integer, Integer, Class)}\r
diff --git a/cdmlib-remote/src/main/java/eu/etaxonomy/cdm/remote/converter/RestrictionConverter.java b/cdmlib-remote/src/main/java/eu/etaxonomy/cdm/remote/converter/RestrictionConverter.java
new file mode 100644 (file)
index 0000000..7e6a53d
--- /dev/null
@@ -0,0 +1,51 @@
+/**
+* Copyright (C) 2019 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+package eu.etaxonomy.cdm.remote.converter;
+
+import java.io.IOException;
+
+import org.springframework.core.convert.converter.Converter;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import eu.etaxonomy.cdm.persistence.dao.common.Restriction;
+
+/**
+ * Converter implementation to read a {@link Restriction} from its
+ * json serialization.
+ *
+ * @author a.kohlbecker
+ * @since Jun 3, 2019
+ *
+ */
+public class RestrictionConverter implements Converter<String, Restriction<?>>  {
+
+    private ObjectMapper objectMapper;
+
+    public RestrictionConverter (ObjectMapper objectMapper) {
+        this.objectMapper = objectMapper;
+    }
+
+    @Override
+    public Restriction<?> convert(String source) {
+
+            try {
+                return objectMapper.readValue(source, Restriction.class);
+            } catch (JsonParseException | JsonMappingException e) {
+                throw new IllegalArgumentException(e);
+            }catch (IOException e) {
+                // TODO more specific unchecked exception type?
+                throw new RuntimeException(e);
+            }
+
+    }
+
+}
index 6e5a77ce88f9e9d29363f2d7e8362beb20ac25a3..5831f66a57774c497f24c34678ca14ca2f8020ab 100644 (file)
@@ -8,6 +8,8 @@
     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
     http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
     ">
+    
+  <!-- This xml configuration may be replaced by eu.etaxonomy.cdm.remote.config.CdmRemoteConfiguration in future -->
 
   <bean id="marshaller" name="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
     <property name="classesToBeBound">
index 5f8fd3ed1c4c541040e2f10eda2a0e0b6460142d..39948ac183aff3f54fd80752355bdf881df94e49 100644 (file)
@@ -19,14 +19,11 @@ import java.util.UUID;
 import org.hibernate.LockOptions;\r
 import org.hibernate.Session;\r
 import org.hibernate.criterion.Criterion;\r
-import org.hibernate.event.spi.MergeEvent;\r
 \r
 import eu.etaxonomy.cdm.api.service.pager.Pager;\r
 import eu.etaxonomy.cdm.model.common.ICdmBase;\r
 import eu.etaxonomy.cdm.persistence.dao.common.Restriction;\r
-import eu.etaxonomy.cdm.persistence.dao.initializer.IBeanInitializer;\r
 import eu.etaxonomy.cdm.persistence.dto.MergeResult;\r
-import eu.etaxonomy.cdm.persistence.hibernate.PostMergeEntityListener;\r
 import eu.etaxonomy.cdm.persistence.query.Grouping;\r
 import eu.etaxonomy.cdm.persistence.query.MatchMode;\r
 import eu.etaxonomy.cdm.persistence.query.OrderHint;\r
@@ -447,7 +444,19 @@ public interface IService<T extends ICdmBase>{
 \r
     public <S extends T> Pager<S> page(Class<S> clazz, String param, String queryString, MatchMode matchmode, List<Criterion> criteria, Integer pageSize, Integer pageIndex, List<OrderHint> orderHints, List<String> propertyPaths);\r
 \r
-    public <S extends T> Pager<S> pageByRestrictions(Class<S> clazz, String param, String queryString, MatchMode matchmode, List<Restriction<?>> restrictions, Integer pageSize, Integer pageIndex, List<OrderHint> orderHints,\r
+    public <S extends T> Pager<S> pageByParamWithRestrictions(Class<S> clazz, String param, String queryString, MatchMode matchmode, List<Restriction<?>> restrictions, Integer pageSize, Integer pageIndex, List<OrderHint> orderHints,\r
             List<String> propertyPaths);\r
 \r
+    /**\r
+     * @param clazz\r
+     * @param restrictions\r
+     * @param pageSize\r
+     * @param pageIndex\r
+     * @param orderHints\r
+     * @param propertyPaths\r
+     * @return\r
+     */\r
+    public <S extends T> Pager<S> page(Class<S> clazz, List<Restriction<?>> restrictions, Integer pageSize, Integer pageIndex,\r
+            List<OrderHint> orderHints, List<String> propertyPaths);\r
+\r
 }
index f2299892ff8c5a84cf9e2cf658746ab5e5a2efc9..93d2e316672df0784f9eed65a9288fe8b1041207 100644 (file)
@@ -264,7 +264,7 @@ public class RegistrationServiceImpl extends AnnotatableServiceBase<Registration
             restrictions.add(new Restriction<>("status", null, RegistrationStatus.PUBLISHED));
         }
 
-        Pager<Registration> regPager = pageByRestrictions(Registration.class, "identifier", identifier, MatchMode.EXACT,
+        Pager<Registration> regPager = pageByParamWithRestrictions(Registration.class, "identifier", identifier, MatchMode.EXACT,
                 restrictions, pageSize, pageIndex, null, propertyPaths);
 
 
@@ -275,7 +275,7 @@ public class RegistrationServiceImpl extends AnnotatableServiceBase<Registration
     @Transactional(readOnly = true)
     public Map<UUID, RegistrationStatus> statusByIdentifier(String identifier) throws IOException {
 
-        Pager<Registration> regPager = pageByRestrictions(Registration.class, "identifier", identifier, MatchMode.EXACT,
+        Pager<Registration> regPager = pageByParamWithRestrictions(Registration.class, "identifier", identifier, MatchMode.EXACT,
                 null, null, null, null, Arrays.asList("status"));
 
         Map<UUID, RegistrationStatus> map = new HashMap<>();
index c3ffe126f4e7286f76597f9729c2b0f3cb6865b5..38cbe65ae29fd5f9162131cace8e818e3662d945 100644 (file)
@@ -328,7 +328,7 @@ public abstract class ServiceBase<T extends CdmBase, DAO extends ICdmEntityDao<T
 \r
     @Override\r
     @Transactional(readOnly = true)\r
-    public <S extends T> Pager<S> pageByRestrictions(Class<S> clazz, String param, String queryString, MatchMode matchmode, List<Restriction<?>> restrictions, Integer pageSize, Integer pageIndex, List<OrderHint> orderHints, List<String> propertyPaths){\r
+    public <S extends T> Pager<S> pageByParamWithRestrictions(Class<S> clazz, String param, String queryString, MatchMode matchmode, List<Restriction<?>> restrictions, Integer pageSize, Integer pageIndex, List<OrderHint> orderHints, List<String> propertyPaths){\r
 \r
         List<S> records;\r
         long resultSize = dao.countByParamWithRestrictions(clazz, param, queryString, matchmode, restrictions);\r
@@ -341,6 +341,21 @@ public abstract class ServiceBase<T extends CdmBase, DAO extends ICdmEntityDao<T
         return pager;\r
     }\r
 \r
+    @Override\r
+    @Transactional(readOnly = true)\r
+    public <S extends T> Pager<S> page(Class<S> clazz, List<Restriction<?>> restrictions, Integer pageSize, Integer pageIndex, List<OrderHint> orderHints, List<String> propertyPaths){\r
+\r
+        List<S> records;\r
+        long resultSize = dao.count(clazz, restrictions);\r
+        if(AbstractPagerImpl.hasResultsInRange(resultSize, pageIndex, pageSize)){\r
+            records = dao.list(clazz, restrictions, pageSize, pageIndex, orderHints, propertyPaths);\r
+        } else {\r
+            records = new ArrayList<>();\r
+        }\r
+        Pager<S> pager = new DefaultPagerImpl<>(pageIndex, resultSize, pageSize, records);\r
+        return pager;\r
+    }\r
+\r
 \r
     /**\r
      * Throws an exception if the publishable entity should not be published.\r
index d3053cf25d774d4e501bdfdf55e8f7d581402c7b..1cd46554d0d60a49693a537995e426c0ffa6b4b8 100644 (file)
@@ -409,6 +409,7 @@ public class TaxonServiceImpl
         this.dao = dao;
     }
 
+
     @Override
     public Pager<TaxonBase> findTaxaByName(Class<? extends TaxonBase> clazz, String uninomial, String infragenericEpithet, String specificEpithet,     String infraspecificEpithet, String authorship, Rank rank, Integer pageSize,Integer pageNumber) {
         long numberOfResults = dao.countTaxaByName(clazz, uninomial, infragenericEpithet, specificEpithet, infraspecificEpithet, rank);