1 // $Id: TaxonController.java 5473 2009-03-25 13:42:07Z a.kohlbecker $
3 * Copyright (C) 2007 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
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.
11 package eu
.etaxonomy
.cdm
.remote
.controller
;
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
;
22 import java
.util
.UUID
;
24 import javax
.servlet
.http
.HttpServletRequest
;
25 import javax
.servlet
.http
.HttpServletResponse
;
27 import org
.apache
.commons
.lang
.ObjectUtils
;
28 import org
.apache
.log4j
.Logger
;
29 import org
.springframework
.beans
.factory
.annotation
.Autowired
;
30 import org
.springframework
.stereotype
.Controller
;
31 import org
.springframework
.web
.bind
.WebDataBinder
;
32 import org
.springframework
.web
.bind
.annotation
.InitBinder
;
33 import org
.springframework
.web
.bind
.annotation
.PathVariable
;
34 import org
.springframework
.web
.bind
.annotation
.RequestMapping
;
35 import org
.springframework
.web
.bind
.annotation
.RequestMethod
;
36 import org
.springframework
.web
.bind
.annotation
.RequestParam
;
37 import org
.springframework
.web
.servlet
.ModelAndView
;
39 import eu
.etaxonomy
.cdm
.api
.service
.DistributionTree
;
40 import eu
.etaxonomy
.cdm
.api
.service
.IDescriptionService
;
41 import eu
.etaxonomy
.cdm
.api
.service
.INameService
;
42 import eu
.etaxonomy
.cdm
.api
.service
.IReferenceService
;
43 import eu
.etaxonomy
.cdm
.api
.service
.ITaxonService
;
44 import eu
.etaxonomy
.cdm
.api
.service
.ITaxonTreeService
;
45 import eu
.etaxonomy
.cdm
.api
.service
.config
.ITaxonServiceConfigurator
;
46 import eu
.etaxonomy
.cdm
.api
.service
.config
.impl
.TaxonServiceConfiguratorImpl
;
47 import eu
.etaxonomy
.cdm
.api
.service
.pager
.Pager
;
48 import eu
.etaxonomy
.cdm
.database
.UpdatableRoutingDataSource
;
49 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableEntity
;
50 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionElementBase
;
51 import eu
.etaxonomy
.cdm
.model
.description
.TaxonDescription
;
52 import eu
.etaxonomy
.cdm
.model
.description
.TaxonNameDescription
;
53 import eu
.etaxonomy
.cdm
.model
.location
.NamedArea
;
54 import eu
.etaxonomy
.cdm
.model
.location
.NamedAreaLevel
;
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
.TaxonNameBase
;
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
.TaxonomicTree
;
67 import eu
.etaxonomy
.cdm
.persistence
.query
.MatchMode
;
68 import eu
.etaxonomy
.cdm
.remote
.editor
.MatchModePropertyEditor
;
69 import eu
.etaxonomy
.cdm
.remote
.editor
.NamedAreaPropertyEditor
;
70 import eu
.etaxonomy
.cdm
.remote
.editor
.UUIDPropertyEditor
;
71 import eu
.etaxonomy
.cdm
.remote
.editor
.UuidList
;
74 * The TaxonPortalController class is a Spring MVC Controller.
76 * The syntax of the mapped service URIs contains the the {datasource-name} path element.
77 * The available {datasource-name}s are defined in a configuration file which
78 * is loaded by the {@link UpdatableRoutingDataSource}. If the
79 * UpdatableRoutingDataSource is not being used in the actual application
80 * context any arbitrary {datasource-name} may be used.
82 * Methods mapped at type level, inherited from super classes ({@link BaseController}):
84 * URI: <b>/{datasource-name}/portal/taxon/{taxon-uuid}</b>
86 * Get the {@link TaxonBase} instance identified by the <code>{taxon-uuid}</code>.
87 * The returned Taxon is initialized by
88 * the following strategy {@link #TAXON_INIT_STRATEGY}
91 * @author a.kohlbecker
96 @RequestMapping(value
= {"/portal/taxon/*", "/portal/taxon/{uuid}", "/portal/taxon/*/*", "/portal/name/*/*", "/portal/taxon/*/media/*/*", "/portal/taxon/*/subtree/media/*/*"})
97 public class TaxonPortalController
extends BaseController
<TaxonBase
, ITaxonService
>
99 public static final Logger logger
= Logger
.getLogger(TaxonPortalController
.class);
102 private INameService nameService
;
104 private IDescriptionService descriptionService
;
106 private IReferenceService referenceService
;
109 private ITaxonTreeService taxonTreeService
;
112 private ITaxonService taxonService
;
114 private static final List
<String
> TAXON_INIT_STRATEGY
= Arrays
.asList(new String
[]{
117 "relationsToThisName.fromTaxon.name.taggedName",
121 "name.rank.representations",
122 "name.status.type.representations",
124 // "name.combinationAuthorTeam.titleCache",
125 // "name.basionymAuthorTeam.titleCache",
126 // "name.exCombinationAuthorTeam.titleCache",
127 // "name.exBasionymAuthorTeam.titleCache",
129 // taxon descriptions
130 "descriptions.elements.$",
131 "descriptions.elements.area",
132 "descriptions.elements.area.$",
133 "descriptions.elements.multilanguageText",
134 "descriptions.elements.media.representations.parts",
135 "descriptions.elements.media.title",
137 // // typeDesignations
138 // "name.typeDesignations.$",
139 // "name.typeDesignations.citation.authorTeam",
140 // "name.typeDesignations.typeName.$",
141 // "name.typeDesignations.typeStatus.representations",
142 // "name.typeDesignations.typeSpecimen.media.representations.parts"
146 private static final List
<String
> TAXON_WITH_NODES_INIT_STRATEGY
= Arrays
.asList(new String
[]{
148 "taxonNodes.taxonomicTree.$",
149 "taxonNodes.childNodes.$"
152 private static final List
<String
> SIMPLE_TAXON_INIT_STRATEGY
= Arrays
.asList(new String
[]{
155 "relationsToThisName.fromTaxon.name.taggedName",
159 "name.rank.representations",
160 "name.status.type.representations",
162 // "name.combinationAuthorTeam.titleCache",
163 // "name.basionymAuthorTeam.titleCache",
164 // "name.exCombinationAuthorTeam.titleCache",
165 // "name.exBasionymAuthorTeam.titleCache",
168 private static final List
<String
> SYNONYMY_INIT_STRATEGY
= Arrays
.asList(new String
[]{
169 // initialize homotypical and heterotypical groups; needs synonyms
170 "synonymRelations.$",
171 "synonymRelations.synonym.$",
172 "synonymRelations.synonym.name.status.type",
173 "synonymRelations.synonym.name.status.type.representation",
174 "synonymRelations.synonym.name.taggedName",
175 "synonymRelations.synonym.name.nomenclaturalReference.inBook",
176 "synonymRelations.synonym.name.nomenclaturalReference.inJournal",
177 "synonymRelations.synonym.name.nomenclaturalReference.inProceedings",
178 "synonymRelations.synonym.name.homotypicalGroup.typifiedNames.$",
179 "synonymRelations.synonym.name.homotypicalGroup.typifiedNames.name.taggedName",
180 "synonymRelations.synonym.name.homotypicalGroup.typifiedNames.taxonBases.$",
181 "synonymRelations.synonym.name.homotypicalGroup.typifiedNames.taxonBases.sec.titleCache", // needed to avoid lazyLoading Exceptions
182 "synonymRelations.synonym.name.homotypicalGroup.typifiedNames.taxonBases.name.taggedName",
184 "name.homotypicalGroup.$",
185 "name.homotypicalGroup.typifiedNames.$",
186 "name.homotypicalGroup.typifiedNames.name.taggedName",
188 "name.homotypicalGroup.typifiedNames.taxonBases.$",
189 "name.homotypicalGroup.typifiedNames.taxonBases.sec.titleCache", // needed to avoid lazyLoading Exceptions
190 "name.homotypicalGroup.typifiedNames.taxonBases.titleCache",
191 //"name.homotypicalGroup.typifiedNames.taxonBases.name.taggedName"
195 private static final List
<String
> TAXONRELATIONSHIP_INIT_STRATEGY
= Arrays
.asList(new String
[]{
197 "type.inverseRepresentations",
199 "fromTaxon.name.taggedName"
202 private static final List
<String
> NAMERELATIONSHIP_INIT_STRATEGY
= Arrays
.asList(new String
[]{
204 "type.inverseRepresentations",
205 "fromName.taggedName",
210 protected static final List
<String
> TAXONDESCRIPTION_INIT_STRATEGY
= Arrays
.asList(new String
[]{
213 "elements.sources.citation.",
214 // "elements.sources.citation.authorTeam.$",
215 // "elements.sources.citation.authorTeam.titleCache",
216 // "elements.sources.citation.authorTeam.nomenclaturalTitleCache",
217 "elements.sources.nameUsedInSource.titleCache",
218 "elements.sources.nameUsedInSource.originalNameString",
219 "elements.multilanguageText",
220 "elements.media.representations.parts",
221 "elements.media.title",
225 private static final List
<String
> NAMEDESCRIPTION_INIT_STRATEGY
= Arrays
.asList(new String
[]{
229 "elements.multilanguageText",
230 "elements.media.representations.parts",
231 "elements.media.title",
234 protected static final List
<String
> TAXONDESCRIPTION_MEDIA_INIT_STRATEGY
= Arrays
.asList(new String
[]{
235 "elements.media.representations.parts",
236 "elements.media.title"
240 private static final List
<String
> TYPEDESIGNATION_INIT_STRATEGY
= Arrays
.asList(new String
[]{
243 "typeStatus.representations",
245 "typeName.taggedName",
248 protected static final List
<String
> TAXONNODE_WITHTAXON_INIT_STRATEGY
= Arrays
.asList(new String
[]{
252 protected static final List
<String
> TAXONNODE_INIT_STRATEGY
= Arrays
.asList(new String
[]{
253 "taxonNodes.taxonomicTree"
258 private static final String featureTreeUuidPattern
= "^/taxon(?:(?:/)([^/?#&\\.]+))+.*";
260 public TaxonPortalController(){
262 setInitializationStrategy(TAXON_INIT_STRATEGY
);
263 setUuidParameterPattern("^/portal/(?:[^/]+)/([^/?#&\\.]+).*");
267 * @see eu.etaxonomy.cdm.remote.controller.GenericController#setService(eu.etaxonomy.cdm.api.service.IService)
271 public void setService(ITaxonService service
) {
272 this.service
= service
;
276 public void initBinder(WebDataBinder binder
) {
277 binder
.registerCustomEditor(UUID
.class, new UUIDPropertyEditor());
278 binder
.registerCustomEditor(NamedArea
.class, new NamedAreaPropertyEditor());
279 binder
.registerCustomEditor(MatchMode
.class, new MatchModePropertyEditor());
284 * @see eu.etaxonomy.cdm.remote.controller.BaseController#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
287 @RequestMapping(method = RequestMethod.GET)
288 public TaxonBase doGet(HttpServletRequest request, HttpServletResponse response)throws IOException {
289 logger.info("doGet()");
290 TaxonBase tb = getCdmBase(request, response, TAXON_INIT_STRATEGY, TaxonBase.class);
295 * Find Taxa, Synonyms, Common Names by name, either globally or in a specific geographic area.
297 * URI: <b>/{datasource-name}/portal/taxon/find</b>
300 * the string to query for. Since the wildcard character '*'
301 * internally always is appended to the query string, a search
302 * always compares the query string with the beginning of a name.
303 * - <i>required parameter</i>
305 * the {@link UUID} of a {@link TaxonomicTree} to which the
306 * search is to be restricted. - <i>optional parameter</i>
308 * restrict the search to a set of geographic {@link NamedArea}s.
309 * The parameter currently takes a list of TDWG area labels.
310 * - <i>optional parameter</i>
312 * the number of the page to be returned, the first page has the
313 * pageNumber = 1 - <i>optional parameter</i>
315 * the maximum number of entities returned per page (can be -1
316 * to return all entities in a single page) - <i>optional parameter</i>
318 * weather to search for instances of {@link Taxon} - <i>optional parameter</i>
320 * weather to search for instances of {@link Synonym} - <i>optional parameter</i>
321 * @param doTaxaByCommonNames
322 * for instances of {@link Taxon} by a common name used - <i>optional parameter</i>
324 * valid values are "EXACT", "BEGINNING", "ANYWHERE", "END" (case sensitive !!!)
325 * @return a Pager on a list of {@link IdentifiableEntity}s initialized by
326 * the following strategy {@link #SIMPLE_TAXON_INIT_STRATEGY}
327 * @throws IOException
329 @RequestMapping(method
= RequestMethod
.GET
,
330 value
= {"/portal/taxon/find"}) //TODO map to path /*/portal/taxon/
331 public Pager
<IdentifiableEntity
> doFind(
332 @RequestParam(value
= "query", required
= false) String query
,
333 @RequestParam(value
= "tree", required
= false) UUID treeUuid
,
334 @RequestParam(value
= "area", required
= false) Set
<NamedArea
> areas
,
335 @RequestParam(value
= "page", required
= false) Integer page
,
336 @RequestParam(value
= "pageSize", required
= false) Integer pageSize
,
337 @RequestParam(value
= "doTaxa", required
= false) Boolean doTaxa
,
338 @RequestParam(value
= "doSynonyms", required
= false) Boolean doSynonyms
,
339 @RequestParam(value
= "doTaxaByCommonNames", required
= false) Boolean doTaxaByCommonNames
,
340 @RequestParam(value
= "matchMode", required
= false) MatchMode matchMode
344 logger
.info("doFind( " +
345 "query=\"" + ObjectUtils
.toString(query
) + "\", treeUuid=" + ObjectUtils
.toString(treeUuid
) +
346 ", area=" + ObjectUtils
.toString(areas
) +
347 ", pageSize=" + ObjectUtils
.toString(pageSize
) + ", page=" + ObjectUtils
.toString(page
) +
348 ", doTaxa=" + ObjectUtils
.toString(doTaxa
) + ", doSynonyms=" + ObjectUtils
.toString(doSynonyms
)
349 +", doTaxaByCommonNames=" + ObjectUtils
.toString(doTaxaByCommonNames
) +")" );
351 if(page
== null){ page
= BaseListController
.DEFAULT_PAGE_NUMBER
;}
352 if(pageSize
== null){ pageSize
= BaseListController
.DEFAULT_PAGESIZE
;}
357 ITaxonServiceConfigurator config
= new TaxonServiceConfiguratorImpl();
358 config
.setPageNumber(page
);
359 config
.setPageSize(pageSize
);
360 config
.setSearchString(query
);
361 config
.setDoTaxa(doTaxa
!= null ? doTaxa
: Boolean
.FALSE
);
362 config
.setDoSynonyms(doSynonyms
!= null ? doSynonyms
: Boolean
.FALSE
);
363 config
.setDoTaxaByCommonNames(doTaxaByCommonNames
!= null ? doTaxaByCommonNames
: Boolean
.FALSE
);
364 config
.setMatchMode(matchMode
!= null ? matchMode
: MatchMode
.BEGINNING
);
365 config
.setTaxonPropertyPath(SIMPLE_TAXON_INIT_STRATEGY
);
366 config
.setNamedAreas(areas
);
367 if(treeUuid
!= null){
368 TaxonomicTree taxonomicTree
= taxonTreeService
.find(treeUuid
);
369 config
.setTaxonomicTree(taxonomicTree
);
372 return (Pager
<IdentifiableEntity
>) service
.findTaxaAndNames(config
);
376 * Get the synonymy for a taxon identified by the <code>{taxon-uuid}</code>.
377 * The synonymy consists
378 * of two parts: The group of homotypic synonyms of the taxon and the
379 * heterotypic synonymy groups of the taxon. The synonymy is ordered
380 * historically by the type designations and by the publication date of the
381 * nomenclatural reference
384 * <b>/{datasource-name}/portal/taxon/{taxon-uuid}/synonymy</b>
389 * @return a Map with to entries which are mapped by the following keys:
390 * "homotypicSynonymsByHomotypicGroup", "heterotypicSynonymyGroups",
391 * containing lists of {@link Synonym}s which are initialized using the
392 * following initialization strategy: {@link #SYNONYMY_INIT_STRATEGY}
394 * @throws IOException
397 value
= {"/portal/taxon/*/synonymy"},
398 method
= RequestMethod
.GET
)
399 public ModelAndView
doGetSynonymy(HttpServletRequest request
, HttpServletResponse response
)throws IOException
{
401 logger
.info("doGetSynonymy() " + request
.getServletPath());
402 ModelAndView mv
= new ModelAndView();
403 TaxonBase tb
= getCdmBase(request
, response
, null, Taxon
.class);
404 Taxon taxon
= (Taxon
)tb
;
405 Map
<String
, List
<?
>> synonymy
= new Hashtable
<String
, List
<?
>>();
406 synonymy
.put("homotypicSynonymsByHomotypicGroup", service
.getHomotypicSynonymsByHomotypicGroup(taxon
, SYNONYMY_INIT_STRATEGY
));
407 synonymy
.put("heterotypicSynonymyGroups", service
.getHeterotypicSynonymyGroups(taxon
, SYNONYMY_INIT_STRATEGY
));
408 mv
.addObject(synonymy
);
413 * Get the set of accepted {@link Taxon} entities for a given
414 * {@link TaxonBase} entity identified by the <code>{taxon-uuid}</code>.
416 * URI: <b>/{datasource-name}/portal/taxon/{taxon-uuid}/accepted</b>
420 * @return a Set of {@link Taxon} entities which are initialized
421 * using the following initialization strategy:
422 * {@link #SYNONYMY_INIT_STRATEGY}
423 * @throws IOException
425 @RequestMapping(value
= "/portal/taxon/*/accepted", method
= RequestMethod
.GET
)
426 public Set
<TaxonBase
> getAccepted(HttpServletRequest request
, HttpServletResponse response
) throws IOException
{
428 logger
.info("getAccepted() " + request
.getServletPath());
430 UUID uuid
= readValueUuid(request
, null);
431 TaxonBase tb
= service
.load(uuid
, SYNONYMY_INIT_STRATEGY
);
433 response
.sendError(HttpServletResponse
.SC_NOT_FOUND
, "A taxon with the uuid " + uuid
+ " does not exist");
436 HashSet
<TaxonBase
> resultset
= new HashSet
<TaxonBase
>();
437 if(tb
instanceof Taxon
){
438 //the taxon already is accepted
439 //FIXME take the current view into account once views are implemented!!!
440 resultset
.add((Taxon
)tb
);
442 Synonym syn
= (Synonym
)tb
;
443 for(TaxonBase accepted
: syn
.getAcceptedTaxa()){
444 accepted
= service
.load(accepted
.getUuid(), SIMPLE_TAXON_INIT_STRATEGY
);
445 resultset
.add(accepted
);
452 * Get the list of {@link TaxonRelationship}s for the given
453 * {@link TaxonBase} instance identified by the <code>{taxon-uuid}</code>.
455 * URI: <b>/{datasource-name}/portal/taxon/{taxon-uuid}/taxonRelationships</b>
459 * @return a List of {@link TaxonRelationship} entities which are initialized
460 * using the following initialization strategy:
461 * {@link #TAXONRELATIONSHIP_INIT_STRATEGY}
462 * @throws IOException
465 value
= {"/portal/taxon/*/taxonRelationships"},
466 method
= RequestMethod
.GET
)
467 public List
<TaxonRelationship
> doGetTaxonRelations(HttpServletRequest request
, HttpServletResponse response
)throws IOException
{
469 logger
.info("doGetTaxonRelations()" + request
.getServletPath());
470 TaxonBase tb
= getCdmBase(request
, response
, null, Taxon
.class);
471 Taxon taxon
= (Taxon
)tb
;
472 List
<TaxonRelationship
> relations
= new ArrayList
<TaxonRelationship
>();
473 List
<TaxonRelationship
> results
= service
.listToTaxonRelationships(taxon
, TaxonRelationshipType
.MISAPPLIED_NAME_FOR(), null, null, null, TAXONRELATIONSHIP_INIT_STRATEGY
);
474 relations
.addAll(results
);
475 results
= service
.listToTaxonRelationships(taxon
, TaxonRelationshipType
.INVALID_DESIGNATION_FOR(), null, null, null, TAXONRELATIONSHIP_INIT_STRATEGY
);
476 relations
.addAll(results
);
482 * Get the list of {@link NameRelationship}s of the Name associated with the
483 * {@link TaxonBase} instance identified by the <code>{taxon-uuid}</code>.
485 * URI: <b>/{datasource-name}/portal/taxon/{taxon-uuid}/nameRelationships</b>
489 * @return a List of {@link NameRelationship} entities which are initialized
490 * using the following initialization strategy:
491 * {@link #NAMERELATIONSHIP_INIT_STRATEGY}
492 * @throws IOException
495 value
= {"/portal/taxon/*/toNameRelationships"},
496 method
= RequestMethod
.GET
)
497 public List
<NameRelationship
> doGetToNameRelations(HttpServletRequest request
, HttpServletResponse response
)throws IOException
{
498 logger
.info("doGetNameRelations()" + request
.getServletPath());
499 TaxonBase tb
= getCdmBase(request
, response
, SIMPLE_TAXON_INIT_STRATEGY
, Taxon
.class);
500 List
<NameRelationship
> list
= nameService
.listToNameRelationships(tb
.getName(), null, null, null, null, NAMERELATIONSHIP_INIT_STRATEGY
);
505 * Get the list of {@link NameRelationship}s of the Name associated with the
506 * {@link TaxonBase} instance identified by the <code>{taxon-uuid}</code>.
508 * URI: <b>/{datasource-name}/portal/taxon/{taxon-uuid}/nameRelationships</b>
512 * @return a List of {@link NameRelationship} entities which are initialized
513 * using the following initialization strategy:
514 * {@link #NAMERELATIONSHIP_INIT_STRATEGY}
515 * @throws IOException
518 value
= {"/portal/taxon/*/fromNameRelationships"},
519 method
= RequestMethod
.GET
)
520 public List
<NameRelationship
> doGetFromNameRelations(HttpServletRequest request
, HttpServletResponse response
)throws IOException
{
521 logger
.info("doGetNameRelations()" + request
.getServletPath());
522 TaxonBase tb
= getCdmBase(request
, response
, SIMPLE_TAXON_INIT_STRATEGY
, Taxon
.class);
523 List
<NameRelationship
> list
= nameService
.listFromNameRelationships(tb
.getName(), null, null, null, null, NAMERELATIONSHIP_INIT_STRATEGY
);
528 * Get the list of {@link TaxonNameDescription}s of the Name associated with the
529 * {@link TaxonNameBase} instance identified by the <code>{name-uuid}</code>.
531 * URI: <b>/{datasource-name}/portal/name/{name-uuid}/descriptions</b>
535 * @return a List of {@link TaxonNameDescription} entities which are initialized
536 * using the following initialization strategy:
537 * {@link #NAMEDESCRIPTION_INIT_STRATEGY}
538 * @throws IOException
541 value
= {"/portal/name/*/descriptions"},
542 method
= RequestMethod
.GET
)
543 public List
<TaxonNameDescription
> doGetNameDescriptions(HttpServletRequest request
, HttpServletResponse response
)throws IOException
{
544 logger
.info("doGetNameDescriptions()" + request
.getServletPath());
545 UUID nameUuuid
= readValueUuid(request
, null);
546 TaxonNameBase tnb
= nameService
.load(nameUuuid
, null);
547 Pager
<TaxonNameDescription
> p
= descriptionService
.getTaxonNameDescriptions(tnb
, null, null, NAMEDESCRIPTION_INIT_STRATEGY
);
548 return p
.getRecords();
552 * Get the list of {@link TypeDesignationBase}s of the
553 * {@link TaxonBase} instance identified by the <code>{taxon-uuid}</code>.
555 * URI: <b>/{datasource-name}/portal/taxon/{taxon-uuid}/nameTypeDesignations</b>
559 * @return a List of {@link TypeDesignationBase} entities which are initialized
560 * using the following initialization strategy:
561 * {@link #TYPEDESIGNATION_INIT_STRATEGY}
562 * @throws IOException
565 value
= {"/portal/taxon/*/nameTypeDesignations"},
566 method
= RequestMethod
.GET
)
567 public List
<TypeDesignationBase
> doGetNameTypeDesignations(HttpServletRequest request
, HttpServletResponse response
)throws IOException
{
568 logger
.info("doGetNameTypeDesignations()" + request
.getServletPath());
569 TaxonBase tb
= getCdmBase(request
, response
, SIMPLE_TAXON_INIT_STRATEGY
, Taxon
.class);
570 Pager
<TypeDesignationBase
> p
= nameService
.getTypeDesignations(tb
.getName(), null, null, null, TYPEDESIGNATION_INIT_STRATEGY
);
571 return p
.getRecords();
574 @RequestMapping(value
= "{uuid}/taxonNodes", method
= RequestMethod
.GET
)
575 public Set
<TaxonNode
> doGetTaxonNodes(
576 @PathVariable("uuid") UUID uuid
,
577 HttpServletRequest request
,
578 HttpServletResponse response
) throws IOException
{
579 TaxonBase tb
= service
.load(uuid
, TAXONNODE_INIT_STRATEGY
);
580 if(tb
instanceof Taxon
){
581 return ((Taxon
)tb
).getTaxonNodes();
583 HttpStatusMessage
.UUID_REFERENCES_WRONG_TYPE
.send(response
);
589 * Get the list of {@link TaxonDescription}s of the
590 * {@link Taxon} instance identified by the <code>{taxon-uuid}</code>.
592 * URI: <b>/{datasource-name}/portal/taxon/{taxon-uuid}/descriptions</b>
596 * @return a List of {@link TaxonDescription} entities which are initialized
597 * using the following initialization strategy:
598 * {@link #TAXONDESCRIPTION_INIT_STRATEGY}
599 * @throws IOException
602 value
= {"/portal/taxon/*/descriptions"},
603 method
= RequestMethod
.GET
)
604 public List
<TaxonDescription
> doGetDescriptions(HttpServletRequest request
, HttpServletResponse response
)throws IOException
{
605 logger
.info("doGetDescriptions()" + request
.getServletPath());
606 Taxon t
= getCdmBase(request
, response
, null, Taxon
.class);
607 Pager
<TaxonDescription
> p
= descriptionService
.getTaxonDescriptions(t
, null, null, null, null, TAXONDESCRIPTION_INIT_STRATEGY
);
608 return p
.getRecords();
612 * Get the {@link Media} attached to the {@link Taxon} instance
613 * identified by the <code>{taxon-uuid}</code>.
615 * Usage /{datasource-name}/portal/taxon/{taxon-
616 * uuid}/media/{mime type
617 * list}/{size}[,[widthOrDuration}][,{height}]/
621 * <li><b>{mime type list}</b>: a comma separated list of mime types, in the
622 * order of preference. The forward slashes contained in the mime types must
623 * be replaced by a colon. Regular expressions can be used. Each media
624 * associated with this given taxon is being searched whereas the first
625 * matching mime type matching a representation always rules.</li>
626 * <li><b>{size},{widthOrDuration},{height}</b>: <i>not jet implemented</i>
627 * valid values are an integer or the asterisk '*' as a wildcard</li>
632 * @return a List of {@link Media} entities which are initialized
633 * using the following initialization strategy:
634 * {@link #TAXONDESCRIPTION_INIT_STRATEGY}
635 * @throws IOException
638 value
= {"/portal/taxon/*/media/*/*"},
639 method
= RequestMethod
.GET
)
640 public List
<Media
> doGetMedia(HttpServletRequest request
, HttpServletResponse response
) throws IOException
{
641 logger
.info("doGetMedia()" + request
.getServletPath());
642 Taxon t
= getCdmBase(request
, response
, null, Taxon
.class);
643 String path
= request
.getServletPath();
644 List
<Media
> returnMedia
= getMediaForTaxon(t
, path
, 5);
649 value
= {"/portal/taxon/*/subtree/media/*/*"},
650 method
= RequestMethod
.GET
)
651 public List
<Media
> doGetSubtreeMedia(HttpServletRequest request
, HttpServletResponse response
)throws IOException
{
652 logger
.info("doGetMedia()" + request
.getServletPath());
653 Taxon t
= getCdmBase(request
, response
, TAXON_WITH_NODES_INIT_STRATEGY
, Taxon
.class);
654 String path
= request
.getServletPath();
655 List
<Media
> returnMedia
= getMediaForTaxon(t
, path
, 6);
657 //looking for all medias of genus
658 if (t
.getTaxonNodes().size()>0){
659 Set
<TaxonNode
> nodes
= t
.getTaxonNodes();
660 Iterator
<TaxonNode
> iterator
= nodes
.iterator();
662 node
= iterator
.next();
663 //überprüfen, ob der TaxonNode zum aktuellen Baum gehört.
665 node
= taxonTreeService
.loadTaxonNode(node
, TAXONNODE_WITHTAXON_INIT_STRATEGY
);
666 Set
<TaxonNode
> children
= node
.getChildNodes();
668 for (TaxonNode child
: children
){
669 childTaxon
= child
.getTaxon();
670 childTaxon
= (Taxon
)taxonService
.load(childTaxon
.getUuid(), null);
671 returnMedia
.addAll(getMediaForTaxon(childTaxon
, path
, 6));
678 private List
<Media
> getMediaForTaxon(Taxon taxon
, String path
, int mimeTypeTokenPosition
){
680 Pager
<TaxonDescription
> p
=
681 descriptionService
.getTaxonDescriptions(taxon
, null, null, null, null, TAXONDESCRIPTION_MEDIA_INIT_STRATEGY
);
683 // pars the media and quality parameters
686 // collect all media of the given taxon
687 boolean limitToGalleries
= false;
688 List
<Media
> taxonMedia
= new ArrayList
<Media
>();
689 for(TaxonDescription desc
: p
.getRecords()){
690 if(!limitToGalleries
|| desc
.isImageGallery()){
691 for(DescriptionElementBase element
: desc
.getElements()){
692 for(Media media
: element
.getMedia()){
693 taxonMedia
.add(media
);
699 String
[] pathTokens
= path
.split("/");
701 String
[] mimeTypes
= pathTokens
[mimeTypeTokenPosition
].split(",");
702 String
[] sizeTokens
= pathTokens
[mimeTypeTokenPosition
+ 1].split(",");
703 Integer widthOrDuration
= null;
704 Integer height
= null;
707 List
<Media
> returnMedia
= MediaUtils
.findPreferredMedia(taxonMedia
, mimeTypes
,
708 sizeTokens
, widthOrDuration
, height
, size
);
714 // ---------------------- code snippet preserved for possible later use --------------------
716 // value = {"/*/portal/taxon/*/descriptions"},
717 // method = RequestMethod.GET)
718 // public List<TaxonDescription> doGetDescriptionsbyFeatureTree(HttpServletRequest request, HttpServletResponse response)throws IOException {
719 // TaxonBase tb = getCdmBase(request, response, null, Taxon.class);
720 // if(tb instanceof Taxon){
721 // //T O D O this is a quick and dirty implementation -> generalize
722 // UUID featureTreeUuid = readValueUuid(request, featureTreeUuidPattern);
724 // FeatureTree featureTree = descriptionService.getFeatureTreeByUuid(featureTreeUuid);
725 // Pager<TaxonDescription> p = descriptionService.getTaxonDescriptions((Taxon)tb, null, null, null, null, TAXONDESCRIPTION_INIT_STRATEGY);
726 // List<TaxonDescription> descriptions = p.getRecords();
728 // if(!featureTree.isDescriptionSeparated()){
730 // TaxonDescription superDescription = TaxonDescription.NewInstance();
731 // //put all descriptionElements in superDescription and make it invisible
732 // for(TaxonDescription description: descriptions){
733 // for(DescriptionElementBase element: description.getElements()){
734 // superDescription.addElement(element);
737 // List<TaxonDescription> separatedDescriptions = new ArrayList<TaxonDescription>(descriptions.size());
738 // separatedDescriptions.add(superDescription);
739 // return separatedDescriptions;
741 // return descriptions;
744 // response.sendError(HttpServletResponse.SC_NOT_FOUND, "invalid type; Taxon expected but " + tb.getClass().getSimpleName() + " found.");