Controller class which contains entry points for Name Search, Name Information and...
[cdmlib.git] / cdmlib-remote / src / main / java / eu / etaxonomy / cdm / remote / controller / NameCatalogueController.java
1 package eu.etaxonomy.cdm.remote.controller;
2
3 import java.io.IOException;
4 import java.util.ArrayList;
5 import java.util.Arrays;
6 import java.util.LinkedHashMap;
7 import java.util.List;
8 import java.util.Map;
9 import java.util.Set;
10 import java.util.UUID;
11
12 import javax.servlet.http.HttpServletRequest;
13 import javax.servlet.http.HttpServletResponse;
14
15 import java.util.Hashtable;
16 import org.springframework.beans.factory.annotation.Autowired;
17 import org.springframework.stereotype.Controller;
18 import org.springframework.web.bind.annotation.RequestMapping;
19 import org.springframework.web.bind.annotation.RequestMethod;
20 import org.springframework.web.bind.annotation.RequestParam;
21 import org.springframework.web.servlet.ModelAndView;
22
23 import eu.etaxonomy.cdm.api.service.IClassificationService;
24 import eu.etaxonomy.cdm.api.service.INameService;
25 import eu.etaxonomy.cdm.api.service.ITaxonService;
26
27 import eu.etaxonomy.cdm.remote.dto.common.ErrorResponse;
28 import eu.etaxonomy.cdm.remote.dto.common.RemoteResponse;
29 import eu.etaxonomy.cdm.remote.dto.namecatalogue.NameInformation;
30 import eu.etaxonomy.cdm.remote.dto.namecatalogue.NameSearch;
31 import eu.etaxonomy.cdm.remote.dto.namecatalogue.TaxonInformation;
32 import eu.etaxonomy.cdm.model.name.NonViralName;
33 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
34 import eu.etaxonomy.cdm.model.name.TypeDesignationBase;
35 import eu.etaxonomy.cdm.model.reference.Reference;
36 import eu.etaxonomy.cdm.model.taxon.Synonym;
37 import eu.etaxonomy.cdm.model.taxon.Taxon;
38 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
39 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
40 import eu.etaxonomy.cdm.persistence.query.MatchMode;
41
42 /**
43 * The controller class for the namespace 'name_catalogue'.
44 * This controller provides search mechanisims for searching by taxon name as well as taxon.
45 *
46 * @author c.mathew
47 * @version 1.0
48 * @created 15-Apr-2012
49 */
50
51 @Controller
52 @RequestMapping(value = {"/name_catalogue"})
53 public class NameCatalogueController extends BaseController<TaxonNameBase, INameService> {
54
55 /** Taxon status strings*/
56 public static final String ACCECPTED_NAME_STATUS = "accepted_name";
57 public static final String SYNONYM_STATUS = "synonym";
58
59 /** Flag strings*/
60 public static final String DOUBTFUL_FLAG = "doubtful";
61
62 @Autowired
63 private ITaxonService taxonService;
64
65 @Autowired
66 private IClassificationService classificationService;
67
68 private static final List<String> NAME_SEARCH_INIT_STRATEGY = Arrays.asList(new String []{
69 "combinationAuthorTeam.$",
70 "exCombinationAuthorTeam.$",
71 "basionymAuthorTeam.$",
72 "exBasionymAuthorTeam.$",
73 "taxonBases"
74 });
75
76 private static final List<String> NAME_INFORMATION_INIT_STRATEGY = Arrays.asList(new String []{
77 "taxonBases",
78 "status",
79 "nomenclaturalReference.$",
80 "combinationAuthorTeam.$",
81 "exCombinationAuthorTeam.$",
82 "basionymAuthorTeam.$",
83 "exBasionymAuthorTeam.$",
84 "relationsToThisName.$",
85 "relationsFromThisName.$"
86 });
87
88 private static final List<String> TAXON_INFORMATION_INIT_STRATEGY = Arrays.asList(new String []{
89 "synonymRelations",
90 "taxonNodes",
91 "taxonNodes.classification"
92 });
93
94 private static final List<String> TAXON_NODE_INIT_STRATEGY = Arrays.asList(new String[]{
95 "taxon.sec",
96 "taxon.name",
97 "classification",
98 "classification.reference.$",
99 "classification.reference.authorTeam.$"
100 });
101
102 public NameCatalogueController(){
103 super();
104 setInitializationStrategy(Arrays.asList(new String[]{"$"})); //TODO still needed????
105 }
106
107 /* (non-Javadoc)
108 * @see eu.etaxonomy.cdm.remote.controller.GenericController#setService(eu.etaxonomy.cdm.api.service.IService)
109 */
110 @Autowired
111 @Override
112 public void setService(INameService service) {
113 this.service = service;
114 }
115
116 /**
117 * Returns a list of taxon names matching the <code>{query}</code> string pattern.
118 * Each of these taxon names is accompanied by a list of name uuids and
119 * a list of taxon uuids.
120 * <p>
121 * URI: <b>&#x002F;{datasource-name}&#x002F;name_catalogue</b>
122 *
123 * @param query
124 * The taxon name pattern(s) to query for. The query can contain wildcard characters ('*').
125 * The query can be performed with no wildcard or with the wildcard at the begin and / or end
126 * depending on the search pattern.
127 * @param request
128 * @param response
129 * @return a List of {@link NameSearch} objects each corresponding to a single query. These are built from
130 * {@TaxonNameBase} entities which are in turn initialized using the {@link #NAME_SEARCH_INIT_STRATEGY}
131 * @throws IOException
132 */
133 @RequestMapping(value = {""},
134 method = RequestMethod.GET)
135 public ModelAndView doGetNameSearch(@RequestParam(value = "query", required = true) String[] queries,
136 HttpServletRequest request,
137 HttpServletResponse response) throws IOException {
138 ModelAndView mv = new ModelAndView();
139 List <RemoteResponse> nsList = new ArrayList<RemoteResponse>();
140 for(String query : queries ) {
141
142 String queryWOWildcards = getQueryWithoutWildCards(query);
143 MatchMode mm = getMatchModeFromQuery(query);
144 logger.info("doGetNameSearch()" + request.getServletPath() + " for query \"" + query + "\" without wild cards : " + queryWOWildcards + " and match mode : " + mm);
145 List<NonViralName> nameList = (List<NonViralName>)service.findNamesByTitleCache(queryWOWildcards, mm, NAME_SEARCH_INIT_STRATEGY);
146 if(nameList == null || !nameList.isEmpty()) {
147 System.out.println("Size : " + nameList.size());
148
149 NameSearch ns = new NameSearch();
150 ns.setRequest(query);
151
152 for (NonViralName nvn : nameList)
153 {
154 String titleCacheString = nvn.getTitleCache();
155 ns.addToResponseList(titleCacheString, nvn.getUuid().toString(), nvn.getTaxonBases());
156 }
157 nsList.add(ns);
158
159 } else {
160 ErrorResponse er = new ErrorResponse();
161 er.setErrorMessage("No Taxon Name for given query : " + query);
162 nsList.add(er);
163 }
164 }
165 mv.addObject(nsList);
166 return mv;
167 }
168
169 /**
170 * Returns information related to the taxon name matching the given <code>{nameUuid}</code>.
171 * The information includes the name string, relationships, rank, list of related lsids / taxon uuids, etc.
172 * <p>
173 * URI: <b>&#x002F;{datasource-name}&#x002F;name_catalogue</b>
174 *
175 * @param query
176 * The taxon name pattern(s) to query for. The query can contain wildcard characters ('*').
177 * The query can be performed with no wildcard or with the wildcard at the begin and / or end
178 * depending on the search pattern.
179 * @param request
180 * @param response
181 * @return a List of {@link NameSearch} objects each corresponding to a single query. These are built from
182 * {@TaxonNameBase} entities which are in turn initialized using the {@link #NAME_SEARCH_INIT_STRATEGY}
183 * @throws IOException
184 */
185 @RequestMapping(value = {"name"},
186 method = RequestMethod.GET)
187 public ModelAndView doGetNameInformation(@RequestParam(value = "nameUuid", required = true) String[] nameUuids,
188 HttpServletRequest request,
189 HttpServletResponse response) throws IOException {
190 ModelAndView mv = new ModelAndView();
191 List <RemoteResponse> niList = new ArrayList<RemoteResponse>();
192 for(String nameUuid : nameUuids ) {
193 logger.info("doGetNameInformation()" + request.getServletPath() + " for name uuid \"" + nameUuid);
194 NonViralName nvn = (NonViralName)service.findNameByUuid(UUID.fromString(nameUuid), NAME_INFORMATION_INIT_STRATEGY);
195 if(nvn != null) {
196 NameInformation ni = new NameInformation();
197 ni.setRequest(nameUuid);
198 Reference ref = (Reference) nvn.getNomenclaturalReference();
199 String citation = "";
200 String citation_details = "";
201 if(ref != null) {
202 citation = ref.getTitleCache();
203 }
204 ni.setResponse(nvn.getTitleCache(),
205 nvn.getRank().getTitleCache(),
206 nvn.getStatus(),
207 citation,
208 nvn.getRelationsFromThisName(),
209 nvn.getRelationsToThisName(),
210 nvn.getTaxonBases());
211 niList.add(ni);
212 } else {
213 ErrorResponse re = new ErrorResponse();
214 re.setErrorMessage("No Taxon Name for given UUID : " + nameUuid);
215 niList.add(re);
216 }
217 }
218 mv.addObject(niList);
219 return mv;
220 }
221
222 @RequestMapping(value = {"taxon"},
223 method = RequestMethod.GET)
224 public ModelAndView doGetTaxonInformation(@RequestParam(value = "taxonUuid", required = true) String[] taxonUuids,
225 HttpServletRequest request,
226 HttpServletResponse response) throws IOException {
227 ModelAndView mv = new ModelAndView();
228 List <RemoteResponse> tiList = new ArrayList<RemoteResponse>();
229 for(String taxonUuid : taxonUuids ) {
230 logger.info("doGetTaxonInformation()" + request.getServletPath() + " for taxon uuid \"" + taxonUuid);
231 TaxonBase tb= taxonService.findTaxonByUuid(UUID.fromString(taxonUuid), TAXON_INFORMATION_INIT_STRATEGY);
232 if(tb != null) {
233 System.out.println("Name : " + tb.getTitleCache());
234 TaxonInformation ti = new TaxonInformation();
235 ti.setRequest(taxonUuid);
236
237 if(tb.isInstanceOf(Taxon.class)) {
238 Taxon taxon = (Taxon)tb;
239 System.out.println("Is a Taxon");
240 ti.setResponseTaxon(tb.getTitleCache(),
241 ACCECPTED_NAME_STATUS,
242 buildFlagMap(tb),
243 buildClassificationMap(taxon));
244 Set<Synonym> synonyms = taxon.getSynonyms();
245 for(Synonym syn: synonyms) {
246 String uuid = syn.getUuid().toString();
247 String name = syn.getTitleCache();
248 String status = SYNONYM_STATUS;
249 ti.addToResponseRelatedTaxa(taxonUuid, name, status, "");
250 }
251 } else if(tb instanceof Synonym) {
252 Synonym synonym = (Synonym)tb;
253 System.out.println("Is a Synonym");
254 ti.setResponseTaxon(tb.getTitleCache(),
255 SYNONYM_STATUS,
256 buildFlagMap(tb),
257 null);
258 Set<Taxon> acceptedTaxa = synonym.getAcceptedTaxa();
259 for(Taxon taxon : acceptedTaxa) {
260 String uuid = taxon.getUuid().toString();
261 String name = taxon.getTitleCache();
262 String status = ACCECPTED_NAME_STATUS;
263 ti.addToResponseRelatedTaxa(taxonUuid, name, status, "");
264 }
265 }
266 tiList.add(ti);
267 } else {
268 ErrorResponse re = new ErrorResponse();
269 re.setErrorMessage("No Taxon for given UUID : " + taxonUuid);
270 tiList.add(re);
271 }
272 }
273 mv.addObject(tiList);
274 return mv;
275 }
276
277 private MatchMode getMatchModeFromQuery(String query) {
278 if(query.startsWith("*") && query.endsWith("*")) {
279 return MatchMode.ANYWHERE;
280 } else if(query.startsWith("*")) {
281 return MatchMode.END;
282 } else if(query.endsWith("*")) {
283 return MatchMode.BEGINNING;
284 } else {
285 return MatchMode.EXACT;
286 }
287 }
288
289 private String getQueryWithoutWildCards(String query) {
290
291 String newQuery = query;
292 if(query.startsWith("*")) {
293 newQuery = newQuery.substring(1, newQuery.length());
294 }
295
296 if(query.endsWith("*")) {
297 newQuery = newQuery.substring(0, newQuery.length()-1);
298 }
299 return newQuery;
300 }
301
302 private Map<String, String> buildFlagMap(TaxonBase tb) {
303 Map<String, String> flags = new Hashtable<String, String>();
304 flags.put(DOUBTFUL_FLAG, Boolean.toString(tb.isDoubtful()));
305 return flags;
306 }
307
308 private Map<String, Map> buildClassificationMap(Taxon taxon) {
309 Map<String, Map> classificationMap = new Hashtable<String, Map>();
310 Set<TaxonNode> taxonNodes = taxon.getTaxonNodes();
311
312 for(TaxonNode tn : taxonNodes) {
313 Map<String, String> classification = new LinkedHashMap<String, String>();
314 List<TaxonNode> tnList = classificationService.loadTreeBranchToTaxon(taxon, tn.getClassification(), null, TAXON_NODE_INIT_STRATEGY);
315 for(TaxonNode classificationtn : tnList) {
316
317 classification.put(classificationtn.getTaxon().getName().getRank().getTitleCache(),
318 classificationtn.getTaxon().getName().getTitleCache());
319 System.out.println("Classification : " + classificationtn.getTaxon().getName().getRank().getTitleCache());
320
321 }
322 System.out.println("CTitle : " + tn.getClassification().getTitleCache());
323 String cname = tn.getClassification().getTitleCache();
324 String [] words = cname.split("\\s+");
325 //"\\s+" in regular expression language meaning one or more spaces
326 StringBuilder builder = new StringBuilder();
327 for (String word : words){
328 builder.append(word);
329 }
330 cname = builder.toString();
331 classificationMap.put(cname, classification);
332 }
333 return classificationMap;
334 }
335
336
337 }