3 * Copyright (C) 2009 EDIT European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 See LICENSE.TXT at the top of this package for the full license terms.
10 package eu
.etaxonomy
.cdm
.remote
.controller
;
12 import java
.io
.IOException
;
14 import java
.net
.URISyntaxException
;
15 import java
.util
.ArrayList
;
16 import java
.util
.Arrays
;
17 import java
.util
.Hashtable
;
18 import java
.util
.List
;
19 import java
.util
.UUID
;
20 import java
.util
.regex
.Matcher
;
21 import java
.util
.regex
.Pattern
;
23 import javax
.servlet
.http
.HttpServletRequest
;
24 import javax
.servlet
.http
.HttpServletResponse
;
26 import org
.apache
.log4j
.Logger
;
27 import org
.springframework
.beans
.factory
.annotation
.Autowired
;
28 import org
.springframework
.stereotype
.Controller
;
29 import org
.springframework
.web
.bind
.WebDataBinder
;
30 import org
.springframework
.web
.bind
.annotation
.InitBinder
;
31 import org
.springframework
.web
.bind
.annotation
.RequestMapping
;
32 import org
.springframework
.web
.bind
.annotation
.RequestMethod
;
34 import eu
.etaxonomy
.cdm
.api
.service
.IReferenceService
;
35 import eu
.etaxonomy
.cdm
.api
.service
.ITaxonService
;
36 import eu
.etaxonomy
.cdm
.api
.service
.ITermService
;
37 import eu
.etaxonomy
.cdm
.model
.common
.DefinedTermBase
;
38 import eu
.etaxonomy
.cdm
.model
.name
.Rank
;
39 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
40 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
41 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonNode
;
42 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonomicTree
;
43 import eu
.etaxonomy
.cdm
.remote
.editor
.RankPropertyEditor
;
44 import eu
.etaxonomy
.cdm
.remote
.editor
.UUIDPropertyEditor
;
45 import eu
.etaxonomy
.cdm
.strategy
.exceptions
.UnknownCdmTypeException
;
48 * @author a.kohlbecker
52 public class TaxonomicTreeController
extends AbstractListController
<TaxonBase
, ITaxonService
> {
55 private static final List
<String
> TAXONTREE_INIT_STRATEGY
= Arrays
.asList(new String
[]{
56 "reference.authorTeam.titleCache"
59 private static final List
<String
> NODE_INIT_STRATEGY
= Arrays
.asList(new String
[]{
61 "taxon.name.taggedName",
65 //TODO get rid of the bloodyRankLabelMap ------ can be deleted once the FIXME in getPathToRoot is solved
66 private static Hashtable
<String
, String
> bloodyRankLabelMap
= new Hashtable
<String
, String
>();
68 bloodyRankLabelMap
.put("Subfamily", "Subfamilia");
69 bloodyRankLabelMap
.put("Family", "Familia");
70 bloodyRankLabelMap
.put("Suborder", "Subordo");
71 bloodyRankLabelMap
.put("Order", "Ordo");
74 // --------------------------------------------
76 public static final Logger logger
= Logger
.getLogger(TaxonomicTreeController
.class);
78 private ITaxonService service
;
81 private ITermService termService
;
83 private IReferenceService referenceService
;
86 private Pattern parameterPattern
= Pattern
.compile("^/(?:[^/]+)/taxontree/([^?#&\\.]+).*");
89 public void setService(ITaxonService service
) {
90 this.service
= service
;
94 public void setTermService(ITermService termService
) {
95 this.termService
= termService
;
99 public void setReferenceService(IReferenceService referenceService
) {
100 this.referenceService
= referenceService
;
104 public void initBinder(WebDataBinder binder
) {
105 binder
.registerCustomEditor(UUID
.class, new UUIDPropertyEditor());
106 binder
.registerCustomEditor(Rank
.class, new RankPropertyEditor());
115 * @throws IOException
118 // value = {"/*/taxontree/"},
119 // params = {"uuid"},
120 // method = RequestMethod.GET)
121 // public String findTaxon(
122 // @RequestParam(value = "uuid", required = true) UUID uuid,
123 // @RequestParam(value = "rankUuid", required = false) UUID rankUuid,
124 // @RequestParam(value = "viewUuid", required = false) UUID viewUuid,
125 // HttpServletRequest request, HttpServletResponse response) throws IOException {
127 // String msg404 = rank != null ? "Taxon not found within rank "+ rank.getLabel() : "Taxon not found.";
129 // TaxonBase tb = service.load(uuid, TAXON_INIT_STRATEGY);
131 // if(tb != null && Taxon.class.isAssignableFrom(tb.getClass())){
132 // Taxon t = (Taxon)tb;
133 // String relPath = "";
134 // String basePath = FilenameUtils.removeExtension(request.getServletPath());
135 // basePath += "/" + t.getSec().getUuid().toString();
137 // basePath += "," + rank.getLabel();
140 // // compose path of parent uuids
142 // while( taxon != null && (rank == null || taxon.getName().getRank() == null || taxon.getName().getRank().compareTo(rank) <= 0) ) {
143 // relPath = "/" + taxon.getUuid().toString() + relPath;
144 // taxon = taxon.getTaxonomicParent();
145 // if(taxon != null){
146 // taxon = (Taxon)service.load(taxon.getUuid(), TAXON_INIT_STRATEGY);
150 // if(relPath.length() > 0){
153 // redirectUri = relativeToFullUri(request, basePath + relPath);
154 // if(logger.isInfoEnabled()){
155 // logger.info("redirecting to " + redirectUri);
157 // response.sendRedirect(redirectUri.toString());
159 // } catch (URISyntaxException e) {
160 // logger.error(e.getMessage(), e);
164 // msg404 = "The taxon is not accepted";
166 // response.sendError(HttpServletResponse.SC_NOT_FOUND, msg404);
172 @RequestMapping(value
= { "/*/taxontree" }, method
= RequestMethod
.GET
)
173 public List
<TaxonomicTree
> getTaxonomicTrees(HttpServletRequest request
, HttpServletResponse response
)
175 logger
.info("getTaxonomicTrees()");
176 return service
.listTaxonomicTrees(null, null, null, TAXONTREE_INIT_STRATEGY
);
181 * /*/taxontree/{viewUuid},{rankUuid}/
186 value
= {"/*/taxontree/?*"},
187 method
= RequestMethod
.GET
)
188 public List
<TaxonNode
> getRootTaxa(HttpServletRequest request
, HttpServletResponse response
) throws IOException
{
189 logger
.info("getRootTaxa()");
190 List
<String
> uriParams
= readUriParameters(request
);
191 TaxonomicTree tree
= null;
193 if(uriParams
.size() == 1){
195 tree
= readTreeByUuid(uriParams
.get(0));
196 rank
= readRankByUuid(uriParams
.get(0));
199 response
.sendError(404 , "TaxonomicTree not found using " + stringToUuid(uriParams
.get(0)) );
203 if(uriParams
.size() > 1){
204 response
.sendError(400, "A maximum of two uuid parameter expected but found " + uriParams
.size());
207 return service
.loadRankSpecificRootNodes(tree
, rank
, NODE_INIT_STRATEGY
);
214 * @throws IOException
217 value
= {"/*/taxontree/*/?*", "/*/taxontree/*/**/?*"},
218 method
= RequestMethod
.GET
)
219 public List
<TaxonNode
> getChildTaxa(HttpServletRequest request
, HttpServletResponse response
) throws IOException
{
220 logger
.info("getChildTaxa()");
221 List
<String
> uriParams
= readUriParameters(request
);
222 if(uriParams
.size() <= 1){
223 response
.sendError(400, "At least two uuid parameters expected but found " + uriParams
.size());
227 TaxonomicTree tree
= readTreeByUuid(uriParams
.get(0));
229 response
.sendError(500, "The specified instance identified by " + uriParams
.get(0) + " is not a taxonomicTree");
232 Rank rank
= readRankByUuid(uriParams
.get(0));
233 //TODO rank is being ignored
235 UUID uuid
= stringToUuid(uriParams
.get(uriParams
.size() - 1));
236 Taxon taxon
= (Taxon
) service
.load(uuid
);
237 List
<TaxonNode
> childs
= service
.loadChildNodesOfTaxon(taxon
, tree
, NODE_INIT_STRATEGY
);
239 } catch (ClassCastException cce
) {
240 response
.sendError(500, "The specified instance is not a taxon");
248 * @throws IOException
251 value
= {"/*/taxontree/*/*/path", "/*/taxontree/*/**/*/path"},
252 method
= RequestMethod
.GET
)
253 public List
<TaxonNode
> getPathToRoot(HttpServletRequest request
, HttpServletResponse response
) throws IOException
{
254 logger
.info("getPathToRoot()");
255 List
<Taxon
> pathToRoot
= new ArrayList
<Taxon
>();
256 List
<String
> uriParams
= readUriParameters(request
);
257 if(uriParams
.size() <= 1){
258 response
.sendError(400, "At least two uuid parameters expected but found " + uriParams
.size());
262 TaxonomicTree tree
= readTreeByUuid(uriParams
.get(0));
263 Rank rank
= readRankByUuid(uriParams
.get(0));
264 UUID taxonUuid
= stringToUuid(uriParams
.get(uriParams
.size() - 2));
265 Taxon taxon
= (Taxon
) service
.load(taxonUuid
);
267 return service
.loadTreeBranchToTaxon(taxon
, tree
, rank
, NODE_INIT_STRATEGY
);
271 * reads <code>{secuuid},{rank label}/..</code> from <code>/{database key}/taxonomy/{secuuid},{rank label}/..<code>
275 protected List
<String
> readUriParameters(HttpServletRequest request
) {
277 List
<String
> parameters
= null;
278 String path
= request
.getServletPath();
280 Matcher uuidMatcher
= parameterPattern
.matcher(path
);
281 if(uuidMatcher
.matches() && uuidMatcher
.groupCount() > 0){
282 String
[] pa
= uuidMatcher
.group(1).split("/");
283 parameters
= Arrays
.asList(pa
);
293 private Rank
readRankByLabel(String paramStr
) throws IllegalArgumentException
{
295 if((pos
= paramStr
.indexOf(',')) > 0){
296 String rankLabel
= paramStr
.substring(pos
+ 1);
298 return Rank
.getRankByName(rankLabel
);
299 } catch (UnknownCdmTypeException e
) {
300 throw new IllegalArgumentException("400Not a valid rank name");
306 private Rank
readRankByUuid(String paramStr
) throws IllegalArgumentException
{
308 if((pos
= paramStr
.indexOf(',')) > 0){
309 String uuidStr
= paramStr
.substring(pos
+ 1);
310 UUID uuid
= UUID
.fromString(uuidStr
);
311 DefinedTermBase dt
= termService
.findByUuid(uuid
);
312 if(dt
instanceof Rank
){
315 new IllegalArgumentException("Term is not a Rank");
325 private TaxonomicTree
readTreeByUuid(String paramStr
) {
328 if((pos
= paramStr
.indexOf(',')) > 0){
330 viewUuid
= stringToUuid(paramStr
.substring(0, pos
));
332 viewUuid
= stringToUuid(paramStr
);
334 return service
.getTaxonomicTreeByUuid(viewUuid
);
341 private UUID
stringToUuid(String uuidStr
) {
344 UUID uuid
= UUID
.fromString(uuidStr
);
346 } catch (Exception e
) {
347 throw new IllegalArgumentException(uuidStr
+ " is not a uuid");
351 private URI
relativeToFullUri(HttpServletRequest request
,
352 String relativePath
) throws URISyntaxException
{
356 request
.getServerName(),
357 request
.getServerPort(),