optimizing initialization strategies
[cdmlib.git] / cdmlib-remote / src / main / java / eu / etaxonomy / cdm / remote / controller / TaxonPortalController.java
index 77eac7dfb0b52029d5e38d43aefb5069dce2e549..18fc0773c8f4d28674a9c03e00af1a23fff44e9d 100644 (file)
 package eu.etaxonomy.cdm.remote.controller;\r
 \r
 import java.io.IOException;\r
+import java.util.ArrayList;\r
 import java.util.Arrays;\r
+import java.util.HashSet;\r
 import java.util.Hashtable;\r
+import java.util.Iterator;\r
 import java.util.List;\r
 import java.util.Map;\r
+import java.util.Set;\r
 import java.util.UUID;\r
 \r
 import javax.servlet.http.HttpServletRequest;\r
 import javax.servlet.http.HttpServletResponse;\r
 \r
+import org.apache.commons.lang.ObjectUtils;\r
 import org.apache.log4j.Logger;\r
 import org.springframework.beans.factory.annotation.Autowired;\r
 import org.springframework.stereotype.Controller;\r
-import org.springframework.util.Assert;\r
+import org.springframework.web.bind.WebDataBinder;\r
+import org.springframework.web.bind.annotation.InitBinder;\r
+import org.springframework.web.bind.annotation.PathVariable;\r
 import org.springframework.web.bind.annotation.RequestMapping;\r
 import org.springframework.web.bind.annotation.RequestMethod;\r
+import org.springframework.web.bind.annotation.RequestParam;\r
 import org.springframework.web.servlet.ModelAndView;\r
 \r
+import eu.etaxonomy.cdm.api.service.IDescriptionService;\r
+import eu.etaxonomy.cdm.api.service.INameService;\r
+import eu.etaxonomy.cdm.api.service.IReferenceService;\r
 import eu.etaxonomy.cdm.api.service.ITaxonService;\r
+import eu.etaxonomy.cdm.api.service.ITaxonTreeService;\r
+import eu.etaxonomy.cdm.api.service.config.ITaxonServiceConfigurator;\r
+import eu.etaxonomy.cdm.api.service.config.impl.TaxonServiceConfiguratorImpl;\r
+import eu.etaxonomy.cdm.api.service.pager.Pager;\r
+import eu.etaxonomy.cdm.database.UpdatableRoutingDataSource;\r
+import eu.etaxonomy.cdm.model.common.IdentifiableEntity;\r
+import eu.etaxonomy.cdm.model.description.DescriptionElementBase;\r
+import eu.etaxonomy.cdm.model.description.TaxonDescription;\r
+import eu.etaxonomy.cdm.model.description.TaxonNameDescription;\r
+import eu.etaxonomy.cdm.model.location.NamedArea;\r
+import eu.etaxonomy.cdm.model.media.Media;\r
+import eu.etaxonomy.cdm.model.media.MediaUtils;\r
+import eu.etaxonomy.cdm.model.name.NameRelationship;\r
+import eu.etaxonomy.cdm.model.name.TaxonNameBase;\r
+import eu.etaxonomy.cdm.model.name.TypeDesignationBase;\r
+import eu.etaxonomy.cdm.model.taxon.Synonym;\r
 import eu.etaxonomy.cdm.model.taxon.Taxon;\r
 import eu.etaxonomy.cdm.model.taxon.TaxonBase;\r
+import eu.etaxonomy.cdm.model.taxon.TaxonNode;\r
+import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;\r
+import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;\r
+import eu.etaxonomy.cdm.model.taxon.TaxonomicTree;\r
+import eu.etaxonomy.cdm.persistence.query.MatchMode;\r
+import eu.etaxonomy.cdm.remote.editor.MatchModePropertyEditor;\r
+import eu.etaxonomy.cdm.remote.editor.NamedAreaPropertyEditor;\r
+import eu.etaxonomy.cdm.remote.editor.UUIDPropertyEditor;\r
 \r
 /**\r
+ * The TaxonPortalController class is a Spring MVC Controller.\r
+ * <p>\r
+ * The syntax of the mapped service URIs contains the the {datasource-name} path element.\r
+ * The available {datasource-name}s are defined in a configuration file which\r
+ * is loaded by the {@link UpdatableRoutingDataSource}. If the\r
+ * UpdatableRoutingDataSource is not being used in the actual application\r
+ * context any arbitrary {datasource-name} may be used.\r
+ * <p>\r
+ * Methods mapped at type level, inherited from super classes ({@link BaseController}):\r
+ * <blockquote>\r
+ * URI: <b>&#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;{taxon-uuid}</b>\r
+ * \r
+ * Get the {@link TaxonBase} instance identified by the <code>{taxon-uuid}</code>.\r
+ * The returned Taxon is initialized by\r
+ * the following strategy {@link #TAXON_INIT_STRATEGY}\r
+ * </blockquote>\r
+ * \r
  * @author a.kohlbecker\r
+ * @date 20.07.2009\r
  *\r
  */\r
