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