2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
9 package eu
.etaxonomy
.cdm
.remote
.controller
;
11 import java
.io
.IOException
;
12 import java
.util
.ArrayList
;
13 import java
.util
.List
;
14 import java
.util
.UUID
;
16 import javax
.servlet
.http
.HttpServletRequest
;
17 import javax
.servlet
.http
.HttpServletResponse
;
19 import org
.apache
.logging
.log4j
.LogManager
;
20 import org
.apache
.logging
.log4j
.Logger
;
21 import org
.springframework
.web
.bind
.WebDataBinder
;
22 import org
.springframework
.web
.bind
.annotation
.InitBinder
;
23 import org
.springframework
.web
.bind
.annotation
.RequestMapping
;
24 import org
.springframework
.web
.bind
.annotation
.RequestMethod
;
25 import org
.springframework
.web
.bind
.annotation
.RequestParam
;
27 import eu
.etaxonomy
.cdm
.api
.service
.IClassificationService
;
28 import eu
.etaxonomy
.cdm
.api
.service
.IService
;
29 import eu
.etaxonomy
.cdm
.api
.service
.ITaxonNodeService
;
30 import eu
.etaxonomy
.cdm
.api
.service
.pager
.Pager
;
31 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
32 import eu
.etaxonomy
.cdm
.model
.taxon
.Classification
;
33 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonNode
;
34 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.Restriction
;
35 import eu
.etaxonomy
.cdm
.remote
.controller
.util
.PagerParameters
;
36 import eu
.etaxonomy
.cdm
.remote
.editor
.CdmTypePropertyEditor
;
37 import eu
.etaxonomy
.cdm
.remote
.editor
.UUIDPropertyEditor
;
40 * @author a.kohlbecker
43 public abstract class BaseListController
<T
extends CdmBase
, SERVICE
extends IService
<T
>> extends AbstractListController
<T
, SERVICE
> {
45 private static final Logger logger
= LogManager
.getLogger();
48 public void initBinder(WebDataBinder binder
) {
49 binder
.registerCustomEditor(UUID
.class, new UUIDPropertyEditor());
50 binder
.registerCustomEditor(Class
.class, new CdmTypePropertyEditor());
54 * NOTE: The indices for pages are 0-based see {@link Pager}
57 * the index of the page to be returned, the first page has the
58 * pageIndex = 0 - <i>optional parameter</i>. Defaults to 0 if
59 * set to <code>NULL</code>.
61 * the maximum number of entities returned per page.
62 * The {@link #DEFAULT_PAGE_SIZE} will be used if pageSize is set to
63 * <code>null</code> - <i>optional parameter</i>
65 * Further restricts the type of entities to be returned.
66 * If null the base type <code><T></code> is being used. - <i>optional parameter</i>
70 @SuppressWarnings("unchecked")
71 @RequestMapping(method
= RequestMethod
.GET
)
72 public Pager
<T
> doPage(
73 @RequestParam(value
= "pageIndex", required
= false) Integer pageIndex
,
74 @RequestParam(value
= "pageSize", required
= false) Integer pageSize
,
75 @RequestParam(value
= "class", required
= false) Class type
,
76 @RequestParam(name
="orderBy", defaultValue
="BY_TITLE_CACHE_ASC", required
=true) OrderHintPreset orderBy
,
77 HttpServletRequest request
,
78 HttpServletResponse response
) throws IOException
81 logger
.info("doPage() " + requestPathAndQuery(request
));
82 PagerParameters pagerParameters
= new PagerParameters(pageSize
, pageIndex
).normalizeAndValidate(response
);
85 orderBy
= orderBy
.checkSuitableFor(type
);
86 // TODO how can we check in case type == null?
88 return service
.page(type
, pagerParameters
.getPageSize(), pagerParameters
.getPageIndex(), orderBy
.orderHints(), getInitializationStrategy());
91 @SuppressWarnings("unchecked")
92 @RequestMapping(method
= {RequestMethod
.GET
, RequestMethod
.POST
}, params
={"restriction"})
93 public Pager
<T
> doPageByRestrictions(
94 @RequestParam(value
= "pageIndex", required
= false) Integer pageIndex
,
95 @RequestParam(value
= "pageSize", required
= false) Integer pageSize
,
96 @RequestParam(value
= "class", required
= false) Class type
,
97 @RequestParam(value
= "restriction", required
= true) List
<Restriction
<?
>> restrictions
,
98 @RequestParam(value
= "initStrategy", required
= true) List
<String
> initStrategy
,
99 @RequestParam(name
="orderBy", defaultValue
="BY_TITLE_CACHE_ASC", required
=true) OrderHintPreset orderBy
,
100 HttpServletRequest request
,
101 HttpServletResponse response
) throws IOException
104 // NOTE: for testing with httpi and jq:
105 // 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'
106 logger
.info("doPageByRestrictions() " + requestPathAndQuery(request
));
107 PagerParameters pagerParameters
= new PagerParameters(pageSize
, pageIndex
).normalizeAndValidate(response
);
110 orderBy
= orderBy
.checkSuitableFor(type
);
113 return pageByRestrictions(type
, initStrategy
, orderBy
, pagerParameters
, new ArrayList
<>(restrictions
));
117 * This method can be overwritten by subclasses, for example to apply additional filtering like for the publish flag.
120 * @param initStrategy
122 * @param pagerParameters
123 * @param restrictions
126 protected Pager
<T
> pageByRestrictions(Class
<T
> type
, List
<String
> initStrategy
, OrderHintPreset orderBy
,
127 PagerParameters pagerParameters
, ArrayList
<Restriction
<?
>> restrictions
) {
128 return service
.page(type
, restrictions
, pagerParameters
.getPageSize(), pagerParameters
.getPageIndex(), orderBy
.orderHints(), initStrategy
);
132 // * Parameter less method to be used as default when request without parameter are made. Otherwise
133 // * the nameless methods {@link #doPage(Integer, Integer, Class)} and {@link #doList(Integer, Integer, Class)}
136 // * @throws IOException
138 // @RequestMapping(method = RequestMethod.GET)
139 // public Pager<T> doPage(HttpServletRequest request, HttpServletResponse response) throws IOException{
140 // return doPage(null, null, null, request, response);
145 * The offset index from the start of the list. The first entity
146 * has the index = 0 - <i>required parameter</i>
148 * The maximum number of entities returned. - <i>optional parameter</i>
149 * If limit is set to a value < 1 all entities will be returned
151 * Further restricts the type of entities to be returned.
152 * If null the base type <code><T></code> is being used. - <i>optional parameter</i>
153 * @return a List of entities
155 @RequestMapping(method
= RequestMethod
.GET
, params
= "start")
156 public List
<T
> doList(
157 @RequestParam(value
= "start", required
= true) Integer start
,
158 @RequestParam(value
= "limit", required
= false) Integer limit
,
159 @RequestParam(value
= "class", required
= false) Class
<T
> type
,
160 HttpServletRequest request
,
161 @SuppressWarnings("unused") HttpServletResponse response
) {
163 if (request
!= null){
164 logger
.info("doList() " + requestPathAndQuery(request
));
167 //if(start == null){ start = 0;}
169 limit
= PagerParameters
.DEFAULT_PAGESIZE
;
173 return service
.list(type
, limit
, start
, null, getInitializationStrategy());
177 * Retrieves the according taxon node representing the taxon subtree. If no such taxon node
178 * is found an 404 error response is sent.
180 // this is a copy from BaseController, should be unified
181 protected TaxonNode
getSubtreeOrError(UUID subtreeUuid
, ITaxonNodeService taxonNodeService
, HttpServletResponse response
) throws IOException
{
182 TaxonNode subtree
= null;
183 if (subtreeUuid
!= null){
184 subtree
= taxonNodeService
.find(subtreeUuid
);
185 if(subtree
== null) {
186 response
.sendError(404 , "Taxon node for subtree not found: " + subtreeUuid
);
194 // this is a copy from BaseController, should be unified
195 protected Classification
getClassificationOrError(UUID classificationUuid
,
196 IClassificationService classificationService
, HttpServletResponse response
) throws IOException
{
197 Classification classification
= null;
198 if (classificationUuid
!= null){
199 classification
= classificationService
.find(classificationUuid
);
200 if(classification
== null) {
201 response
.sendError(404 , "Classification not found: " + classificationUuid
);
206 return classification
;
210 @RequestMapping(method = RequestMethod.POST)
211 public T doPost(@ModelAttribute("object") T object, BindingResult result) {
212 validator.validate(object, result);
213 if (result.hasErrors()) {
214 // set http status code depending upon what happened, possibly return
215 // the put object and errors so that they can be rendered into a suitable error response
217 // should set the status to 201 created and "Location" header to "/resource/uuid"
218 service.save(object);