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