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 static java
.net
.HttpURLConnection
.HTTP_BAD_REQUEST
;
15 import java
.io
.IOException
;
16 import java
.util
.ArrayList
;
17 import java
.util
.Arrays
;
18 import java
.util
.HashSet
;
19 import java
.util
.Hashtable
;
20 import java
.util
.Iterator
;
21 import java
.util
.List
;
24 import java
.util
.UUID
;
26 import javax
.servlet
.http
.HttpServletRequest
;
27 import javax
.servlet
.http
.HttpServletResponse
;
29 import org
.apache
.commons
.lang
.ObjectUtils
;
30 import org
.apache
.http
.HttpRequest
;
31 import org
.apache
.log4j
.Logger
;
32 import org
.apache
.lucene
.queryParser
.ParseException
;
33 import org
.springframework
.beans
.factory
.annotation
.Autowired
;
34 import org
.springframework
.stereotype
.Controller
;
35 import org
.springframework
.web
.bind
.WebDataBinder
;
36 import org
.springframework
.web
.bind
.annotation
.InitBinder
;
37 import org
.springframework
.web
.bind
.annotation
.PathVariable
;
38 import org
.springframework
.web
.bind
.annotation
.RequestMapping
;
39 import org
.springframework
.web
.bind
.annotation
.RequestMethod
;
40 import org
.springframework
.web
.bind
.annotation
.RequestParam
;
41 import org
.springframework
.web
.servlet
.ModelAndView
;
44 import eu
.etaxonomy
.cdm
.api
.service
.IDescriptionService
;
45 import eu
.etaxonomy
.cdm
.api
.service
.IFeatureTreeService
;
46 import eu
.etaxonomy
.cdm
.api
.service
.IMarkerService
;
47 import eu
.etaxonomy
.cdm
.api
.service
.INameService
;
48 import eu
.etaxonomy
.cdm
.api
.service
.IOccurrenceService
;
49 import eu
.etaxonomy
.cdm
.api
.service
.IService
;
50 import eu
.etaxonomy
.cdm
.api
.service
.ITaxonService
;
51 import eu
.etaxonomy
.cdm
.api
.service
.IClassificationService
;
52 import eu
.etaxonomy
.cdm
.api
.service
.ITermService
;
53 import eu
.etaxonomy
.cdm
.api
.service
.config
.IFindTaxaAndNamesConfigurator
;
54 import eu
.etaxonomy
.cdm
.api
.service
.config
.FindTaxaAndNamesConfiguratorImpl
;
55 import eu
.etaxonomy
.cdm
.api
.service
.pager
.Pager
;
56 import eu
.etaxonomy
.cdm
.api
.service
.search
.SearchResult
;
57 import eu
.etaxonomy
.cdm
.database
.UpdatableRoutingDataSource
;
58 import eu
.etaxonomy
.cdm
.model
.common
.DefinedTermBase
;
59 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableEntity
;
60 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableSource
;
61 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
62 import eu
.etaxonomy
.cdm
.model
.common
.Marker
;
63 import eu
.etaxonomy
.cdm
.model
.common
.MarkerType
;
64 import eu
.etaxonomy
.cdm
.model
.common
.RelationshipBase
.Direction
;
65 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionElementBase
;
66 import eu
.etaxonomy
.cdm
.model
.description
.Feature
;
67 import eu
.etaxonomy
.cdm
.model
.description
.TaxonDescription
;
68 import eu
.etaxonomy
.cdm
.model
.location
.NamedArea
;
69 import eu
.etaxonomy
.cdm
.model
.location
.NamedAreaLevel
;
70 import eu
.etaxonomy
.cdm
.model
.media
.Media
;
71 import eu
.etaxonomy
.cdm
.model
.media
.MediaRepresentationPart
;
72 import eu
.etaxonomy
.cdm
.model
.media
.MediaUtils
;
73 import eu
.etaxonomy
.cdm
.model
.name
.NameRelationship
;
74 import eu
.etaxonomy
.cdm
.model
.name
.TypeDesignationBase
;
75 import eu
.etaxonomy
.cdm
.model
.taxon
.Synonym
;
76 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
77 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
78 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonNode
;
79 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationship
;
80 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationshipType
;
81 import eu
.etaxonomy
.cdm
.model
.taxon
.Classification
;
82 import eu
.etaxonomy
.cdm
.persistence
.query
.MatchMode
;
83 import eu
.etaxonomy
.cdm
.persistence
.query
.OrderHint
;
84 import eu
.etaxonomy
.cdm
.remote
.controller
.util
.PagerParameters
;
85 import eu
.etaxonomy
.cdm
.remote
.editor
.CdmTypePropertyEditor
;
86 import eu
.etaxonomy
.cdm
.remote
.editor
.MatchModePropertyEditor
;
87 import eu
.etaxonomy
.cdm
.remote
.editor
.NamedAreaPropertyEditor
;
88 import eu
.etaxonomy
.cdm
.remote
.editor
.UUIDListPropertyEditor
;
89 import eu
.etaxonomy
.cdm
.remote
.editor
.UuidList
;
92 * The TaxonPortalController class is a Spring MVC Controller.
94 * The syntax of the mapped service URIs contains the the {datasource-name} path element.
95 * The available {datasource-name}s are defined in a configuration file which
96 * is loaded by the {@link UpdatableRoutingDataSource}. If the
97 * UpdatableRoutingDataSource is not being used in the actual application
98 * context any arbitrary {datasource-name} may be used.
100 * Methods mapped at type level, inherited from super classes ({@link BaseController}):
102 * URI: <b>/{datasource-name}/portal/taxon/{taxon-uuid}</b>
104 * Get the {@link TaxonBase} instance identified by the <code>{taxon-uuid}</code>.
105 * The returned Taxon is initialized by
106 * the following strategy {@link #TAXON_INIT_STRATEGY}
109 * @author a.kohlbecker
114 @RequestMapping(value
= {"/portal/taxon/{uuid}"})
115 public class TaxonPortalController
extends BaseController
<TaxonBase
, ITaxonService
>
117 public static final Logger logger
= Logger
.getLogger(TaxonPortalController
.class);
120 private INameService nameService
;
123 private IDescriptionService descriptionService
;
126 private IOccurrenceService occurrenceService
;
129 private IClassificationService classificationService
;
132 private ITaxonService taxonService
;
135 private ITermService termService
;
138 private IFeatureTreeService featureTreeService
;
140 private static final List
<String
> TAXON_INIT_STRATEGY
= Arrays
.asList(new String
[]{
143 "relationsToThisName.fromTaxon.name",
146 "name.rank.representations",
147 "name.status.type.representations",
149 // taxon descriptions
150 "descriptions.elements.area.$",
151 "descriptions.elements.multilanguageText",
152 "descriptions.elements.media.representations.parts",
153 "descriptions.elements.media.title",
157 private static final List
<String
> TAXON_WITH_NODES_INIT_STRATEGY
= Arrays
.asList(new String
[]{
159 "taxonNodes.classification.$",
160 "taxonNodes.childNodes.$"
163 private static final List
<String
> SIMPLE_TAXON_INIT_STRATEGY
= Arrays
.asList(new String
[]{
166 "relationsToThisName.fromTaxon.name",
169 "name.rank.representations",
170 "name.status.type.representations",
171 "name.nomenclaturalReference"
174 private static final List
<String
> SYNONYMY_INIT_STRATEGY
= Arrays
.asList(new String
[]{
175 // initialize homotypical and heterotypical groups; needs synonyms
176 "synonymRelations.$",
177 "synonymRelations.synonym.$",
178 "synonymRelations.synonym.name.status.type.representation",
179 "synonymRelations.synonym.name.nomenclaturalReference.inReference",
180 "synonymRelations.synonym.name.homotypicalGroup.typifiedNames.$",
181 "synonymRelations.synonym.name.homotypicalGroup.typifiedNames.taxonBases.$",
182 "synonymRelations.synonym.name.combinationAuthorTeam.$",
184 "name.typeDesignations",
186 "name.homotypicalGroup.$",
187 "name.homotypicalGroup.typifiedNames.$",
188 "name.homotypicalGroup.typifiedNames.nomenclaturalReference.authorTeam",
190 "name.homotypicalGroup.typifiedNames.taxonBases.$"
193 private static final List
<String
> SYNONYMY_WITH_NODES_INIT_STRATEGY
= Arrays
.asList(new String
[]{
194 // initialize homotypical and heterotypical groups; needs synonyms
195 "synonymRelations.$",
196 "synonymRelations.synonym.$",
197 "synonymRelations.synonym.name.status.type.representation",
198 "synonymRelations.synonym.name.nomenclaturalReference.inReference",
199 "synonymRelations.synonym.name.homotypicalGroup.typifiedNames.$",
200 "synonymRelations.synonym.name.homotypicalGroup.typifiedNames.taxonBases.$",
201 "synonymRelations.synonym.name.combinationAuthorTeam.$",
203 "name.homotypicalGroup.$",
204 "name.homotypicalGroup.typifiedNames.$",
205 "name.homotypicalGroup.typifiedNames.nomenclaturalReference.authorTeam",
207 "name.homotypicalGroup.typifiedNames.taxonBases.$",
210 "taxonNodes.classification.$",
211 "taxonNodes.childNodes.$"
213 private static final List
<String
> SIMPLE_TAXON_WITH_NODES_INIT_STRATEGY
= Arrays
.asList(new String
[]{
216 "relationsToThisName.fromTaxon.name",
219 "name.rank.representations",
220 "name.status.type.representations",
221 "name.nomenclaturalReference",
224 "taxonNodes.classification.$",
225 "taxonNodes.childNodes.$"
229 private static final List
<String
> TAXONRELATIONSHIP_INIT_STRATEGY
= Arrays
.asList(new String
[]{
231 "type.inverseRepresentations",
238 private static final List
<String
> NAMERELATIONSHIP_INIT_STRATEGY
= Arrays
.asList(new String
[]{
240 "type.inverseRepresentations",
246 protected static final List
<String
> TAXONDESCRIPTION_INIT_STRATEGY
= Arrays
.asList(new String
[]{
249 "elements.sources.citation.authorTeam",
250 "elements.sources.nameUsedInSource.originalNameString",
251 "elements.multilanguageText",
252 "elements.media.representations.parts",
253 "elements.media.title",
256 protected static final List
<String
> TAXONUSEDESCRIPTION_INIT_STRATEGY
= Arrays
.asList(new String
[]{
259 "name.rank.representations",
260 "name.status.type.representations",
264 "elements.sources.citation.authorTeam",
265 "elements.sources.nameUsedInSource.originalNameString",
266 /*//"elements.multilanguageText",
267 "elements.media.representations.parts",*/
268 "elements.media.title",
271 protected static final List
<String
> DESCRIPTION_ELEMENT_INIT_STRATEGY
= Arrays
.asList(new String
[]{
273 "sources.citation.authorTeam",
274 "sources.nameUsedInSource.originalNameString",
276 "media.representations.parts",
281 // private static final List<String> NAMEDESCRIPTION_INIT_STRATEGY = Arrays.asList(new String []{
285 // "elements.multilanguageText",
286 // "elements.media.representations.parts",
287 // "elements.media.title",
290 protected static final List
<String
> TAXONDESCRIPTION_MEDIA_INIT_STRATEGY
= Arrays
.asList(new String
[]{
291 "elements.media.representations.parts",
292 "elements.media.title"
296 private static final List
<String
> TYPEDESIGNATION_INIT_STRATEGY
= Arrays
.asList(new String
[]{
298 "citation.authorTeam.$",
303 protected static final List
<String
> TAXONNODE_WITHTAXON_INIT_STRATEGY
= Arrays
.asList(new String
[]{
307 protected static final List
<String
> TAXONNODE_INIT_STRATEGY
= Arrays
.asList(new String
[]{
308 "taxonNodes.classification"
313 private static final String featureTreeUuidPattern
= "^/taxon(?:(?:/)([^/?#&\\.]+))+.*";
315 public TaxonPortalController(){
317 setInitializationStrategy(TAXON_INIT_STRATEGY
);
321 * @see eu.etaxonomy.cdm.remote.controller.GenericController#setService(eu.etaxonomy.cdm.api.service.IService)
325 public void setService(ITaxonService service
) {
326 this.service
= service
;
331 public void initBinder(WebDataBinder binder
) {
332 super.initBinder(binder
);
333 binder
.registerCustomEditor(NamedArea
.class, new NamedAreaPropertyEditor());
334 binder
.registerCustomEditor(MatchMode
.class, new MatchModePropertyEditor());
335 binder
.registerCustomEditor(Class
.class, new CdmTypePropertyEditor());
336 binder
.registerCustomEditor(UuidList
.class, new UUIDListPropertyEditor());
342 * @see eu.etaxonomy.cdm.remote.controller.BaseController#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
345 @RequestMapping(method = RequestMethod.GET)
346 public TaxonBase doGet(HttpServletRequest request, HttpServletResponse response)throws IOException {
347 logger.info("doGet()");
348 TaxonBase tb = getCdmBase(request, response, TAXON_INIT_STRATEGY, TaxonBase.class);
353 * Find Taxa, Synonyms, Common Names by name, either globally or in a specific geographic area.
355 * URI: <b>/{datasource-name}/portal/taxon/find</b>
358 * the string to query for. Since the wildcard character '*'
359 * internally always is appended to the query string, a search
360 * always compares the query string with the beginning of a name.
361 * - <i>required parameter</i>
363 * the {@link UUID} of a {@link Classification} to which the
364 * search is to be restricted. - <i>optional parameter</i>
366 * restrict the search to a set of geographic {@link NamedArea}s.
367 * The parameter currently takes a list of TDWG area labels.
368 * - <i>optional parameter</i>
370 * the number of the page to be returned, the first page has the
371 * pageNumber = 1 - <i>optional parameter</i>
373 * the maximum number of entities returned per page (can be -1
374 * to return all entities in a single page) - <i>optional parameter</i>
376 * weather to search for instances of {@link Taxon} - <i>optional parameter</i>
378 * weather to search for instances of {@link Synonym} - <i>optional parameter</i>
379 * @param doTaxaByCommonNames
380 * for instances of {@link Taxon} by a common name used - <i>optional parameter</i>
382 * valid values are "EXACT", "BEGINNING", "ANYWHERE", "END" (case sensitive !!!)
383 * @return a Pager on a list of {@link IdentifiableEntity}s initialized by
384 * the following strategy {@link #SIMPLE_TAXON_INIT_STRATEGY}
385 * @throws IOException
387 @RequestMapping(method
= RequestMethod
.GET
,
388 value
= {"/portal/taxon/find"}) //TODO map to path /*/portal/taxon/
389 public Pager
<IdentifiableEntity
> doFind(
390 @RequestParam(value
= "query", required
= false) String query
,
391 @RequestParam(value
= "tree", required
= false) UUID treeUuid
,
392 @RequestParam(value
= "area", required
= false) Set
<NamedArea
> areas
,
393 @RequestParam(value
= "pageNumber", required
= false) Integer pageNumber
,
394 @RequestParam(value
= "pageSize", required
= false) Integer pageSize
,
395 @RequestParam(value
= "doTaxa", required
= false) Boolean doTaxa
,
396 @RequestParam(value
= "doSynonyms", required
= false) Boolean doSynonyms
,
397 @RequestParam(value
= "doMisappliedNames", required
= false) Boolean doMisappliedNames
,
398 @RequestParam(value
= "doTaxaByCommonNames", required
= false) Boolean doTaxaByCommonNames
,
399 @RequestParam(value
= "matchMode", required
= false) MatchMode matchMode
,
400 HttpServletRequest request
,
401 HttpServletResponse response
405 logger
.info("doFind : " + request
.getRequestURI() + "?" + request
.getQueryString() );
407 PagerParameters pagerParams
= new PagerParameters(pageSize
, pageNumber
);
408 pagerParams
.normalizeAndValidate(response
);
410 IFindTaxaAndNamesConfigurator config
= new FindTaxaAndNamesConfiguratorImpl();
411 config
.setPageNumber(pagerParams
.getPageIndex());
412 config
.setPageSize(pagerParams
.getPageSize());
413 config
.setTitleSearchString(query
);
414 config
.setDoTaxa(doTaxa
!= null ? doTaxa
: Boolean
.FALSE
);
415 config
.setDoSynonyms(doSynonyms
!= null ? doSynonyms
: Boolean
.FALSE
);
416 config
.setDoMisappliedNames(doMisappliedNames
!= null ? doMisappliedNames
: Boolean
.FALSE
);
417 config
.setDoTaxaByCommonNames(doTaxaByCommonNames
!= null ? doTaxaByCommonNames
: Boolean
.FALSE
);
418 config
.setMatchMode(matchMode
!= null ? matchMode
: MatchMode
.BEGINNING
);
419 config
.setTaxonPropertyPath(SIMPLE_TAXON_INIT_STRATEGY
);
420 config
.setNamedAreas(areas
);
421 if(treeUuid
!= null){
422 Classification classification
= classificationService
.find(treeUuid
);
423 config
.setClassification(classification
);
426 return (Pager
<IdentifiableEntity
>) service
.findTaxaAndNames(config
);
434 * @param features one or more feature uuids
440 * @throws IOException
441 * @throws ParseException
443 @RequestMapping(method
= RequestMethod
.GET
, value
={"/portal/taxon/findByDescriptionElementFullText"})
444 public Pager
<SearchResult
<TaxonBase
>> dofindByDescriptionElementFullText(
445 @RequestParam(value
= "clazz", required
= false) Class clazz
,
446 @RequestParam(value
= "query", required
= true) String queryString
,
447 @RequestParam(value
= "tree", required
= false) UUID treeUuid
,
448 @RequestParam(value
= "features", required
= false) UuidList featureUuids
,
449 @RequestParam(value
= "languages", required
= false) List
<Language
> languages
,
450 @RequestParam(value
= "hl", required
= false) Boolean highlighting
,
451 @RequestParam(value
= "pageNumber", required
= false) Integer pageNumber
,
452 @RequestParam(value
= "pageSize", required
= false) Integer pageSize
,
453 HttpServletRequest request
,
454 HttpServletResponse response
456 throws IOException
, ParseException
{
458 logger
.info("findByDescriptionElementFullText : " + request
.getRequestURI() + "?" + request
.getQueryString() );
460 PagerParameters pagerParams
= new PagerParameters(pageSize
, pageNumber
);
461 pagerParams
.normalizeAndValidate(response
);
463 if(highlighting
== null){
464 highlighting
= false;
467 Classification classification
= null;
468 if(treeUuid
!= null){
469 classification
= classificationService
.find(treeUuid
);
472 List
<Feature
> features
= null;
473 if(featureUuids
!= null){
474 features
= new ArrayList
<Feature
>(featureUuids
.size());
475 for(UUID uuid
: featureUuids
){
476 features
.add((Feature
) termService
.find(uuid
));
480 Pager
<SearchResult
<TaxonBase
>> pager
= service
.findByDescriptionElementFullText(clazz
, queryString
, classification
, features
, languages
, highlighting
, pagerParams
.getPageSize(), pagerParams
.getPageIndex(), ((List
<OrderHint
>)null), SIMPLE_TAXON_INIT_STRATEGY
);
485 * Get the synonymy for a taxon identified by the <code>{taxon-uuid}</code>.
486 * The synonymy consists
487 * of two parts: The group of homotypic synonyms of the taxon and the
488 * heterotypic synonymy groups of the taxon. The synonymy is ordered
489 * historically by the type designations and by the publication date of the
490 * nomenclatural reference
493 * <b>/{datasource-name}/portal/taxon/{taxon-uuid}/synonymy</b>
498 * @return a Map with to entries which are mapped by the following keys:
499 * "homotypicSynonymsByHomotypicGroup", "heterotypicSynonymyGroups",
500 * containing lists of {@link Synonym}s which are initialized using the
501 * following initialization strategy: {@link #SYNONYMY_INIT_STRATEGY}
503 * @throws IOException
506 value
= {"synonymy"},
507 method
= RequestMethod
.GET
)
508 public ModelAndView
doGetSynonymy(@PathVariable("uuid") UUID uuid
,
509 HttpServletRequest request
, HttpServletResponse response
)throws IOException
{
512 logger
.info("doGetSynonymy() " + request
.getServletPath());
514 ModelAndView mv
= new ModelAndView();
515 Taxon taxon
= getCdmBaseInstance(Taxon
.class, uuid
, response
, (List
<String
>)null);
516 Map
<String
, List
<?
>> synonymy
= new Hashtable
<String
, List
<?
>>();
517 synonymy
.put("homotypicSynonymsByHomotypicGroup", service
.getHomotypicSynonymsByHomotypicGroup(taxon
, SYNONYMY_INIT_STRATEGY
));
518 synonymy
.put("heterotypicSynonymyGroups", service
.getHeterotypicSynonymyGroups(taxon
, SYNONYMY_INIT_STRATEGY
));
519 mv
.addObject(synonymy
);
524 * Get the set of accepted {@link Taxon} entities for a given
525 * {@link TaxonBase} entity identified by the <code>{taxon-uuid}</code>.
527 * URI: <b>/{datasource-name}/portal/taxon/{taxon-uuid}/accepted</b>
531 * @return a Set of {@link Taxon} entities which are initialized
532 * using the following initialization strategy:
533 * {@link #SYNONYMY_INIT_STRATEGY}
534 * @throws IOException
536 @RequestMapping(value
= "accepted/{classification_uuid}", method
= RequestMethod
.GET
)
537 public Set
<TaxonBase
> getAccepted(
538 @PathVariable("uuid") UUID uuid
,
539 @PathVariable("classification_uuid") UUID classification_uuid
,
540 HttpServletRequest request
,
541 HttpServletResponse response
)
545 logger
.info("getAccepted() " + request
.getServletPath());
548 TaxonBase tb
= service
.load(uuid
, SYNONYMY_WITH_NODES_INIT_STRATEGY
);
550 response
.sendError(HttpServletResponse
.SC_NOT_FOUND
, "A taxon with the uuid " + uuid
+ " does not exist");
554 HashSet
<TaxonBase
> resultset
= new HashSet
<TaxonBase
>();
556 if (tb
instanceof Taxon
){
557 Taxon taxon
= (Taxon
) tb
;
558 Set
<TaxonNode
> nodes
= taxon
.getTaxonNodes();
559 for (TaxonNode taxonNode
: nodes
) {
560 if (taxonNode
.getClassification().compareTo(classification_uuid
) == 0){
561 resultset
.add((Taxon
) tb
);
564 if (resultset
.size() > 1){
565 //error!! A taxon is not allow to have more taxonnodes for a given classification
566 response
.sendError(HttpServletResponse
.SC_INTERNAL_SERVER_ERROR
,
567 "A taxon with the uuid " + uuid
+ " has more than one taxon node for the given classification" + classification_uuid
);
570 Synonym syn
= (Synonym
) tb
;
571 for(TaxonBase accepted
: syn
.getAcceptedTaxa()){
572 tb
= service
.load(accepted
.getUuid(), SIMPLE_TAXON_WITH_NODES_INIT_STRATEGY
);
573 if (tb
instanceof Taxon
){
574 Taxon taxon
= (Taxon
) tb
;
575 Set
<TaxonNode
> nodes
= taxon
.getTaxonNodes();
576 for (TaxonNode taxonNode
: nodes
) {
577 if (taxonNode
.getClassification().compareTo(classification_uuid
) == 0){
578 resultset
.add((Taxon
) tb
);
581 if (resultset
.size() > 1){
582 //error!! A taxon is not allow to have more taxonnodes for a given classification
583 response
.sendError(HttpServletResponse
.SC_INTERNAL_SERVER_ERROR
,
584 "A taxon with the uuid " + uuid
+ " has more than one taxon node for the given classification" + classification_uuid
);
587 //ERROR!! perhaps missapplied name????
588 //syn.getRelationType((Taxon)accepted);
594 if(tb instanceof Taxon){
595 //the taxon already is accepted
596 //FIXME take the current view into account once views are implemented!!!
597 resultset.add((Taxon)tb);
599 Synonym syn = (Synonym)tb;
600 for(TaxonBase accepted : syn.getAcceptedTaxa()){
601 accepted = service.load(accepted.getUuid(), SIMPLE_TAXON_INIT_STRATEGY);
602 resultset.add(accepted);
610 * Get the list of {@link TaxonRelationship}s for the given
611 * {@link TaxonBase} instance identified by the <code>{taxon-uuid}</code>.
613 * URI: <b>/{datasource-name}/portal/taxon/{taxon-uuid}/taxonRelationships</b>
617 * @return a List of {@link TaxonRelationship} entities which are initialized
618 * using the following initialization strategy:
619 * {@link #TAXONRELATIONSHIP_INIT_STRATEGY}
620 * @throws IOException
623 value
= {"taxonRelationships"},
624 method
= RequestMethod
.GET
)
625 public List
<TaxonRelationship
> doGetTaxonRelations(@PathVariable("uuid") UUID uuid
,
626 HttpServletRequest request
, HttpServletResponse response
)throws IOException
{
628 logger
.info("doGetTaxonRelations()" + request
.getServletPath());
629 Taxon taxon
= getCdmBaseInstance(Taxon
.class, uuid
, response
, (List
<String
>)null);
630 List
<TaxonRelationship
> toRelationships
= service
.listToTaxonRelationships(taxon
, null, null, null, null, TAXONRELATIONSHIP_INIT_STRATEGY
);
631 List
<TaxonRelationship
> fromRelationships
= service
.listFromTaxonRelationships(taxon
, null, null, null, null, TAXONRELATIONSHIP_INIT_STRATEGY
);
633 List
<TaxonRelationship
> allRelationships
= new ArrayList
<TaxonRelationship
>(toRelationships
.size() + fromRelationships
.size());
634 allRelationships
.addAll(toRelationships
);
635 allRelationships
.addAll(fromRelationships
);
637 return allRelationships
;
641 * Get the list of {@link NameRelationship}s of the Name associated with the
642 * {@link TaxonBase} instance identified by the <code>{taxon-uuid}</code>.
644 * URI: <b>/{datasource-name}/portal/taxon/{taxon-uuid}/nameRelationships</b>
648 * @return a List of {@link NameRelationship} entities which are initialized
649 * using the following initialization strategy:
650 * {@link #NAMERELATIONSHIP_INIT_STRATEGY}
651 * @throws IOException
654 value
= {"toNameRelationships"},
655 method
= RequestMethod
.GET
)
656 public List
<NameRelationship
> doGetToNameRelations(@PathVariable("uuid") UUID uuid
,
657 HttpServletRequest request
, HttpServletResponse response
)throws IOException
{
658 logger
.info("doGetNameRelations()" + request
.getServletPath());
659 TaxonBase taxonBase
= getCdmBaseInstance(TaxonBase
.class, uuid
, response
, (List
<String
>)null);
660 List
<NameRelationship
> list
= nameService
.listNameRelationships(taxonBase
.getName(), Direction
.relatedTo
, null, null, 0, null, NAMERELATIONSHIP_INIT_STRATEGY
);
661 //List<NameRelationship> list = nameService.listToNameRelationships(taxonBase.getName(), null, null, null, null, NAMERELATIONSHIP_INIT_STRATEGY);
666 * Get the list of {@link NameRelationship}s of the Name associated with the
667 * {@link TaxonBase} instance identified by the <code>{taxon-uuid}</code>.
669 * URI: <b>/{datasource-name}/portal/taxon/{taxon-uuid}/nameRelationships</b>
673 * @return a List of {@link NameRelationship} entities which are initialized
674 * using the following initialization strategy:
675 * {@link #NAMERELATIONSHIP_INIT_STRATEGY}
676 * @throws IOException
679 value
= {"fromNameRelationships"},
680 method
= RequestMethod
.GET
)
681 public List
<NameRelationship
> doGetFromNameRelations(@PathVariable("uuid") UUID uuid
,
682 HttpServletRequest request
, HttpServletResponse response
)throws IOException
{
683 logger
.info("doGetNameFromNameRelations()" + request
.getServletPath());
685 TaxonBase taxonbase
= getCdmBaseInstance(TaxonBase
.class, uuid
, response
, SIMPLE_TAXON_INIT_STRATEGY
);
686 List
<NameRelationship
> list
= nameService
.listNameRelationships(taxonbase
.getName(), Direction
.relatedFrom
, null, null, 0, null, NAMERELATIONSHIP_INIT_STRATEGY
);
687 //List<NameRelationship> list = nameService.listFromNameRelationships(taxonbase.getName(), null, null, null, null, NAMERELATIONSHIP_INIT_STRATEGY);
692 * Get the list of {@link TypeDesignationBase}s of the
693 * {@link TaxonBase} instance identified by the <code>{taxon-uuid}</code>.
695 * URI: <b>/{datasource-name}/portal/taxon/{taxon-uuid}/nameTypeDesignations</b>
699 * @return a List of {@link TypeDesignationBase} entities which are initialized
700 * using the following initialization strategy:
701 * {@link #TYPEDESIGNATION_INIT_STRATEGY}
702 * @throws IOException
703 * @Deprecated use /name/{uuid}/typeDesignations & /derivedunitfacade/{uuid} instead
704 * also see http://dev.e-taxonomy.eu/trac/ticket/2280
708 value
= {"nameTypeDesignations"},
709 method
= RequestMethod
.GET
)
710 public List
<TypeDesignationBase
> doGetNameTypeDesignations(@PathVariable("uuid") UUID uuid
,
711 HttpServletRequest request
, HttpServletResponse response
)throws IOException
{
712 logger
.info("doGetNameTypeDesignations()" + request
.getServletPath());
713 Taxon taxon
= getCdmBaseInstance(Taxon
.class, uuid
, response
, SIMPLE_TAXON_INIT_STRATEGY
);
714 Pager
<TypeDesignationBase
> p
= nameService
.getTypeDesignations(taxon
.getName(), null, null, null, TYPEDESIGNATION_INIT_STRATEGY
);
715 return p
.getRecords();
718 @RequestMapping(value
= "taxonNodes", method
= RequestMethod
.GET
)
719 public Set
<TaxonNode
> doGetTaxonNodes(
720 @PathVariable("uuid") UUID uuid
,
721 HttpServletRequest request
,
722 HttpServletResponse response
) throws IOException
{
723 TaxonBase tb
= service
.load(uuid
, TAXONNODE_INIT_STRATEGY
);
724 if(tb
instanceof Taxon
){
725 return ((Taxon
)tb
).getTaxonNodes();
727 HttpStatusMessage
.UUID_REFERENCES_WRONG_TYPE
.send(response
);
733 * Get the list of {@link TaxonDescription}s of the
734 * {@link Taxon} instance identified by the <code>{taxon-uuid}</code>.
736 * URI: <b>/{datasource-name}/portal/taxon/{taxon-uuid}/descriptions</b>
740 * @return a List of {@link TaxonDescription} entities which are initialized
741 * using the following initialization strategy:
742 * {@link #TAXONDESCRIPTION_INIT_STRATEGY}
743 * @throws IOException
746 value
= {"descriptions"},
747 method
= RequestMethod
.GET
)
748 public List
<TaxonDescription
> doGetDescriptions(
749 @PathVariable("uuid") UUID uuid
,
750 @RequestParam(value
= "markerTypes", required
= false) UuidList markerTypeUUIDs
,
751 HttpServletRequest request
,
752 HttpServletResponse response
)throws IOException
{
754 logger
.info("doGetDescriptions()" + request
.getServletPath());
756 List
<DefinedTermBase
> markerTypeTerms
= null;
757 Set
<UUID
> sMarkerTypeUUIDs
= null;
759 if(markerTypeUUIDs
!= null && !markerTypeUUIDs
.isEmpty()){
760 sMarkerTypeUUIDs
= new HashSet
<UUID
>(markerTypeUUIDs
);
761 markerTypeTerms
= termService
.find(sMarkerTypeUUIDs
);
762 } else if(markerTypeUUIDs
!= null && markerTypeUUIDs
.isEmpty()){
763 markerTypeTerms
= new ArrayList
<DefinedTermBase
>();
765 Set
<MarkerType
> markerTypes
= new HashSet
<MarkerType
>();
766 List
<TaxonDescription
> descriptions
= new ArrayList
<TaxonDescription
>();
767 if (markerTypeTerms
!= null) {
768 for (DefinedTermBase markerTypeTerm
: markerTypeTerms
) {
769 markerTypes
.add((MarkerType
)markerTypeTerm
);
772 Taxon t
= getCdmBaseInstance(Taxon
.class, uuid
, response
, (List
<String
>)null);
773 if (markerTypeTerms
== null) {
775 Pager
<TaxonDescription
> p
= descriptionService
.getTaxonDescriptions(t
, null, null, null, null, TAXONDESCRIPTION_INIT_STRATEGY
);
776 descriptions
= p
.getRecords();
779 else if (markerTypeTerms
!= null && markerTypeTerms
.isEmpty()) {
780 descriptions
= descriptionService
.listTaxonDescriptions(t
, null, null, markerTypes
, null, null, TAXONUSEDESCRIPTION_INIT_STRATEGY
);
784 descriptions
= descriptionService
.listTaxonDescriptions(t
, null, null, markerTypes
, null, null, TAXONUSEDESCRIPTION_INIT_STRATEGY
);
785 /*for (TaxonDescription description: descriptions) {
786 for (IdentifiableSource source :description.getSources()) {
787 if (source.getOriginalNameString() != null) {
799 @RequestMapping(value
= "useDescriptions", method
= RequestMethod
.GET
)
800 public List
<TaxonDescription
> doGetUseDescriptions(
801 @PathVariable("uuid") UUID uuid
,
802 HttpServletRequest request
,
803 HttpServletResponse response
) throws IOException
{
804 logger
.info("doGetDescriptionElements() - " + request
.getServletPath());
806 //ModelAndView mv = new ModelAndView();
807 Taxon t
= getCdmBaseInstance(Taxon
.class, uuid
, response
, (List
<String
>)null);
809 //MarkerType useMarkerType = (MarkerType) markerTypeService.find(UUID.fromString("2e6e42d9-e92a-41f4-899b-03c0ac64f059"));
810 MarkerType useMarkerType
= (MarkerType
) termService
.find(UUID
.fromString("2e6e42d9-e92a-41f4-899b-03c0ac64f039"));
812 //find(UUID.fromString("2e6e42d9-e92a-41f4-899b-03c0ac64f059"));
813 Set
<MarkerType
> markerTypes
= new HashSet
<MarkerType
>();
814 markerTypes
.add(useMarkerType
);
815 List
<TaxonDescription
> descriptionElements
= descriptionService
.listTaxonDescriptions(t
, null, null, markerTypes
, null, null, TAXONUSEDESCRIPTION_INIT_STRATEGY
);
816 //getDescriptionElements(description, features, type, pageSize, pageNumber, propertyPaths) load(uuid);
818 /*if(!(description instanceof TaxonDescription)){
819 HttpStatusMessage.UUID_REFERENCES_WRONG_TYPE.send(response);
820 // will terminate thread
823 //boolean hasStructuredData = service. hasStructuredData(description);
825 //mv.addObject(hasStructuredData);
827 return descriptionElements
;
830 @RequestMapping(value
= "descriptions/elementsByType/{classSimpleName}", method
= RequestMethod
.GET
)
831 public ModelAndView
doGetDescriptionElementsByType(
832 @PathVariable("uuid") UUID uuid
,
833 @PathVariable("classSimpleName") String classSimpleName
,
834 @RequestParam(value
= "markerTypes", required
= false) UuidList markerTypeUUIDs
,
835 @RequestParam(value
= "count", required
= false, defaultValue
= "false") Boolean doCount
,
836 HttpServletRequest request
,
837 HttpServletResponse response
) throws IOException
{
838 logger
.info("doGetDescriptionElementsByType() - " + request
.getServletPath());
840 ModelAndView mv
= new ModelAndView();
842 List
<DescriptionElementBase
> allElements
= new ArrayList
<DescriptionElementBase
>();
843 List
<DescriptionElementBase
> elements
;
846 List
<String
> initStrategy
= doCount ?
null : DESCRIPTION_ELEMENT_INIT_STRATEGY
;
848 List
<TaxonDescription
> taxonDescriptions
= doGetDescriptions(uuid
, markerTypeUUIDs
, request
, response
);
851 type
= Class
.forName("eu.etaxonomy.cdm.model.description."
853 if (taxonDescriptions
!= null) {
854 for (TaxonDescription description
: taxonDescriptions
) {
855 elements
= descriptionService
.listDescriptionElements(description
, null, type
, null, 0, initStrategy
);
856 allElements
.addAll(elements
);
857 count
+= elements
.size();
861 } catch (ClassNotFoundException e
) {
862 HttpStatusMessage
.fromString(e
.getLocalizedMessage()).send(response
);
867 mv
.addObject(allElements
);
872 // @RequestMapping(value = "specimens", method = RequestMethod.GET)
873 // public ModelAndView doGetSpecimens(
874 // @PathVariable("uuid") UUID uuid,
875 // HttpServletRequest request,
876 // HttpServletResponse response) throws IOException, ClassNotFoundException {
877 // logger.info("doGetSpecimens() - " + request.getServletPath());
879 // ModelAndView mv = new ModelAndView();
881 // List<DerivedUnitFacade> derivedUnitFacadeList = new ArrayList<DerivedUnitFacade>();
883 // // find speciemens in the TaxonDescriptions
884 // List<TaxonDescription> taxonDescriptions = doGetDescriptions(uuid, request, response);
885 // if (taxonDescriptions != null) {
887 // for (TaxonDescription description : taxonDescriptions) {
888 // derivedUnitFacadeList.addAll( occurrenceService.listDerivedUnitFacades(description, null) );
891 // // TODO find speciemens in the NameDescriptions ??
893 // // TODO also find type specimens
895 // mv.addObject(derivedUnitFacadeList);
901 * Get the {@link Media} attached to the {@link Taxon} instance
902 * identified by the <code>{taxon-uuid}</code>.
904 * Usage /{datasource-name}/portal/taxon/{taxon-
905 * uuid}/media/{mime type
906 * list}/{size}[,[widthOrDuration}][,{height}]/
910 * <li><b>{mime type list}</b>: a comma separated list of mime types, in the
911 * order of preference. The forward slashes contained in the mime types must
912 * be replaced by a colon. Regular expressions can be used. Each media
913 * associated with this given taxon is being searched whereas the first
914 * matching mime type matching a representation always rules.</li>
915 * <li><b>{size},{widthOrDuration},{height}</b>: <i>not jet implemented</i>
916 * valid values are an integer or the asterisk '*' as a wildcard</li>
921 * @return a List of {@link Media} entities which are initialized
922 * using the following initialization strategy:
923 * {@link #TAXONDESCRIPTION_INIT_STRATEGY}
924 * @throws IOException
928 method
= RequestMethod
.GET
)
929 public List
<Media
> doGetMedia(
930 @PathVariable("uuid") UUID uuid
,
931 @RequestParam(value
= "type", required
= false) Class
<?
extends MediaRepresentationPart
> type
,
932 @RequestParam(value
= "mimeTypes", required
= false) String
[] mimeTypes
,
933 @RequestParam(value
= "widthOrDuration", required
= false) Integer widthOrDuration
,
934 @RequestParam(value
= "height", required
= false) Integer height
,
935 @RequestParam(value
= "size", required
= false) Integer size
,
936 HttpServletRequest request
, HttpServletResponse response
) throws IOException
{
938 logger
.info("doGetMedia()" + request
.getServletPath());
939 Taxon t
= getCdmBaseInstance(Taxon
.class, uuid
, response
, (List
<String
>)null);
940 String path
= request
.getServletPath();
941 List
<Media
> returnMedia
= getMediaForTaxon(t
, type
, mimeTypes
, widthOrDuration
, height
, size
);
946 value
= {"subtree/media"},
947 method
= RequestMethod
.GET
)
948 public List
<Media
> doGetSubtreeMedia(
949 @PathVariable("uuid") UUID uuid
,
950 @RequestParam(value
= "type", required
= false) Class
<?
extends MediaRepresentationPart
> type
,
951 @RequestParam(value
= "mimeTypes", required
= false) String
[] mimeTypes
,
952 @RequestParam(value
= "widthOrDuration", required
= false) Integer widthOrDuration
,
953 @RequestParam(value
= "height", required
= false) Integer height
,
954 @RequestParam(value
= "size", required
= false) Integer size
,
955 HttpServletRequest request
, HttpServletResponse response
)throws IOException
{
956 logger
.info("doGetMedia()" + request
.getServletPath());
957 Taxon taxon
= getCdmBaseInstance(Taxon
.class, uuid
, response
, TAXON_WITH_NODES_INIT_STRATEGY
);
958 String requestPath
= request
.getServletPath();
959 List
<Media
> returnMedia
= getMediaForTaxon(taxon
, type
, mimeTypes
, widthOrDuration
, height
, size
);
961 //looking for all medias of genus
962 if (taxon
.getTaxonNodes().size()>0){
963 Set
<TaxonNode
> nodes
= taxon
.getTaxonNodes();
964 Iterator
<TaxonNode
> iterator
= nodes
.iterator();
966 node
= iterator
.next();
967 //Check if TaxonNode belongs to the current tree
969 node
= classificationService
.loadTaxonNode(node
, TAXONNODE_WITHTAXON_INIT_STRATEGY
);
970 Set
<TaxonNode
> children
= node
.getChildNodes();
972 for (TaxonNode child
: children
){
973 childTaxon
= child
.getTaxon();
974 childTaxon
= (Taxon
)taxonService
.load(childTaxon
.getUuid(), null);
975 returnMedia
.addAll(getMediaForTaxon(childTaxon
, type
, mimeTypes
, widthOrDuration
, height
, size
));
982 private List
<Media
> getMediaForTaxon(Taxon taxon
, Class
<?
extends MediaRepresentationPart
> type
, String
[] mimeTypes
,
983 Integer widthOrDuration
, Integer height
, Integer size
){
985 List
<Media
> taxonGalleryMedia
= service
.listTaxonDescriptionMedia(taxon
, false, TAXONDESCRIPTION_MEDIA_INIT_STRATEGY
);
987 List
<Media
> returnMedia
= MediaUtils
.findPreferredMedia(taxonGalleryMedia
, type
,
988 mimeTypes
, null, widthOrDuration
, height
, size
);
996 private List<Media> listTaxonDescriptionMedia(Taxon taxon, boolean limitToGalleries) {
997 Pager<TaxonDescription> p =
998 descriptionService.getTaxonDescriptions(taxon, null, null, null, null, TAXONDESCRIPTION_MEDIA_INIT_STRATEGY);
1000 // pars the media and quality parameters
1003 // collect all media of the given taxon
1004 List<Media> taxonMedia = new ArrayList<Media>();
1005 List<Media> taxonGalleryMedia = new ArrayList<Media>();
1006 for(TaxonDescription desc : p.getRecords()){
1008 if(desc.isImageGallery()){
1009 for(DescriptionElementBase element : desc.getElements()){
1010 for(Media media : element.getMedia()){
1011 taxonGalleryMedia.add(media);
1014 } else if(!limitToGalleries){
1015 for(DescriptionElementBase element : desc.getElements()){
1016 for(Media media : element.getMedia()){
1017 taxonMedia.add(media);
1024 taxonGalleryMedia.addAll(taxonMedia);
1025 return taxonGalleryMedia;
1030 // ---------------------- code snippet preserved for possible later use --------------------
1032 // value = {"/*/portal/taxon/*/descriptions"},
1033 // method = RequestMethod.GET)
1034 // public List<TaxonDescription> doGetDescriptionsbyFeatureTree(HttpServletRequest request, HttpServletResponse response)throws IOException {
1035 // TaxonBase tb = getCdmBase(request, response, null, Taxon.class);
1036 // if(tb instanceof Taxon){
1037 // //T O D O this is a quick and dirty implementation -> generalize
1038 // UUID featureTreeUuid = readValueUuid(request, featureTreeUuidPattern);
1040 // FeatureTree featureTree = descriptionService.getFeatureTreeByUuid(featureTreeUuid);
1041 // Pager<TaxonDescription> p = descriptionService.getTaxonDescriptions((Taxon)tb, null, null, null, null, TAXONDESCRIPTION_INIT_STRATEGY);
1042 // List<TaxonDescription> descriptions = p.getRecords();
1044 // if(!featureTree.isDescriptionSeparated()){
1046 // TaxonDescription superDescription = TaxonDescription.NewInstance();
1047 // //put all descriptionElements in superDescription and make it invisible
1048 // for(TaxonDescription description: descriptions){
1049 // for(DescriptionElementBase element: description.getElements()){
1050 // superDescription.addElement(element);
1053 // List<TaxonDescription> separatedDescriptions = new ArrayList<TaxonDescription>(descriptions.size());
1054 // separatedDescriptions.add(superDescription);
1055 // return separatedDescriptions;
1057 // return descriptions;
1060 // response.sendError(HttpServletResponse.SC_NOT_FOUND, "invalid type; Taxon expected but " + tb.getClass().getSimpleName() + " found.");