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