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