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