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