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