2 package eu
.etaxonomy
.cdm
.remote
.controller
;
5 import java
.io
.IOException
;
6 import java
.io
.InputStream
;
7 import java
.util
.ArrayList
;
8 import java
.util
.Arrays
;
9 import java
.util
.HashMap
;
10 import java
.util
.HashSet
;
11 import java
.util
.LinkedHashMap
;
12 import java
.util
.List
;
15 import java
.util
.TreeMap
;
16 import java
.util
.UUID
;
18 import javax
.servlet
.http
.HttpServletRequest
;
19 import javax
.servlet
.http
.HttpServletResponse
;
21 import java
.util
.Hashtable
;
23 import org
.springframework
.beans
.factory
.annotation
.Autowired
;
24 import org
.springframework
.context
.ResourceLoaderAware
;
25 import org
.springframework
.core
.io
.Resource
;
26 import org
.springframework
.core
.io
.ResourceLoader
;
27 import org
.springframework
.stereotype
.Controller
;
28 import org
.springframework
.web
.bind
.annotation
.RequestMapping
;
29 import org
.springframework
.web
.bind
.annotation
.RequestMethod
;
30 import org
.springframework
.web
.bind
.annotation
.RequestParam
;
31 import org
.springframework
.web
.servlet
.ModelAndView
;
33 import eu
.etaxonomy
.cdm
.api
.service
.IClassificationService
;
34 import eu
.etaxonomy
.cdm
.api
.service
.INameService
;
35 import eu
.etaxonomy
.cdm
.api
.service
.ITaxonService
;
36 import eu
.etaxonomy
.cdm
.common
.DocUtils
;
38 import eu
.etaxonomy
.cdm
.remote
.dto
.common
.ErrorResponse
;
39 import eu
.etaxonomy
.cdm
.remote
.dto
.common
.RemoteResponse
;
40 import eu
.etaxonomy
.cdm
.remote
.dto
.namecatalogue
.NameInformation
;
41 import eu
.etaxonomy
.cdm
.remote
.dto
.namecatalogue
.NameSearch
;
42 import eu
.etaxonomy
.cdm
.remote
.dto
.namecatalogue
.TaxonInformation
;
43 import eu
.etaxonomy
.cdm
.remote
.view
.HtmlView
;
44 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
45 import eu
.etaxonomy
.cdm
.model
.name
.NonViralName
;
46 import eu
.etaxonomy
.cdm
.model
.name
.TaxonNameBase
;
47 import eu
.etaxonomy
.cdm
.model
.reference
.Reference
;
48 import eu
.etaxonomy
.cdm
.model
.taxon
.Synonym
;
49 import eu
.etaxonomy
.cdm
.model
.taxon
.SynonymRelationship
;
50 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
51 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
52 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonNode
;
53 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationship
;
54 import eu
.etaxonomy
.cdm
.persistence
.query
.MatchMode
;
57 * The controller class for the namespace 'name_catalogue'. This web service namespace
58 * is an add-on to the already existing CDM REST API and provides information relating
59 * to scientific names as well as taxa present in the underlying datasource.
63 * @created 15-Apr-2012
67 @RequestMapping(value
= { "/name_catalogue" })
68 public class NameCatalogueController
extends BaseController
<TaxonNameBase
, INameService
> implements ResourceLoaderAware
{
70 private ResourceLoader resourceLoader
;
72 /** Taxonomic status 'accepted' string */
73 public static final String ACCEPTED_NAME_STATUS
= "accepted";
75 /** Taxonpmic status 'synonym' string */
76 public static final String SYNONYM_STATUS
= "synonym";
78 /** Flag 'doubtful' strings */
79 public static final String DOUBTFUL_FLAG
= "doubtful";
81 /** Base scientific name search type */
82 public static final String NAME_SEARCH
= "name";
84 /** Complete scientific name search type */
85 public static final String TITLE_SEARCH
= "title";
87 /** Default name search type */
88 public static final String DEFAULT_SEARCH_TYPE
= NAME_SEARCH
;
90 /** Classifcation 'default' key */
91 public static final String CLASSIFICATION_DEFAULT
= "default";
93 /** Classifcation 'all' key */
94 public static final String CLASSIFICATION_ALL
= "all";
97 private ITaxonService taxonService
;
100 private IClassificationService classificationService
;
102 /** Hibernate name search initialisation strategy */
103 private static final List
<String
> NAME_SEARCH_INIT_STRATEGY
= Arrays
.asList(new String
[] {
104 "combinationAuthorTeam.$",
105 "exCombinationAuthorTeam.$",
106 "basionymAuthorTeam.$",
107 "exBasionymAuthorTeam.$",
110 "taxonBases.synonymRelations.type.$"});
112 /** Hibernate name information initialisation strategy */
113 private static final List
<String
> NAME_INFORMATION_INIT_STRATEGY
= Arrays
.asList(new String
[] {
116 "nomenclaturalReference.$",
117 "combinationAuthorTeam.$",
118 "exCombinationAuthorTeam.$",
119 "basionymAuthorTeam.$",
120 "exBasionymAuthorTeam.$",
121 "relationsToThisName.$",
122 "relationsFromThisName.$" });
124 /** Hibernate taxon information initialisation strategy */
125 private static final List
<String
> TAXON_INFORMATION_INIT_STRATEGY
= Arrays
.asList(new String
[] {
126 "synonymRelations.type.$",
127 "relationsFromThisTaxon.type.$",
128 "relationsToThisTaxon.type.$",
130 "taxonNodes.classification" });
132 /** Hibernate taxon node initialisation strategy */
133 private static final List
<String
> TAXON_NODE_INIT_STRATEGY
= Arrays
.asList(new String
[] {
137 "classification.reference.$",
138 "classification.reference.authorTeam.$" });
140 public NameCatalogueController() {
142 setInitializationStrategy(Arrays
.asList(new String
[] { "$" }));
149 * eu.etaxonomy.cdm.remote.controller.GenericController#setService(eu
150 * .etaxonomy.cdm.api.service.IService)
154 public void setService(INameService service
) {
155 this.service
= service
;
159 * Returns a documentation page for the Name Search API.
161 * URI: <b>/{datasource-name}/name_catalogue</b>
165 * @return Html page describing the Name Search API
166 * @throws IOException
168 @RequestMapping(value
= { "" }, method
= RequestMethod
.GET
, params
= {})
169 public ModelAndView
doGetNameSearchDocumentation(
170 HttpServletRequest request
, HttpServletResponse response
)
172 ModelAndView mv
= new ModelAndView();
173 // Read apt documentation file.
174 Resource resource
= resourceLoader
.getResource("classpath:eu/etaxonomy/cdm/doc/remote/apt/name-catalogue-default.apt");
175 // using input stream as this works for both files in the classes directory
176 // as well as files inside jars
177 InputStream aptInputStream
= resource
.getInputStream();
179 HtmlView hv
= new HtmlView();
180 Map
<String
, String
> modelMap
= new HashMap
<String
, String
>();
181 modelMap
.put("title", "Name Search API");
182 // Convert Apt to Html
183 modelMap
.put("body", DocUtils
.convertAptToHtml(aptInputStream
));
184 mv
.addAllObjects(modelMap
);
191 * Returns a list of scientific names matching the <code>{query}</code>
192 * string pattern. Each of these scientific names is accompanied by a list of
193 * name uuids, a list of taxon uuids, a list of accepted taxon uuids, etc.
195 * Endpoint documentation can be found <a href="{@docRoot}/../remote/name-catalogue-default.html">here</a>
197 * URI: <b>/{datasource-name}/name_catalogue</b>
200 * The base scientific name pattern(s) to query for. The query can
201 * contain wildcard characters ('*'). The query can be
202 * performed with no wildcard or with the wildcard at the
203 * begin and / or end depending on the search pattern.
204 * @param request Http servlet request.
205 * @param response Http servlet response.
206 * @return a list of {@link NameSearch} objects each corresponding to a
207 * single query. These are built from {@link TaxonNameBase}
208 * entities which are in turn initialized using
209 * the {@link #NAME_SEARCH_INIT_STRATEGY}
210 * @throws IOException
212 @RequestMapping(value
= { "" }, method
= RequestMethod
.GET
, params
= {"query"})
213 public ModelAndView
doGetNameSearch(@RequestParam(value
= "query", required
= true) String
[] queries
,
214 HttpServletRequest request
, HttpServletResponse response
) throws IOException
{
215 return doGetNameSearch(queries
, DEFAULT_SEARCH_TYPE
, request
, response
);
219 * Returns a list of scientific names matching the <code>{query}</code>
220 * string pattern. Each of these scientific names is accompanied by a list of
221 * name uuids, a list of taxon uuids and a list of accepted taxon uuids.
223 * Endpoint documentation can be found <a href="{@docRoot}/../remote/name-catalogue-default.html">here</a>
225 * URI: <b>/{datasource-name}/name_catalogue</b>
228 * The scientific name pattern(s) to query for. The query can
229 * contain wildcard characters ('*'). The query can be
230 * performed with no wildcard or with the wildcard at the
231 * begin and / or end depending on the search pattern.
233 * The type of name to query. This be either
234 * "name" : scientific name corresponding to 'name cache' in CDM or
235 * "title" : complete name corresponding to 'title cache' in CDM
236 * @param request Http servlet request.
237 * @param response Http servlet response.
238 * @return a List of {@link NameSearch} objects each corresponding to a
239 * single query. These are built from {@link TaxonNameBase} entities
240 * which are in turn initialized using the {@link #NAME_SEARCH_INIT_STRATEGY}
241 * @throws IOException
243 @RequestMapping(value
= { "" }, method
= RequestMethod
.GET
, params
= {"query", "type"})
244 public ModelAndView
doGetNameSearch(@RequestParam(value
= "query", required
= true) String
[] queries
,
245 @RequestParam(value
= "type", required
= false, defaultValue
= DEFAULT_SEARCH_TYPE
) String searchType
,
246 HttpServletRequest request
, HttpServletResponse response
) throws IOException
{
247 ModelAndView mv
= new ModelAndView();
248 List
<RemoteResponse
> nsList
= new ArrayList
<RemoteResponse
>();
250 // if search type is not known then return error
251 if (!searchType
.equals(NAME_SEARCH
) && !searchType
.equals(TITLE_SEARCH
)) {
252 ErrorResponse er
= new ErrorResponse();
253 er
.setErrorMessage("searchType parameter can only be set as" + NAME_SEARCH
+ " or "
259 // search through each query
260 for (String query
: queries
) {
262 String queryWOWildcards
= getQueryWithoutWildCards(query
);
263 MatchMode mm
= getMatchModeFromQuery(query
);
264 logger
.info("doGetNameSearch()" + request
.getServletPath() + " for query \"" + query
265 + "\" without wild cards : " + queryWOWildcards
+ " and match mode : " + mm
);
266 List
<NonViralName
> nameList
= new ArrayList
<NonViralName
>();
268 // if "name" search then find by name cache
269 if (searchType
.equals(NAME_SEARCH
)) {
270 nameList
= (List
<NonViralName
>) service
.findNamesByNameCache(queryWOWildcards
, mm
,
271 NAME_SEARCH_INIT_STRATEGY
);
274 //if "title" search then find by title cache
275 if (searchType
.equals(TITLE_SEARCH
)) {
276 nameList
= (List
<NonViralName
>) service
.findNamesByTitleCache(queryWOWildcards
, mm
,
277 NAME_SEARCH_INIT_STRATEGY
);
280 // if search is successful then get related information , else return error
281 if (nameList
== null || !nameList
.isEmpty()) {
282 NameSearch ns
= new NameSearch();
283 ns
.setRequest(query
);
285 for (NonViralName nvn
: nameList
) {
286 // we need to retrieve both taxon uuid of name queried and
287 // the corresponding accepted taxa.
288 // reason to return accepted taxa also, is to be able to get from
289 // scientific name to taxon concept in two web service calls.
290 Set
<TaxonBase
> tbSet
= nvn
.getTaxonBases();
291 Set
<TaxonBase
> accTbSet
= new HashSet
<TaxonBase
>();
292 for (TaxonBase tb
: tbSet
) {
293 // if synonym then get accepted taxa.
294 if (tb
instanceof Synonym
) {
295 Synonym synonym
= (Synonym
) tb
;
296 Set
<SynonymRelationship
> synRelationships
= synonym
.getSynonymRelations();
297 for (SynonymRelationship sr
: synRelationships
) {
298 Taxon accTaxon
= sr
.getAcceptedTaxon();
299 accTbSet
.add(accTaxon
);
305 // update name search object
306 ns
.addToResponseList(nvn
.getTitleCache(), nvn
.getNameCache(), nvn
.getUuid()
307 .toString(), tbSet
, accTbSet
);
312 ErrorResponse er
= new ErrorResponse();
313 er
.setErrorMessage("No Taxon Name for given query : " + query
);
317 mv
.addObject(nsList
);
323 * Returns a documentation page for the Name Information API.
325 * URI: <b>/{datasource-name}/name_catalogue/name</b>
327 * @param request Http servlet request.
328 * @param response Http servlet response.
329 * @return Html page describing the Name Information API
330 * @throws IOException
332 @RequestMapping(value
= { "name" }, method
= RequestMethod
.GET
, params
= {})
333 public ModelAndView
doGetNameInformationDocumentation(
334 HttpServletRequest request
, HttpServletResponse response
)
336 ModelAndView mv
= new ModelAndView();
337 // Read apt documentation file.
338 Resource resource
= resourceLoader
.getResource("classpath:eu/etaxonomy/cdm/doc/remote/apt/name-catalogue-name-info.apt");
339 // using input stream as this works for both files in the classes directory
340 // as well as files inside jars
341 InputStream aptInputStream
= resource
.getInputStream();
343 HtmlView hv
= new HtmlView();
344 Map
<String
, String
> modelMap
= new HashMap
<String
, String
>();
345 modelMap
.put("title", "Name Information API");
346 // Convert Apt to Html
347 modelMap
.put("body", DocUtils
.convertAptToHtml(aptInputStream
));
348 mv
.addAllObjects(modelMap
);
355 * Returns information related to the scientific name matching the given
356 * <code>{nameUuid}</code>. The information includes the name string,
357 * relationships, rank, list of related lsids / taxon uuids, etc.
359 * Endpoint documentation can be found <a href="{@docRoot}/../remote/name-catalogue-name-info.html">here</a>
361 * URI: <b>/{datasource-name}/name_catalogue/name</b>
363 * @param nameUuids uuid(s) of the scientific name to search for.
364 * @param request Http servlet request.
365 * @param response Http servlet response.
366 * @return a List of {@link NameInformation} objects each corresponding to a
367 * single name uuid. These are built from {@link TaxonNameBase} entities
368 * which are in turn initialized using the {@link #NAME_INFORMATION_INIT_STRATEGY}
369 * @throws IOException
371 @RequestMapping(value
= { "name" }, method
= RequestMethod
.GET
, params
= {"nameUuid"})
372 public ModelAndView
doGetNameInformation(@RequestParam(value
= "nameUuid", required
= true) String
[] nameUuids
,
373 HttpServletRequest request
, HttpServletResponse response
) throws IOException
{
374 ModelAndView mv
= new ModelAndView();
375 List
<RemoteResponse
> niList
= new ArrayList
<RemoteResponse
>();
376 // loop through each name uuid
377 for (String nameUuid
: nameUuids
) {
378 logger
.info("doGetNameInformation()" + request
.getServletPath() + " for name uuid \""
381 NonViralName nvn
= (NonViralName
) service
.findNameByUuid(UUID
.fromString(nameUuid
),
382 NAME_INFORMATION_INIT_STRATEGY
);
384 // if search is successful then get related information, else return error
386 NameInformation ni
= new NameInformation();
387 ni
.setRequest(nameUuid
);
388 Reference ref
= (Reference
) nvn
.getNomenclaturalReference();
389 String citation
= "";
390 String citation_details
= "";
392 citation
= ref
.getTitleCache();
394 // update name information object
395 ni
.setResponse(nvn
.getTitleCache(), nvn
.getNameCache(), nvn
.getRank().getTitleCache(),
396 nvn
.getStatus(), citation
, nvn
.getRelationsFromThisName(),
397 nvn
.getRelationsToThisName(), nvn
.getTaxonBases());
400 ErrorResponse re
= new ErrorResponse();
401 re
.setErrorMessage("No Taxon Name for given UUID : " + nameUuid
);
405 mv
.addObject(niList
);
410 * Returns a documentation page for the Taxon Information API.
412 * URI: <b>/{datasource-name}/name_catalogue/taxon</b>
414 * @param request Http servlet request.
415 * @param response Http servlet response.
416 * @return Html page describing the Taxon Information API
417 * @throws IOException
419 @RequestMapping(value
= { "taxon" }, method
= RequestMethod
.GET
, params
= {})
420 public ModelAndView
doGetTaxonInformation(
421 HttpServletRequest request
, HttpServletResponse response
)
423 ModelAndView mv
= new ModelAndView();
424 // Read apt documentation file.
425 Resource resource
= resourceLoader
.getResource("classpath:eu/etaxonomy/cdm/doc/remote/apt/name-catalogue-taxon-info.apt");
426 // using input stream as this works for both files in the classes directory
427 // as well as files inside jars
428 InputStream aptInputStream
= resource
.getInputStream();
430 HtmlView hv
= new HtmlView();
431 Map
<String
, String
> modelMap
= new HashMap
<String
, String
>();
432 modelMap
.put("title", "Taxon Information API");
433 // Convert Apt to Html
434 modelMap
.put("body", DocUtils
.convertAptToHtml(aptInputStream
));
435 mv
.addAllObjects(modelMap
);
442 * Returns information related to the taxon matching the given
443 * <code>{taxonUuid}</code>. The information includes the name cache, title cache
444 * relationship type, taxonomic status, information , etc.
446 * Endpoint documentation can be found <a href="{@docRoot}/../remote/name-catalogue-taxon-info.html">here</a>
448 * URI: <b>/{datasource-name}/name_catalogue</b>
451 * The taxon uuid to query for. The classification returned corresponds
452 * to the first in the alphabetically sorted list of classifications
453 * currently available in the database.
455 * @param request Http servlet request.
456 * @param response Http servlet response.
457 * @return a List of {@link TaxonInformation} objects each corresponding to a
458 * single query. These are built from {@TaxonBase} entities which are
459 * in turn initialized using the {@link #TAXON_INFORMATION_INIT_STRATEGY}
460 * @throws IOException
462 @RequestMapping(value
= { "taxon" }, method
= RequestMethod
.GET
,params
= {"taxonUuid"})
463 public ModelAndView
doGetTaxonInformation(
464 @RequestParam(value
= "taxonUuid", required
= true) String
[] taxonUuids
,
465 HttpServletRequest request
, HttpServletResponse response
) throws IOException
{
466 return doGetTaxonInformation(taxonUuids
,CLASSIFICATION_DEFAULT
, request
, response
);
470 * Returns information related to the taxon matching the given
471 * <code>{taxonUuid}</code>. The information includes the name cache, title cache
472 * relationship type, taxonomic status, information , etc.
474 * Endpoint documentation can be found <a href="{@docRoot}/../remote/name-catalogue-taxon-info.html">here</a>
476 * URI: <b>/{datasource-name}/name_catalogue/taxon</b>
479 * The taxon uuid to query for.
480 * @param classification
481 * [Optional] String representing the taxonomic classification to use for
482 * building the classification tree. Defaults to the first in the alphabetically
483 * sorted list of classifications currently available in the database.
485 * @param request Http servlet request.
486 * @param response Http servlet response.
487 * @return a List of {@link TaxonInformation} objects each corresponding to a
488 * single query. These are built from {@TaxonBase} entities which are
489 * in turn initialized using the {@link #TAXON_INFORMATION_INIT_STRATEGY}
490 * @throws IOException
492 @RequestMapping(value
= { "taxon" }, method
= RequestMethod
.GET
, params
= {"taxonUuid", "classification"})
493 public ModelAndView
doGetTaxonInformation(
494 @RequestParam(value
= "taxonUuid", required
= true) String
[] taxonUuids
,
495 @RequestParam(value
= "classification", required
= false, defaultValue
= CLASSIFICATION_DEFAULT
) String classificationType
,
496 HttpServletRequest request
, HttpServletResponse response
) throws IOException
{
497 ModelAndView mv
= new ModelAndView();
498 List
<RemoteResponse
> tiList
= new ArrayList
<RemoteResponse
>();
499 // loop through each name uuid
500 for (String taxonUuid
: taxonUuids
) {
501 logger
.info("doGetTaxonInformation()" + request
.getServletPath() + " for taxon uuid \""
504 TaxonBase tb
= taxonService
.findTaxonByUuid(UUID
.fromString(taxonUuid
),
505 TAXON_INFORMATION_INIT_STRATEGY
);
506 // if search is successful then get related information, else return error
508 TaxonInformation ti
= new TaxonInformation();
509 ti
.setRequest(taxonUuid
);
510 // check if result (taxon base) is a taxon or synonym
511 if (tb
.isInstanceOf(Taxon
.class)) {
512 Taxon taxon
= (Taxon
) tb
;
513 // build classification map
514 Map classificationMap
= buildClassificationMap(taxon
, classificationType
);
515 if (classificationMap
== null) {
516 ErrorResponse er
= new ErrorResponse();
517 er
.setErrorMessage("Invalid classification type");
522 if (classificationMap
.isEmpty()) {
523 ErrorResponse er
= new ErrorResponse();
524 er
.setErrorMessage("No classification available for requested type");
528 // update taxon information object with taxon related data
529 ti
.setResponseTaxon(tb
.getTitleCache(), ACCEPTED_NAME_STATUS
, buildFlagMap(tb
),
531 Set
<SynonymRelationship
> synRelationships
= taxon
.getSynonymRelations();
532 // add synonyms (if exists) to taxon information object
533 for (SynonymRelationship sr
: synRelationships
) {
534 Synonym syn
= sr
.getSynonym();
535 String uuid
= syn
.getUuid().toString();
536 String title
= syn
.getTitleCache();
537 String status
= SYNONYM_STATUS
;
538 String relLabel
= sr
.getType()
539 .getInverseRepresentation(Language
.DEFAULT())
541 ti
.addToResponseRelatedTaxa(uuid
, title
, status
, "", relLabel
);
544 // build relationship information as,
545 // - relationships from the requested taxon
546 Set
<TaxonRelationship
> trFromSet
= taxon
.getRelationsFromThisTaxon();
547 for (TaxonRelationship tr
: trFromSet
) {
548 String titleTo
= tr
.getRelatedTo().getTitleCache();
549 String uuid
= tr
.getRelatedTo().getUuid().toString();
550 String status
= ACCEPTED_NAME_STATUS
;
551 String relLabel
= tr
.getType().getRepresentation(Language
.DEFAULT())
553 ti
.addToResponseRelatedTaxa(uuid
, titleTo
, status
, "", relLabel
);
556 // - relationships from the requested taxon
557 Set
<TaxonRelationship
> trToSet
= taxon
.getRelationsToThisTaxon();
558 for (TaxonRelationship tr
: trToSet
) {
559 String titleFrom
= tr
.getRelatedFrom().getTitleCache();
560 String uuid
= tr
.getRelatedFrom().getUuid().toString();
561 String status
= ACCEPTED_NAME_STATUS
;
562 String relLabel
= tr
.getType()
563 .getInverseRepresentation(Language
.DEFAULT())
565 ti
.addToResponseRelatedTaxa(uuid
, titleFrom
, status
, "", relLabel
);
567 } else if (tb
instanceof Synonym
) {
568 Synonym synonym
= (Synonym
) tb
;
569 // update taxon information object with synonym related data
570 ti
.setResponseTaxon(synonym
.getTitleCache(), SYNONYM_STATUS
,
571 buildFlagMap(synonym
), null);
572 // add accepted taxa (if exists) to taxon information object
573 Set
<SynonymRelationship
> synRelationships
= synonym
.getSynonymRelations();
574 for (SynonymRelationship sr
: synRelationships
) {
575 Taxon accTaxon
= sr
.getAcceptedTaxon();
576 String uuid
= accTaxon
.getUuid().toString();
577 String title
= accTaxon
.getTitleCache();
578 String status
= ACCEPTED_NAME_STATUS
;
579 String relLabel
= sr
.getType().getRepresentation(Language
.DEFAULT())
581 ti
.addToResponseRelatedTaxa(uuid
, title
, status
, "", relLabel
);
586 ErrorResponse re
= new ErrorResponse();
587 re
.setErrorMessage("No Taxon for given UUID : " + taxonUuid
);
591 mv
.addObject(tiList
);
596 * Returns the match mode by parsing the input string of wildcards.
601 * @return {@link MatchMode} depending on the the position of the wildcard (*)
603 private MatchMode
getMatchModeFromQuery(String query
) {
604 if (query
.startsWith("*") && query
.endsWith("*")) {
605 return MatchMode
.ANYWHERE
;
606 } else if (query
.startsWith("*")) {
607 return MatchMode
.END
;
608 } else if (query
.endsWith("*")) {
609 return MatchMode
.BEGINNING
;
611 return MatchMode
.EXACT
;
616 * Removes wildcards from the input string.
621 * @return input string with wildcards removed
623 private String
getQueryWithoutWildCards(String query
) {
625 String newQuery
= query
;
627 if (query
.startsWith("*")) {
628 newQuery
= newQuery
.substring(1, newQuery
.length());
631 if (query
.endsWith("*")) {
632 newQuery
= newQuery
.substring(0, newQuery
.length() - 1);
635 return newQuery
.trim();
639 * Build map with taxon flag key-value pairs.
641 private Map
<String
, String
> buildFlagMap(TaxonBase tb
) {
642 Map
<String
, String
> flags
= new Hashtable
<String
, String
>();
643 flags
.put(DOUBTFUL_FLAG
, Boolean
.toString(tb
.isDoubtful()));
648 * Build classification map.
650 private Map
<String
, Map
> buildClassificationMap(Taxon taxon
, String classificationType
) {
651 // Using TreeMap is important, because we need the sorting of the classification keys
652 // in the map to be stable.
653 TreeMap
<String
, Map
> sourceClassificationMap
= new TreeMap
<String
, Map
>();
654 Set
<TaxonNode
> taxonNodes
= taxon
.getTaxonNodes();
655 //loop through taxon nodes and build classification map for each classification key
656 for (TaxonNode tn
: taxonNodes
) {
657 Map
<String
, String
> classificationMap
= new LinkedHashMap
<String
, String
>();
658 List
<TaxonNode
> tnList
= classificationService
.loadTreeBranchToTaxon(taxon
,
659 tn
.getClassification(), null, TAXON_NODE_INIT_STRATEGY
);
660 for (TaxonNode classificationtn
: tnList
) {
662 classificationMap
.put(classificationtn
.getTaxon().getName().getRank().getTitleCache(),
663 classificationtn
.getTaxon().getName().getTitleCache());
666 String cname
= tn
.getClassification().getTitleCache();
667 String
[] words
= cname
.split("\\s+");
668 // "\\s+" in regular expression language meaning one or
670 StringBuilder builder
= new StringBuilder();
671 for (String word
: words
) {
672 builder
.append(word
);
674 cname
= builder
.toString();
675 sourceClassificationMap
.put(cname
, classificationMap
);
678 // if classification key is 'default' then return the first element of the map
679 if(classificationType
.equals(CLASSIFICATION_DEFAULT
) && !sourceClassificationMap
.isEmpty()) {
680 return sourceClassificationMap
.firstEntry().getValue();
681 // if classification key is provided then return the classification corresponding to the key
682 } else if(sourceClassificationMap
.containsKey(classificationType
)) {
683 return sourceClassificationMap
.get(classificationType
);
684 // if classification key is 'all' then return the entire map
685 } else if(classificationType
.equals(CLASSIFICATION_ALL
)) {
686 return sourceClassificationMap
;
693 public void setResourceLoader(ResourceLoader resourceLoader
) {
694 this.resourceLoader
= resourceLoader
;