optimizing initialization strategies
[cdmlib.git] / cdmlib-remote / src / main / java / eu / etaxonomy / cdm / remote / controller / TaxonPortalController.java
1 // $Id: TaxonController.java 5473 2009-03-25 13:42:07Z a.kohlbecker $
2 /**
3 * Copyright (C) 2007 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
6 *
7 * The contents of this file are subject to the Mozilla Public License Version 1.1
8 * See LICENSE.TXT at the top of this package for the full license terms.
9 */
10
11 package eu.etaxonomy.cdm.remote.controller;
12
13 import java.io.IOException;
14 import java.util.ArrayList;
15 import java.util.Arrays;
16 import java.util.HashSet;
17 import java.util.Hashtable;
18 import java.util.Iterator;
19 import java.util.List;
20 import java.util.Map;
21 import java.util.Set;
22 import java.util.UUID;
23
24 import javax.servlet.http.HttpServletRequest;
25 import javax.servlet.http.HttpServletResponse;
26
27 import org.apache.commons.lang.ObjectUtils;
28 import org.apache.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;
38
39 import eu.etaxonomy.cdm.api.service.IDescriptionService;
40 import eu.etaxonomy.cdm.api.service.INameService;
41 import eu.etaxonomy.cdm.api.service.IReferenceService;
42 import eu.etaxonomy.cdm.api.service.ITaxonService;
43 import eu.etaxonomy.cdm.api.service.ITaxonTreeService;
44 import eu.etaxonomy.cdm.api.service.config.ITaxonServiceConfigurator;
45 import eu.etaxonomy.cdm.api.service.config.impl.TaxonServiceConfiguratorImpl;
46 import eu.etaxonomy.cdm.api.service.pager.Pager;
47 import eu.etaxonomy.cdm.database.UpdatableRoutingDataSource;
48 import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
49 import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
50 import eu.etaxonomy.cdm.model.description.TaxonDescription;
51 import eu.etaxonomy.cdm.model.description.TaxonNameDescription;
52 import eu.etaxonomy.cdm.model.location.NamedArea;
53 import eu.etaxonomy.cdm.model.media.Media;
54 import eu.etaxonomy.cdm.model.media.MediaUtils;
55 import eu.etaxonomy.cdm.model.name.NameRelationship;
56 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
57 import eu.etaxonomy.cdm.model.name.TypeDesignationBase;
58 import eu.etaxonomy.cdm.model.taxon.Synonym;
59 import eu.etaxonomy.cdm.model.taxon.Taxon;
60 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
61 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
62 import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
63 import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
64 import eu.etaxonomy.cdm.model.taxon.TaxonomicTree;
65 import eu.etaxonomy.cdm.persistence.query.MatchMode;
66 import eu.etaxonomy.cdm.remote.editor.MatchModePropertyEditor;
67 import eu.etaxonomy.cdm.remote.editor.NamedAreaPropertyEditor;
68 import eu.etaxonomy.cdm.remote.editor.UUIDPropertyEditor;
69
70 /**
71 * The TaxonPortalController class is a Spring MVC Controller.
72 * <p>
73 * The syntax of the mapped service URIs contains the the {datasource-name} path element.
74 * The available {datasource-name}s are defined in a configuration file which
75 * is loaded by the {@link UpdatableRoutingDataSource}. If the
76 * UpdatableRoutingDataSource is not being used in the actual application
77 * context any arbitrary {datasource-name} may be used.
78 * <p>
79 * Methods mapped at type level, inherited from super classes ({@link BaseController}):
80 * <blockquote>
81 * URI: <b>&#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;{taxon-uuid}</b>
82 *
83 * Get the {@link TaxonBase} instance identified by the <code>{taxon-uuid}</code>.
84 * The returned Taxon is initialized by
85 * the following strategy {@link #TAXON_INIT_STRATEGY}
86 * </blockquote>
87 *
88 * @author a.kohlbecker
89 * @date 20.07.2009
90 *
91 */
92 @Controller
93 @RequestMapping(value = {"/portal/taxon/{uuid}"})
94 public class TaxonPortalController extends BaseController<TaxonBase, ITaxonService>
95 {
96 public static final Logger logger = Logger.getLogger(TaxonPortalController.class);
97
98 @Autowired
99 private INameService nameService;
100
101 @Autowired
102 private IDescriptionService descriptionService;
103
104 @Autowired
105 private ITaxonTreeService taxonTreeService;
106
107 @Autowired
108 private ITaxonService taxonService;
109
110 private static final List<String> TAXON_INIT_STRATEGY = Arrays.asList(new String []{
111 "*",
112 // taxon relations
113 "relationsToThisName.fromTaxon.name",
114 // the name
115 "name.$",
116 "name.rank.representations",
117 "name.status.type.representations",
118
119 // taxon descriptions
120 "descriptions.elements.area.$",
121 "descriptions.elements.multilanguageText",
122 "descriptions.elements.media.representations.parts",
123 "descriptions.elements.media.title",
124
125 });
126
127 private static final List<String> TAXON_WITH_NODES_INIT_STRATEGY = Arrays.asList(new String []{
128 "taxonNodes.$",
129 "taxonNodes.taxonomicTree.$",
130 "taxonNodes.childNodes.$"
131 });
132
133 private static final List<String> SIMPLE_TAXON_INIT_STRATEGY = Arrays.asList(new String []{
134 "*",
135 // taxon relations
136 "relationsToThisName.fromTaxon.name",
137 // the name
138 "name.$",
139 "name.rank.representations",
140 "name.status.type.representations",
141 "name.nomenclaturalReference"
142 });
143
144 private static final List<String> SYNONYMY_INIT_STRATEGY = Arrays.asList(new String []{
145 // initialize homotypical and heterotypical groups; needs synonyms
146 "synonymRelations.$",
147 "synonymRelations.synonym.$",
148 "synonymRelations.synonym.name.status.type.representation",
149 "synonymRelations.synonym.name.nomenclaturalReference.inReference",
150 "synonymRelations.synonym.name.homotypicalGroup.typifiedNames.$",
151 "synonymRelations.synonym.name.homotypicalGroup.typifiedNames.taxonBases.$",
152 "synonymRelations.synonym.name.combinationAuthorTeam.$",
153
154 "name.homotypicalGroup.$",
155 "name.homotypicalGroup.typifiedNames.$",
156
157 "name.homotypicalGroup.typifiedNames.taxonBases.$"
158 });
159
160 private static final List<String> TAXONRELATIONSHIP_INIT_STRATEGY = Arrays.asList(new String []{
161 "$",
162 "type.inverseRepresentations",
163 "fromTaxon.sec",
164 "fromTaxon.name"
165 });
166
167 private static final List<String> NAMERELATIONSHIP_INIT_STRATEGY = Arrays.asList(new String []{
168 "$",
169 "type.inverseRepresentations",
170 "fromName",
171 "toName.$",
172 });
173
174
175 protected static final List<String> TAXONDESCRIPTION_INIT_STRATEGY = Arrays.asList(new String []{
176 "$",
177 "elements.$",
178 "elements.sources.citation.",
179 "elements.sources.nameUsedInSource.originalNameString",
180 "elements.multilanguageText",
181 "elements.media.representations.parts",
182 "elements.media.title",
183 });
184
185
186 private static final List<String> NAMEDESCRIPTION_INIT_STRATEGY = Arrays.asList(new String []{
187 "uuid",
188 "feature",
189 "elements.$",
190 "elements.multilanguageText",
191 "elements.media.representations.parts",
192 "elements.media.title",
193 });
194
195 protected static final List<String> TAXONDESCRIPTION_MEDIA_INIT_STRATEGY = Arrays.asList(new String []{
196 "elements.media.representations.parts",
197 "elements.media.title"
198
199 });
200
201 private static final List<String> TYPEDESIGNATION_INIT_STRATEGY = Arrays.asList(new String []{
202 //"$",
203 "typeSpecimen.$",
204 "citation",
205 "typeName",
206 });
207
208 protected static final List<String> TAXONNODE_WITHTAXON_INIT_STRATEGY = Arrays.asList(new String []{
209 "childNodes.taxon",
210 });
211
212 protected static final List<String> TAXONNODE_INIT_STRATEGY = Arrays.asList(new String []{
213 "taxonNodes.taxonomicTree"
214 });
215
216
217
218 private static final String featureTreeUuidPattern = "^/taxon(?:(?:/)([^/?#&\\.]+))+.*";
219
220 public TaxonPortalController(){
221 super();
222 setInitializationStrategy(TAXON_INIT_STRATEGY);
223 }
224
225 /* (non-Javadoc)
226 * @see eu.etaxonomy.cdm.remote.controller.GenericController#setService(eu.etaxonomy.cdm.api.service.IService)
227 */
228 @Autowired
229 @Override
230 public void setService(ITaxonService service) {
231 this.service = service;
232 }
233
234 @InitBinder
235 public void initBinder(WebDataBinder binder) {
236 binder.registerCustomEditor(UUID.class, new UUIDPropertyEditor());
237 binder.registerCustomEditor(NamedArea.class, new NamedAreaPropertyEditor());
238 binder.registerCustomEditor(MatchMode.class, new MatchModePropertyEditor());
239 }
240
241
242 /* (non-Javadoc)
243 * @see eu.etaxonomy.cdm.remote.controller.BaseController#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
244
245 @Override
246 @RequestMapping(method = RequestMethod.GET)
247 public TaxonBase doGet(HttpServletRequest request, HttpServletResponse response)throws IOException {
248 logger.info("doGet()");
249 TaxonBase tb = getCdmBase(request, response, TAXON_INIT_STRATEGY, TaxonBase.class);
250 return tb;
251 }
252 */
253 /**
254 * Find Taxa, Synonyms, Common Names by name, either globally or in a specific geographic area.
255 * <p>
256 * URI: <b>&#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;find</b>
257 *
258 * @param query
259 * the string to query for. Since the wildcard character '*'
260 * internally always is appended to the query string, a search
261 * always compares the query string with the beginning of a name.
262 * - <i>required parameter</i>
263 * @param treeUuid
264 * the {@link UUID} of a {@link TaxonomicTree} to which the
265 * search is to be restricted. - <i>optional parameter</i>
266 * @param areas
267 * restrict the search to a set of geographic {@link NamedArea}s.
268 * The parameter currently takes a list of TDWG area labels.
269 * - <i>optional parameter</i>
270 * @param page
271 * the number of the page to be returned, the first page has the
272 * pageNumber = 1 - <i>optional parameter</i>
273 * @param pageSize
274 * the maximum number of entities returned per page (can be -1
275 * to return all entities in a single page) - <i>optional parameter</i>
276 * @param doTaxa
277 * weather to search for instances of {@link Taxon} - <i>optional parameter</i>
278 * @param doSynonyms
279 * weather to search for instances of {@link Synonym} - <i>optional parameter</i>
280 * @param doTaxaByCommonNames
281 * for instances of {@link Taxon} by a common name used - <i>optional parameter</i>
282 * @param matchMode
283 * valid values are "EXACT", "BEGINNING", "ANYWHERE", "END" (case sensitive !!!)
284 * @return a Pager on a list of {@link IdentifiableEntity}s initialized by
285 * the following strategy {@link #SIMPLE_TAXON_INIT_STRATEGY}
286 * @throws IOException
287 */
288 @RequestMapping(method = RequestMethod.GET,
289 value = {"/portal/taxon/find"}) //TODO map to path /*/portal/taxon/
290 public Pager<IdentifiableEntity> doFind(
291 @RequestParam(value = "query", required = false) String query,
292 @RequestParam(value = "tree", required = false) UUID treeUuid,
293 @RequestParam(value = "area", required = false) Set<NamedArea> areas,
294 @RequestParam(value = "page", required = false) Integer page,
295 @RequestParam(value = "pageSize", required = false) Integer pageSize,
296 @RequestParam(value = "doTaxa", required = false) Boolean doTaxa,
297 @RequestParam(value = "doSynonyms", required = false) Boolean doSynonyms,
298 @RequestParam(value = "doTaxaByCommonNames", required = false) Boolean doTaxaByCommonNames,
299 @RequestParam(value = "matchMode", required = false) MatchMode matchMode
300 )
301 throws IOException {
302
303 logger.info("doFind( " +
304 "query=\"" + ObjectUtils.toString(query) + "\", treeUuid=" + ObjectUtils.toString(treeUuid) +
305 ", area=" + ObjectUtils.toString(areas) +
306 ", pageSize=" + ObjectUtils.toString(pageSize) + ", page=" + ObjectUtils.toString(page) +
307 ", doTaxa=" + ObjectUtils.toString(doTaxa) + ", doSynonyms=" + ObjectUtils.toString(doSynonyms)
308 +", doTaxaByCommonNames=" + ObjectUtils.toString(doTaxaByCommonNames) +")" );
309
310 if(page == null){ page = BaseListController.DEFAULT_PAGE_NUMBER;}
311 if(pageSize == null){ pageSize = BaseListController.DEFAULT_PAGESIZE;}
312 if(pageSize == -1){
313 pageSize = null;
314 }
315
316 ITaxonServiceConfigurator config = new TaxonServiceConfiguratorImpl();
317 config.setPageNumber(page);
318 config.setPageSize(pageSize);
319 config.setSearchString(query);
320 config.setDoTaxa(doTaxa!= null ? doTaxa : Boolean.FALSE );
321 config.setDoSynonyms(doSynonyms != null ? doSynonyms : Boolean.FALSE );
322 config.setDoTaxaByCommonNames(doTaxaByCommonNames != null ? doTaxaByCommonNames : Boolean.FALSE );
323 config.setMatchMode(matchMode != null ? matchMode : MatchMode.BEGINNING);
324 config.setTaxonPropertyPath(SIMPLE_TAXON_INIT_STRATEGY);
325 config.setNamedAreas(areas);
326 if(treeUuid != null){
327 TaxonomicTree taxonomicTree = taxonTreeService.find(treeUuid);
328 config.setTaxonomicTree(taxonomicTree);
329 }
330
331 return (Pager<IdentifiableEntity>) service.findTaxaAndNames(config);
332 }
333
334 /**
335 * Get the synonymy for a taxon identified by the <code>{taxon-uuid}</code>.
336 * The synonymy consists
337 * of two parts: The group of homotypic synonyms of the taxon and the
338 * heterotypic synonymy groups of the taxon. The synonymy is ordered
339 * historically by the type designations and by the publication date of the
340 * nomenclatural reference
341 * <p>
342 * URI:
343 * <b>&#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;{taxon-uuid}&#x002F;synonymy</b>
344 *
345 *
346 * @param request
347 * @param response
348 * @return a Map with to entries which are mapped by the following keys:
349 * "homotypicSynonymsByHomotypicGroup", "heterotypicSynonymyGroups",
350 * containing lists of {@link Synonym}s which are initialized using the
351 * following initialization strategy: {@link #SYNONYMY_INIT_STRATEGY}
352 *
353 * @throws IOException
354 */
355 @RequestMapping(
356 value = {"synonymy"},
357 method = RequestMethod.GET)
358 public ModelAndView doGetSynonymy(@PathVariable("uuid") UUID uuid,
359 HttpServletRequest request, HttpServletResponse response)throws IOException {
360
361 logger.info("doGetSynonymy() " + request.getServletPath());
362 ModelAndView mv = new ModelAndView();
363 Taxon taxon = getCdmBaseInstance(Taxon.class, uuid, response, (List<String>)null);
364 Map<String, List<?>> synonymy = new Hashtable<String, List<?>>();
365 synonymy.put("homotypicSynonymsByHomotypicGroup", service.getHomotypicSynonymsByHomotypicGroup(taxon, SYNONYMY_INIT_STRATEGY));
366 synonymy.put("heterotypicSynonymyGroups", service.getHeterotypicSynonymyGroups(taxon, SYNONYMY_INIT_STRATEGY));
367 mv.addObject(synonymy);
368 return mv;
369 }
370
371 /**
372 * Get the set of accepted {@link Taxon} entities for a given
373 * {@link TaxonBase} entity identified by the <code>{taxon-uuid}</code>.
374 * <p>
375 * URI: <b>&#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;{taxon-uuid}&#x002F;accepted</b>
376 *
377 * @param request
378 * @param response
379 * @return a Set of {@link Taxon} entities which are initialized
380 * using the following initialization strategy:
381 * {@link #SYNONYMY_INIT_STRATEGY}
382 * @throws IOException
383 */
384 @RequestMapping(value = "accepted", method = RequestMethod.GET)
385 public Set<TaxonBase> getAccepted(@PathVariable("uuid") UUID uuid,
386 HttpServletRequest request, HttpServletResponse response) throws IOException {
387
388 logger.info("getAccepted() " + request.getServletPath());
389
390 TaxonBase tb = service.load(uuid, SYNONYMY_INIT_STRATEGY);
391 if(tb == null){
392 response.sendError(HttpServletResponse.SC_NOT_FOUND, "A taxon with the uuid " + uuid + " does not exist");
393 return null;
394 }
395 HashSet<TaxonBase> resultset = new HashSet<TaxonBase>();
396 if(tb instanceof Taxon){
397 //the taxon already is accepted
398 //FIXME take the current view into account once views are implemented!!!
399 resultset.add((Taxon)tb);
400 } else {
401 Synonym syn = (Synonym)tb;
402 for(TaxonBase accepted : syn.getAcceptedTaxa()){
403 accepted = service.load(accepted.getUuid(), SIMPLE_TAXON_INIT_STRATEGY);
404 resultset.add(accepted);
405 }
406 }
407 return resultset;
408 }
409
410 /**
411 * Get the list of {@link TaxonRelationship}s for the given
412 * {@link TaxonBase} instance identified by the <code>{taxon-uuid}</code>.
413 * <p>
414 * URI: <b>&#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;{taxon-uuid}&#x002F;taxonRelationships</b>
415 *
416 * @param request
417 * @param response
418 * @return a List of {@link TaxonRelationship} entities which are initialized
419 * using the following initialization strategy:
420 * {@link #TAXONRELATIONSHIP_INIT_STRATEGY}
421 * @throws IOException
422 */
423 @RequestMapping(
424 value = {"taxonRelationships"},
425 method = RequestMethod.GET)
426 public List<TaxonRelationship> doGetTaxonRelations(@PathVariable("uuid") UUID uuid,
427 HttpServletRequest request, HttpServletResponse response)throws IOException {
428
429 logger.info("doGetTaxonRelations()" + request.getServletPath());
430 Taxon taxon = getCdmBaseInstance(Taxon.class, uuid, response, (List<String>)null);
431 List<TaxonRelationship> relations = new ArrayList<TaxonRelationship>();
432 List<TaxonRelationship> results = service.listToTaxonRelationships(taxon, TaxonRelationshipType.MISAPPLIED_NAME_FOR(), null, null, null, TAXONRELATIONSHIP_INIT_STRATEGY);
433 relations.addAll(results);
434 results = service.listToTaxonRelationships(taxon, TaxonRelationshipType.INVALID_DESIGNATION_FOR(), null, null, null, TAXONRELATIONSHIP_INIT_STRATEGY);
435 relations.addAll(results);
436
437 return relations;
438 }
439
440 /**
441 * Get the list of {@link NameRelationship}s of the Name associated with the
442 * {@link TaxonBase} instance identified by the <code>{taxon-uuid}</code>.
443 * <p>
444 * URI: <b>&#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;{taxon-uuid}&#x002F;nameRelationships</b>
445 *
446 * @param request
447 * @param response
448 * @return a List of {@link NameRelationship} entities which are initialized
449 * using the following initialization strategy:
450 * {@link #NAMERELATIONSHIP_INIT_STRATEGY}
451 * @throws IOException
452 */
453 @RequestMapping(
454 value = {"toNameRelationships"},
455 method = RequestMethod.GET)
456 public List<NameRelationship> doGetToNameRelations(@PathVariable("uuid") UUID uuid,
457 HttpServletRequest request, HttpServletResponse response)throws IOException {
458 logger.info("doGetNameRelations()" + request.getServletPath());
459 Taxon taxon = getCdmBaseInstance(Taxon.class, uuid, response, (List<String>)null);
460 List<NameRelationship> list = nameService.listToNameRelationships(taxon.getName(), null, null, null, null, NAMERELATIONSHIP_INIT_STRATEGY);
461 return list;
462 }
463
464 /**
465 * Get the list of {@link NameRelationship}s of the Name associated with the
466 * {@link TaxonBase} instance identified by the <code>{taxon-uuid}</code>.
467 * <p>
468 * URI: <b>&#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;{taxon-uuid}&#x002F;nameRelationships</b>
469 *
470 * @param request
471 * @param response
472 * @return a List of {@link NameRelationship} entities which are initialized
473 * using the following initialization strategy:
474 * {@link #NAMERELATIONSHIP_INIT_STRATEGY}
475 * @throws IOException
476 */
477 @RequestMapping(
478 value = {"fromNameRelationships"},
479 method = RequestMethod.GET)
480 public List<NameRelationship> doGetFromNameRelations(@PathVariable("uuid") UUID uuid,
481 HttpServletRequest request, HttpServletResponse response)throws IOException {
482 logger.info("doGetNameFromNameRelations()" + request.getServletPath());
483
484 TaxonBase taxonbase = getCdmBaseInstance(TaxonBase.class, uuid, response, SIMPLE_TAXON_INIT_STRATEGY);
485 List<NameRelationship> list = nameService.listFromNameRelationships(taxonbase.getName(), null, null, null, null, NAMERELATIONSHIP_INIT_STRATEGY);
486 return list;
487 }
488
489 /**
490 * Get the list of {@link TypeDesignationBase}s of the
491 * {@link TaxonBase} instance identified by the <code>{taxon-uuid}</code>.
492 * <p>
493 * URI: <b>&#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;{taxon-uuid}&#x002F;nameTypeDesignations</b>
494 *
495 * @param request
496 * @param response
497 * @return a List of {@link TypeDesignationBase} entities which are initialized
498 * using the following initialization strategy:
499 * {@link #TYPEDESIGNATION_INIT_STRATEGY}
500 * @throws IOException
501 * @Deprecated use &#x002F;name&#x002F;{uuid}&#x002F;typeDesignations & &#x002F;derivedunitfacade&#x002F;{uuid} instead
502 */
503 @Deprecated
504 @RequestMapping(
505 value = {"nameTypeDesignations"},
506 method = RequestMethod.GET)
507 public List<TypeDesignationBase> doGetNameTypeDesignations(@PathVariable("uuid") UUID uuid,
508 HttpServletRequest request, HttpServletResponse response)throws IOException {
509 logger.info("doGetNameTypeDesignations()" + request.getServletPath());
510 Taxon taxon = getCdmBaseInstance(Taxon.class, uuid, response, SIMPLE_TAXON_INIT_STRATEGY);
511 Pager<TypeDesignationBase> p = nameService.getTypeDesignations(taxon.getName(), null, null, null, TYPEDESIGNATION_INIT_STRATEGY);
512 return p.getRecords();
513 }
514
515 @RequestMapping(value = "taxonNodes", method = RequestMethod.GET)
516 public Set<TaxonNode> doGetTaxonNodes(
517 @PathVariable("uuid") UUID uuid,
518 HttpServletRequest request,
519 HttpServletResponse response) throws IOException {
520 TaxonBase tb = service.load(uuid, TAXONNODE_INIT_STRATEGY);
521 if(tb instanceof Taxon){
522 return ((Taxon)tb).getTaxonNodes();
523 } else {
524 HttpStatusMessage.UUID_REFERENCES_WRONG_TYPE.send(response);
525 return null;
526 }
527 }
528
529 /**
530 * Get the list of {@link TaxonDescription}s of the
531 * {@link Taxon} instance identified by the <code>{taxon-uuid}</code>.
532 * <p>
533 * URI: <b>&#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;{taxon-uuid}&#x002F;descriptions</b>
534 *
535 * @param request
536 * @param response
537 * @return a List of {@link TaxonDescription} entities which are initialized
538 * using the following initialization strategy:
539 * {@link #TAXONDESCRIPTION_INIT_STRATEGY}
540 * @throws IOException
541 */
542 @RequestMapping(
543 value = {"descriptions"},
544 method = RequestMethod.GET)
545 public List<TaxonDescription> doGetDescriptions(@PathVariable("uuid") UUID uuid,
546 HttpServletRequest request, HttpServletResponse response)throws IOException {
547 logger.info("doGetDescriptions()" + request.getServletPath());
548 Taxon t = getCdmBaseInstance(Taxon.class, uuid, response, (List<String>)null);
549 Pager<TaxonDescription> p = descriptionService.getTaxonDescriptions(t, null, null, null, null, TAXONDESCRIPTION_INIT_STRATEGY);
550 return p.getRecords();
551 }
552
553 /**
554 * Get the {@link Media} attached to the {@link Taxon} instance
555 * identified by the <code>{taxon-uuid}</code>.
556 *
557 * Usage &#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;{taxon-
558 * uuid}&#x002F;media&#x002F;{mime type
559 * list}&#x002F;{size}[,[widthOrDuration}][,{height}]&#x002F;
560 *
561 * Whereas
562 * <ul>
563 * <li><b>{mime type list}</b>: a comma separated list of mime types, in the
564 * order of preference. The forward slashes contained in the mime types must
565 * be replaced by a colon. Regular expressions can be used. Each media
566 * associated with this given taxon is being searched whereas the first
567 * matching mime type matching a representation always rules.</li>
568 * <li><b>{size},{widthOrDuration},{height}</b>: <i>not jet implemented</i>
569 * valid values are an integer or the asterisk '*' as a wildcard</li>
570 * </ul>
571 *
572 * @param request
573 * @param response
574 * @return a List of {@link Media} entities which are initialized
575 * using the following initialization strategy:
576 * {@link #TAXONDESCRIPTION_INIT_STRATEGY}
577 * @throws IOException
578 */
579 @RequestMapping(
580 value = {"media/*/*"},
581 method = RequestMethod.GET)
582 public List<Media> doGetMedia(@PathVariable("uuid") UUID uuid,
583 HttpServletRequest request, HttpServletResponse response) throws IOException {
584 logger.info("doGetMedia()" + request.getServletPath());
585 Taxon t = getCdmBaseInstance(Taxon.class, uuid, response, (List<String>)null);
586 String path = request.getServletPath();
587 List<Media> returnMedia = getMediaForTaxon(t, path, 5);
588 return returnMedia;
589 }
590
591 @RequestMapping(
592 value = {"subtree/media/*/*"},
593 method = RequestMethod.GET)
594 public List<Media> doGetSubtreeMedia(@PathVariable("uuid") UUID uuid,
595 HttpServletRequest request, HttpServletResponse response)throws IOException {
596 logger.info("doGetMedia()" + request.getServletPath());
597 Taxon t = getCdmBaseInstance(Taxon.class, uuid, response, TAXON_WITH_NODES_INIT_STRATEGY);
598 String path = request.getServletPath();
599 List<Media> returnMedia = getMediaForTaxon(t, path, 6);
600 TaxonNode node;
601 //looking for all medias of genus
602 if (t.getTaxonNodes().size()>0){
603 Set<TaxonNode> nodes = t.getTaxonNodes();
604 Iterator<TaxonNode> iterator = nodes.iterator();
605 //TaxonNode holen
606 node = iterator.next();
607 //überprüfen, ob der TaxonNode zum aktuellen Baum gehört.
608
609 node = taxonTreeService.loadTaxonNode(node, TAXONNODE_WITHTAXON_INIT_STRATEGY);
610 Set<TaxonNode> children = node.getChildNodes();
611 Taxon childTaxon;
612 for (TaxonNode child : children){
613 childTaxon = child.getTaxon();
614 childTaxon = (Taxon)taxonService.load(childTaxon.getUuid(), null);
615 returnMedia.addAll(getMediaForTaxon(childTaxon, path, 6));
616 }
617 }
618 return returnMedia;
619 }
620
621
622 private List<Media> getMediaForTaxon(Taxon taxon, String path, int mimeTypeTokenPosition){
623
624 Pager<TaxonDescription> p =
625 descriptionService.getTaxonDescriptions(taxon, null, null, null, null, TAXONDESCRIPTION_MEDIA_INIT_STRATEGY);
626
627 // pars the media and quality parameters
628
629
630 // collect all media of the given taxon
631 boolean limitToGalleries = false;
632 List<Media> taxonMedia = new ArrayList<Media>();
633 for(TaxonDescription desc : p.getRecords()){
634 if(!limitToGalleries || desc.isImageGallery()){
635 for(DescriptionElementBase element : desc.getElements()){
636 for(Media media : element.getMedia()){
637 taxonMedia.add(media);
638 }
639 }
640 }
641 }
642
643 String[] pathTokens = path.split("/");
644
645 String[] mimeTypes = pathTokens[mimeTypeTokenPosition].split(",");
646 String[] sizeTokens = pathTokens[mimeTypeTokenPosition + 1].split(",");
647 Integer widthOrDuration = null;
648 Integer height = null;
649 Integer size = null;
650
651 List<Media> returnMedia = MediaUtils.findPreferredMedia(taxonMedia, mimeTypes,
652 sizeTokens, widthOrDuration, height, size);
653
654 return returnMedia;
655 }
656
657
658 // ---------------------- code snippet preserved for possible later use --------------------
659 // @RequestMapping(
660 // value = {"/*/portal/taxon/*/descriptions"},
661 // method = RequestMethod.GET)
662 // public List<TaxonDescription> doGetDescriptionsbyFeatureTree(HttpServletRequest request, HttpServletResponse response)throws IOException {
663 // TaxonBase tb = getCdmBase(request, response, null, Taxon.class);
664 // if(tb instanceof Taxon){
665 // //T O D O this is a quick and dirty implementation -> generalize
666 // UUID featureTreeUuid = readValueUuid(request, featureTreeUuidPattern);
667 //
668 // FeatureTree featureTree = descriptionService.getFeatureTreeByUuid(featureTreeUuid);
669 // Pager<TaxonDescription> p = descriptionService.getTaxonDescriptions((Taxon)tb, null, null, null, null, TAXONDESCRIPTION_INIT_STRATEGY);
670 // List<TaxonDescription> descriptions = p.getRecords();
671 //
672 // if(!featureTree.isDescriptionSeparated()){
673 //
674 // TaxonDescription superDescription = TaxonDescription.NewInstance();
675 // //put all descriptionElements in superDescription and make it invisible
676 // for(TaxonDescription description: descriptions){
677 // for(DescriptionElementBase element: description.getElements()){
678 // superDescription.addElement(element);
679 // }
680 // }
681 // List<TaxonDescription> separatedDescriptions = new ArrayList<TaxonDescription>(descriptions.size());
682 // separatedDescriptions.add(superDescription);
683 // return separatedDescriptions;
684 // }else{
685 // return descriptions;
686 // }
687 // } else {
688 // response.sendError(HttpServletResponse.SC_NOT_FOUND, "invalid type; Taxon expected but " + tb.getClass().getSimpleName() + " found.");
689 // return null;
690 // }
691 // }
692
693 }