minimum base web services for CDM Portal v2.0
[cdmlib.git] / cdmlib-remote / src / main / java / eu / etaxonomy / cdm / remote / controller / TaxonPortalController.java
1 // $Id: TaxonController.java 5473 2009-03-25 13:42:07Z a.kohlbecker $
2 /**
3 * Copyright (C) 2007 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
6 *
7 * The contents of this file are subject to the Mozilla Public License Version 1.1
8 * See LICENSE.TXT at the top of this package for the full license terms.
9 */
10
11 package eu.etaxonomy.cdm.remote.controller;
12
13 import java.io.IOException;
14 import java.util.ArrayList;
15 import java.util.Arrays;
16 import java.util.Hashtable;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.UUID;
20
21 import javax.servlet.http.HttpServletRequest;
22 import javax.servlet.http.HttpServletResponse;
23
24 import org.apache.log4j.Logger;
25 import org.springframework.beans.factory.annotation.Autowired;
26 import org.springframework.stereotype.Controller;
27 import org.springframework.web.bind.WebDataBinder;
28 import org.springframework.web.bind.annotation.InitBinder;
29 import org.springframework.web.bind.annotation.RequestMapping;
30 import org.springframework.web.bind.annotation.RequestMethod;
31 import org.springframework.web.bind.annotation.RequestParam;
32 import org.springframework.web.servlet.ModelAndView;
33
34 import eu.etaxonomy.cdm.api.service.IDescriptionService;
35 import eu.etaxonomy.cdm.api.service.INameService;
36 import eu.etaxonomy.cdm.api.service.IReferenceService;
37 import eu.etaxonomy.cdm.api.service.ITaxonService;
38 import eu.etaxonomy.cdm.api.service.config.ITaxonServiceConfigurator;
39 import eu.etaxonomy.cdm.api.service.config.impl.TaxonServiceConfiguratorImpl;
40 import eu.etaxonomy.cdm.api.service.pager.Pager;
41 import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
42 import eu.etaxonomy.cdm.model.description.TaxonDescription;
43 import eu.etaxonomy.cdm.model.description.TaxonNameDescription;
44 import eu.etaxonomy.cdm.model.name.NameRelationship;
45 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
46 import eu.etaxonomy.cdm.model.name.TypeDesignationBase;
47 import eu.etaxonomy.cdm.model.reference.ReferenceBase;
48 import eu.etaxonomy.cdm.model.taxon.Taxon;
49 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
50 import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
51 import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
52 import eu.etaxonomy.cdm.persistence.query.MatchMode;
53 import eu.etaxonomy.cdm.remote.editor.UUIDPropertyEditor;
54
55 /**
56 * @author a.kohlbecker
57 *
58 */
59
60 @Controller
61 @RequestMapping(value = {"/*/portal/taxon/*", "/*/portal/taxon/*/*", "/*/portal/name/*/*"})
62 public class TaxonPortalController extends BaseController<TaxonBase, ITaxonService>
63 {
64 public static final Logger logger = Logger.getLogger(TaxonPortalController.class);
65
66 @Autowired
67 private INameService nameService;
68 @Autowired
69 private IDescriptionService descriptionService;
70 @Autowired
71 private IReferenceService referenceService;
72
73
74 private static final List<String> TAXON_INIT_STRATEGY = Arrays.asList(new String []{
75 "*",
76 // taxon relations
77 "relationsToThisName.fromTaxon.name.taggedName",
78 // the name
79 "name.$",
80 "name.taggedName",
81 "name.rank.representations",
82 "name.status.type.representations",
83
84 // taxon descriptions
85 "descriptions.elements.$",
86 "descriptions.elements.area",
87 "descriptions.elements.area.$",
88 "descriptions.elements.multilanguageText",
89 "descriptions.elements.media.representations.parts",
90
91 // // typeDesignations
92 // "name.typeDesignations.$",
93 // "name.typeDesignations.citation.authorTeam",
94 // "name.typeDesignations.typeName.$",
95 // "name.typeDesignations.typeStatus.representations",
96 // "name.typeDesignations.typeSpecimen.media.representations.parts"
97
98 });
99
100 private static final List<String> SIMPLE_TAXON_INIT_STRATEGY = Arrays.asList(new String []{
101 "*",
102 // taxon relations
103 "relationsToThisName.fromTaxon.name.taggedName",
104 // the name
105 "name.$",
106 "name.taggedName",
107 "name.rank.representations",
108 "name.status.type.representations"
109 });
110
111 private static final List<String> SYNONYMY_INIT_STRATEGY = Arrays.asList(new String []{
112 // initialize homotypical and heterotypical groups; needs synonyms
113 "synonymRelations.$",
114 "synonymRelations.synonym.$",
115 "synonymRelations.synonym.name.taggedName",
116 "synonymRelations.synonym.name.homotypicalGroup.typifiedNames.$",
117 "synonymRelations.synonym.name.homotypicalGroup.typifiedNames.name.taggedName",
118 "synonymRelations.synonym.name.homotypicalGroup.typifiedNames.taxonBases.$",
119 "synonymRelations.synonym.name.homotypicalGroup.typifiedNames.taxonBases.name.taggedName",
120
121 "name.homotypicalGroup.$",
122 "name.homotypicalGroup.typifiedNames.$",
123 "name.homotypicalGroup.typifiedNames.name.taggedName",
124 "name.homotypicalGroup.typifiedNames.taxonBases.$",
125 "name.homotypicalGroup.typifiedNames.taxonBases.name.taggedName"
126 });
127
128 private static final List<String> TAXONRELATIONSHIP_INIT_STRATEGY = Arrays.asList(new String []{
129 "$",
130 "type.inverseRepresentations",
131 "fromTaxon.sec.authorTeam",
132 "fromTaxon.name.taggedName"
133 });
134
135 private static final List<String> NAMERELATIONSHIP_INIT_STRATEGY = Arrays.asList(new String []{
136 "$",
137 "type.inverseRepresentations",
138 "fromName.taggedName",
139 });
140
141
142 protected static final List<String> TAXONDESCRIPTION_INIT_STRATEGY = Arrays.asList(new String []{
143 "$",
144 "elements.$",
145 "elements.citation.authorTeam",
146 "elements.multilanguageText",
147 "elements.media.representations.parts",
148 });
149
150 private static final List<String> NAMEDESCRIPTION_INIT_STRATEGY = Arrays.asList(new String []{
151 "uuid",
152 "feature",
153
154 "elements.$",
155 "elements.multilanguageText",
156 "elements.media.representations.parts",
157 });
158
159 private static final List<String> TYPEDESIGNATION_INIT_STRATEGY = Arrays.asList(new String []{
160 //"$",
161 "typeSpecimen.$",
162 "typeStatus.representations",
163 "citation.authorTeam",
164 "typeName.taggedName"
165 });
166
167
168
169 private static final String featureTreeUuidPattern = "^/(?:[^/]+)/taxon(?:(?:/)([^/?#&\\.]+))+.*";
170
171 public TaxonPortalController(){
172 super();
173 setUuidParameterPattern("^/(?:[^/]+)/portal/(?:[^/]+)/([^/?#&\\.]+).*");
174 }
175
176 /* (non-Javadoc)
177 * @see eu.etaxonomy.cdm.remote.controller.GenericController#setService(eu.etaxonomy.cdm.api.service.IService)
178 */
179 @Autowired
180 @Override
181 public void setService(ITaxonService service) {
182 this.service = service;
183 }
184
185 @InitBinder
186 public void initBinder(WebDataBinder binder) {
187 binder.registerCustomEditor(UUID.class, new UUIDPropertyEditor());
188 }
189
190
191 @Override
192 @RequestMapping(method = RequestMethod.GET)
193 public TaxonBase doGet(HttpServletRequest request, HttpServletResponse response)throws IOException {
194 TaxonBase tb = getCdmBase(request, response, TAXON_INIT_STRATEGY, TaxonBase.class);
195 return tb;
196 }
197
198 @RequestMapping(method = RequestMethod.GET,
199 value = {"/*/portal/taxon/find"}) //TODO map to path /*/portal/taxon/
200 public Pager<IdentifiableEntity> doFind(
201 @RequestParam(value = "q", required = false) String query,
202 @RequestParam(value = "page", required = false) Integer page,
203 @RequestParam(value = "pageSize", required = false) Integer pageSize,
204 @RequestParam(value = "doTaxa", required = false) Boolean doTaxa,
205 @RequestParam(value = "doSynonyms", required = false) Boolean doSynonyms,
206 @RequestParam(value = "doTaxaByCommonNames", required = false) Boolean doTaxaByCommonNames,
207 @RequestParam(value = "secUuid", required = false) UUID secUuid) throws IOException {
208
209 if(page == null){ page = BaseListController.DEFAULT_PAGE;}
210 if(pageSize == null){ pageSize = BaseListController.DEFAULT_PAGESIZE;}
211
212 ITaxonServiceConfigurator config = new TaxonServiceConfiguratorImpl();
213 config.setPageNumber(page);
214 config.setPageSize(pageSize);
215 config.setSearchString(query);
216 config.setDoTaxa(doTaxa!= null ? doTaxa : Boolean.FALSE );
217 config.setDoSynonyms(doSynonyms != null ? doSynonyms : Boolean.FALSE );
218 config.setDoTaxaByCommonNames(doTaxaByCommonNames != null ? doTaxaByCommonNames : Boolean.FALSE );
219 config.setMatchMode(MatchMode.BEGINNING);
220 config.setTaxonPropertyPath(SIMPLE_TAXON_INIT_STRATEGY);
221 if(secUuid != null){
222 ReferenceBase sec = referenceService.findByUuid(secUuid);
223 config.setSec(sec);
224 }
225
226 return (Pager<IdentifiableEntity>) service.findTaxaAndNames(config);
227 }
228
229
230 @RequestMapping(
231 value = {"/*/portal/taxon/*/synonymy"},
232 method = RequestMethod.GET)
233 public ModelAndView doGetSynonymy(HttpServletRequest request, HttpServletResponse response)throws IOException {
234 ModelAndView mv = new ModelAndView();
235 TaxonBase tb = getCdmBase(request, response, null, Taxon.class);
236 Taxon taxon = (Taxon)tb;
237 Map<String, List<?>> synonymy = new Hashtable<String, List<?>>();
238 synonymy.put("homotypicSynonymsByHomotypicGroup", service.getHomotypicSynonymsByHomotypicGroup(taxon, SYNONYMY_INIT_STRATEGY));
239 synonymy.put("heterotypicSynonymyGroups", service.getHeterotypicSynonymyGroups(taxon, SYNONYMY_INIT_STRATEGY));
240 mv.addObject(synonymy);
241 return mv;
242 }
243
244 @RequestMapping(
245 value = {"/*/portal/taxon/*/taxonRelationships"},
246 method = RequestMethod.GET)
247 public List<TaxonRelationship> doGetTaxonRelations(HttpServletRequest request, HttpServletResponse response)throws IOException {
248
249 TaxonBase tb = getCdmBase(request, response, null, Taxon.class);
250 Taxon taxon = (Taxon)tb;
251 List<TaxonRelationship> relations = new ArrayList<TaxonRelationship>();
252 List<TaxonRelationship> results = service.listToTaxonRelationships(taxon, TaxonRelationshipType.MISAPPLIED_NAME_FOR(), null, null, null, TAXONRELATIONSHIP_INIT_STRATEGY);
253 relations.addAll(results);
254 results = service.listToTaxonRelationships(taxon, TaxonRelationshipType.INVALID_DESIGNATION_FOR(), null, null, null, TAXONRELATIONSHIP_INIT_STRATEGY);
255 relations.addAll(results);
256
257 return relations;
258 }
259
260 @RequestMapping(
261 value = {"/*/portal/taxon/*/nameRelationships"},
262 method = RequestMethod.GET)
263 public List<NameRelationship> doGetNameRelations(HttpServletRequest request, HttpServletResponse response)throws IOException {
264 TaxonBase tb = getCdmBase(request, response, SIMPLE_TAXON_INIT_STRATEGY, Taxon.class);
265 List<NameRelationship> list = nameService.listToNameRelationships(tb.getName(), null, null, null, null, NAMERELATIONSHIP_INIT_STRATEGY);
266 return list;
267 }
268
269 @RequestMapping(
270 value = {"/*/portal/name/*/descriptions"},
271 method = RequestMethod.GET)
272 public List<TaxonNameDescription> doGetNameDescriptions(HttpServletRequest request, HttpServletResponse response)throws IOException {
273 UUID nameUuuid = readValueUuid(request, null);
274 TaxonNameBase tnb = nameService.load(nameUuuid, null);
275 Pager<TaxonNameDescription> p = descriptionService.getTaxonNameDescriptions(tnb, null, null, NAMEDESCRIPTION_INIT_STRATEGY);
276 return p.getRecords();
277 }
278
279 @RequestMapping(
280 value = {"/*/portal/taxon/*/nameTypeDesignations"},
281 method = RequestMethod.GET)
282 public List<TypeDesignationBase> doGetNameTypeDesignations(HttpServletRequest request, HttpServletResponse response)throws IOException {
283 TaxonBase tb = getCdmBase(request, response, SIMPLE_TAXON_INIT_STRATEGY, Taxon.class);
284 Pager<TypeDesignationBase> p = nameService.getTypeDesignations(tb.getName(), null, null, null, TYPEDESIGNATION_INIT_STRATEGY);
285 return p.getRecords();
286 }
287
288 @RequestMapping(
289 value = {"/*/portal/taxon/*/descriptions"},
290 method = RequestMethod.GET)
291 public List<TaxonDescription> doGetDescriptions(HttpServletRequest request, HttpServletResponse response)throws IOException {
292 TaxonBase tb = getCdmBase(request, response, null, Taxon.class);
293 if(tb instanceof Taxon){
294 Pager<TaxonDescription> p = descriptionService.getTaxonDescriptions((Taxon)tb, null, null, null, null, TAXONDESCRIPTION_INIT_STRATEGY);
295 return p.getRecords();
296 } else {
297 response.sendError(HttpServletResponse.SC_NOT_FOUND, "invalid type; Taxon expected but " + tb.getClass().getSimpleName() + " found.");
298 return null;
299 }
300 }
301
302 // @RequestMapping(
303 // value = {"/*/portal/taxon/*/descriptions"},
304 // method = RequestMethod.GET)
305 // public List<TaxonDescription> doGetDescriptionsbyFeatureTree(HttpServletRequest request, HttpServletResponse response)throws IOException {
306 // TaxonBase tb = getCdmBase(request, response, null, Taxon.class);
307 // if(tb instanceof Taxon){
308 // //TODO this is a quick and dirty implementation -> generalize
309 // UUID featureTreeUuid = readValueUuid(request, featureTreeUuidPattern);
310 //
311 // FeatureTree featureTree = descriptionService.getFeatureTreeByUuid(featureTreeUuid);
312 // Pager<TaxonDescription> p = descriptionService.getTaxonDescriptions((Taxon)tb, null, null, null, null, TAXONDESCRIPTION_INIT_STRATEGY);
313 // List<TaxonDescription> descriptions = p.getRecords();
314 //
315 // if(!featureTree.isDescriptionSeparated()){
316 //
317 // TaxonDescription superDescription = TaxonDescription.NewInstance();
318 // //put all descriptionElements in superDescription and make it invisible
319 // for(TaxonDescription description: descriptions){
320 // for(DescriptionElementBase element: description.getElements()){
321 // superDescription.addElement(element);
322 // }
323 // }
324 // List<TaxonDescription> separatedDescriptions = new ArrayList<TaxonDescription>(descriptions.size());
325 // separatedDescriptions.add(superDescription);
326 // return separatedDescriptions;
327 // }else{
328 // return descriptions;
329 // }
330 // } else {
331 // response.sendError(HttpServletResponse.SC_NOT_FOUND, "invalid type; Taxon expected but " + tb.getClass().getSimpleName() + " found.");
332 // return null;
333 // }
334 // }
335
336 }