cleanup
[cdmlib.git] / cdmlib-remote / src / main / java / eu / etaxonomy / cdm / remote / controller / BaseListController.java
1 /**
2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
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.
8 */
9 package eu.etaxonomy.cdm.remote.controller;
10
11 import java.io.IOException;
12 import java.util.ArrayList;
13 import java.util.List;
14 import java.util.UUID;
15
16 import javax.servlet.http.HttpServletRequest;
17 import javax.servlet.http.HttpServletResponse;
18
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;
26
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;
38
39 /**
40 * @author a.kohlbecker
41 * @since 22.07.2009
42 */
43 public abstract class BaseListController <T extends CdmBase, SERVICE extends IService<T>> extends AbstractListController<T, SERVICE> {
44
45 private static final Logger logger = LogManager.getLogger();
46
47 @InitBinder
48 public void initBinder(WebDataBinder binder) {
49 binder.registerCustomEditor(UUID.class, new UUIDPropertyEditor());
50 binder.registerCustomEditor(Class.class, new CdmTypePropertyEditor());
51 }
52
53 /**
54 * NOTE: The indices for pages are 0-based see {@link Pager}
55 *
56 * @param pageIndex
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>.
60 * @param pageSize
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>
64 * @param type
65 * Further restricts the type of entities to be returned.
66 * If null the base type <code>&lt;T&gt;</code> is being used. - <i>optional parameter</i>
67 * @return
68 * @throws IOException
69 */
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
79 {
80
81 logger.info("doPage() " + requestPathAndQuery(request));
82 PagerParameters pagerParameters = new PagerParameters(pageSize, pageIndex).normalizeAndValidate(response);
83
84 if(type != null) {
85 orderBy = orderBy.checkSuitableFor(type);
86 // TODO how can we check in case type == null?
87 }
88 return service.page(type, pagerParameters.getPageSize(), pagerParameters.getPageIndex(), orderBy.orderHints(), getInitializationStrategy());
89 }
90
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
102 {
103
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);
108
109 if(type != null) {
110 orderBy = orderBy.checkSuitableFor(type);
111 }
112
113 return pageByRestrictions(type, initStrategy, orderBy, pagerParameters, new ArrayList<>(restrictions));
114 }
115
116 /**
117 * This method can be overwritten by subclasses, for example to apply additional filtering like for the publish flag.
118 *
119 * @param type
120 * @param initStrategy
121 * @param orderBy
122 * @param pagerParameters
123 * @param restrictions
124 * @return
125 */
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);
129 }
130
131 // /**
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)}
134 // * are ambigous.
135 // * @return
136 // * @throws IOException
137 // */
138 // @RequestMapping(method = RequestMethod.GET)
139 // public Pager<T> doPage(HttpServletRequest request, HttpServletResponse response) throws IOException{
140 // return doPage(null, null, null, request, response);
141 // }
142
143 /**
144 * @param start
145 * The offset index from the start of the list. The first entity
146 * has the index = 0 - <i>required parameter</i>
147 * @param limit
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
150 * @param type
151 * Further restricts the type of entities to be returned.
152 * If null the base type <code>&lt;T&gt;</code> is being used. - <i>optional parameter</i>
153 * @return a List of entities
154 */
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) {
162
163 if (request != null){
164 logger.info("doList() " + requestPathAndQuery(request));
165 }
166
167 //if(start == null){ start = 0;}
168 if(limit == null){
169 limit = PagerParameters.DEFAULT_PAGESIZE;
170 }else if(limit < 1){
171 limit = null;
172 }
173 return service.list(type, limit, start, null, getInitializationStrategy());
174 }
175
176 // this is a copy from BaseController, should be unified
177 protected TaxonNode getSubtreeOrError(UUID subtreeUuid, ITaxonNodeService taxonNodeService, HttpServletResponse response) throws IOException {
178 TaxonNode subtree = null;
179 if (subtreeUuid != null){
180 subtree = taxonNodeService.find(subtreeUuid);
181 if(subtree == null) {
182 response.sendError(404 , "Taxon node for subtree not found: " + subtreeUuid );
183 //will not happen
184 return null;
185 }
186 }
187 return subtree;
188 }
189
190 // this is a copy from BaseController, should be unified
191 protected Classification getClassificationOrError(UUID classificationUuid,
192 IClassificationService classificationService, HttpServletResponse response) throws IOException {
193 Classification classification = null;
194 if (classificationUuid != null){
195 classification = classificationService.find(classificationUuid);
196 if(classification == null) {
197 response.sendError(404 , "Classification not found: " + classificationUuid );
198 //will not happen
199 return null;
200 }
201 }
202 return classification;
203 }
204
205 /* TODO
206 @RequestMapping(method = RequestMethod.POST)
207 public T doPost(@ModelAttribute("object") T object, BindingResult result) {
208 validator.validate(object, result);
209 if (result.hasErrors()) {
210 // set http status code depending upon what happened, possibly return
211 // the put object and errors so that they can be rendered into a suitable error response
212 } else {
213 // should set the status to 201 created and "Location" header to "/resource/uuid"
214 service.save(object);
215 }
216 }
217 */
218 }