1 package eu
.etaxonomy
.cdm
.remote
.controller
;
3 import java
.io
.IOException
;
4 import java
.util
.ArrayList
;
5 import java
.util
.Arrays
;
6 import java
.util
.LinkedHashMap
;
10 import java
.util
.UUID
;
12 import javax
.servlet
.http
.HttpServletRequest
;
13 import javax
.servlet
.http
.HttpServletResponse
;
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
;
23 import eu
.etaxonomy
.cdm
.api
.service
.IClassificationService
;
24 import eu
.etaxonomy
.cdm
.api
.service
.INameService
;
25 import eu
.etaxonomy
.cdm
.api
.service
.ITaxonService
;
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
;
43 * The controller class for the namespace 'name_catalogue'.
44 * This controller provides search mechanisims for searching by taxon name as well as taxon.
48 * @created 15-Apr-2012
52 @RequestMapping(value
= {"/name_catalogue"})
53 public class NameCatalogueController
extends BaseController
<TaxonNameBase
, INameService
> {
55 /** Taxon status strings*/
56 public static final String ACCECPTED_NAME_STATUS
= "accepted_name";
57 public static final String SYNONYM_STATUS
= "synonym";
60 public static final String DOUBTFUL_FLAG
= "doubtful";
63 private ITaxonService taxonService
;
66 private IClassificationService classificationService
;
68 private static final List
<String
> NAME_SEARCH_INIT_STRATEGY
= Arrays
.asList(new String
[]{
69 "combinationAuthorTeam.$",
70 "exCombinationAuthorTeam.$",
71 "basionymAuthorTeam.$",
72 "exBasionymAuthorTeam.$",
76 private static final List
<String
> NAME_INFORMATION_INIT_STRATEGY
= Arrays
.asList(new String
[]{
79 "nomenclaturalReference.$",
80 "combinationAuthorTeam.$",
81 "exCombinationAuthorTeam.$",
82 "basionymAuthorTeam.$",
83 "exBasionymAuthorTeam.$",
84 "relationsToThisName.$",
85 "relationsFromThisName.$"
88 private static final List
<String
> TAXON_INFORMATION_INIT_STRATEGY
= Arrays
.asList(new String
[]{
91 "taxonNodes.classification"
94 private static final List
<String
> TAXON_NODE_INIT_STRATEGY
= Arrays
.asList(new String
[]{
98 "classification.reference.$",
99 "classification.reference.authorTeam.$"
102 public NameCatalogueController(){
104 setInitializationStrategy(Arrays
.asList(new String
[]{"$"})); //TODO still needed????
108 * @see eu.etaxonomy.cdm.remote.controller.GenericController#setService(eu.etaxonomy.cdm.api.service.IService)
112 public void setService(INameService service
) {
113 this.service
= service
;
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.
121 * URI: <b>/{datasource-name}/name_catalogue</b>
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.
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
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
) {
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 NameSearch ns
= new NameSearch();
148 ns
.setRequest(query
);
150 for (NonViralName nvn
: nameList
)
152 String titleCacheString
= nvn
.getTitleCache();
153 ns
.addToResponseList(titleCacheString
, nvn
.getUuid().toString(), nvn
.getTaxonBases());
158 ErrorResponse er
= new ErrorResponse();
159 er
.setErrorMessage("No Taxon Name for given query : " + query
);
163 mv
.addObject(nsList
);
168 * Returns information related to the taxon name matching the given <code>{nameUuid}</code>.
169 * The information includes the name string, relationships, rank, list of related lsids / taxon uuids, etc.
171 * URI: <b>/{datasource-name}/name_catalogue</b>
174 * The taxon name pattern(s) to query for. The query can contain wildcard characters ('*').
175 * The query can be performed with no wildcard or with the wildcard at the begin and / or end
176 * depending on the search pattern.
179 * @return a List of {@link NameSearch} objects each corresponding to a single query. These are built from
180 * {@TaxonNameBase} entities which are in turn initialized using the {@link #NAME_SEARCH_INIT_STRATEGY}
181 * @throws IOException
183 @RequestMapping(value
= {"name"},
184 method
= RequestMethod
.GET
)
185 public ModelAndView
doGetNameInformation(@RequestParam(value
= "nameUuid", required
= true) String
[] nameUuids
,
186 HttpServletRequest request
,
187 HttpServletResponse response
) throws IOException
{
188 ModelAndView mv
= new ModelAndView();
189 List
<RemoteResponse
> niList
= new ArrayList
<RemoteResponse
>();
190 for(String nameUuid
: nameUuids
) {
191 logger
.info("doGetNameInformation()" + request
.getServletPath() + " for name uuid \"" + nameUuid
+ "\"");
192 NonViralName nvn
= (NonViralName
)service
.findNameByUuid(UUID
.fromString(nameUuid
), NAME_INFORMATION_INIT_STRATEGY
);
194 NameInformation ni
= new NameInformation();
195 ni
.setRequest(nameUuid
);
196 Reference ref
= (Reference
) nvn
.getNomenclaturalReference();
197 String citation
= "";
198 String citation_details
= "";
200 citation
= ref
.getTitleCache();
202 ni
.setResponse(nvn
.getTitleCache(),
203 nvn
.getRank().getTitleCache(),
206 nvn
.getRelationsFromThisName(),
207 nvn
.getRelationsToThisName(),
208 nvn
.getTaxonBases());
211 ErrorResponse re
= new ErrorResponse();
212 re
.setErrorMessage("No Taxon Name for given UUID : " + nameUuid
);
216 mv
.addObject(niList
);
220 @RequestMapping(value
= {"taxon"},
221 method
= RequestMethod
.GET
)
222 public ModelAndView
doGetTaxonInformation(@RequestParam(value
= "taxonUuid", required
= true) String
[] taxonUuids
,
223 HttpServletRequest request
,
224 HttpServletResponse response
) throws IOException
{
225 ModelAndView mv
= new ModelAndView();
226 List
<RemoteResponse
> tiList
= new ArrayList
<RemoteResponse
>();
227 for(String taxonUuid
: taxonUuids
) {
228 logger
.info("doGetTaxonInformation()" + request
.getServletPath() + " for taxon uuid \"" + taxonUuid
);
229 TaxonBase tb
= taxonService
.findTaxonByUuid(UUID
.fromString(taxonUuid
), TAXON_INFORMATION_INIT_STRATEGY
);
231 TaxonInformation ti
= new TaxonInformation();
232 ti
.setRequest(taxonUuid
);
234 if(tb
.isInstanceOf(Taxon
.class)) {
235 Taxon taxon
= (Taxon
)tb
;
236 ti
.setResponseTaxon(tb
.getTitleCache(),
237 ACCECPTED_NAME_STATUS
,
239 buildClassificationMap(taxon
));
240 Set
<Synonym
> synonyms
= taxon
.getSynonyms();
241 for(Synonym syn
: synonyms
) {
242 String uuid
= syn
.getUuid().toString();
243 String name
= syn
.getTitleCache();
244 String status
= SYNONYM_STATUS
;
245 ti
.addToResponseRelatedTaxa(taxonUuid
, name
, status
, "");
247 } else if(tb
instanceof Synonym
) {
248 Synonym synonym
= (Synonym
)tb
;
249 ti
.setResponseTaxon(tb
.getTitleCache(),
253 Set
<Taxon
> acceptedTaxa
= synonym
.getAcceptedTaxa();
254 for(Taxon taxon
: acceptedTaxa
) {
255 String uuid
= taxon
.getUuid().toString();
256 String name
= taxon
.getTitleCache();
257 String status
= ACCECPTED_NAME_STATUS
;
258 ti
.addToResponseRelatedTaxa(taxonUuid
, name
, status
, "");
263 ErrorResponse re
= new ErrorResponse();
264 re
.setErrorMessage("No Taxon for given UUID : " + taxonUuid
);
268 mv
.addObject(tiList
);
272 private MatchMode
getMatchModeFromQuery(String query
) {
273 if(query
.startsWith("*") && query
.endsWith("*")) {
274 return MatchMode
.ANYWHERE
;
275 } else if(query
.startsWith("*")) {
276 return MatchMode
.END
;
277 } else if(query
.endsWith("*")) {
278 return MatchMode
.BEGINNING
;
280 return MatchMode
.EXACT
;
284 private String
getQueryWithoutWildCards(String query
) {
286 String newQuery
= query
;
288 if(query
.startsWith("*")) {
289 newQuery
= newQuery
.substring(1, newQuery
.length());
292 if(query
.endsWith("*")) {
293 newQuery
= newQuery
.substring(0, newQuery
.length()-1);
296 return newQuery
.trim();
299 private Map
<String
, String
> buildFlagMap(TaxonBase tb
) {
300 Map
<String
, String
> flags
= new Hashtable
<String
, String
>();
301 flags
.put(DOUBTFUL_FLAG
, Boolean
.toString(tb
.isDoubtful()));
305 private Map
<String
, Map
> buildClassificationMap(Taxon taxon
) {
306 Map
<String
, Map
> classificationMap
= new Hashtable
<String
, Map
>();
307 Set
<TaxonNode
> taxonNodes
= taxon
.getTaxonNodes();
309 for(TaxonNode tn
: taxonNodes
) {
310 Map
<String
, String
> classification
= new LinkedHashMap
<String
, String
>();
311 List
<TaxonNode
> tnList
= classificationService
.loadTreeBranchToTaxon(taxon
, tn
.getClassification(), null, TAXON_NODE_INIT_STRATEGY
);
312 for(TaxonNode classificationtn
: tnList
) {
314 classification
.put(classificationtn
.getTaxon().getName().getRank().getTitleCache(),
315 classificationtn
.getTaxon().getName().getTitleCache());
318 String cname
= tn
.getClassification().getTitleCache();
319 String
[] words
= cname
.split("\\s+");
320 //"\\s+" in regular expression language meaning one or more spaces
321 StringBuilder builder
= new StringBuilder();
322 for (String word
: words
){
323 builder
.append(word
);
325 cname
= builder
.toString();
326 classificationMap
.put(cname
, classification
);
328 return classificationMap
;