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
.HashMap
;
17 import java
.util
.HashSet
;
18 import java
.util
.Hashtable
;
19 import java
.util
.Iterator
;
20 import java
.util
.List
;
22 import java
.util
.NoSuchElementException
;
24 import java
.util
.SortedMap
;
25 import java
.util
.TreeMap
;
26 import java
.util
.UUID
;
27 import java
.util
.regex
.Matcher
;
28 import java
.util
.regex
.Pattern
;
30 import javax
.servlet
.http
.HttpServletRequest
;
31 import javax
.servlet
.http
.HttpServletResponse
;
33 import org
.apache
.commons
.lang
.ObjectUtils
;
34 import org
.apache
.log4j
.Logger
;
35 import org
.springframework
.beans
.factory
.annotation
.Autowired
;
36 import org
.springframework
.beans
.factory
.parsing
.ParseState
.Entry
;
37 import org
.springframework
.stereotype
.Controller
;
38 import org
.springframework
.web
.bind
.WebDataBinder
;
39 import org
.springframework
.web
.bind
.annotation
.InitBinder
;
40 import org
.springframework
.web
.bind
.annotation
.RequestMapping
;
41 import org
.springframework
.web
.bind
.annotation
.RequestMethod
;
42 import org
.springframework
.web
.bind
.annotation
.RequestParam
;
43 import org
.springframework
.web
.servlet
.ModelAndView
;
45 import eu
.etaxonomy
.cdm
.api
.service
.IDescriptionService
;
46 import eu
.etaxonomy
.cdm
.api
.service
.INameService
;
47 import eu
.etaxonomy
.cdm
.api
.service
.IReferenceService
;
48 import eu
.etaxonomy
.cdm
.api
.service
.ITaxonService
;
49 import eu
.etaxonomy
.cdm
.api
.service
.ITaxonTreeService
;
50 import eu
.etaxonomy
.cdm
.api
.service
.config
.ITaxonServiceConfigurator
;
51 import eu
.etaxonomy
.cdm
.api
.service
.config
.impl
.TaxonServiceConfiguratorImpl
;
52 import eu
.etaxonomy
.cdm
.api
.service
.pager
.Pager
;
53 import eu
.etaxonomy
.cdm
.database
.UpdatableRoutingDataSource
;
54 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableEntity
;
55 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionElementBase
;
56 import eu
.etaxonomy
.cdm
.model
.description
.TaxonDescription
;
57 import eu
.etaxonomy
.cdm
.model
.description
.TaxonNameDescription
;
58 import eu
.etaxonomy
.cdm
.model
.location
.NamedArea
;
59 import eu
.etaxonomy
.cdm
.model
.media
.Media
;
60 import eu
.etaxonomy
.cdm
.model
.media
.MediaRepresentation
;
61 import eu
.etaxonomy
.cdm
.model
.name
.NameRelationship
;
62 import eu
.etaxonomy
.cdm
.model
.name
.TaxonNameBase
;
63 import eu
.etaxonomy
.cdm
.model
.name
.TypeDesignationBase
;
64 import eu
.etaxonomy
.cdm
.model
.taxon
.Synonym
;
65 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
66 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
67 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonNode
;
68 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationship
;
69 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationshipType
;
70 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonomicTree
;
71 import eu
.etaxonomy
.cdm
.persistence
.query
.MatchMode
;
72 import eu
.etaxonomy
.cdm
.remote
.editor
.NamedAreaPropertyEditor
;
73 import eu
.etaxonomy
.cdm
.remote
.editor
.UUIDPropertyEditor
;
76 * The TaxonPortalController class is a Spring MVC Controller.
78 * The syntax of the mapped service URIs contains the the {datasource-name} path element.
79 * The available {datasource-name}s are defined in a configuration file which
80 * is loaded by the {@link UpdatableRoutingDataSource}. If the
81 * UpdatableRoutingDataSource is not being used in the actual application
82 * context any arbitrary {datasource-name} may be used.
84 * Methods mapped at type level, inherited from super classes ({@link BaseController}):
86 * URI: <b>/{datasource-name}/portal/taxon/{taxon-uuid}</b>
88 * Get the {@link TaxonBase} instance identified by the <code>{taxon-uuid}</code>.
89 * The returned Taxon is initialized by
90 * the following strategy {@link #TAXON_INIT_STRATEGY}
93 * @author a.kohlbecker
98 @RequestMapping(value
= {"/*/portal/taxon/*", "/*/portal/taxon/*/*", "/*/portal/name/*/*", "/*/portal/taxon/*/media/*/*"})
99 public class TaxonPortalController
extends BaseController
<TaxonBase
, ITaxonService
>
101 public static final Logger logger
= Logger
.getLogger(TaxonPortalController
.class);
104 private INameService nameService
;
106 private IDescriptionService descriptionService
;
108 private IReferenceService referenceService
;
111 private ITaxonTreeService taxonTreeService
;
114 private ITaxonService taxonService
;
116 private static final List
<String
> TAXON_INIT_STRATEGY
= Arrays
.asList(new String
[]{
119 "relationsToThisName.fromTaxon.name.taggedName",
123 "name.rank.representations",
124 "name.status.type.representations",
126 // taxon descriptions
127 "descriptions.elements.$",
128 "descriptions.elements.area",
129 "descriptions.elements.area.$",
130 "descriptions.elements.multilanguageText",
131 "descriptions.elements.media.representations.parts",
133 // // typeDesignations
134 // "name.typeDesignations.$",
135 // "name.typeDesignations.citation.authorTeam",
136 // "name.typeDesignations.typeName.$",
137 // "name.typeDesignations.typeStatus.representations",
138 // "name.typeDesignations.typeSpecimen.media.representations.parts"
142 private static final List
<String
> SIMPLE_TAXON_INIT_STRATEGY
= Arrays
.asList(new String
[]{
145 "relationsToThisName.fromTaxon.name.taggedName",
149 "name.rank.representations",
150 "name.status.type.representations"
153 private static final List
<String
> SYNONYMY_INIT_STRATEGY
= Arrays
.asList(new String
[]{
154 // initialize homotypical and heterotypical groups; needs synonyms
155 "synonymRelations.$",
156 "synonymRelations.synonym.$",
157 "synonymRelations.synonym.name.taggedName",
158 "synonymRelations.synonym.name.nomenclaturalReference.inBook.authorTeam",
159 "synonymRelations.synonym.name.nomenclaturalReference.inJournal",
160 "synonymRelations.synonym.name.nomenclaturalReference.inProceedings",
161 "synonymRelations.synonym.name.homotypicalGroup.typifiedNames.$",
162 "synonymRelations.synonym.name.homotypicalGroup.typifiedNames.name.taggedName",
163 "synonymRelations.synonym.name.homotypicalGroup.typifiedNames.taxonBases.$",
164 "synonymRelations.synonym.name.homotypicalGroup.typifiedNames.taxonBases.name.taggedName",
166 "name.homotypicalGroup.$",
167 "name.homotypicalGroup.typifiedNames.$",
168 "name.homotypicalGroup.typifiedNames.name.taggedName",
170 "name.homotypicalGroup.typifiedNames.taxonBases.$",
171 "name.homotypicalGroup.typifiedNames.taxonBases.name.taggedName"
175 private static final List
<String
> TAXONRELATIONSHIP_INIT_STRATEGY
= Arrays
.asList(new String
[]{
177 "type.inverseRepresentations",
178 "fromTaxon.sec.authorTeam",
179 "fromTaxon.name.taggedName"
182 private static final List
<String
> NAMERELATIONSHIP_INIT_STRATEGY
= Arrays
.asList(new String
[]{
184 "type.inverseRepresentations",
185 "fromName.taggedName",
189 protected static final List
<String
> TAXONDESCRIPTION_INIT_STRATEGY
= Arrays
.asList(new String
[]{
192 "elements.sources.citation.",
193 "elements.sources.citation.authorTeam.$",
194 //"elements.sources.citation.authorTeam.teamMembers.",
195 "elements.multilanguageText",
196 "elements.media.representations.parts",
199 protected static final List
<String
> TAXON_MEDIA_INIT_STRATEGY
= Arrays
.asList(new String
[]{
201 "media.representations.",
202 "media.representations.parts"
205 private static final List
<String
> NAMEDESCRIPTION_INIT_STRATEGY
= Arrays
.asList(new String
[]{
209 "elements.multilanguageText",
210 "elements.media.representations.parts",
213 private static final List
<String
> TYPEDESIGNATION_INIT_STRATEGY
= Arrays
.asList(new String
[]{
216 "typeStatus.representations",
217 "citation.authorTeam",
218 "typeName.taggedName"
223 private static final String featureTreeUuidPattern
= "^/(?:[^/]+)/taxon(?:(?:/)([^/?#&\\.]+))+.*";
225 public TaxonPortalController(){
227 setInitializationStrategy(TAXON_INIT_STRATEGY
);
228 setUuidParameterPattern("^/(?:[^/]+)/portal/(?:[^/]+)/([^/?#&\\.]+).*");
232 * @see eu.etaxonomy.cdm.remote.controller.GenericController#setService(eu.etaxonomy.cdm.api.service.IService)
236 public void setService(ITaxonService service
) {
237 this.service
= service
;
241 public void initBinder(WebDataBinder binder
) {
242 binder
.registerCustomEditor(UUID
.class, new UUIDPropertyEditor());
243 binder
.registerCustomEditor(NamedArea
.class, new NamedAreaPropertyEditor());
248 * @see eu.etaxonomy.cdm.remote.controller.BaseController#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
251 @RequestMapping(method = RequestMethod.GET)
252 public TaxonBase doGet(HttpServletRequest request, HttpServletResponse response)throws IOException {
253 logger.info("doGet()");
254 TaxonBase tb = getCdmBase(request, response, TAXON_INIT_STRATEGY, TaxonBase.class);
259 * Find Taxa, Synonyms, Common Names by name, either globally or in a specific geographic area.
261 * URI: <b>/{datasource-name}/portal/taxon/find</b>
264 * the string to query for. Since the wildcard character '*'
265 * internally always is appended to the query string, a search
266 * always compares the query string with the beginning of a name.
267 * - <i>required parameter</i>
269 * the {@link UUID} of a {@link TaxonomicTree} to which the
270 * search is to be restricted. - <i>optional parameter</i>
272 * restrict the search to a set of geographic {@link NamedArea}s.
273 * The parameter currently takes a list of TDWG area labels.
274 * - <i>optional parameter</i>
276 * the number of the page to be returned, the first page has the
277 * pageNumber = 1 - <i>optional parameter</i>
279 * the maximum number of entities returned per page (can be null
280 * to return all entities in a single page) - <i>optional parameter</i>
282 * weather to search for instances of {@link Taxon} - <i>optional parameter</i>
284 * weather to search for instances of {@link Synonym} - <i>optional parameter</i>
285 * @param doTaxaByCommonNames
286 * for instances of {@link Taxon} by a common name used - <i>optional parameter</i>
287 * @return a Pager on a list of {@link IdentifiableEntity}s initialized by
288 * the following strategy {@link #SIMPLE_TAXON_INIT_STRATEGY}
289 * @throws IOException
291 @RequestMapping(method
= RequestMethod
.GET
,
292 value
= {"/*/portal/taxon/find"}) //TODO map to path /*/portal/taxon/
293 public Pager
<IdentifiableEntity
> doFind(
294 @RequestParam(value
= "query", required
= false) String query
,
295 @RequestParam(value
= "tree", required
= false) UUID treeUuid
,
296 @RequestParam(value
= "area", required
= false) Set
<NamedArea
> areas
,
297 @RequestParam(value
= "page", required
= false) Integer page
,
298 @RequestParam(value
= "pageSize", required
= false) Integer pageSize
,
299 @RequestParam(value
= "doTaxa", required
= false) Boolean doTaxa
,
300 @RequestParam(value
= "doSynonyms", required
= false) Boolean doSynonyms
,
301 @RequestParam(value
= "doTaxaByCommonNames", required
= false) Boolean doTaxaByCommonNames
)
304 logger
.info("doFind( " +
305 "query=\"" + ObjectUtils
.toString(query
) + "\", treeUuid=" + ObjectUtils
.toString(treeUuid
) +
306 ", area=" + ObjectUtils
.toString(areas
) +
307 ", pageSize=" + ObjectUtils
.toString(pageSize
) + ", page=" + ObjectUtils
.toString(page
) +
308 ", doTaxa=" + ObjectUtils
.toString(doTaxa
) + ", doSynonyms=" + ObjectUtils
.toString(doSynonyms
) +")" );
310 if(page
== null){ page
= BaseListController
.DEFAULT_PAGE_NUMBER
;}
311 if(pageSize
== null){ pageSize
= BaseListController
.DEFAULT_PAGESIZE
;}
313 ITaxonServiceConfigurator config
= new TaxonServiceConfiguratorImpl();
314 config
.setPageNumber(page
);
315 config
.setPageSize(pageSize
);
316 config
.setSearchString(query
);
317 config
.setDoTaxa(doTaxa
!= null ? doTaxa
: Boolean
.FALSE
);
318 config
.setDoSynonyms(doSynonyms
!= null ? doSynonyms
: Boolean
.FALSE
);
319 config
.setDoTaxaByCommonNames(doTaxaByCommonNames
!= null ? doTaxaByCommonNames
: Boolean
.FALSE
);
320 config
.setMatchMode(MatchMode
.BEGINNING
);
321 config
.setTaxonPropertyPath(SIMPLE_TAXON_INIT_STRATEGY
);
322 config
.setNamedAreas(areas
);
323 if(treeUuid
!= null){
324 TaxonomicTree taxonomicTree
= taxonTreeService
.find(treeUuid
);
325 config
.setTaxonomicTree(taxonomicTree
);
328 return (Pager
<IdentifiableEntity
>) service
.findTaxaAndNames(config
);
332 * Get the synonymy for a taxon identified by the <code>{taxon-uuid}</code>.
333 * The synonymy consists
334 * of two parts: The group of homotypic synonyms of the taxon and the
335 * heterotypic synonymy groups of the taxon. The synonymy is ordered
336 * historically by the type designations and by the publication date of the
337 * nomenclatural reference
340 * <b>/{datasource-name}/portal/taxon/{taxon-uuid}/synonymy</b>
345 * @return a Map with to entries which are mapped by the following keys:
346 * "homotypicSynonymsByHomotypicGroup", "heterotypicSynonymyGroups",
347 * containing lists of {@link Synonym}s which are initialized using the
348 * following initialization strategy: {@link #SYNONYMY_INIT_STRATEGY}
350 * @throws IOException
353 value
= {"/*/portal/taxon/*/synonymy"},
354 method
= RequestMethod
.GET
)
355 public ModelAndView
doGetSynonymy(HttpServletRequest request
, HttpServletResponse response
)throws IOException
{
357 logger
.info("doGetSynonymy() " + request
.getServletPath());
358 ModelAndView mv
= new ModelAndView();
359 TaxonBase tb
= getCdmBase(request
, response
, null, Taxon
.class);
360 Taxon taxon
= (Taxon
)tb
;
361 Map
<String
, List
<?
>> synonymy
= new Hashtable
<String
, List
<?
>>();
362 synonymy
.put("homotypicSynonymsByHomotypicGroup", service
.getHomotypicSynonymsByHomotypicGroup(taxon
, SYNONYMY_INIT_STRATEGY
));
363 synonymy
.put("heterotypicSynonymyGroups", service
.getHeterotypicSynonymyGroups(taxon
, SYNONYMY_INIT_STRATEGY
));
364 mv
.addObject(synonymy
);
369 * Get the set of accepted {@link Taxon} entities for a given
370 * {@link TaxonBase} entity identified by the <code>{taxon-uuid}</code>.
372 * URI: <b>/{datasource-name}/portal/taxon/{taxon-uuid}/accepted</b>
376 * @return a Set of {@link Taxon} entities which are initialized
377 * using the following initialization strategy:
378 * {@link #SYNONYMY_INIT_STRATEGY}
379 * @throws IOException
381 @RequestMapping(value
= "/*/portal/taxon/*/accepted", method
= RequestMethod
.GET
)
382 public Set
<TaxonBase
> getAccepted(HttpServletRequest request
, HttpServletResponse response
) throws IOException
{
384 logger
.info("getAccepted() " + request
.getServletPath());
386 UUID uuid
= readValueUuid(request
, null);
387 TaxonBase tb
= service
.load(uuid
, SYNONYMY_INIT_STRATEGY
);
389 response
.sendError(HttpServletResponse
.SC_NOT_FOUND
, "A taxon with the uuid " + uuid
+ " does not exist");
392 HashSet
<TaxonBase
> resultset
= new HashSet
<TaxonBase
>();
393 if(tb
instanceof Taxon
){
394 //the taxon already is accepted
395 //FIXME take the current view into account once views are implemented!!!
396 resultset
.add((Taxon
)tb
);
398 Synonym syn
= (Synonym
)tb
;
399 for(TaxonBase accepted
: syn
.getAcceptedTaxa()){
400 accepted
= service
.load(accepted
.getUuid(), SIMPLE_TAXON_INIT_STRATEGY
);
401 resultset
.add(accepted
);
408 * Get the list of {@link TaxonRelationship}s for the given
409 * {@link TaxonBase} instance identified by the <code>{taxon-uuid}</code>.
411 * URI: <b>/{datasource-name}/portal/taxon/{taxon-uuid}/taxonRelationships</b>
415 * @return a List of {@link TaxonRelationship} entities which are initialized
416 * using the following initialization strategy:
417 * {@link #TAXONRELATIONSHIP_INIT_STRATEGY}
418 * @throws IOException
421 value
= {"/*/portal/taxon/*/taxonRelationships"},
422 method
= RequestMethod
.GET
)
423 public List
<TaxonRelationship
> doGetTaxonRelations(HttpServletRequest request
, HttpServletResponse response
)throws IOException
{
425 logger
.info("doGetTaxonRelations()" + request
.getServletPath());
426 TaxonBase tb
= getCdmBase(request
, response
, null, Taxon
.class);
427 Taxon taxon
= (Taxon
)tb
;
428 List
<TaxonRelationship
> relations
= new ArrayList
<TaxonRelationship
>();
429 List
<TaxonRelationship
> results
= service
.listToTaxonRelationships(taxon
, TaxonRelationshipType
.MISAPPLIED_NAME_FOR(), null, null, null, TAXONRELATIONSHIP_INIT_STRATEGY
);
430 relations
.addAll(results
);
431 results
= service
.listToTaxonRelationships(taxon
, TaxonRelationshipType
.INVALID_DESIGNATION_FOR(), null, null, null, TAXONRELATIONSHIP_INIT_STRATEGY
);
432 relations
.addAll(results
);
438 * Get the list of {@link NameRelationship}s of the Name associated with the
439 * {@link TaxonBase} instance identified by the <code>{taxon-uuid}</code>.
441 * URI: <b>/{datasource-name}/portal/taxon/{taxon-uuid}/nameRelationships</b>
445 * @return a List of {@link NameRelationship} entities which are initialized
446 * using the following initialization strategy:
447 * {@link #NAMERELATIONSHIP_INIT_STRATEGY}
448 * @throws IOException
451 value
= {"/*/portal/taxon/*/nameRelationships"},
452 method
= RequestMethod
.GET
)
453 public List
<NameRelationship
> doGetNameRelations(HttpServletRequest request
, HttpServletResponse response
)throws IOException
{
454 logger
.info("doGetNameRelations()" + request
.getServletPath());
455 TaxonBase tb
= getCdmBase(request
, response
, SIMPLE_TAXON_INIT_STRATEGY
, Taxon
.class);
456 List
<NameRelationship
> list
= nameService
.listToNameRelationships(tb
.getName(), null, null, null, null, NAMERELATIONSHIP_INIT_STRATEGY
);
461 * Get the list of {@link TaxonNameDescription}s of the Name associated with the
462 * {@link TaxonNameBase} instance identified by the <code>{name-uuid}</code>.
464 * URI: <b>/{datasource-name}/portal/name/{name-uuid}/descriptions</b>
468 * @return a List of {@link TaxonNameDescription} entities which are initialized
469 * using the following initialization strategy:
470 * {@link #NAMEDESCRIPTION_INIT_STRATEGY}
471 * @throws IOException
474 value
= {"/*/portal/name/*/descriptions"},
475 method
= RequestMethod
.GET
)
476 public List
<TaxonNameDescription
> doGetNameDescriptions(HttpServletRequest request
, HttpServletResponse response
)throws IOException
{
477 logger
.info("doGetNameDescriptions()" + request
.getServletPath());
478 UUID nameUuuid
= readValueUuid(request
, null);
479 TaxonNameBase tnb
= nameService
.load(nameUuuid
, null);
480 Pager
<TaxonNameDescription
> p
= descriptionService
.getTaxonNameDescriptions(tnb
, null, null, NAMEDESCRIPTION_INIT_STRATEGY
);
481 return p
.getRecords();
485 * Get the list of {@link TypeDesignationBase}s of the
486 * {@link TaxonBase} instance identified by the <code>{taxon-uuid}</code>.
488 * URI: <b>/{datasource-name}/portal/taxon/{taxon-uuid}/nameTypeDesignations</b>
492 * @return a List of {@link TypeDesignationBase} entities which are initialized
493 * using the following initialization strategy:
494 * {@link #TYPEDESIGNATION_INIT_STRATEGY}
495 * @throws IOException
498 value
= {"/*/portal/taxon/*/nameTypeDesignations"},
499 method
= RequestMethod
.GET
)
500 public List
<TypeDesignationBase
> doGetNameTypeDesignations(HttpServletRequest request
, HttpServletResponse response
)throws IOException
{
501 logger
.info("doGetNameTypeDesignations()" + request
.getServletPath());
502 TaxonBase tb
= getCdmBase(request
, response
, SIMPLE_TAXON_INIT_STRATEGY
, Taxon
.class);
503 Pager
<TypeDesignationBase
> p
= nameService
.getTypeDesignations(tb
.getName(), null, null, null, TYPEDESIGNATION_INIT_STRATEGY
);
504 return p
.getRecords();
508 * Get the list of {@link TaxonDescription}s of the
509 * {@link Taxon} instance identified by the <code>{taxon-uuid}</code>.
511 * URI: <b>/{datasource-name}/portal/taxon/{taxon-uuid}/descriptions</b>
515 * @return a List of {@link TaxonDescription} entities which are initialized
516 * using the following initialization strategy:
517 * {@link #TAXONDESCRIPTION_INIT_STRATEGY}
518 * @throws IOException
521 value
= {"/*/portal/taxon/*/descriptions"},
522 method
= RequestMethod
.GET
)
523 public List
<TaxonDescription
> doGetDescriptions(HttpServletRequest request
, HttpServletResponse response
)throws IOException
{
524 logger
.info("doGetDescriptions()" + request
.getServletPath());
525 Taxon t
= getCdmBase(request
, response
, null, Taxon
.class);
526 Pager
<TaxonDescription
> p
= descriptionService
.getTaxonDescriptions(t
, null, null, null, null,
527 TAXONDESCRIPTION_INIT_STRATEGY
);
528 return p
.getRecords();
532 * Get the {@link Media} attached to the {@link Taxon} instance
533 * identified by the <code>{taxon-uuid}</code>.
535 * Usage /{datasource-name}/portal/taxon/{taxon-
536 * uuid}/media/{mime type
537 * list}/{size}[,[widthOrDuration}][,{height}]/
541 * <li><b>{mime type list}</b>: a comma separated list of mime types, in the
542 * order of preference. The forward slashes contained in the mime types must
543 * be replaced by a colon. Regular expressions can be used. Each media
544 * associated with this given taxon is being searched whereas the first
545 * matching mime type matching a representation always rules.</li>
546 * <li><b>{size},{widthOrDuration},{height}</b>: <i>not jet implemented</i>
547 * valid values are an integer or the asterisk '*' as a wildcard</li>
552 * @return a List of {@link Media} entities which are initialized
553 * using the following initialization strategy:
554 * {@link #TAXONDESCRIPTION_INIT_STRATEGY}
555 * @throws IOException
558 value
= {"/*/portal/taxon/*/media/*/*"},
559 method
= RequestMethod
.GET
)
560 public ModelAndView
doGetMedia(HttpServletRequest request
, HttpServletResponse response
)throws IOException
{
561 logger
.info("doGetMedia()" + request
.getServletPath());
562 Taxon t
= getCdmBase(request
, response
, null, Taxon
.class);
563 Map
<String
,List
<MediaRepresentation
>> p
= new HashMap
<String
,List
<MediaRepresentation
>>();
564 boolean hasChildren
= false;
565 if (!t
.getTaxonNodes().isEmpty()){
566 Iterator
<TaxonNode
> nodes
= t
.getTaxonNodes().iterator();
567 TaxonNode node
= nodes
.next();
568 hasChildren
= !node
.getChildNodes().isEmpty();
569 Map
<UUID
,List
<MediaRepresentation
>> allMedia
;
571 allMedia
= taxonTreeService
.getAllMediaForChildNodes(node
, TAXON_MEDIA_INIT_STRATEGY
, null, null, null, null);
572 Set
<Map
.Entry
<UUID
, List
<MediaRepresentation
>>> entries
= allMedia
.entrySet();
573 for (Map
.Entry
<UUID
, List
<MediaRepresentation
>> entry
: entries
){
574 p
.put(entry
.toString(), entry
.getValue());
578 String path
= request
.getServletPath();
579 String
[] pathTokens
= path
.split("/");
580 String
[] mimeTypes
= pathTokens
[6].split(",");
581 String
[] sizeTokens
= pathTokens
[7].split(",");
582 Integer widthOrDuration
= null;
583 Integer height
= null;
586 for(int i
=0; i
<mimeTypes
.length
; i
++){
587 mimeTypes
[i
] = mimeTypes
[i
].replace(':', '/');
590 if(sizeTokens
.length
> 0){
592 size
= Integer
.valueOf(sizeTokens
[0]);
593 } catch (NumberFormatException nfe
) {
597 if(sizeTokens
.length
> 1){
599 widthOrDuration
= Integer
.valueOf(sizeTokens
[1]);
600 } catch (NumberFormatException nfe
) {
604 if(sizeTokens
.length
> 2){
606 height
= Integer
.valueOf(sizeTokens
[2]);
607 } catch (NumberFormatException nfe
) {
612 List
<MediaRepresentation
> mr
=
613 taxonService
.getAllMedia(t
, size
, height
, widthOrDuration
, mimeTypes
, TAXON_INIT_STRATEGY
);
615 p
.put(t
.getUuid().toString(), mr
);
617 // pars the media and quality parameters
620 /* collect all media of the given taxon
621 boolean limitToGalleries = false;
622 List<Media> taxonMedia = new ArrayList<Media>();
623 for(TaxonDescription desc : p.getRecords()){
624 if(!limitToGalleries || desc.isImageGallery()){
625 for(DescriptionElementBase element : desc.getElements()){
626 for(Media media : element.getMedia()){
627 taxonMedia.add(media);
633 // move into media ...
635 // find best matching representations of each media
638 ModelAndView mv
= new ModelAndView();
645 * @param mimeTypeRegexes
647 * @param widthOrDuration
651 * TODO move into a media utils class
652 * TODO implement the quality filter
654 private SortedMap
<String
, MediaRepresentation
> orderMediaRepresentations(Media media
, String
[] mimeTypeRegexes
,
655 Integer size
, Integer widthOrDuration
, Integer height
) {
656 SortedMap
<String
, MediaRepresentation
> prefRepr
= new TreeMap
<String
, MediaRepresentation
>();
657 for (String mimeTypeRegex
: mimeTypeRegexes
) {
658 // getRepresentationByMimeType
659 Pattern mimeTypePattern
= Pattern
.compile(mimeTypeRegex
);
660 int representationCnt
= 0;
661 for (MediaRepresentation representation
: media
.getRepresentations()) {
662 Matcher mather
= mimeTypePattern
.matcher(representation
.getMimeType());
663 if (mather
.matches()) {
666 /* TODO the quality filter part is being skipped
667 * // look for representation with the best matching parts
668 for (MediaRepresentationPart part : representation.getParts()) {
669 if (part instanceof ImageFile) {
670 ImageFile image = (ImageFile) part;
671 int dw = image.getWidth() * image.getHeight() - height * widthOrDuration;
677 dwa = (representation.getParts().size() > 0 ? dwa / representation.getParts().size() : 0);
679 prefRepr
.put((dwa
+ representationCnt
++) + '_' + representation
.getMimeType(), representation
);
681 // preferred mime type found => end loop
689 // ---------------------- code snippet preserved for possible later use --------------------
691 // value = {"/*/portal/taxon/*/descriptions"},
692 // method = RequestMethod.GET)
693 // public List<TaxonDescription> doGetDescriptionsbyFeatureTree(HttpServletRequest request, HttpServletResponse response)throws IOException {
694 // TaxonBase tb = getCdmBase(request, response, null, Taxon.class);
695 // if(tb instanceof Taxon){
696 // //T O D O this is a quick and dirty implementation -> generalize
697 // UUID featureTreeUuid = readValueUuid(request, featureTreeUuidPattern);
699 // FeatureTree featureTree = descriptionService.getFeatureTreeByUuid(featureTreeUuid);
700 // Pager<TaxonDescription> p = descriptionService.getTaxonDescriptions((Taxon)tb, null, null, null, null, TAXONDESCRIPTION_INIT_STRATEGY);
701 // List<TaxonDescription> descriptions = p.getRecords();
703 // if(!featureTree.isDescriptionSeparated()){
705 // TaxonDescription superDescription = TaxonDescription.NewInstance();
706 // //put all descriptionElements in superDescription and make it invisible
707 // for(TaxonDescription description: descriptions){
708 // for(DescriptionElementBase element: description.getElements()){
709 // superDescription.addElement(element);
712 // List<TaxonDescription> separatedDescriptions = new ArrayList<TaxonDescription>(descriptions.size());
713 // separatedDescriptions.add(superDescription);
714 // return separatedDescriptions;
716 // return descriptions;
719 // response.sendError(HttpServletResponse.SC_NOT_FOUND, "invalid type; Taxon expected but " + tb.getClass().getSimpleName() + " found.");