Merge branch 'release/5.45.0'
[cdmlib.git] / cdmlib-remote / src / main / java / eu / etaxonomy / cdm / remote / controller / TaxonController.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
10 package eu.etaxonomy.cdm.remote.controller;
11
12 import java.io.IOException;
13 import java.util.ArrayList;
14 import java.util.Arrays;
15 import java.util.Collection;
16 import java.util.EnumSet;
17 import java.util.HashSet;
18 import java.util.List;
19 import java.util.Set;
20 import java.util.UUID;
21
22 import javax.persistence.EntityNotFoundException;
23 import javax.servlet.http.HttpServletRequest;
24 import javax.servlet.http.HttpServletResponse;
25
26 import org.apache.commons.lang3.StringUtils;
27 import org.apache.logging.log4j.LogManager;
28 import org.apache.logging.log4j.Logger;
29 import org.springframework.beans.factory.annotation.Autowired;
30 import org.springframework.stereotype.Controller;
31 import org.springframework.web.bind.WebDataBinder;
32 import org.springframework.web.bind.annotation.PathVariable;
33 import org.springframework.web.bind.annotation.RequestMapping;
34 import org.springframework.web.bind.annotation.RequestMethod;
35 import org.springframework.web.bind.annotation.RequestParam;
36 import org.springframework.web.servlet.ModelAndView;
37
38 import eu.etaxonomy.cdm.api.dto.SpecimenOrObservationBaseDTO;
39 import eu.etaxonomy.cdm.api.filter.TaxonOccurrenceRelationType;
40 import eu.etaxonomy.cdm.api.service.IDescriptionService;
41 import eu.etaxonomy.cdm.api.service.INameService;
42 import eu.etaxonomy.cdm.api.service.IOccurrenceService;
43 import eu.etaxonomy.cdm.api.service.ITaxonNodeService;
44 import eu.etaxonomy.cdm.api.service.ITaxonService;
45 import eu.etaxonomy.cdm.api.service.ITermService;
46 import eu.etaxonomy.cdm.api.service.config.FindOccurrencesConfigurator;
47 import eu.etaxonomy.cdm.api.service.config.IncludedTaxonConfiguration;
48 import eu.etaxonomy.cdm.api.service.dto.IncludedTaxaDTO;
49 import eu.etaxonomy.cdm.api.service.dto.TaxonRelationshipsDTO;
50 import eu.etaxonomy.cdm.api.service.pager.Pager;
51 import eu.etaxonomy.cdm.exception.UnpublishedException;
52 import eu.etaxonomy.cdm.model.common.CdmBase;
53 import eu.etaxonomy.cdm.model.common.MarkerType;
54 import eu.etaxonomy.cdm.model.common.RelationshipBase.Direction;
55 import eu.etaxonomy.cdm.model.description.DescriptionBase;
56 import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
57 import eu.etaxonomy.cdm.model.description.DescriptionType;
58 import eu.etaxonomy.cdm.model.description.TaxonDescription;
59 import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
60 import eu.etaxonomy.cdm.model.taxon.Classification;
61 import eu.etaxonomy.cdm.model.taxon.Synonym;
62 import eu.etaxonomy.cdm.model.taxon.Taxon;
63 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
64 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
65 import eu.etaxonomy.cdm.model.taxon.TaxonNodeAgentRelation;
66 import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
67 import eu.etaxonomy.cdm.model.term.DefinedTermBase;
68 import eu.etaxonomy.cdm.persistence.dao.initializer.EntityInitStrategy;
69 import eu.etaxonomy.cdm.persistence.dto.TaxonNodeDto;
70 import eu.etaxonomy.cdm.persistence.query.OrderHint;
71 import eu.etaxonomy.cdm.persistence.query.OrderHint.SortOrder;
72 import eu.etaxonomy.cdm.remote.controller.util.PagerParameters;
73 import eu.etaxonomy.cdm.remote.dto.common.StringResultDTO;
74 import eu.etaxonomy.cdm.remote.editor.TermBasePropertyEditor;
75 import eu.etaxonomy.cdm.remote.editor.UuidList;
76 import io.swagger.annotations.Api;
77
78 /**
79 * TODO write controller documentation
80 *
81 * @author a.kohlbecker
82 * @since 20.07.2009
83 */
84 @Controller
85 @Api("taxon")
86 @RequestMapping(value = {"/taxon/{uuid}"})
87 public class TaxonController extends AbstractIdentifiableController<TaxonBase, ITaxonService>{
88
89 private static final Logger logger = LogManager.getLogger();
90
91 @Autowired
92 private IOccurrenceService occurrenceService;
93
94 @Autowired
95 private INameService nameService;
96
97 @Autowired
98 private ITaxonNodeService nodeService;
99
100 @Autowired
101 private IDescriptionService descriptionService;
102
103 @Autowired
104 private ITermService termService;
105
106 protected static final EntityInitStrategy TAXONNODE_INIT_STRATEGY = new EntityInitStrategy(Arrays.asList(new String []{
107 "taxonNodes.classification",
108 "taxonNodes.parent",
109 "taxonNodes.parent.childNodes", //currently needed to compute sortindex //TODO improve
110 "taxonNodes.taxon.name",
111 "taxonNodes.taxon.secSource.citation",
112 "taxonNodes.statusNote",
113 "acceptedTaxon.taxonNodes.classification"
114 }));
115
116 public TaxonController(){
117 super();
118 setInitializationStrategy(Arrays.asList(new String[]{
119 "$",
120 "name.nomenclaturalSource.citation"
121 }
122 ));
123 }
124
125 @Override
126 @Autowired
127 public void setService(ITaxonService service) {
128 this.service = service;
129 }
130
131 @Override
132 public void initBinder(WebDataBinder binder) {
133 super.initBinder(binder);
134 binder.registerCustomEditor(MarkerType.class, new TermBasePropertyEditor<>(termService));
135 }
136
137 public static EnumSet<TaxonOccurrenceRelationType> bindAssociationFilter(String taxOccRelFilter) {
138 //TODO implement as binder
139 EnumSet<TaxonOccurrenceRelationType> taxonOccurrenceRelTypes = EnumSet.noneOf(TaxonOccurrenceRelationType.class);;
140 if (!StringUtils.isEmpty(taxOccRelFilter) && !"ALL".equalsIgnoreCase(taxOccRelFilter)) {
141 for (String split: taxOccRelFilter.split(",")){
142 TaxonOccurrenceRelationType relType = TaxonOccurrenceRelationType.of(split);
143 if(relType != null) {
144 taxonOccurrenceRelTypes.add(relType);
145 }
146 }
147 }
148 if (taxonOccurrenceRelTypes.isEmpty()) {
149 taxonOccurrenceRelTypes = TaxonOccurrenceRelationType.All();
150
151 }
152 return taxonOccurrenceRelTypes;
153 }
154
155 protected List<String> getTaxonDescriptionInitStrategy() {
156 return getInitializationStrategy(); // return Arrays.asList("$", "")
157 }
158
159 protected List<String> getTaxonDescriptionElementInitStrategy() {
160 return getInitializationStrategy();
161 }
162
163 @RequestMapping(params="subtree", method = RequestMethod.GET)
164 public TaxonBase<?> doGet(@PathVariable("uuid") UUID uuid,
165 @RequestParam(value = "subtree", required = true) UUID subtreeUuid, //if subtree does not exist the base class method is used, therefore required
166 HttpServletRequest request,
167 HttpServletResponse response) throws IOException {
168 if(request != null) {
169 logger.info("doGet() " + requestPathAndQuery(request));
170 }
171 //TODO do we want to allow Synonyms at all? Maybe needs initialization
172 EntityInitStrategy initStrategy = new EntityInitStrategy(getInitializationStrategy());
173 initStrategy.extend(null, getTaxonNodeInitStrategy(), false);
174 TaxonBase<?> taxonBase = getCdmBaseInstance(uuid, response, initStrategy.getPropertyPaths());
175 //TODO we should move subtree check down to service or persistence
176 TaxonNode subtree = getSubtreeOrError(subtreeUuid, nodeService, response);
177 taxonBase = checkExistsSubtreeAndAccess(taxonBase, subtree, NO_UNPUBLISHED, response);
178 return taxonBase;
179 }
180
181 /**
182 * Checks if a {@link TaxonBase taxonBase} is public and belongs to a {@link TaxonNode subtree}
183 * as accepted taxon or synonym.
184 * If not the according {@link HttpStatusMessage http messages} are send to response.
185 * <BR>
186 * Not (yet) checked is the relation to a subtree via a concept relationship.
187 * @param taxonBase
188 * @param includeUnpublished
189 * @param response
190 * @return
191 * @throws IOException
192 */
193 protected <S extends TaxonBase<?>> S checkExistsSubtreeAndAccess(S taxonBase,
194 TaxonNode subtree, boolean includeUnpublished,
195 HttpServletResponse response) throws IOException {
196 taxonBase = checkExistsAndAccess(taxonBase, NO_UNPUBLISHED, response);
197 if (subtree == null){
198 return taxonBase;
199 }else if(taxonBase != null){
200 //TODO synonyms maybe can not be initialized
201 Taxon taxon = taxonBase.isInstanceOf(Synonym.class)?
202 CdmBase.deproxy(taxonBase, Synonym.class).getAcceptedTaxon():
203 CdmBase.deproxy(taxonBase, Taxon.class);
204 //check if taxon has any node that is a descendant of subtree
205 for (TaxonNode taxonNode :taxon.getTaxonNodes()){
206 if (subtree.isAncestor(taxonNode)){
207 return taxonBase;
208 }
209 }
210 HttpStatusMessage.ACCESS_DENIED.send(response);
211 }
212 return null;
213 }
214
215
216 /**
217 * Get the accepted {@link Taxon} for a given
218 * {@link TaxonBase} entity identified by the <code>{taxon-uuid}</code>.
219 * <p>
220 * URI: <b>&#x002F;{datasource-name}&#x002F;taxon&#x002F;{taxon-uuid}&#x002F;accepted</b>
221 *
222 * @param request
223 * @param response
224 * @return a set on a list of {@link Taxon} entities which are initialized
225 * using the following initialization strategy:
226 * {@link #DEFAULT_INIT_STRATEGY}
227 * @throws IOException
228 */
229 @RequestMapping(value = "accepted", method = RequestMethod.GET)
230 public Taxon doGetAcceptedFor(
231 @PathVariable("uuid") UUID uuid,
232 @RequestParam(value = "classificationFilter", required = false) UUID classification_uuid,
233 HttpServletRequest request,
234 HttpServletResponse response)
235 throws IOException {
236 if(request != null){
237 logger.info("doGetAcceptedFor() " + requestPathAndQuery(request));
238 }
239
240 try {
241 boolean includeUnpublished = NO_UNPUBLISHED;
242 Taxon result = service.findAcceptedTaxonFor(uuid, classification_uuid, includeUnpublished, getInitializationStrategy());
243 result = checkExistsAndAccess(result, includeUnpublished, response);
244
245 return result;
246 } catch (EntityNotFoundException e){
247 HttpStatusMessage.UUID_NOT_FOUND.send(response, e.getMessage());
248 } catch (UnpublishedException e) {
249 HttpStatusMessage.ACCESS_DENIED.send(response, e.getMessage());
250 }
251 return null;
252
253 }
254
255 @RequestMapping(value = "classifications", method = RequestMethod.GET)
256 public List<Classification> doGetClassifications(
257 @PathVariable("uuid") UUID uuid,
258 HttpServletRequest request,
259 HttpServletResponse response) throws IOException {
260
261 boolean includeUnpublished = NO_UNPUBLISHED;
262
263 logger.info("doGetClassifications(): " + request.getRequestURI());
264 TaxonBase<?> taxonBase = service.load(uuid);
265 taxonBase = checkExistsAndAccess(taxonBase, includeUnpublished, response);
266
267 return service.listClassifications(taxonBase, null, null, getInitializationStrategy());
268 }
269
270 @RequestMapping(value = "taxonNodes", method = RequestMethod.GET)
271 public Collection<TaxonNodeDto> doGetTaxonNodes(
272 @PathVariable("uuid") UUID taxonUuid,
273 @RequestParam(value = "subtree", required = false) UUID subtreeUuid,
274 HttpServletRequest request,
275 HttpServletResponse response) throws IOException {
276
277 logger.info("doGetTaxonNodes" + requestPathAndQuery(request));
278 //this should be done by treeIndex as parameter, but as first implementation we get the node and then the treeinde
279 String subTreeIndex = null;
280 if (subtreeUuid != null){
281 TaxonNode subtree = getSubtreeOrError(subtreeUuid, nodeService, response);
282 subTreeIndex = subtree != null? subtree.treeIndex(): null;
283 }
284 try {
285 return nodeService.getTaxonNodeDtosFromTaxon(taxonUuid, subTreeIndex);
286 }catch(Exception e) {
287 HttpStatusMessage.UUID_REFERENCES_WRONG_TYPE.send(response);
288 return null;
289 }
290 }
291
292 protected EntityInitStrategy getTaxonNodeInitStrategy() {
293 return TAXONNODE_INIT_STRATEGY;
294 }
295
296 /**
297 * See also {@link AgentController#doGetTaxonNodeAgentRelations(UUID, UUID, Integer, Integer, HttpServletRequest, HttpServletResponse)}
298 */
299 @RequestMapping(value = "taxonNodeAgentRelations/{classification_uuid}", method = RequestMethod.GET)
300 public Pager<TaxonNodeAgentRelation> doGetTaxonNodeAgentRelations(
301 @PathVariable("uuid") UUID uuid,
302 @PathVariable("classification_uuid") UUID classificationUuid,
303 @RequestParam(value = "relType_uuid" , required = false) UUID relTypeUuid,
304 @RequestParam(value = "pageIndex", required = false) Integer pageIndex,
305 @RequestParam(value = "pageSize", required = false) Integer pageSize,
306 HttpServletRequest request,
307 HttpServletResponse response) throws IOException {
308
309 PagerParameters pagerParams = new PagerParameters(pageSize, pageIndex);
310 pagerParams.normalizeAndValidate(response);
311
312 Pager<TaxonNodeAgentRelation> pager = nodeService.pageTaxonNodeAgentRelations(uuid, classificationUuid,
313 null, null, relTypeUuid, pagerParams.getPageSize(), pagerParams.getPageIndex(), null);
314 return pager;
315 }
316
317 @RequestMapping(value = "specimensOrObservationsCount", method = RequestMethod.GET)
318 public StringResultDTO doCountSpecimensOrObservations(
319 @PathVariable("uuid") UUID uuid,
320 @RequestParam(value = "taxOccRelFilter", required = false) String taxOccRelFilter,
321 HttpServletRequest request,
322 HttpServletResponse response) {
323
324 logger.info("doListSpecimensOrObservations() - " + request.getRequestURI());
325 boolean includeUnpublished = NO_UNPUBLISHED;
326 EnumSet<TaxonOccurrenceRelationType> taxonOccurrenceRelTypes = bindAssociationFilter(taxOccRelFilter);
327
328 List<OrderHint> orderHints = new ArrayList<>();
329 orderHints.add(new OrderHint("titleCache", SortOrder.DESCENDING));
330
331 FindOccurrencesConfigurator config = new FindOccurrencesConfigurator();
332 config.setIncludeUnpublished(includeUnpublished);
333 config.setAssociatedTaxonUuid(uuid);
334 config.setTaxonOccurrenceRelTypes(taxonOccurrenceRelTypes);
335 long countSpecimen = occurrenceService.countOccurrences(config);
336 return new StringResultDTO(String.valueOf(countSpecimen));
337 }
338
339 @RequestMapping(value = "rootUnitDTOs", method = RequestMethod.GET)
340 public List<SpecimenOrObservationBaseDTO> doListRooUnitDTOs(
341 @PathVariable("uuid") UUID uuid,
342 //TODO or should it be required
343 @RequestParam(value = "taxOccRelFilter", required = false) String taxOccRelFilter,
344 HttpServletRequest request,
345 HttpServletResponse response) {
346
347 // OccurrenceListController.doListlistRootUnitDTOsByAssociatedTaxon()
348 logger.info("rootUnitDTOs() - " + request.getRequestURI());
349
350 boolean includeUnpublished = NO_UNPUBLISHED;
351
352 EnumSet<TaxonOccurrenceRelationType> taxonOccurrenceRelTypes = bindAssociationFilter(taxOccRelFilter);
353
354 List<SpecimenOrObservationBaseDTO> rootUnitDtos = occurrenceService.listRootUnitDTOsByAssociatedTaxon(
355 uuid, null, includeUnpublished,
356 taxonOccurrenceRelTypes,
357 OccurrenceController.DERIVED_UNIT_INIT_STRATEGY);
358 return rootUnitDtos;
359 }
360
361 @RequestMapping(value = "specimensOrObservations", method = RequestMethod.GET)
362 public List<SpecimenOrObservationBase<?>> doListSpecimensOrObservations(
363 @PathVariable("uuid") UUID uuid,
364 HttpServletRequest request,
365 HttpServletResponse response) throws IOException {
366 logger.info("doListSpecimensOrObservations() - " + request.getRequestURI());
367
368 boolean includeUnpublished = NO_UNPUBLISHED;
369 EnumSet<TaxonOccurrenceRelationType> taxonOccurrenceRelTypes = TaxonOccurrenceRelationType.All();
370
371 TaxonBase<?> tb = service.load(uuid);
372 List<OrderHint> orderHints = new ArrayList<>();
373 orderHints.add(new OrderHint("titleCache", SortOrder.DESCENDING));
374 if(tb instanceof Taxon){
375 List<SpecimenOrObservationBase<?>> specimensOrObservations = occurrenceService.listByAssociatedTaxon(
376 null, null, (Taxon)tb, includeUnpublished,
377 taxonOccurrenceRelTypes,
378 null, null, null, orderHints, null);
379 return specimensOrObservations;
380 } else {
381 HttpStatusMessage.UUID_REFERENCES_WRONG_TYPE.send(response);
382 return null;
383 }
384 }
385
386 @RequestMapping(value = "associatedRootUnits", method = RequestMethod.GET)
387 public Pager<SpecimenOrObservationBase> doGetAssociatedRootUnits(
388 @PathVariable("uuid") UUID uuid,
389 @RequestParam(value = "maxDepth", required = false) Integer maxDepth,
390 @RequestParam(value = "pageIndex", required = false) Integer pageIndex,
391 @RequestParam(value = "pageSize", required = false) Integer pageSize,
392 HttpServletRequest request,
393 HttpServletResponse response) throws IOException {
394 logger.info("doGetAssociatedRootUnits() - " + request.getRequestURI());
395
396 boolean includeUnpublished = NO_UNPUBLISHED;
397 EnumSet<TaxonOccurrenceRelationType> taxonOccurrenceRelTypes = TaxonOccurrenceRelationType.All();
398
399 TaxonBase<?> taxonBase = service.load(uuid);
400 taxonBase = checkExistsAndAccess(taxonBase, includeUnpublished, response);
401
402 List<OrderHint> orderHints = new ArrayList<>();
403 orderHints.add(new OrderHint("titleCache", SortOrder.ASCENDING));
404
405 if(taxonBase instanceof Taxon){
406 PagerParameters pagerParams = new PagerParameters(pageSize, pageIndex);
407 pagerParams.normalizeAndValidate(response);
408
409 return occurrenceService.pageRootUnitsByAssociatedTaxon(null, null, (Taxon) taxonBase,
410 includeUnpublished,
411 taxonOccurrenceRelTypes,
412 maxDepth, pagerParams.getPageSize(), pagerParams.getPageIndex(), orderHints, null);
413 }else{
414 // FIXME proper HTTP code response
415 return null;
416 }
417 }
418
419 @RequestMapping(value = "taggedName", method = RequestMethod.GET)
420 public ModelAndView doGetTaggedName(
421 @PathVariable("uuid") UUID uuid,
422 HttpServletRequest request) {
423 logger.info("doGetDescriptionElementsByType() - " + request.getRequestURI());
424
425 ModelAndView mv = new ModelAndView();
426
427 TaxonBase<?> tb = service.load(uuid, NO_UNPUBLISHED, Arrays.asList(new String[] {"name"}));
428 mv.addObject(nameService.getTaggedName(tb.getName().getUuid()));
429 return mv;
430 }
431
432 /**
433 * This webservice endpoint returns all taxa which are congruent or included in the taxon represented by the given taxon uuid.
434 * The result also returns the path to these taxa represented by the uuids of the taxon relationships types and doubtful information.
435 * If classificationUuids is set only taxa of classifications are returned which are included in the given classifications.
436 * Also the path to these taxa may not include taxa from other classifications.
437 */
438 @RequestMapping(value = { "includedTaxa" }, method = { RequestMethod.GET })
439 public IncludedTaxaDTO doGetIncludedTaxa(
440 @PathVariable("uuid") UUID uuid,
441 @RequestParam(value="classificationFilter", required=false) final List<String> classificationStringList,
442 @RequestParam(value="includeDoubtful", required=false) final boolean includeDoubtful,
443 @RequestParam(value="onlyCongruent", required=false) final boolean onlyCongruent,
444 HttpServletResponse response,
445 HttpServletRequest request) {
446
447
448 if(request != null){
449 logger.info("doGetIncludedTaxa()" + requestPathAndQuery(request));
450 }
451
452 List<UUID> classificationFilter = null;
453 if( classificationStringList != null ){
454 classificationFilter = new ArrayList<>();
455 for(String classString :classificationStringList){
456 classificationFilter.add(UUID.fromString(classString));
457 }
458 }
459 IncludedTaxonConfiguration configuration =
460 new IncludedTaxonConfiguration(classificationFilter, includeDoubtful, onlyCongruent);
461 IncludedTaxaDTO listIncludedTaxa = service.listIncludedTaxa(uuid, configuration);
462 return listIncludedTaxa;
463 }
464
465 // TODO ================================================================================ //
466 // move all description and descriptionElement related methods into the according
467 // Description Controllers
468
469 /**
470 * Get the list of {@link TaxonDescription}s of the
471 * {@link Taxon} instance identified by the <code>{taxon-uuid}</code>.
472 * <p>
473 * URI: <b>&#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;{taxon-uuid}&#x002F;descriptions</b>
474 *
475 * @param request
476 * @param response
477 * @return a List of {@link TaxonDescription} entities which are initialized
478 * using the following initialization strategy:
479 * {@link #TAXONDESCRIPTION_INIT_STRATEGY}
480 * @throws IOException
481 */
482 @RequestMapping(
483 value = {"descriptions"},
484 method = RequestMethod.GET)
485 public Pager<TaxonDescription> doGetDescriptions(
486 @PathVariable("uuid") UUID uuid,
487 @RequestParam(value = "markerTypes", required = false) List<MarkerType> markerTypes,
488 @RequestParam(value = "descriptionTypes", required = false) List<DescriptionType> descriptionTypes,
489 HttpServletRequest request,
490 HttpServletResponse response)throws IOException {
491
492 if(request != null){
493 logger.info("doGetDescriptions()" + requestPathAndQuery(request));
494 }
495
496 Taxon taxon = getCdmBaseInstance(Taxon.class, uuid, response, (List<String>)null);
497 taxon = checkExistsAndAccess(taxon, NO_UNPUBLISHED, response);
498
499 Set<MarkerType> markerTypesSet = new HashSet<>();
500 if (markerTypes != null) {
501 markerTypesSet.addAll(markerTypes);
502 }
503 Set<DescriptionType> descriptionTypesSet = new HashSet<>();
504 if (descriptionTypes != null) {
505 descriptionTypesSet.addAll(descriptionTypes);
506 }
507
508 List<String> taxonDescriptionInitStrategy = getTaxonDescriptionInitStrategy();
509 Pager<TaxonDescription> p = descriptionService.pageTaxonDescriptions(taxon, null, null, markerTypesSet, descriptionTypesSet, null, null, taxonDescriptionInitStrategy);
510
511 return p;
512 }
513
514 @RequestMapping(value = "descriptions/elementsByType/{classSimpleName}", method = RequestMethod.GET)
515 public ModelAndView doGetDescriptionElementsByType(
516 @PathVariable("uuid") UUID uuid,
517 @PathVariable("classSimpleName") String classSimpleName,
518 @RequestParam(value = "markerTypes", required = false) List<MarkerType> markerTypes,
519 @RequestParam(value = "descriptionTypes", required = false) List<DescriptionType> descriptionTypes,
520 @RequestParam(value = "count", required = false, defaultValue = "false") Boolean doCount,
521 HttpServletRequest request,
522 HttpServletResponse response) throws IOException {
523
524 logger.info("doGetDescriptionElementsByType() - " + requestPathAndQuery(request));
525
526 boolean includeUnpublished = NO_UNPUBLISHED;
527
528 ModelAndView mv = new ModelAndView();
529
530 List<DescriptionElementBase> allElements = new ArrayList<>();
531 List<DescriptionElementBase> elements;
532 int count = 0;
533
534 List<String> initStrategy = doCount ? null : getTaxonDescriptionElementInitStrategy();
535
536 Taxon taxon = getCdmBaseInstance(Taxon.class, uuid, response, (List<String>)null);
537
538 taxon = checkExistsAndAccess(taxon, includeUnpublished, response);
539
540
541 Set<MarkerType> markerTypesSet = new HashSet<>();
542 if (markerTypes != null) {
543 markerTypesSet.addAll(markerTypes);
544 }
545 Set<DescriptionType> descriptionTypesSet = new HashSet<>();
546 if (descriptionTypes != null) {
547 descriptionTypesSet.addAll(descriptionTypes);
548 }
549
550 List<TaxonDescription> taxonDescriptions = descriptionService.listTaxonDescriptions(
551 taxon, null, null, markerTypesSet, descriptionTypesSet, null, null, null);
552 try {
553 Class type;
554 type = Class.forName("eu.etaxonomy.cdm.model.description."
555 + classSimpleName);
556 if (taxonDescriptions != null) {
557 for (TaxonDescription description : taxonDescriptions) {
558 Class<? extends DescriptionBase<?>> descriptionType = null;
559 elements = descriptionService.listDescriptionElements(
560 description, descriptionType, null, type, includeUnpublished, null, 0, initStrategy);
561 allElements.addAll(elements);
562 count += elements.size();
563 }
564
565 }
566 } catch (ClassNotFoundException e) {
567 HttpStatusMessage.create(e.getLocalizedMessage(), 400).send(response);
568 }
569 if(doCount){
570 mv.addObject(count);
571 } else {
572 mv.addObject(allElements);
573 }
574 return mv;
575 }
576
577 @RequestMapping(value = "taxonRelationshipsDTO", method = RequestMethod.GET)
578 public TaxonRelationshipsDTO doGetTaxonRelationshipsDTO(
579 @PathVariable("uuid") UUID taxonUuid,
580 @RequestParam(value = "directTypes", required = false) UuidList directTypeUuids,
581 @RequestParam(value = "inversTypes", required = false) UuidList inversTypeUuids,
582 @RequestParam(value = "direction", required = false) Direction direction,
583 @RequestParam(value="groupMisapplications", required=false, defaultValue="false") final boolean groupMisapplications,
584 HttpServletRequest request,
585 HttpServletResponse response) throws IOException {
586
587 boolean includeUnpublished = NO_UNPUBLISHED;
588
589 logger.info("doGetTaxonRelationshipDTOs(): " + request.getRequestURI());
590 TaxonBase<?> taxonBase = service.load(taxonUuid);
591 checkExistsAccessType(taxonBase, includeUnpublished, Taxon.class, response);
592
593 Set<TaxonRelationshipType> directTypes = getTermsByUuidSet(TaxonRelationshipType.class, directTypeUuids);
594 Set<TaxonRelationshipType> inversTypes = getTermsByUuidSet(TaxonRelationshipType.class, inversTypeUuids);
595
596 // Set<TaxonRelationshipType> inversTypes = null;
597 // if (directTypeUuids != null && !directTypeUuids.isEmpty()){
598 // types = new HashSet<>();
599 // List<TaxonRelationshipType> typeList = termService.find(TaxonRelationshipType.class, new HashSet<>(directTypeUuids));
600 // types.addAll(typeList);
601 // //TODO should we handle missing uuids as error response
602 //// HttpStatusMessage.UUID_REFERENCES_WRONG_TYPE.send(response);
603 // }
604
605
606
607 // boolean deduplicateMisapplications = true;
608 Integer pageSize = null;
609 Integer pageNumber = null;
610 return service.listTaxonRelationships(taxonUuid, directTypes, inversTypes, direction, groupMisapplications,
611 includeUnpublished, pageSize, pageNumber);
612 }
613
614 /**
615 * @param directTypeUuids
616 * @return
617 */
618 protected <T extends DefinedTermBase<T>> Set<T> getTermsByUuidSet(Class<T> clazz, UuidList directTypeUuids) {
619 Set<T> directTypes = null;
620
621 if (directTypeUuids != null && !directTypeUuids.isEmpty()){
622 directTypes = new HashSet<>();
623 List<T> typeList = termService.find(clazz, new HashSet<>(directTypeUuids));
624 directTypes.addAll(typeList);
625 //TODO should we handle missing uuids as error response
626 // HttpStatusMessage.UUID_REFERENCES_WRONG_TYPE.send(response);
627 }
628 return directTypes;
629 }
630
631 // TODO ================================================================================ //
632
633 }