discussion
[cdmlib.git] / cdmlib-remote / src / main / java / eu / etaxonomy / cdm / remote / controller / TaxonPortalController.java
1 // $Id: TaxonController.java 5473 2009-03-25 13:42:07Z a.kohlbecker $
2 /**
3 * Copyright (C) 2007 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
6 *
7 * The contents of this file are subject to the Mozilla Public License Version 1.1
8 * See LICENSE.TXT at the top of this package for the full license terms.
9 */
10
11 package eu.etaxonomy.cdm.remote.controller;
12
13 import static java.net.HttpURLConnection.HTTP_BAD_REQUEST;
14
15 import java.io.IOException;
16 import java.util.ArrayList;
17 import java.util.Arrays;
18 import java.util.HashSet;
19 import java.util.Hashtable;
20 import java.util.Iterator;
21 import java.util.List;
22 import java.util.Map;
23 import java.util.Set;
24 import java.util.UUID;
25
26 import javax.servlet.http.HttpServletRequest;
27 import javax.servlet.http.HttpServletResponse;
28
29 import org.apache.commons.lang.ObjectUtils;
30 import org.apache.http.HttpRequest;
31 import org.apache.log4j.Logger;
32 import org.springframework.beans.factory.annotation.Autowired;
33 import org.springframework.stereotype.Controller;
34 import org.springframework.web.bind.WebDataBinder;
35 import org.springframework.web.bind.annotation.InitBinder;
36 import org.springframework.web.bind.annotation.PathVariable;
37 import org.springframework.web.bind.annotation.RequestMapping;
38 import org.springframework.web.bind.annotation.RequestMethod;
39 import org.springframework.web.bind.annotation.RequestParam;
40 import org.springframework.web.servlet.ModelAndView;
41
42
43 import eu.etaxonomy.cdm.api.service.IDescriptionService;
44 import eu.etaxonomy.cdm.api.service.IFeatureTreeService;
45 import eu.etaxonomy.cdm.api.service.IMarkerService;
46 import eu.etaxonomy.cdm.api.service.INameService;
47 import eu.etaxonomy.cdm.api.service.IOccurrenceService;
48 import eu.etaxonomy.cdm.api.service.IService;
49 import eu.etaxonomy.cdm.api.service.ITaxonService;
50 import eu.etaxonomy.cdm.api.service.IClassificationService;
51 import eu.etaxonomy.cdm.api.service.ITermService;
52 import eu.etaxonomy.cdm.api.service.config.ITaxonServiceConfigurator;
53 import eu.etaxonomy.cdm.api.service.config.TaxonServiceConfiguratorImpl;
54 import eu.etaxonomy.cdm.api.service.pager.Pager;
55 import eu.etaxonomy.cdm.database.UpdatableRoutingDataSource;
56 import eu.etaxonomy.cdm.model.common.DefinedTermBase;
57 import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
58 import eu.etaxonomy.cdm.model.common.Marker;
59 import eu.etaxonomy.cdm.model.common.MarkerType;
60 import eu.etaxonomy.cdm.model.common.RelationshipBase.Direction;
61 import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
62 import eu.etaxonomy.cdm.model.description.TaxonDescription;
63 import eu.etaxonomy.cdm.model.location.NamedArea;
64 import eu.etaxonomy.cdm.model.location.NamedAreaLevel;
65 import eu.etaxonomy.cdm.model.media.Media;
66 import eu.etaxonomy.cdm.model.media.MediaRepresentationPart;
67 import eu.etaxonomy.cdm.model.media.MediaUtils;
68 import eu.etaxonomy.cdm.model.name.NameRelationship;
69 import eu.etaxonomy.cdm.model.name.TypeDesignationBase;
70 import eu.etaxonomy.cdm.model.taxon.Synonym;
71 import eu.etaxonomy.cdm.model.taxon.Taxon;
72 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
73 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
74 import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
75 import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
76 import eu.etaxonomy.cdm.model.taxon.Classification;
77 import eu.etaxonomy.cdm.persistence.query.MatchMode;
78 import eu.etaxonomy.cdm.remote.controller.util.PagerParameters;
79 import eu.etaxonomy.cdm.remote.editor.CdmTypePropertyEditor;
80 import eu.etaxonomy.cdm.remote.editor.MatchModePropertyEditor;
81 import eu.etaxonomy.cdm.remote.editor.NamedAreaPropertyEditor;
82 import eu.etaxonomy.cdm.remote.editor.UUIDListPropertyEditor;
83 import eu.etaxonomy.cdm.remote.editor.UuidList;
84
85 /**
86 * The TaxonPortalController class is a Spring MVC Controller.
87 * <p>
88 * The syntax of the mapped service URIs contains the the {datasource-name} path element.
89 * The available {datasource-name}s are defined in a configuration file which
90 * is loaded by the {@link UpdatableRoutingDataSource}. If the
91 * UpdatableRoutingDataSource is not being used in the actual application
92 * context any arbitrary {datasource-name} may be used.
93 * <p>
94 * Methods mapped at type level, inherited from super classes ({@link BaseController}):
95 * <blockquote>
96 * URI: <b>&#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;{taxon-uuid}</b>
97 *
98 * Get the {@link TaxonBase} instance identified by the <code>{taxon-uuid}</code>.
99 * The returned Taxon is initialized by
100 * the following strategy {@link #TAXON_INIT_STRATEGY}
101 * </blockquote>
102 *
103 * @author a.kohlbecker
104 * @date 20.07.2009
105 *
106 */
107 @Controller
108 @RequestMapping(value = {"/portal/taxon/{uuid}"})
109 public class TaxonPortalController extends BaseController<TaxonBase, ITaxonService>
110 {
111 public static final Logger logger = Logger.getLogger(TaxonPortalController.class);
112
113 @Autowired
114 private INameService nameService;
115
116 @Autowired
117 private IDescriptionService descriptionService;
118
119 @Autowired
120 private IOccurrenceService occurrenceService;
121
122 @Autowired
123 private IClassificationService classificationService;
124
125 @Autowired
126 private ITaxonService taxonService;
127
128 @Autowired
129 private ITermService markerTypeService;
130
131 @Autowired
132 private IMarkerService markerService;
133 //private IService<MarkerType> markerTypeService;
134
135 @Autowired
136 private IFeatureTreeService featureTreeService;
137
138 private static final List<String> TAXON_INIT_STRATEGY = Arrays.asList(new String []{
139 "*",
140 // taxon relations
141 "relationsToThisName.fromTaxon.name",
142 // the name
143 "name.$",
144 "name.rank.representations",
145 "name.status.type.representations",
146
147 // taxon descriptions
148 "descriptions.elements.area.$",
149 "descriptions.elements.multilanguageText",
150 "descriptions.elements.media.representations.parts",
151 "descriptions.elements.media.title",
152
153 });
154
155 private static final List<String> TAXON_WITH_NODES_INIT_STRATEGY = Arrays.asList(new String []{
156 "taxonNodes.$",
157 "taxonNodes.classification.$",
158 "taxonNodes.childNodes.$"
159 });
160
161 private static final List<String> SIMPLE_TAXON_INIT_STRATEGY = Arrays.asList(new String []{
162 "*",
163 // taxon relations
164 "relationsToThisName.fromTaxon.name",
165 // the name
166 "name.$",
167 "name.rank.representations",
168 "name.status.type.representations",
169 "name.nomenclaturalReference"
170 });
171
172 private static final List<String> SYNONYMY_INIT_STRATEGY = Arrays.asList(new String []{
173 // initialize homotypical and heterotypical groups; needs synonyms
174 "synonymRelations.$",
175 "synonymRelations.synonym.$",
176 "synonymRelations.synonym.name.status.type.representation",
177 "synonymRelations.synonym.name.nomenclaturalReference.inReference",
178 "synonymRelations.synonym.name.homotypicalGroup.typifiedNames.$",
179 "synonymRelations.synonym.name.homotypicalGroup.typifiedNames.taxonBases.$",
180 "synonymRelations.synonym.name.combinationAuthorTeam.$",
181
182 "name.typeDesignations",
183
184 "name.homotypicalGroup.$",
185 "name.homotypicalGroup.typifiedNames.$",
186 "name.homotypicalGroup.typifiedNames.nomenclaturalReference.authorTeam",
187
188 "name.homotypicalGroup.typifiedNames.taxonBases.$"
189 });
190
191 private static final List<String> SYNONYMY_WITH_NODES_INIT_STRATEGY = Arrays.asList(new String []{
192 // initialize homotypical and heterotypical groups; needs synonyms
193 "synonymRelations.$",
194 "synonymRelations.synonym.$",
195 "synonymRelations.synonym.name.status.type.representation",
196 "synonymRelations.synonym.name.nomenclaturalReference.inReference",
197 "synonymRelations.synonym.name.homotypicalGroup.typifiedNames.$",
198 "synonymRelations.synonym.name.homotypicalGroup.typifiedNames.taxonBases.$",
199 "synonymRelations.synonym.name.combinationAuthorTeam.$",
200
201 "name.homotypicalGroup.$",
202 "name.homotypicalGroup.typifiedNames.$",
203 "name.homotypicalGroup.typifiedNames.nomenclaturalReference.authorTeam",
204
205 "name.homotypicalGroup.typifiedNames.taxonBases.$",
206
207 "taxonNodes.$",
208 "taxonNodes.classification.$",
209 "taxonNodes.childNodes.$"
210 });
211 private static final List<String> SIMPLE_TAXON_WITH_NODES_INIT_STRATEGY = Arrays.asList(new String []{
212 "*",
213 // taxon relations
214 "relationsToThisName.fromTaxon.name",
215 // the name
216 "name.$",
217 "name.rank.representations",
218 "name.status.type.representations",
219 "name.nomenclaturalReference",
220
221 "taxonNodes.$",
222 "taxonNodes.classification.$",
223 "taxonNodes.childNodes.$"
224 });
225
226
227 private static final List<String> TAXONRELATIONSHIP_INIT_STRATEGY = Arrays.asList(new String []{
228 "$",
229 "type.inverseRepresentations",
230 "fromTaxon.sec",
231 "fromTaxon.name",
232 "toTaxon.sec",
233 "toTaxon.name"
234 });
235
236 private static final List<String> NAMERELATIONSHIP_INIT_STRATEGY = Arrays.asList(new String []{
237 "$",
238 "type.inverseRepresentations",
239 "fromName",
240 "toName.$",
241 });
242
243
244 protected static final List<String> TAXONDESCRIPTION_INIT_STRATEGY = Arrays.asList(new String []{
245 "$",
246 "elements.$",
247 "elements.sources.citation.authorTeam",
248 "elements.sources.nameUsedInSource.originalNameString",
249 "elements.multilanguageText",
250 "elements.media.representations.parts",
251 "elements.media.title",
252 });
253
254 protected static final List<String> TAXONUSEDESCRIPTION_INIT_STRATEGY = Arrays.asList(new String []{
255 "$",
256 "sources.$",
257 "elements.$",
258 "elements.states.$",
259 "elements.sources.citation.authorTeam",
260 "elements.sources.nameUsedInSource.originalNameString",
261 /*//"elements.multilanguageText",
262 "elements.media.representations.parts",
263 "elements.media.title",*/
264 });
265
266 protected static final List<String> DESCRIPTION_ELEMENT_INIT_STRATEGY = Arrays.asList(new String []{
267 "$",
268 "sources.citation.authorTeam",
269 "sources.nameUsedInSource.originalNameString",
270 "multilanguageText",
271 "media.representations.parts",
272 "media.title",
273 });
274
275
276 // private static final List<String> NAMEDESCRIPTION_INIT_STRATEGY = Arrays.asList(new String []{
277 // "uuid",
278 // "feature",
279 // "elements.$",
280 // "elements.multilanguageText",
281 // "elements.media.representations.parts",
282 // "elements.media.title",
283 // });
284
285 protected static final List<String> TAXONDESCRIPTION_MEDIA_INIT_STRATEGY = Arrays.asList(new String []{
286 "elements.media.representations.parts",
287 "elements.media.title"
288
289 });
290
291 private static final List<String> TYPEDESIGNATION_INIT_STRATEGY = Arrays.asList(new String []{
292 //"$",
293 "typeSpecimen.$",
294 "citation.authorTeam.$",
295 "typeName",
296 });
297
298 protected static final List<String> TAXONNODE_WITHTAXON_INIT_STRATEGY = Arrays.asList(new String []{
299 "childNodes.taxon",
300 });
301
302 protected static final List<String> TAXONNODE_INIT_STRATEGY = Arrays.asList(new String []{
303 "taxonNodes.classification"
304 });
305
306
307
308 private static final String featureTreeUuidPattern = "^/taxon(?:(?:/)([^/?#&\\.]+))+.*";
309
310 public TaxonPortalController(){
311 super();
312 setInitializationStrategy(TAXON_INIT_STRATEGY);
313 }
314
315 /* (non-Javadoc)
316 * @see eu.etaxonomy.cdm.remote.controller.GenericController#setService(eu.etaxonomy.cdm.api.service.IService)
317 */
318 @Autowired
319 @Override
320 public void setService(ITaxonService service) {
321 this.service = service;
322 }
323
324 @InitBinder
325 @Override
326 public void initBinder(WebDataBinder binder) {
327 super.initBinder(binder);
328 binder.registerCustomEditor(NamedArea.class, new NamedAreaPropertyEditor());
329 binder.registerCustomEditor(MatchMode.class, new MatchModePropertyEditor());
330 binder.registerCustomEditor(Class.class, new CdmTypePropertyEditor());
331 binder.registerCustomEditor(UuidList.class, new UUIDListPropertyEditor());
332
333 }
334
335
336 /* (non-Javadoc)
337 * @see eu.etaxonomy.cdm.remote.controller.BaseController#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
338
339 @Override
340 @RequestMapping(method = RequestMethod.GET)
341 public TaxonBase doGet(HttpServletRequest request, HttpServletResponse response)throws IOException {
342 logger.info("doGet()");
343 TaxonBase tb = getCdmBase(request, response, TAXON_INIT_STRATEGY, TaxonBase.class);
344 return tb;
345 }
346 */
347 /**
348 * Find Taxa, Synonyms, Common Names by name, either globally or in a specific geographic area.
349 * <p>
350 * URI: <b>&#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;find</b>
351 *
352 * @param query
353 * the string to query for. Since the wildcard character '*'
354 * internally always is appended to the query string, a search
355 * always compares the query string with the beginning of a name.
356 * - <i>required parameter</i>
357 * @param treeUuid
358 * the {@link UUID} of a {@link Classification} to which the
359 * search is to be restricted. - <i>optional parameter</i>
360 * @param areas
361 * restrict the search to a set of geographic {@link NamedArea}s.
362 * The parameter currently takes a list of TDWG area labels.
363 * - <i>optional parameter</i>
364 * @param pageNumber
365 * the number of the page to be returned, the first page has the
366 * pageNumber = 1 - <i>optional parameter</i>
367 * @param pageSize
368 * the maximum number of entities returned per page (can be -1
369 * to return all entities in a single page) - <i>optional parameter</i>
370 * @param doTaxa
371 * weather to search for instances of {@link Taxon} - <i>optional parameter</i>
372 * @param doSynonyms
373 * weather to search for instances of {@link Synonym} - <i>optional parameter</i>
374 * @param doTaxaByCommonNames
375 * for instances of {@link Taxon} by a common name used - <i>optional parameter</i>
376 * @param matchMode
377 * valid values are "EXACT", "BEGINNING", "ANYWHERE", "END" (case sensitive !!!)
378 * @return a Pager on a list of {@link IdentifiableEntity}s initialized by
379 * the following strategy {@link #SIMPLE_TAXON_INIT_STRATEGY}
380 * @throws IOException
381 */
382 @RequestMapping(method = RequestMethod.GET,
383 value = {"/portal/taxon/find"}) //TODO map to path /*/portal/taxon/
384 public Pager<IdentifiableEntity> doFind(
385 @RequestParam(value = "query", required = false) String query,
386 @RequestParam(value = "tree", required = false) UUID treeUuid,
387 @RequestParam(value = "area", required = false) Set<NamedArea> areas,
388 @RequestParam(value = "pageNumber", required = false) Integer pageNumber,
389 @RequestParam(value = "pageSize", required = false) Integer pageSize,
390 @RequestParam(value = "doTaxa", required = false) Boolean doTaxa,
391 @RequestParam(value = "doSynonyms", required = false) Boolean doSynonyms,
392 @RequestParam(value = "doMisappliedNames", required = false) Boolean doMisappliedNames,
393 @RequestParam(value = "doTaxaByCommonNames", required = false) Boolean doTaxaByCommonNames,
394 @RequestParam(value = "matchMode", required = false) MatchMode matchMode,
395 HttpServletRequest request,
396 HttpServletResponse response
397 )
398 throws IOException {
399
400 logger.info("doFind : " + request.getRequestURI() + "?" + request.getQueryString() );
401
402 PagerParameters pagerParams = new PagerParameters(pageSize, pageNumber);
403 pagerParams.normalizeAndValidate(response);
404
405 ITaxonServiceConfigurator config = new TaxonServiceConfiguratorImpl();
406 config.setPageNumber(pagerParams.getPageIndex());
407 config.setPageSize(pagerParams.getPageSize());
408 config.setTitleSearchString(query);
409 config.setDoTaxa(doTaxa!= null ? doTaxa : Boolean.FALSE );
410 config.setDoSynonyms(doSynonyms != null ? doSynonyms : Boolean.FALSE );
411 config.setDoMisappliedNames(doMisappliedNames != null ? doMisappliedNames : Boolean.FALSE);
412 config.setDoTaxaByCommonNames(doTaxaByCommonNames != null ? doTaxaByCommonNames : Boolean.FALSE );
413 config.setMatchMode(matchMode != null ? matchMode : MatchMode.BEGINNING);
414 config.setTaxonPropertyPath(SIMPLE_TAXON_INIT_STRATEGY);
415 config.setNamedAreas(areas);
416 if(treeUuid != null){
417 Classification classification = classificationService.find(treeUuid);
418 config.setClassification(classification);
419 }
420
421 return (Pager<IdentifiableEntity>) service.findTaxaAndNames(config);
422 }
423
424 /**
425 * Get the synonymy for a taxon identified by the <code>{taxon-uuid}</code>.
426 * The synonymy consists
427 * of two parts: The group of homotypic synonyms of the taxon and the
428 * heterotypic synonymy groups of the taxon. The synonymy is ordered
429 * historically by the type designations and by the publication date of the
430 * nomenclatural reference
431 * <p>
432 * URI:
433 * <b>&#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;{taxon-uuid}&#x002F;synonymy</b>
434 *
435 *
436 * @param request
437 * @param response
438 * @return a Map with to entries which are mapped by the following keys:
439 * "homotypicSynonymsByHomotypicGroup", "heterotypicSynonymyGroups",
440 * containing lists of {@link Synonym}s which are initialized using the
441 * following initialization strategy: {@link #SYNONYMY_INIT_STRATEGY}
442 *
443 * @throws IOException
444 */
445 @RequestMapping(
446 value = {"synonymy"},
447 method = RequestMethod.GET)
448 public ModelAndView doGetSynonymy(@PathVariable("uuid") UUID uuid,
449 HttpServletRequest request, HttpServletResponse response)throws IOException {
450
451 if(request != null){
452 logger.info("doGetSynonymy() " + request.getServletPath());
453 }
454 ModelAndView mv = new ModelAndView();
455 Taxon taxon = getCdmBaseInstance(Taxon.class, uuid, response, (List<String>)null);
456 Map<String, List<?>> synonymy = new Hashtable<String, List<?>>();
457 synonymy.put("homotypicSynonymsByHomotypicGroup", service.getHomotypicSynonymsByHomotypicGroup(taxon, SYNONYMY_INIT_STRATEGY));
458 synonymy.put("heterotypicSynonymyGroups", service.getHeterotypicSynonymyGroups(taxon, SYNONYMY_INIT_STRATEGY));
459 mv.addObject(synonymy);
460 return mv;
461 }
462
463 /**
464 * Get the set of accepted {@link Taxon} entities for a given
465 * {@link TaxonBase} entity identified by the <code>{taxon-uuid}</code>.
466 * <p>
467 * URI: <b>&#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;{taxon-uuid}&#x002F;accepted</b>
468 *
469 * @param request
470 * @param response
471 * @return a Set of {@link Taxon} entities which are initialized
472 * using the following initialization strategy:
473 * {@link #SYNONYMY_INIT_STRATEGY}
474 * @throws IOException
475 */
476 @RequestMapping(value = "accepted/{classification_uuid}", method = RequestMethod.GET)
477 public Set<TaxonBase> getAccepted(
478 @PathVariable("uuid") UUID uuid,
479 @PathVariable("classification_uuid") UUID classification_uuid,
480 HttpServletRequest request,
481 HttpServletResponse response)
482 throws IOException {
483
484 if(request != null){
485 logger.info("getAccepted() " + request.getServletPath());
486 }
487
488 TaxonBase tb = service.load(uuid, SYNONYMY_WITH_NODES_INIT_STRATEGY);
489 if(tb == null){
490 response.sendError(HttpServletResponse.SC_NOT_FOUND, "A taxon with the uuid " + uuid + " does not exist");
491 return null;
492 }
493
494 HashSet<TaxonBase> resultset = new HashSet<TaxonBase>();
495
496 if (tb instanceof Taxon){
497 Taxon taxon = (Taxon) tb;
498 Set<TaxonNode> nodes = taxon.getTaxonNodes();
499 for (TaxonNode taxonNode : nodes) {
500 if (taxonNode.getClassification().compareTo(classification_uuid) == 0){
501 resultset.add((Taxon) tb);
502 }
503 }
504 if (resultset.size() > 1){
505 //error!! A taxon is not allow to have more taxonnodes for a given classification
506 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
507 "A taxon with the uuid " + uuid + " has more than one taxon node for the given classification" + classification_uuid);
508 }
509 }else{
510 Synonym syn = (Synonym) tb;
511 for(TaxonBase accepted : syn.getAcceptedTaxa()){
512 tb = service.load(accepted.getUuid(), SIMPLE_TAXON_WITH_NODES_INIT_STRATEGY);
513 if (tb instanceof Taxon){
514 Taxon taxon = (Taxon) tb;
515 Set<TaxonNode> nodes = taxon.getTaxonNodes();
516 for (TaxonNode taxonNode : nodes) {
517 if (taxonNode.getClassification().compareTo(classification_uuid) == 0){
518 resultset.add((Taxon) tb);
519 }
520 }
521 if (resultset.size() > 1){
522 //error!! A taxon is not allow to have more taxonnodes for a given classification
523 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
524 "A taxon with the uuid " + uuid + " has more than one taxon node for the given classification" + classification_uuid);
525 }
526 }else{
527 //ERROR!! perhaps missapplied name????
528 //syn.getRelationType((Taxon)accepted);
529 }
530 }
531 }
532 /**
533 * OLD CODE!!
534 if(tb instanceof Taxon){
535 //the taxon already is accepted
536 //FIXME take the current view into account once views are implemented!!!
537 resultset.add((Taxon)tb);
538 } else {
539 Synonym syn = (Synonym)tb;
540 for(TaxonBase accepted : syn.getAcceptedTaxa()){
541 accepted = service.load(accepted.getUuid(), SIMPLE_TAXON_INIT_STRATEGY);
542 resultset.add(accepted);
543 }
544 }
545 */
546 return resultset;
547 }
548
549 /**
550 * Get the list of {@link TaxonRelationship}s for the given
551 * {@link TaxonBase} instance identified by the <code>{taxon-uuid}</code>.
552 * <p>
553 * URI: <b>&#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;{taxon-uuid}&#x002F;taxonRelationships</b>
554 *
555 * @param request
556 * @param response
557 * @return a List of {@link TaxonRelationship} entities which are initialized
558 * using the following initialization strategy:
559 * {@link #TAXONRELATIONSHIP_INIT_STRATEGY}
560 * @throws IOException
561 */
562 @RequestMapping(
563 value = {"taxonRelationships"},
564 method = RequestMethod.GET)
565 public List<TaxonRelationship> doGetTaxonRelations(@PathVariable("uuid") UUID uuid,
566 HttpServletRequest request, HttpServletResponse response)throws IOException {
567
568 logger.info("doGetTaxonRelations()" + request.getServletPath());
569 Taxon taxon = getCdmBaseInstance(Taxon.class, uuid, response, (List<String>)null);
570 List<TaxonRelationship> toRelationships = service.listToTaxonRelationships(taxon, null, null, null, null, TAXONRELATIONSHIP_INIT_STRATEGY);
571 List<TaxonRelationship> fromRelationships = service.listFromTaxonRelationships(taxon, null, null, null, null, TAXONRELATIONSHIP_INIT_STRATEGY);
572
573 List<TaxonRelationship> allRelationships = new ArrayList<TaxonRelationship>(toRelationships.size() + fromRelationships.size());
574 allRelationships.addAll(toRelationships);
575 allRelationships.addAll(fromRelationships);
576
577 return allRelationships;
578 }
579
580 /**
581 * Get the list of {@link NameRelationship}s of the Name associated with the
582 * {@link TaxonBase} instance identified by the <code>{taxon-uuid}</code>.
583 * <p>
584 * URI: <b>&#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;{taxon-uuid}&#x002F;nameRelationships</b>
585 *
586 * @param request
587 * @param response
588 * @return a List of {@link NameRelationship} entities which are initialized
589 * using the following initialization strategy:
590 * {@link #NAMERELATIONSHIP_INIT_STRATEGY}
591 * @throws IOException
592 */
593 @RequestMapping(
594 value = {"toNameRelationships"},
595 method = RequestMethod.GET)
596 public List<NameRelationship> doGetToNameRelations(@PathVariable("uuid") UUID uuid,
597 HttpServletRequest request, HttpServletResponse response)throws IOException {
598 logger.info("doGetNameRelations()" + request.getServletPath());
599 TaxonBase taxonBase = getCdmBaseInstance(TaxonBase.class, uuid, response, (List<String>)null);
600 List<NameRelationship> list = nameService.listNameRelationships(taxonBase.getName(), Direction.relatedTo, null, null, 0, null, NAMERELATIONSHIP_INIT_STRATEGY);
601 //List<NameRelationship> list = nameService.listToNameRelationships(taxonBase.getName(), null, null, null, null, NAMERELATIONSHIP_INIT_STRATEGY);
602 return list;
603 }
604
605 /**
606 * Get the list of {@link NameRelationship}s of the Name associated with the
607 * {@link TaxonBase} instance identified by the <code>{taxon-uuid}</code>.
608 * <p>
609 * URI: <b>&#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;{taxon-uuid}&#x002F;nameRelationships</b>
610 *
611 * @param request
612 * @param response
613 * @return a List of {@link NameRelationship} entities which are initialized
614 * using the following initialization strategy:
615 * {@link #NAMERELATIONSHIP_INIT_STRATEGY}
616 * @throws IOException
617 */
618 @RequestMapping(
619 value = {"fromNameRelationships"},
620 method = RequestMethod.GET)
621 public List<NameRelationship> doGetFromNameRelations(@PathVariable("uuid") UUID uuid,
622 HttpServletRequest request, HttpServletResponse response)throws IOException {
623 logger.info("doGetNameFromNameRelations()" + request.getServletPath());
624
625 TaxonBase taxonbase = getCdmBaseInstance(TaxonBase.class, uuid, response, SIMPLE_TAXON_INIT_STRATEGY);
626 List<NameRelationship> list = nameService.listNameRelationships(taxonbase.getName(), Direction.relatedFrom, null, null, 0, null, NAMERELATIONSHIP_INIT_STRATEGY);
627 //List<NameRelationship> list = nameService.listFromNameRelationships(taxonbase.getName(), null, null, null, null, NAMERELATIONSHIP_INIT_STRATEGY);
628 return list;
629 }
630
631 /**
632 * Get the list of {@link TypeDesignationBase}s of the
633 * {@link TaxonBase} instance identified by the <code>{taxon-uuid}</code>.
634 * <p>
635 * URI: <b>&#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;{taxon-uuid}&#x002F;nameTypeDesignations</b>
636 *
637 * @param request
638 * @param response
639 * @return a List of {@link TypeDesignationBase} entities which are initialized
640 * using the following initialization strategy:
641 * {@link #TYPEDESIGNATION_INIT_STRATEGY}
642 * @throws IOException
643 * @Deprecated use &#x002F;name&#x002F;{uuid}&#x002F;typeDesignations & &#x002F;derivedunitfacade&#x002F;{uuid} instead
644 * also see http://dev.e-taxonomy.eu/trac/ticket/2280
645 */
646 @Deprecated
647 @RequestMapping(
648 value = {"nameTypeDesignations"},
649 method = RequestMethod.GET)
650 public List<TypeDesignationBase> doGetNameTypeDesignations(@PathVariable("uuid") UUID uuid,
651 HttpServletRequest request, HttpServletResponse response)throws IOException {
652 logger.info("doGetNameTypeDesignations()" + request.getServletPath());
653 Taxon taxon = getCdmBaseInstance(Taxon.class, uuid, response, SIMPLE_TAXON_INIT_STRATEGY);
654 Pager<TypeDesignationBase> p = nameService.getTypeDesignations(taxon.getName(), null, null, null, TYPEDESIGNATION_INIT_STRATEGY);
655 return p.getRecords();
656 }
657
658 @RequestMapping(value = "taxonNodes", method = RequestMethod.GET)
659 public Set<TaxonNode> doGetTaxonNodes(
660 @PathVariable("uuid") UUID uuid,
661 HttpServletRequest request,
662 HttpServletResponse response) throws IOException {
663 TaxonBase tb = service.load(uuid, TAXONNODE_INIT_STRATEGY);
664 if(tb instanceof Taxon){
665 return ((Taxon)tb).getTaxonNodes();
666 } else {
667 HttpStatusMessage.UUID_REFERENCES_WRONG_TYPE.send(response);
668 return null;
669 }
670 }
671
672 /**
673 * Get the list of {@link TaxonDescription}s of the
674 * {@link Taxon} instance identified by the <code>{taxon-uuid}</code>.
675 * <p>
676 * URI: <b>&#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;{taxon-uuid}&#x002F;descriptions</b>
677 *
678 * @param request
679 * @param response
680 * @return a List of {@link TaxonDescription} entities which are initialized
681 * using the following initialization strategy:
682 * {@link #TAXONDESCRIPTION_INIT_STRATEGY}
683 * @throws IOException
684 */
685 @RequestMapping(
686 value = {"descriptions"},
687 method = RequestMethod.GET)
688 public List<TaxonDescription> doGetDescriptions(
689 @PathVariable("uuid") UUID uuid,
690 @RequestParam(value = "markerTypes", required = false) UuidList markerTypeUUIDs,
691 // @PathVariable("markerTypes") String markerTypeUUIDs,
692 HttpServletRequest request,
693 HttpServletResponse response)throws IOException {
694 if(request != null){
695 logger.info("doGetDescriptions()" + request.getServletPath());
696 }
697 List<DefinedTermBase> markerTypeTerms = new ArrayList<DefinedTermBase>();
698 Set<UUID> sMarkerTypeUUIDs = new HashSet<UUID>();
699 //if(markerTypeUUIDs !=null) {
700 // if(!markerTypeUUIDs.equals("test") && !markerTypeUUIDs.equals("$1") ) {
701 // String[] strMarkerTypeUUIDs = markerTypeUUIDs.split(",");
702 // for (String uuidMarkerType : strMarkerTypeUUIDs) {
703 // sMarkerTypeUUIDs.add(UUID.fromString(uuidMarkerType));
704 // }
705 //
706 // markerTypeTerms = markerTypeService.find(sMarkerTypeUUIDs);
707 // }
708 if(markerTypeUUIDs != null && !markerTypeUUIDs.isEmpty()){
709 markerTypeTerms = markerTypeService.find(sMarkerTypeUUIDs);
710 } else if(markerTypeUUIDs.isEmpty()){
711 markerTypeTerms = new ArrayList<DefinedTermBase>();
712 }
713 Set<MarkerType> markerTypes = new HashSet<MarkerType>();
714 List<TaxonDescription> descriptions = new ArrayList<TaxonDescription>();
715 for (DefinedTermBase markerTypeTerm : markerTypeTerms) {
716 markerTypes.add((MarkerType)markerTypeTerm);
717 }
718 Taxon t = getCdmBaseInstance(Taxon.class, uuid, response, (List<String>)null);
719 if (markerTypes == null) {
720
721 Pager<TaxonDescription> p = descriptionService.getTaxonDescriptions(t, null, null, null, null, TAXONDESCRIPTION_INIT_STRATEGY);
722 descriptions = p.getRecords();
723 }
724
725 else if (sMarkerTypeUUIDs.isEmpty()) {
726 descriptions = descriptionService.listTaxonDescriptions(t, null, null, markerTypes, null, null, TAXONUSEDESCRIPTION_INIT_STRATEGY);
727
728 }
729 else {
730 descriptions = descriptionService.listTaxonDescriptions(t, null, null, markerTypes, null, null, TAXONUSEDESCRIPTION_INIT_STRATEGY);
731 }
732 /*Set<MarkerType> sMarkerTypes = new HashSet<MarkerType>(markerTypeService.listByTermClass(MarkerType.class, null, null, null, null));
733 //Set<MarkerType> markerTypesToUse = new HashSet<MarkerType>(markerTypeService.);
734 //MarkerType useMarkerType = (MarkerType) markerTypeService.find(UUID.fromString("2e6e42d9-e92a-41f4-899b-03c0ac64f059"));
735 MarkerType useMarkerType = (MarkerType) markerTypeService.find(UUID.fromString("2e6e42d9-e92a-41f4-899b-03c0ac64f039"));
736
737 markerTypes.remove(useMarkerType);
738
739 //List<TaxonDescription> descriptions = descriptionService.listTaxonDescriptions(t, null, null, markerTypes, null, null, TAXONUSEDESCRIPTION_INIT_STRATEGY);
740 Pager<TaxonDescription> p = descriptionService.getTaxonDescriptions(t, null, null, null, null, TAXONDESCRIPTION_INIT_STRATEGY);
741 //List<TaxonDescription> descriptions = p.getRecords();
742 Iterator<TaxonDescription> itr = descriptions.iterator();
743 //for(TaxonDescription taxonDesc: descriptions) {
744 while (itr.hasNext()) {
745 TaxonDescription taxonDesc = (TaxonDescription) itr.next();
746 Pager<Marker> pMarkers = descriptionService.getMarkers(taxonDesc, null, null, null, null, null);
747 Pager<Marker> useMarkers = markerService.page(useMarkerType, null, null, null, null);
748 List<DefinedTermBase> useMarkers2 = markerTypeService.list(MarkerType.class, null, null, null, null);
749 if(pMarkers.getCount() != 0) {
750 List<Marker> testMarkers = pMarkers.getRecords();
751 List<Marker> testUseMarkers = useMarkers.getRecords();
752 for (Marker marker: testMarkers) {
753 for (Marker useMaker: testUseMarkers){
754 if(marker.equals(useMaker)) {
755 itr.remove();
756 }
757 }
758 }
759 }
760 }*/
761 //return p.getRecords();
762 return descriptions;
763 }
764
765 @RequestMapping(value = "useDescriptions", method = RequestMethod.GET)
766 public List<TaxonDescription> doGetUseDescriptions(
767 @PathVariable("uuid") UUID uuid,
768 HttpServletRequest request,
769 HttpServletResponse response) throws IOException {
770 logger.info("doGetDescriptionElements() - " + request.getServletPath());
771
772 //ModelAndView mv = new ModelAndView();
773 Taxon t = getCdmBaseInstance(Taxon.class, uuid, response, (List<String>)null);
774
775 //MarkerType useMarkerType = (MarkerType) markerTypeService.find(UUID.fromString("2e6e42d9-e92a-41f4-899b-03c0ac64f059"));
776 MarkerType useMarkerType = (MarkerType) markerTypeService.find(UUID.fromString("2e6e42d9-e92a-41f4-899b-03c0ac64f039"));
777
778 //find(UUID.fromString("2e6e42d9-e92a-41f4-899b-03c0ac64f059"));
779 Set<MarkerType> markerTypes = new HashSet<MarkerType>();
780 markerTypes.add(useMarkerType);
781 List<TaxonDescription> descriptionElements = descriptionService.listTaxonDescriptions(t, null, null, markerTypes, null, null, TAXONUSEDESCRIPTION_INIT_STRATEGY);
782 //getDescriptionElements(description, features, type, pageSize, pageNumber, propertyPaths) load(uuid);
783
784 /*if(!(description instanceof TaxonDescription)){
785 HttpStatusMessage.UUID_REFERENCES_WRONG_TYPE.send(response);
786 // will terminate thread
787 }*/
788
789 //boolean hasStructuredData = service. hasStructuredData(description);
790
791 //mv.addObject(hasStructuredData);
792
793 return descriptionElements;
794 }
795
796 @RequestMapping(value = "descriptions/elementsByType/{classSimpleName}", method = RequestMethod.GET)
797 public ModelAndView doGetDescriptionElementsByType(
798 @PathVariable("uuid") UUID uuid,
799 @PathVariable("classSimpleName") String classSimpleName,
800 //@RequestParam(value = "markerTypes", required = false, defaultValue = "false") Set<UUID> markerTypes,
801 // @PathVariable(value = "markerTypes") String markerTypes,
802 @RequestParam(value = "markerTypes", required = false) UuidList markerTypeUUIDs,
803 @RequestParam(value = "count", required = false, defaultValue = "false") Boolean doCount,
804 HttpServletRequest request,
805 HttpServletResponse response) throws IOException {
806 logger.info("doGetDescriptionElementsByType() - " + request.getServletPath());
807
808 ModelAndView mv = new ModelAndView();
809
810 List<DescriptionElementBase> allElements = new ArrayList<DescriptionElementBase>();
811 List<DescriptionElementBase> elements;
812 int count = 0;
813
814 List<String> initStrategy = doCount ? null : DESCRIPTION_ELEMENT_INIT_STRATEGY;
815
816 List<TaxonDescription> taxonDescriptions = doGetDescriptions(uuid, markerTypeUUIDs, request, response);
817 try {
818 Class type;
819 type = Class.forName("eu.etaxonomy.cdm.model.description."
820 + classSimpleName);
821 if (taxonDescriptions != null) {
822 for (TaxonDescription description : taxonDescriptions) {
823 elements = descriptionService.listDescriptionElements(description, null, type, null, 0, initStrategy);
824 allElements.addAll(elements);
825 count += elements.size();
826 }
827
828 }
829 } catch (ClassNotFoundException e) {
830 HttpStatusMessage.fromString(e.getLocalizedMessage()).send(response);
831 }
832 if(doCount){
833 mv.addObject(count);
834 } else {
835 mv.addObject(allElements);
836 }
837 return mv;
838 }
839
840 // @RequestMapping(value = "specimens", method = RequestMethod.GET)
841 // public ModelAndView doGetSpecimens(
842 // @PathVariable("uuid") UUID uuid,
843 // HttpServletRequest request,
844 // HttpServletResponse response) throws IOException, ClassNotFoundException {
845 // logger.info("doGetSpecimens() - " + request.getServletPath());
846 //
847 // ModelAndView mv = new ModelAndView();
848 //
849 // List<DerivedUnitFacade> derivedUnitFacadeList = new ArrayList<DerivedUnitFacade>();
850 //
851 // // find speciemens in the TaxonDescriptions
852 // List<TaxonDescription> taxonDescriptions = doGetDescriptions(uuid, request, response);
853 // if (taxonDescriptions != null) {
854 //
855 // for (TaxonDescription description : taxonDescriptions) {
856 // derivedUnitFacadeList.addAll( occurrenceService.listDerivedUnitFacades(description, null) );
857 // }
858 // }
859 // // TODO find speciemens in the NameDescriptions ??
860 //
861 // // TODO also find type specimens
862 //
863 // mv.addObject(derivedUnitFacadeList);
864 //
865 // return mv;
866 // }
867
868 /**
869 * Get the {@link Media} attached to the {@link Taxon} instance
870 * identified by the <code>{taxon-uuid}</code>.
871 *
872 * Usage &#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;{taxon-
873 * uuid}&#x002F;media&#x002F;{mime type
874 * list}&#x002F;{size}[,[widthOrDuration}][,{height}]&#x002F;
875 *
876 * Whereas
877 * <ul>
878 * <li><b>{mime type list}</b>: a comma separated list of mime types, in the
879 * order of preference. The forward slashes contained in the mime types must
880 * be replaced by a colon. Regular expressions can be used. Each media
881 * associated with this given taxon is being searched whereas the first
882 * matching mime type matching a representation always rules.</li>
883 * <li><b>{size},{widthOrDuration},{height}</b>: <i>not jet implemented</i>
884 * valid values are an integer or the asterisk '*' as a wildcard</li>
885 * </ul>
886 *
887 * @param request
888 * @param response
889 * @return a List of {@link Media} entities which are initialized
890 * using the following initialization strategy:
891 * {@link #TAXONDESCRIPTION_INIT_STRATEGY}
892 * @throws IOException
893 */
894 @RequestMapping(
895 value = {"media"},
896 method = RequestMethod.GET)
897 public List<Media> doGetMedia(
898 @PathVariable("uuid") UUID uuid,
899 @RequestParam(value = "type", required = false) Class<? extends MediaRepresentationPart> type,
900 @RequestParam(value = "mimeTypes", required = false) String[] mimeTypes,
901 @RequestParam(value = "widthOrDuration", required = false) Integer widthOrDuration,
902 @RequestParam(value = "height", required = false) Integer height,
903 @RequestParam(value = "size", required = false) Integer size,
904 HttpServletRequest request, HttpServletResponse response) throws IOException {
905
906 logger.info("doGetMedia()" + request.getServletPath());
907 Taxon t = getCdmBaseInstance(Taxon.class, uuid, response, (List<String>)null);
908 String path = request.getServletPath();
909 List<Media> returnMedia = getMediaForTaxon(t, type, mimeTypes, widthOrDuration, height, size);
910 return returnMedia;
911 }
912
913 @RequestMapping(
914 value = {"subtree/media"},
915 method = RequestMethod.GET)
916 public List<Media> doGetSubtreeMedia(
917 @PathVariable("uuid") UUID uuid,
918 @RequestParam(value = "type", required = false) Class<? extends MediaRepresentationPart> type,
919 @RequestParam(value = "mimeTypes", required = false) String[] mimeTypes,
920 @RequestParam(value = "widthOrDuration", required = false) Integer widthOrDuration,
921 @RequestParam(value = "height", required = false) Integer height,
922 @RequestParam(value = "size", required = false) Integer size,
923 HttpServletRequest request, HttpServletResponse response)throws IOException {
924 logger.info("doGetMedia()" + request.getServletPath());
925 Taxon taxon = getCdmBaseInstance(Taxon.class, uuid, response, TAXON_WITH_NODES_INIT_STRATEGY);
926 String requestPath = request.getServletPath();
927 List<Media> returnMedia = getMediaForTaxon(taxon, type, mimeTypes, widthOrDuration, height, size);
928 TaxonNode node;
929 //looking for all medias of genus
930 if (taxon.getTaxonNodes().size()>0){
931 Set<TaxonNode> nodes = taxon.getTaxonNodes();
932 Iterator<TaxonNode> iterator = nodes.iterator();
933 //TaxonNode holen
934 node = iterator.next();
935 //Check if TaxonNode belongs to the current tree
936
937 node = classificationService.loadTaxonNode(node, TAXONNODE_WITHTAXON_INIT_STRATEGY);
938 Set<TaxonNode> children = node.getChildNodes();
939 Taxon childTaxon;
940 for (TaxonNode child : children){
941 childTaxon = child.getTaxon();
942 childTaxon = (Taxon)taxonService.load(childTaxon.getUuid(), null);
943 returnMedia.addAll(getMediaForTaxon(childTaxon, type, mimeTypes, widthOrDuration, height, size));
944 }
945 }
946 return returnMedia;
947 }
948
949
950 private List<Media> getMediaForTaxon(Taxon taxon, Class<? extends MediaRepresentationPart> type, String[] mimeTypes,
951 Integer widthOrDuration, Integer height, Integer size){
952
953 Pager<TaxonDescription> p =
954 descriptionService.getTaxonDescriptions(taxon, null, null, null, null, TAXONDESCRIPTION_MEDIA_INIT_STRATEGY);
955
956 // pars the media and quality parameters
957
958
959 // collect all media of the given taxon
960 boolean limitToGalleries = false;
961 List<Media> taxonMedia = new ArrayList<Media>();
962 List<Media> taxonGalleryMedia = new ArrayList<Media>();
963 for(TaxonDescription desc : p.getRecords()){
964
965 if(desc.isImageGallery()){
966 for(DescriptionElementBase element : desc.getElements()){
967 for(Media media : element.getMedia()){
968 taxonGalleryMedia.add(media);
969 }
970 }
971 } else if(!limitToGalleries){
972 for(DescriptionElementBase element : desc.getElements()){
973 for(Media media : element.getMedia()){
974 taxonMedia.add(media);
975 }
976 }
977 }
978
979 }
980
981 taxonGalleryMedia.addAll(taxonMedia);
982
983 List<Media> returnMedia = MediaUtils.findPreferredMedia(taxonGalleryMedia, type,
984 mimeTypes, null, widthOrDuration, height, size);
985
986 return returnMedia;
987 }
988
989
990 // ---------------------- code snippet preserved for possible later use --------------------
991 // @RequestMapping(
992 // value = {"/*/portal/taxon/*/descriptions"},
993 // method = RequestMethod.GET)
994 // public List<TaxonDescription> doGetDescriptionsbyFeatureTree(HttpServletRequest request, HttpServletResponse response)throws IOException {
995 // TaxonBase tb = getCdmBase(request, response, null, Taxon.class);
996 // if(tb instanceof Taxon){
997 // //T O D O this is a quick and dirty implementation -> generalize
998 // UUID featureTreeUuid = readValueUuid(request, featureTreeUuidPattern);
999 //
1000 // FeatureTree featureTree = descriptionService.getFeatureTreeByUuid(featureTreeUuid);
1001 // Pager<TaxonDescription> p = descriptionService.getTaxonDescriptions((Taxon)tb, null, null, null, null, TAXONDESCRIPTION_INIT_STRATEGY);
1002 // List<TaxonDescription> descriptions = p.getRecords();
1003 //
1004 // if(!featureTree.isDescriptionSeparated()){
1005 //
1006 // TaxonDescription superDescription = TaxonDescription.NewInstance();
1007 // //put all descriptionElements in superDescription and make it invisible
1008 // for(TaxonDescription description: descriptions){
1009 // for(DescriptionElementBase element: description.getElements()){
1010 // superDescription.addElement(element);
1011 // }
1012 // }
1013 // List<TaxonDescription> separatedDescriptions = new ArrayList<TaxonDescription>(descriptions.size());
1014 // separatedDescriptions.add(superDescription);
1015 // return separatedDescriptions;
1016 // }else{
1017 // return descriptions;
1018 // }
1019 // } else {
1020 // response.sendError(HttpServletResponse.SC_NOT_FOUND, "invalid type; Taxon expected but " + tb.getClass().getSimpleName() + " found.");
1021 // return null;
1022 // }
1023 // }
1024
1025 }