fixing NPE in DescriptionListController
[cdmlib.git] / cdmlib-remote / src / main / java / eu / etaxonomy / cdm / remote / controller / DescriptionListController.java
1 // $Id$
2 /**
3 * Copyright (C) 2009 EDIT 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
7 * 1.1 See LICENSE.TXT at the top of this package for the full license terms.
8 */
9
10 package eu.etaxonomy.cdm.remote.controller;
11
12 import java.io.IOException;
13 import java.util.Arrays;
14 import java.util.List;
15 import java.util.UUID;
16
17 import javax.servlet.http.HttpServletRequest;
18 import javax.servlet.http.HttpServletResponse;
19
20 import org.springframework.beans.factory.annotation.Autowired;
21 import org.springframework.stereotype.Controller;
22 import org.springframework.web.bind.WebDataBinder;
23 import org.springframework.web.bind.annotation.InitBinder;
24 import org.springframework.web.bind.annotation.RequestMapping;
25 import org.springframework.web.bind.annotation.RequestMethod;
26 import org.springframework.web.bind.annotation.RequestParam;
27 import org.springframework.web.servlet.ModelAndView;
28
29 import eu.etaxonomy.cdm.api.service.IDescriptionService;
30 import eu.etaxonomy.cdm.api.service.ITaxonService;
31 import eu.etaxonomy.cdm.api.service.ITermService;
32 import eu.etaxonomy.cdm.api.service.description.TransmissionEngineDistribution;
33 import eu.etaxonomy.cdm.api.service.description.TransmissionEngineDistribution.AggregationMode;
34 import eu.etaxonomy.cdm.api.service.pager.Pager;
35 import eu.etaxonomy.cdm.model.description.DescriptionBase;
36 import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
37 import eu.etaxonomy.cdm.model.description.Feature;
38 import eu.etaxonomy.cdm.model.location.NamedArea;
39 import eu.etaxonomy.cdm.model.location.NamedAreaLevel;
40 import eu.etaxonomy.cdm.model.location.NamedAreaType;
41 import eu.etaxonomy.cdm.model.name.Rank;
42 import eu.etaxonomy.cdm.model.taxon.Taxon;
43 import eu.etaxonomy.cdm.persistence.query.MatchMode;
44 import eu.etaxonomy.cdm.persistence.query.OrderHint;
45 import eu.etaxonomy.cdm.remote.controller.util.PagerParameters;
46 import eu.etaxonomy.cdm.remote.controller.util.ProgressMonitorUtil;
47 import eu.etaxonomy.cdm.remote.editor.DefinedTermBaseList;
48 import eu.etaxonomy.cdm.remote.editor.TermBaseListPropertyEditor;
49
50 /**
51 * TODO write controller documentation
52 *
53 * @author a.kohlbecker
54 * @date 24.03.2009
55 */
56 @Controller
57 @RequestMapping(value = {"/description"})
58 public class DescriptionListController extends IdentifiableListController<DescriptionBase, IDescriptionService> {
59
60
61 @Autowired
62 private ITermService termService;
63
64 @Autowired
65 private ITaxonService taxonService;
66
67
68 @Autowired
69 public TransmissionEngineDistribution transmissionEngineDistribution;
70
71 @Autowired
72 public ProgressMonitorController progressMonitorController;
73
74 /**
75 * There should only be one longtime processes
76 * therefore the according progress monitor uuid is stored in
77 * this static field.
78 */
79 private static UUID transmissionEngineMonitorUuid = null;
80
81
82
83 /* (non-Javadoc)
84 * @see eu.etaxonomy.cdm.remote.controller.BaseListController#setService(eu.etaxonomy.cdm.api.service.IService)
85 */
86 @Override
87 @Autowired
88 public void setService(IDescriptionService service) {
89 this.service = service;
90 }
91
92 @InitBinder
93 @Override
94 public void initBinder(WebDataBinder binder) {
95 super.initBinder(binder);
96 binder.registerCustomEditor(DefinedTermBaseList.class, new TermBaseListPropertyEditor<Feature>(termService));
97 }
98
99
100 /**
101 * Runs the {@link TransmissionEngineDistribution} in a separate Thread and
102 * responds with a redirect to a progress monitor REST service end point.
103 * <p>
104 * <b>NOTE</b> this is still a special implementation for the Euro+Med project.
105 * The parameters for the <i>superAreas</i>, the areas to which the subordinate areas should be projected,
106 * <i>lowerRank</i>, <i>upperRank</i> are hardcoded to: <code>TDWG_LEVEL3 areas, SUBSPECIES, GENUS</code>
107 *
108 * @param mode
109 * one of <code>byAreas</code>, <code>byRanks</code>,
110 * <code>byAreasAndRanks</code>
111 * @param frontendBaseUrl
112 * the cdm server instance base URL, this is needed for the a
113 * proper redirect URL when the service is running behind a
114 * reverse HTTP proxy
115 * @param priority
116 * the priority for the Thread to spawn, see
117 * {@link Thread#setPriority(int)}, defaults to 3
118 * @param request
119 * @param response
120 * @return
121 * @throws IOException
122 */
123 @RequestMapping(value = { "accumulateDistributions" }, method = RequestMethod.GET)
124 public ModelAndView doAccumulateDistributions(
125 @RequestParam(value= "mode", required = true) final AggregationMode mode,
126 @RequestParam(value = "frontendBaseUrl", required = false) String frontendBaseUrl,
127 @RequestParam(value = "priority", required = false) Integer priority,
128 HttpServletRequest request,
129 HttpServletResponse response) throws IOException {
130
131 logger.info("doAccumulateDistributions()" + request.getRequestURI());
132
133 // transmissionEngineDistribution.updatePriorities();
134
135 String processLabel = "accumulating distributions";
136
137 ProgressMonitorUtil progressUtil = new ProgressMonitorUtil(progressMonitorController);
138
139 final List<String> term_init_strategy = Arrays.asList(new String []{
140 "representations"
141 });
142
143 if (!progressMonitorController.isMonitorRunning(transmissionEngineMonitorUuid)) {
144 transmissionEngineMonitorUuid = progressUtil.registerNewMonitor();
145 Thread subThread = new Thread() {
146 @Override
147 public void run() {
148 Pager<NamedArea> areaPager = termService.list(NamedAreaLevel.TDWG_LEVEL3(), (NamedAreaType) null,
149 null, null, (List<OrderHint>) null, term_init_strategy);
150 transmissionEngineDistribution.accumulate(mode, areaPager.getRecords(), Rank.SUBSPECIES(), Rank.GENUS(),
151 null, progressMonitorController.getMonitor(transmissionEngineMonitorUuid));
152 }
153 };
154 if(priority == null) {
155 priority = AbstractController.DEFAULT_BATCH_THREAD_PRIORITY;
156 }
157 subThread.setPriority(priority);
158 subThread.start();
159 }
160
161 // send redirect "see other"
162 return progressUtil.respondWithMonitor(frontendBaseUrl, request, response, processLabel, transmissionEngineMonitorUuid);
163 }
164
165 /**
166 *
167 * @param queryString
168 * @param type
169 * @param pageSize
170 * @param pageNumber
171 * @param matchMode
172 * @param request
173 * @param response
174 * @return
175 * @throws IOException
176 */
177 @RequestMapping(value = "/descriptionElement/find", method = RequestMethod.GET)
178 public Pager<DescriptionElementBase> doFindDescriptionElements(
179 @RequestParam(value = "query", required = true) String queryString,
180 @RequestParam(value = "type", required = false) Class<? extends DescriptionElementBase> type,
181 @RequestParam(value = "pageSize", required = false) Integer pageSize,
182 @RequestParam(value = "pageNumber", required = false) Integer pageNumber,
183 @RequestParam(value = "matchMode", required = false) MatchMode matchMode,
184 HttpServletRequest request,
185 HttpServletResponse response
186 )
187 throws IOException {
188
189 logger.info("doFindDescriptionElements : " + requestPathAndQuery(request) );
190
191 PagerParameters pagerParams = new PagerParameters(pageSize, pageNumber);
192 pagerParams.normalizeAndValidate(response);
193
194 Pager<DescriptionElementBase> pager = service.searchElements(type, queryString, pageSize, pageNumber, null, getInitializationStrategy());
195
196 return pager;
197 }
198
199 /**
200 * Requires the query parameter "descriptionType" to be present
201 *
202 * @param features
203 * @param descriptionType
204 * @param type
205 * @param pageSize
206 * @param pageNumber
207 * @param request
208 * @param response
209 * @return
210 * @throws IOException
211 */
212 @RequestMapping(value = "/descriptionElement/byFeature", method = RequestMethod.GET)
213 public Pager<DescriptionElementBase> doPageDescriptionElementsByFeature(
214 @RequestParam(value = "features", required = false) DefinedTermBaseList<Feature> features,
215 @RequestParam(value = "descriptionType", required = true) Class<? extends DescriptionBase> descriptionType,
216 @RequestParam(value = "type", required = false) Class<? extends DescriptionElementBase> type,
217 @RequestParam(value = "pageSize", required = false) Integer pageSize,
218 @RequestParam(value = "pageNumber", required = false) Integer pageNumber, HttpServletRequest request,
219 HttpServletResponse response) throws IOException {
220
221 logger.info("doPageDescriptionElementsByFeature : " + requestPathAndQuery(request));
222
223 PagerParameters pagerParams = new PagerParameters(pageSize, pageNumber);
224 pagerParams.normalizeAndValidate(response);
225
226 if(features == null){
227 features = new DefinedTermBaseList<Feature>();
228 }
229
230 Pager<DescriptionElementBase> pager = service.pageDescriptionElements(null, descriptionType, features.asSet(),
231 type, pagerParams.getPageSize(), pagerParams.getPageIndex(), getInitializationStrategy());
232
233 return pager;
234 }
235
236 /**
237 * Requires the query parameter "taxon" to be present
238 *
239 * @param taxon_uuid
240 * @param features
241 * @param type
242 * @param pageSize
243 * @param pageNumber
244 * @param request
245 * @param response
246 * @return
247 * @throws IOException
248 */
249 @RequestMapping(value = "/descriptionElement/byTaxon", method = {RequestMethod.GET, RequestMethod.POST})
250 public <T extends DescriptionElementBase> Pager<T> getDescriptionElementsForTaxon(
251 @RequestParam(value = "taxon", required = true) UUID taxon_uuid,
252 @RequestParam(value = "features", required = false) DefinedTermBaseList<Feature> features,
253 @RequestParam(value = "type", required = false) Class<T> type,
254 @RequestParam(value = "pageSize", required = false) Integer pageSize,
255 @RequestParam(value = "pageNumber", required = false) Integer pageNumber, HttpServletRequest request,
256 HttpServletResponse response) throws IOException {
257
258 logger.info("getDescriptionElementsForTaxon : " + requestPathAndQuery(request));
259
260 PagerParameters pagerParams = new PagerParameters(pageSize, pageNumber);
261 pagerParams.normalizeAndValidate(response);
262
263 Taxon taxon = null;
264 if( taxon_uuid!= null){
265 try {
266 taxon = (Taxon) taxonService.load(taxon_uuid);
267 } catch (Exception e) {
268 HttpStatusMessage.UUID_NOT_FOUND.send(response);
269 }
270 }
271
272 Pager<T> pager = service.pageDescriptionElementsForTaxon(taxon, features.asSet(), type, pageSize,
273 pageNumber, getInitializationStrategy());
274
275 return pager;
276 }
277
278 @RequestMapping(value = "namedAreasInUse", method = RequestMethod.GET)
279 public Pager<NamedArea> doPageNamedAreasInUse(
280 @RequestParam(value = "pageSize", required = false) Integer pageSize,
281 @RequestParam(value = "pageNumber", required = false) Integer pageNumber, HttpServletRequest request,
282 HttpServletResponse response) throws IOException {
283
284 logger.info("doPageNamedAreasInUse : " + requestPathAndQuery(request));
285
286 PagerParameters pagerParams = new PagerParameters(pageSize, pageNumber);
287 pagerParams.normalizeAndValidate(response);
288
289 Pager<NamedArea> pager = service.pageNamedAreasInUse(pageSize, pageNumber, getInitializationStrategy());
290
291 return pager;
292 }
293 }