-\r
 @Controller\r
-@RequestMapping(value = {"/*/portal/taxon/*", "/*/portal/taxon/*/*"})\r
+@RequestMapping(value = {"/portal/taxon/{uuid}"})\r
 public class TaxonPortalController extends BaseController<TaxonBase, ITaxonService>\r
 {\r
        public static final Logger logger = Logger.getLogger(TaxonPortalController.class);\r
        \r
+       @Autowired\r
+       private INameService nameService;\r
+       \r
+       @Autowired\r
+       private IDescriptionService descriptionService;\r
+       \r
+       @Autowired\r
+       private ITaxonTreeService taxonTreeService;\r
+       \r
+       @Autowired\r
+       private ITaxonService taxonService;\r
+       \r
        private static final List<String> TAXON_INIT_STRATEGY = Arrays.asList(new String []{\r
                        "*",\r
                        // taxon relations \r
-                       "relationsToThisName.fromTaxon.name.taggedName",\r
+                       "relationsToThisName.fromTaxon.name",\r
                        // the name\r
                        "name.$",\r
-                       "name.taggedName",\r
                        "name.rank.representations",\r
                        "name.status.type.representations",\r
                        \r
-                       // descriptions\r
-                       "descriptions.elements.$",\r
-                       "descriptions.elements.area",\r
+                       // taxon descriptions\r
                        "descriptions.elements.area.$",\r
                        "descriptions.elements.multilanguageText",\r
                        "descriptions.elements.media.representations.parts",\r
+                       "descriptions.elements.media.title",\r
                        \r
-//                     // typeDesignations\r
-//                     "name.typeDesignations.$",\r
-//                     "name.typeDesignations.citation.authorTeam",\r
-//                     "name.typeDesignations.typeName.$",\r
-//                     "name.typeDesignations.typeStatus.representations",\r
-//                     "name.typeDesignations.typeSpecimen.media.representations.parts"\r
-                       \r
+                       });\r
+       \r
+       private static final List<String> TAXON_WITH_NODES_INIT_STRATEGY = Arrays.asList(new String []{\r
+                       "taxonNodes.$",\r
+                       "taxonNodes.taxonomicTree.$",\r
+                       "taxonNodes.childNodes.$"\r
+                       });\r
+       \r
+       private static final List<String> SIMPLE_TAXON_INIT_STRATEGY = Arrays.asList(new String []{\r
+                       "*",\r
+                       // taxon relations \r
+                       "relationsToThisName.fromTaxon.name",\r
+                       // the name\r
+                       "name.$",\r
+                       "name.rank.representations",\r
+                       "name.status.type.representations",\r
+                       "name.nomenclaturalReference"\r
                        });\r
        \r
        private static final List<String> SYNONYMY_INIT_STRATEGY = Arrays.asList(new String []{\r
                        // initialize homotypical and heterotypical groups; needs synonyms\r
                        "synonymRelations.$",\r
                        "synonymRelations.synonym.$",\r
-                       "synonymRelations.synonym.name.taggedName",\r
+                       "synonymRelations.synonym.name.status.type.representation",\r
+                       "synonymRelations.synonym.name.nomenclaturalReference.inReference",\r
                        "synonymRelations.synonym.name.homotypicalGroup.typifiedNames.$",\r
-                       "synonymRelations.synonym.name.homotypicalGroup.typifiedNames.name.taggedName",\r
                        "synonymRelations.synonym.name.homotypicalGroup.typifiedNames.taxonBases.$",\r
-                       "synonymRelations.synonym.name.homotypicalGroup.typifiedNames.taxonBases.name.taggedName",\r
+                       "synonymRelations.synonym.name.combinationAuthorTeam.$",\r
                        \r
                        "name.homotypicalGroup.$",\r
                        "name.homotypicalGroup.typifiedNames.$",\r
-                       "name.homotypicalGroup.typifiedNames.name.taggedName",\r
-                       "name.homotypicalGroup.typifiedNames.taxonBases.$",\r
-                       "name.homotypicalGroup.typifiedNames.taxonBases.name.taggedName"\r
+                       \r
+                       "name.homotypicalGroup.typifiedNames.taxonBases.$"\r
+       });\r
+       \r
+       private static final List<String> TAXONRELATIONSHIP_INIT_STRATEGY = Arrays.asList(new String []{\r
+                       "$",\r
+                       "type.inverseRepresentations",\r
+                       "fromTaxon.sec",\r
+                       "fromTaxon.name"\r
+       });\r
+       \r
+       private static final List<String> NAMERELATIONSHIP_INIT_STRATEGY = Arrays.asList(new String []{\r
+                       "$",\r
+                       "type.inverseRepresentations",\r
+                       "fromName",\r
+                       "toName.$",\r
+       });\r
+       \r
+       \r
+       protected static final List<String> TAXONDESCRIPTION_INIT_STRATEGY = Arrays.asList(new String []{\r
+                       "$",\r
+                       "elements.$",\r
+                       "elements.sources.citation.",\r
+                       "elements.sources.nameUsedInSource.originalNameString",\r
+                       "elements.multilanguageText",\r
+                       "elements.media.representations.parts",\r
+                       "elements.media.title",\r
+       });\r
+       \r
+       \r
+       private static final List<String> NAMEDESCRIPTION_INIT_STRATEGY = Arrays.asList(new String []{\r
+                       "uuid",\r
+                       "feature",\r
+                       "elements.$",\r
+                       "elements.multilanguageText",\r
+                       "elements.media.representations.parts",\r
+                       "elements.media.title",\r
+       });\r
+       \r
+       protected static final List<String> TAXONDESCRIPTION_MEDIA_INIT_STRATEGY = Arrays.asList(new String []{\r
+                       "elements.media.representations.parts",\r
+                       "elements.media.title"\r
+                       \r
+       });\r
+\r
+       private static final List<String> TYPEDESIGNATION_INIT_STRATEGY = Arrays.asList(new String []{\r
+                       //"$",\r
+                       "typeSpecimen.$",\r
+                       "citation",                     \r
+                       "typeName",\r
+       });\r
+       \r
+       protected static final List<String> TAXONNODE_WITHTAXON_INIT_STRATEGY = Arrays.asList(new String []{\r
+                       "childNodes.taxon",\r
+       });\r
+       \r
+       protected static final List<String> TAXONNODE_INIT_STRATEGY = Arrays.asList(new String []{\r
+                       "taxonNodes.taxonomicTree"\r
        });\r
        \r
+       \r
+       \r
+       private static final String featureTreeUuidPattern = "^/taxon(?:(?:/)([^/?#&\\.]+))+.*";\r
+       \r
        public TaxonPortalController(){\r
                super();\r
-               setUuidParameterPattern("^/(?:[^/]+)/portal/taxon/([^/?#&\\.]+).*");\r
+               setInitializationStrategy(TAXON_INIT_STRATEGY);\r
        }\r
        \r
        /* (non-Javadoc)\r
@@ -100,21 +231,136 @@ public class TaxonPortalController extends BaseController<TaxonBase, ITaxonServi
                this.service = service;\r
        }\r
        \r
+       @InitBinder\r
+    public void initBinder(WebDataBinder binder) {\r
+               binder.registerCustomEditor(UUID.class, new UUIDPropertyEditor());\r
+               binder.registerCustomEditor(NamedArea.class, new NamedAreaPropertyEditor());\r
+               binder.registerCustomEditor(MatchMode.class, new MatchModePropertyEditor());\r
+       }\r
+       \r
+       \r
+       /* (non-Javadoc)\r
+        * @see eu.etaxonomy.cdm.remote.controller.BaseController#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)\r
+       \r
        @Override\r
        @RequestMapping(method = RequestMethod.GET)\r
        public TaxonBase doGet(HttpServletRequest request, HttpServletResponse response)throws IOException {\r
+               logger.info("doGet()");\r
                TaxonBase tb = getCdmBase(request, response, TAXON_INIT_STRATEGY, TaxonBase.class);\r
                return tb;\r
        }\r
+        */\r
+       /**\r
+        * Find Taxa, Synonyms, Common Names by name, either globally or in a specific geographic area. \r
+        * <p>\r
+        * URI: <b>&#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;find</b>\r
+        * \r
+        * @param query\r
+        *            the string to query for. Since the wildcard character '*'\r
+        *            internally always is appended to the query string, a search\r
+        *            always compares the query string with the beginning of a name.\r
+        *            - <i>required parameter</i>\r
+        * @param treeUuid\r
+        *            the {@link UUID} of a {@link TaxonomicTree} to which the\r
+        *            search is to be restricted. - <i>optional parameter</i>\r
+        * @param areas\r
+        *            restrict the search to a set of geographic {@link NamedArea}s.\r
+        *            The parameter currently takes a list of TDWG area labels.\r
+        *            - <i>optional parameter</i>\r
+        * @param page\r
+        *            the number of the page to be returned, the first page has the\r
+        *            pageNumber = 1 - <i>optional parameter</i>\r
+        * @param pageSize\r
+        *            the maximum number of entities returned per page (can be -1 \r
+        *            to return all entities in a single page) - <i>optional parameter</i>\r
+        * @param doTaxa\r
+        *            weather to search for instances of {@link Taxon} - <i>optional parameter</i>\r
+        * @param doSynonyms\r
+        *            weather to search for instances of {@link Synonym} - <i>optional parameter</i>\r
+        * @param doTaxaByCommonNames\r
+        *            for instances of {@link Taxon} by a common name used - <i>optional parameter</i>\r
+        * @param matchMode\r
+        *           valid values are "EXACT", "BEGINNING", "ANYWHERE", "END" (case sensitive !!!)\r
+        * @return a Pager on a list of {@link IdentifiableEntity}s initialized by\r
+        *         the following strategy {@link #SIMPLE_TAXON_INIT_STRATEGY}\r
+        * @throws IOException\r
+        */\r
+       @RequestMapping(method = RequestMethod.GET,\r
+                       value = {"/portal/taxon/find"}) //TODO map to path /*/portal/taxon/\r
+       public Pager<IdentifiableEntity> doFind(\r
+                       @RequestParam(value = "query", required = false) String query,\r
+                       @RequestParam(value = "tree", required = false) UUID treeUuid,\r
+                       @RequestParam(value = "area", required = false) Set<NamedArea> areas,\r
+                       @RequestParam(value = "page", required = false) Integer page,\r
+                       @RequestParam(value = "pageSize", required = false) Integer pageSize,\r
+                       @RequestParam(value = "doTaxa", required = false) Boolean doTaxa,\r
+                       @RequestParam(value = "doSynonyms", required = false) Boolean doSynonyms,\r
+                       @RequestParam(value = "doTaxaByCommonNames", required = false) Boolean doTaxaByCommonNames,\r
+                       @RequestParam(value = "matchMode", required = false) MatchMode matchMode\r
+                       )\r
+                        throws IOException {\r
+               \r
+               logger.info("doFind( " +\r
+                       "query=\"" + ObjectUtils.toString(query) + "\", treeUuid=" + ObjectUtils.toString(treeUuid) + \r
+                       ", area=" + ObjectUtils.toString(areas) +\r
+                       ", pageSize=" + ObjectUtils.toString(pageSize) +  ", page=" + ObjectUtils.toString(page) + \r
+                       ", doTaxa=" + ObjectUtils.toString(doTaxa) + ", doSynonyms=" + ObjectUtils.toString(doSynonyms) \r
+                       +", doTaxaByCommonNames=" + ObjectUtils.toString(doTaxaByCommonNames) +")" );\r
+               \r
+               if(page == null){ page = BaseListController.DEFAULT_PAGE_NUMBER;}\r
+               if(pageSize == null){ pageSize = BaseListController.DEFAULT_PAGESIZE;}\r
+               if(pageSize == -1){ \r
+                       pageSize = null;\r
+               }\r
+                       \r
+               ITaxonServiceConfigurator config = new TaxonServiceConfiguratorImpl();\r
+               config.setPageNumber(page);\r
+               config.setPageSize(pageSize);\r
+               config.setSearchString(query);\r
+               config.setDoTaxa(doTaxa!= null ? doTaxa : Boolean.FALSE );\r
+               config.setDoSynonyms(doSynonyms != null ? doSynonyms : Boolean.FALSE );\r
+               config.setDoTaxaByCommonNames(doTaxaByCommonNames != null ? doTaxaByCommonNames : Boolean.FALSE );\r
+               config.setMatchMode(matchMode != null ? matchMode : MatchMode.BEGINNING);\r
+               config.setTaxonPropertyPath(SIMPLE_TAXON_INIT_STRATEGY);\r
+               config.setNamedAreas(areas);\r
+               if(treeUuid != null){\r
+                       TaxonomicTree taxonomicTree = taxonTreeService.find(treeUuid);\r
+                       config.setTaxonomicTree(taxonomicTree);\r
+               }\r
+                       \r
+               return (Pager<IdentifiableEntity>) service.findTaxaAndNames(config);\r
+       }\r
 \r
-       \r
+       /**\r
+        * Get the synonymy for a taxon identified by the <code>{taxon-uuid}</code>. \r
+        * The synonymy consists\r
+        * of two parts: The group of homotypic synonyms of the taxon and the\r
+        * heterotypic synonymy groups of the taxon. The synonymy is ordered\r
+        * historically by the type designations and by the publication date of the\r
+        * nomenclatural reference\r
+        * <p>\r
+        * URI:\r
+        * <b>&#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;{taxon-uuid}&#x002F;synonymy</b>\r
+        * \r
+        * \r
+        * @param request\r
+        * @param response\r
+        * @return a Map with to entries which are mapped by the following keys:\r
+        *         "homotypicSynonymsByHomotypicGroup", "heterotypicSynonymyGroups", \r
+        *         containing lists of {@link Synonym}s which are initialized using the \r
+        *         following initialization strategy: {@link #SYNONYMY_INIT_STRATEGY}\r
+        * \r
+        * @throws IOException\r
+        */\r
        @RequestMapping(\r
-                       value = {"/*/portal/taxon/*/synonymy"},\r
+                       value = {"synonymy"},\r
                        method = RequestMethod.GET)\r
-       public ModelAndView doGetSynonymy(HttpServletRequest request, HttpServletResponse response)throws IOException {\r
+       public ModelAndView doGetSynonymy(@PathVariable("uuid") UUID uuid,\r
+                       HttpServletRequest request, HttpServletResponse response)throws IOException {\r
+               \r
+               logger.info("doGetSynonymy() " + request.getServletPath());\r
                ModelAndView mv = new ModelAndView();\r
-               TaxonBase tb = getCdmBase(request, response, null, Taxon.class);\r
-               Taxon taxon = (Taxon)tb;\r
+               Taxon taxon = getCdmBaseInstance(Taxon.class, uuid, response, (List<String>)null);\r
                Map<String, List<?>> synonymy = new Hashtable<String, List<?>>();\r
                synonymy.put("homotypicSynonymsByHomotypicGroup", service.getHomotypicSynonymsByHomotypicGroup(taxon, SYNONYMY_INIT_STRATEGY));\r
                synonymy.put("heterotypicSynonymyGroups", service.getHeterotypicSynonymyGroups(taxon, SYNONYMY_INIT_STRATEGY));\r
@@ -122,29 +368,326 @@ public class TaxonPortalController extends BaseController<TaxonBase, ITaxonServi
                return mv;\r
        }\r
 \r
-//     /**\r
-//      * @param request\r
-//      * @param response\r
-//      * @return\r
-//      * @throws IOException\r
-//      */\r
-//     private <T> T getTaxon(HttpServletRequest request, HttpServletResponse response, List<String> initStrategy, Class<T> clazz) throws IOException {\r
-//             TaxonBase tb = null;\r
-//             try {\r
-//                     UUID uuid = readValueUuid(request);\r
-//                     Assert.notNull(uuid, HttpStatusMessage.UUID_NOT_FOUND.toString());\r
-//                     tb = service.load(uuid, initStrategy);\r
-//                     Assert.notNull(tb, HttpStatusMessage.UUID_NOT_FOUND.toString());\r
-//             } catch (IllegalArgumentException iae) {\r
-//                     HttpStatusMessage.fromString(iae.getMessage()).send(response);\r
-//             }\r
-//             T t;\r
-//             try {\r
-//                     t = (T)tb;\r
-//                     return t;\r
-//             } catch (Exception e) {\r
-//                     HttpStatusMessage.UUID_REFERENCES_WRONG_TYPE.send(response);\r
+       /**\r
+        * Get the set of accepted {@link Taxon} entities for a given\r
+        * {@link TaxonBase} entity identified by the <code>{taxon-uuid}</code>.\r
+        * <p>\r
+        * URI: <b>&#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;{taxon-uuid}&#x002F;accepted</b>\r
+        * \r
+        * @param request\r
+        * @param response\r
+        * @return a Set of {@link Taxon} entities which are initialized\r
+        *         using the following initialization strategy:\r
+        *         {@link #SYNONYMY_INIT_STRATEGY}\r
+        * @throws IOException\r
+        */\r
+       @RequestMapping(value = "accepted", method = RequestMethod.GET)\r
+       public Set<TaxonBase> getAccepted(@PathVariable("uuid") UUID uuid,\r
+                       HttpServletRequest request, HttpServletResponse response) throws IOException {\r
+               \r
+               logger.info("getAccepted() " + request.getServletPath());\r
+               \r
+               TaxonBase tb = service.load(uuid, SYNONYMY_INIT_STRATEGY);\r
+               if(tb == null){\r
+                       response.sendError(HttpServletResponse.SC_NOT_FOUND, "A taxon with the uuid " + uuid + " does not exist");\r
+                       return null;\r
+               }\r
+               HashSet<TaxonBase> resultset = new HashSet<TaxonBase>();\r
+               if(tb instanceof Taxon){\r
+                       //the taxon already is accepted\r
+                       //FIXME take the current view into account once views are implemented!!!\r
+                       resultset.add((Taxon)tb);\r
+               } else {\r
+                       Synonym syn = (Synonym)tb;\r
+                       for(TaxonBase accepted : syn.getAcceptedTaxa()){\r
+                               accepted = service.load(accepted.getUuid(), SIMPLE_TAXON_INIT_STRATEGY);\r
+                               resultset.add(accepted);\r
+                       }\r
+               }\r
+               return resultset;\r
+       }\r
+       \r
+       /**\r
+     * Get the list of {@link TaxonRelationship}s for the given \r
+        * {@link TaxonBase} instance identified by the <code>{taxon-uuid}</code>.\r
+        * <p>\r
+        * URI: <b>&#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;{taxon-uuid}&#x002F;taxonRelationships</b>\r
+        * \r
+        * @param request\r
+        * @param response\r
+        * @return a List of {@link TaxonRelationship} entities which are initialized\r
+        *         using the following initialization strategy:\r
+        *         {@link #TAXONRELATIONSHIP_INIT_STRATEGY}\r
+        * @throws IOException\r
+        */\r
+       @RequestMapping(\r
+                       value = {"taxonRelationships"},\r
+                       method = RequestMethod.GET)\r
+       public List<TaxonRelationship> doGetTaxonRelations(@PathVariable("uuid") UUID uuid,\r
+                       HttpServletRequest request, HttpServletResponse response)throws IOException {\r
+\r
+               logger.info("doGetTaxonRelations()" + request.getServletPath());\r
+               Taxon taxon = getCdmBaseInstance(Taxon.class, uuid, response, (List<String>)null);\r
+               List<TaxonRelationship> relations = new ArrayList<TaxonRelationship>();\r
+               List<TaxonRelationship> results = service.listToTaxonRelationships(taxon, TaxonRelationshipType.MISAPPLIED_NAME_FOR(), null, null, null, TAXONRELATIONSHIP_INIT_STRATEGY);\r
+               relations.addAll(results);\r
+               results = service.listToTaxonRelationships(taxon, TaxonRelationshipType.INVALID_DESIGNATION_FOR(), null, null, null, TAXONRELATIONSHIP_INIT_STRATEGY);\r
+               relations.addAll(results);\r
+\r
+               return relations;\r
+       }\r
+       \r
+       /**\r
+     * Get the list of {@link NameRelationship}s of the Name associated with the \r
+        * {@link TaxonBase} instance identified by the <code>{taxon-uuid}</code>.\r
+        * <p>\r
+        * URI: <b>&#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;{taxon-uuid}&#x002F;nameRelationships</b>\r
+        * \r
+        * @param request\r
+        * @param response\r
+        * @return a List of {@link NameRelationship} entities which are initialized\r
+        *         using the following initialization strategy:\r
+        *         {@link #NAMERELATIONSHIP_INIT_STRATEGY}\r
+        * @throws IOException\r
+        */\r
+       @RequestMapping(\r
+                       value = {"toNameRelationships"},\r
+                       method = RequestMethod.GET)\r
+       public List<NameRelationship> doGetToNameRelations(@PathVariable("uuid") UUID uuid,\r
+                       HttpServletRequest request, HttpServletResponse response)throws IOException {\r
+               logger.info("doGetNameRelations()" + request.getServletPath());\r
+               Taxon taxon = getCdmBaseInstance(Taxon.class, uuid, response, (List<String>)null);\r
+               List<NameRelationship> list = nameService.listToNameRelationships(taxon.getName(), null, null, null, null, NAMERELATIONSHIP_INIT_STRATEGY);\r
+               return list;\r
+       }\r
+       \r
+       /**\r
+     * Get the list of {@link NameRelationship}s of the Name associated with the \r
+        * {@link TaxonBase} instance identified by the <code>{taxon-uuid}</code>.\r
+        * <p>\r
+        * URI: <b>&#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;{taxon-uuid}&#x002F;nameRelationships</b>\r
+        * \r
+        * @param request\r
+        * @param response\r
+        * @return a List of {@link NameRelationship} entities which are initialized\r
+        *         using the following initialization strategy:\r
+        *         {@link #NAMERELATIONSHIP_INIT_STRATEGY}\r
+        * @throws IOException\r
+        */\r
+       @RequestMapping(\r
+                       value = {"fromNameRelationships"},\r
+                       method = RequestMethod.GET)\r
+       public List<NameRelationship> doGetFromNameRelations(@PathVariable("uuid") UUID uuid,\r
+                       HttpServletRequest request, HttpServletResponse response)throws IOException {\r
+               logger.info("doGetNameFromNameRelations()" + request.getServletPath());\r
+\r
+               TaxonBase taxonbase = getCdmBaseInstance(TaxonBase.class, uuid, response, SIMPLE_TAXON_INIT_STRATEGY);\r
+               List<NameRelationship> list = nameService.listFromNameRelationships(taxonbase.getName(), null, null, null, null, NAMERELATIONSHIP_INIT_STRATEGY);\r
+               return list;\r
+       }\r
+       \r
+       /**\r
+     * Get the list of {@link TypeDesignationBase}s of the \r
+        * {@link TaxonBase} instance identified by the <code>{taxon-uuid}</code>.\r
+        * <p>\r
+        * URI: <b>&#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;{taxon-uuid}&#x002F;nameTypeDesignations</b>\r
+        * \r
+        * @param request\r
+        * @param response\r
+        * @return a List of {@link TypeDesignationBase} entities which are initialized\r
+        *         using the following initialization strategy:\r
+        *         {@link #TYPEDESIGNATION_INIT_STRATEGY}\r
+        * @throws IOException\r
+        * @Deprecated use &#x002F;name&#x002F;{uuid}&#x002F;typeDesignations & &#x002F;derivedunitfacade&#x002F;{uuid} instead\r
+        */\r
+       @Deprecated\r
+       @RequestMapping(\r
+                       value = {"nameTypeDesignations"},\r
+                       method = RequestMethod.GET)\r
+       public List<TypeDesignationBase> doGetNameTypeDesignations(@PathVariable("uuid") UUID uuid,\r
+                       HttpServletRequest request, HttpServletResponse response)throws IOException {\r
+               logger.info("doGetNameTypeDesignations()" + request.getServletPath());\r
+               Taxon taxon = getCdmBaseInstance(Taxon.class, uuid, response, SIMPLE_TAXON_INIT_STRATEGY);\r
+               Pager<TypeDesignationBase> p = nameService.getTypeDesignations(taxon.getName(), null, null, null, TYPEDESIGNATION_INIT_STRATEGY);\r
+               return p.getRecords();\r
+       }\r
+       \r
+       @RequestMapping(value = "taxonNodes", method = RequestMethod.GET)\r
+       public Set<TaxonNode>  doGetTaxonNodes(\r
+                       @PathVariable("uuid") UUID uuid,\r
+                       HttpServletRequest request, \r
+                       HttpServletResponse response) throws IOException {\r
+               TaxonBase tb = service.load(uuid, TAXONNODE_INIT_STRATEGY);\r
+               if(tb instanceof Taxon){\r
+                       return ((Taxon)tb).getTaxonNodes();\r
+               } else {\r
+                       HttpStatusMessage.UUID_REFERENCES_WRONG_TYPE.send(response);\r
+                       return null;\r
+               }\r
+       }\r
+       \r
+       /**\r
+     * Get the list of {@link TaxonDescription}s of the \r
+        * {@link Taxon} instance identified by the <code>{taxon-uuid}</code>.\r
+        * <p>\r
+        * URI: <b>&#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;{taxon-uuid}&#x002F;descriptions</b>\r
+        * \r
+        * @param request\r
+        * @param response\r
+        * @return a List of {@link TaxonDescription} entities which are initialized\r
+        *         using the following initialization strategy:\r
+        *         {@link #TAXONDESCRIPTION_INIT_STRATEGY}\r
+        * @throws IOException\r
+        */\r
+       @RequestMapping(\r
+                       value = {"descriptions"},\r
+                       method = RequestMethod.GET)\r
+       public List<TaxonDescription> doGetDescriptions(@PathVariable("uuid") UUID uuid,\r
+                       HttpServletRequest request, HttpServletResponse response)throws IOException {\r
+               logger.info("doGetDescriptions()" + request.getServletPath());\r
+               Taxon t = getCdmBaseInstance(Taxon.class, uuid, response, (List<String>)null);\r
+               Pager<TaxonDescription> p = descriptionService.getTaxonDescriptions(t, null, null, null, null, TAXONDESCRIPTION_INIT_STRATEGY);\r
+               return p.getRecords();\r
+       }\r
+\r
+       /**\r
+        * Get the {@link Media} attached to the {@link Taxon} instance \r
+        * identified by the <code>{taxon-uuid}</code>.\r
+        * \r
+        * Usage &#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;{taxon-\r
+        * uuid}&#x002F;media&#x002F;{mime type\r
+        * list}&#x002F;{size}[,[widthOrDuration}][,{height}]&#x002F;\r
+        * \r
+        * Whereas\r
+        * <ul>\r
+        * <li><b>{mime type list}</b>: a comma separated list of mime types, in the\r
+        * order of preference. The forward slashes contained in the mime types must\r
+        * be replaced by a colon. Regular expressions can be used. Each media\r
+        * associated with this given taxon is being searched whereas the first\r
+        * matching mime type matching a representation always rules.</li>\r
+        * <li><b>{size},{widthOrDuration},{height}</b>: <i>not jet implemented</i>\r
+        * valid values are an integer or the asterisk '*' as a wildcard</li>\r
+        * </ul>\r
+        * \r
+        * @param request\r
+        * @param response\r
+        * @return a List of {@link Media} entities which are initialized\r
+        *         using the following initialization strategy:\r
+        *         {@link #TAXONDESCRIPTION_INIT_STRATEGY}\r
+        * @throws IOException\r
+        */\r
+       @RequestMapping(\r
+               value = {"media/*/*"},\r
+               method = RequestMethod.GET)\r
+       public List<Media> doGetMedia(@PathVariable("uuid") UUID uuid,\r
+                       HttpServletRequest request, HttpServletResponse response) throws IOException {\r
+               logger.info("doGetMedia()" + request.getServletPath());\r
+               Taxon t = getCdmBaseInstance(Taxon.class, uuid, response, (List<String>)null);\r
+               String path = request.getServletPath();\r
+               List<Media> returnMedia = getMediaForTaxon(t, path, 5);\r
+               return returnMedia;\r
+       }\r
+       \r
+       @RequestMapping(\r
+                       value = {"subtree/media/*/*"},\r
+                       method = RequestMethod.GET)\r
+               public List<Media> doGetSubtreeMedia(@PathVariable("uuid") UUID uuid,\r
+                               HttpServletRequest request, HttpServletResponse response)throws IOException {\r
+               logger.info("doGetMedia()" + request.getServletPath());\r
+               Taxon t = getCdmBaseInstance(Taxon.class, uuid, response, TAXON_WITH_NODES_INIT_STRATEGY);\r
+               String path = request.getServletPath();\r
+               List<Media> returnMedia = getMediaForTaxon(t, path, 6);\r
+               TaxonNode node;\r
+               //looking for all medias of genus\r
+               if (t.getTaxonNodes().size()>0){\r
+                       Set<TaxonNode> nodes = t.getTaxonNodes();\r
+                       Iterator<TaxonNode> iterator = nodes.iterator();\r
+                       //TaxonNode holen\r
+                       node = iterator.next();\r
+                       //überprüfen, ob der TaxonNode zum aktuellen Baum gehört.\r
+                       \r
+                       node = taxonTreeService.loadTaxonNode(node, TAXONNODE_WITHTAXON_INIT_STRATEGY);\r
+                       Set<TaxonNode> children = node.getChildNodes();\r
+                       Taxon childTaxon;\r
+                       for (TaxonNode child : children){\r
+                               childTaxon = child.getTaxon();\r
+                               childTaxon = (Taxon)taxonService.load(childTaxon.getUuid(), null);\r
+                               returnMedia.addAll(getMediaForTaxon(childTaxon, path, 6));\r
+                       }\r
+               }\r
+               return returnMedia;\r
+       }\r
+\r
+       \r
+       private List<Media> getMediaForTaxon(Taxon taxon, String path, int mimeTypeTokenPosition){\r
+               \r
+               Pager<TaxonDescription> p = \r
+                       descriptionService.getTaxonDescriptions(taxon, null, null, null, null, TAXONDESCRIPTION_MEDIA_INIT_STRATEGY);\r
+               \r
+               // pars the media and quality parameters\r
+               \r
+               \r
+               // collect all media of the given taxon\r
+               boolean limitToGalleries = false;\r
+               List<Media> taxonMedia = new ArrayList<Media>();\r
+               for(TaxonDescription desc : p.getRecords()){\r
+                       if(!limitToGalleries || desc.isImageGallery()){\r
+                               for(DescriptionElementBase element : desc.getElements()){\r
+                                       for(Media media : element.getMedia()){\r
+                                               taxonMedia.add(media);\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+                       \r
+               String[] pathTokens = path.split("/");\r
+               \r
+               String[] mimeTypes = pathTokens[mimeTypeTokenPosition].split(",");\r
+               String[] sizeTokens = pathTokens[mimeTypeTokenPosition + 1].split(",");\r
+               Integer widthOrDuration = null;\r
+               Integer height = null;\r
+               Integer size = null;\r
+               \r
+               List<Media> returnMedia = MediaUtils.findPreferredMedia(taxonMedia, mimeTypes,\r
+                               sizeTokens, widthOrDuration, height, size);\r
+               \r
+               return returnMedia;\r
+       }\r
+       \r
+       \r
+// ---------------------- code snippet preserved for possible later use --------------------\r
+//     @RequestMapping(\r
+//                     value = {"/*/portal/taxon/*/descriptions"},\r
+//                     method = RequestMethod.GET)\r
+//     public List<TaxonDescription> doGetDescriptionsbyFeatureTree(HttpServletRequest request, HttpServletResponse response)throws IOException {\r
+//             TaxonBase tb = getCdmBase(request, response, null, Taxon.class);\r
+//             if(tb instanceof Taxon){\r
+//                     //T O D O this is a quick and dirty implementation -> generalize\r
+//                     UUID featureTreeUuid = readValueUuid(request, featureTreeUuidPattern);\r
+//                     \r
+//                     FeatureTree featureTree = descriptionService.getFeatureTreeByUuid(featureTreeUuid);\r
+//                     Pager<TaxonDescription> p = descriptionService.getTaxonDescriptions((Taxon)tb, null, null, null, null, TAXONDESCRIPTION_INIT_STRATEGY);\r
+//                     List<TaxonDescription> descriptions = p.getRecords();\r
+//                     \r
+//                     if(!featureTree.isDescriptionSeparated()){\r
+//                             \r
+//                             TaxonDescription superDescription = TaxonDescription.NewInstance();\r
+//                             //put all descriptionElements in superDescription and make it invisible\r
+//                             for(TaxonDescription description: descriptions){\r
+//                                     for(DescriptionElementBase element: description.getElements()){\r
+//                                             superDescription.addElement(element);\r
+//                                     }\r
+//                             }\r
+//                             List<TaxonDescription> separatedDescriptions = new ArrayList<TaxonDescription>(descriptions.size());\r
+//                             separatedDescriptions.add(superDescription);\r
+//                             return separatedDescriptions;\r
+//                     }else{\r
+//                             return descriptions;\r
+//                     }\r
+//             } else {\r
+//                     response.sendError(HttpServletResponse.SC_NOT_FOUND, "invalid type; Taxon expected but " + tb.getClass().getSimpleName() + " found.");\r
 //                     return null;\r
 //             }\r
 //     }\r
+\r
 }\r