org.betaconceptframework.astroboa.resourceapi.resource.TaxonomyResource.java Source code

Java tutorial

Introduction

Here is the source code for org.betaconceptframework.astroboa.resourceapi.resource.TaxonomyResource.java

Source

/*
 * Copyright (C) 2005-2012 BetaCONCEPT Limited
 *
 * This file is part of Astroboa.
 *
 * Astroboa is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Astroboa is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Astroboa.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.betaconceptframework.astroboa.resourceapi.resource;

import java.net.HttpURLConnection;

import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.betaconceptframework.astroboa.api.model.Taxonomy;
import org.betaconceptframework.astroboa.api.model.Topic;
import org.betaconceptframework.astroboa.api.model.io.FetchLevel;
import org.betaconceptframework.astroboa.api.model.io.ImportConfiguration;
import org.betaconceptframework.astroboa.api.model.io.ImportConfiguration.PersistMode;
import org.betaconceptframework.astroboa.api.model.io.ResourceRepresentationType;
import org.betaconceptframework.astroboa.api.model.query.CmsOutcome;
import org.betaconceptframework.astroboa.api.model.query.criteria.TopicCriteria;
import org.betaconceptframework.astroboa.api.security.exception.CmsUnauthorizedAccessException;
import org.betaconceptframework.astroboa.client.AstroboaClient;
import org.betaconceptframework.astroboa.model.factory.CmsCriteriaFactory;
import org.betaconceptframework.astroboa.resourceapi.utility.ContentApiUtils;
import org.betaconceptframework.astroboa.util.CmsConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author Gregory Chomatas (gchomatas@betaconcept.com)
 * @author Savvas Triantafyllou (striantafyllou@betaconcept.com)
 * 
 */
/*
@Name("org.betaconceptframework.astroboa.resourceapi.resource.TaxonomyResource")
*/
public class TaxonomyResource extends AstroboaResource {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    public TaxonomyResource(AstroboaClient astroboaClient) {
        super(astroboaClient);
    }

    // The methods which produce JSON or XML allow "callback" as one extra query parameter 
    // in order to support XML with Padding or JSON with Padding (JSONP) and overcome the SPO restriction of browsers
    // This means that if a "callback" query parameter is provided then the XML or JSON result will be wrapped inside a "callback" script

    @GET
    @Produces("*/*")
    @Path("/{taxonomyIdOrName: " + CmsConstants.UUID_OR_SYSTEM_NAME_REG_EXP_FOR_RESTEASY + "}")
    public Response getTaxonomyByName(@PathParam("taxonomyIdOrName") String taxonomyIdOrName,
            @QueryParam("output") String output, @QueryParam("callback") String callback,
            @QueryParam("prettyPrint") String prettyPrint, @QueryParam("depth") String depth) {

        FetchLevel fetchLevel = ContentApiUtils.getFetchLevel(depth, FetchLevel.ENTITY_AND_CHILDREN);

        if (output == null) {
            return getTaxonomy(taxonomyIdOrName, Output.XML, callback, prettyPrint, fetchLevel);
        }

        Output outputEnum = Output.valueOf(output.toUpperCase());

        return getTaxonomy(taxonomyIdOrName, outputEnum, callback, prettyPrint, fetchLevel);
    }

    @GET
    @Produces({ MediaType.APPLICATION_JSON })
    @Path("/{taxonomyIdOrName: " + CmsConstants.UUID_OR_SYSTEM_NAME_REG_EXP_FOR_RESTEASY + "}")
    public Response getTaxonomyByNameAsJson(@PathParam("taxonomyIdOrName") String taxonomyIdOrName,
            @QueryParam("output") String output, @QueryParam("callback") String callback,
            @QueryParam("prettyPrint") String prettyPrint, @QueryParam("depth") String depth) {
        // URL-based negotiation overrides any Accept header sent by the client
        //i.e. if the url specifies the desired response type in the "output" parameter this method
        // will return the media type specified in "output" request parameter.
        Output outputEnum = Output.JSON;
        if (StringUtils.isNotBlank(output)) {
            outputEnum = Output.valueOf(output.toUpperCase());
        }

        FetchLevel fetchLevel = ContentApiUtils.getFetchLevel(depth, FetchLevel.ENTITY_AND_CHILDREN);

        return getTaxonomy(taxonomyIdOrName, outputEnum, callback, prettyPrint, fetchLevel);
    }

    @GET
    @Produces(MediaType.APPLICATION_XML)
    @Path("/{taxonomyIdOrName: " + CmsConstants.UUID_OR_SYSTEM_NAME_REG_EXP_FOR_RESTEASY + "}")
    public Response getTaxonomyByNameAsXml(@PathParam("taxonomyIdOrName") String taxonomyIdOrName,
            @QueryParam("output") String output, @QueryParam("callback") String callback,
            @QueryParam("prettyPrint") String prettyPrint, @QueryParam("depth") String depth) {
        // URL-based negotiation overrides any Accept header sent by the client
        //i.e. if the url specifies the desired response type in the "output" parameter this method
        // will return the media type specified in "output" request parameter.
        Output outputEnum = Output.XML;
        if (StringUtils.isNotBlank(output)) {
            outputEnum = Output.valueOf(output.toUpperCase());
        }

        FetchLevel fetchLevel = ContentApiUtils.getFetchLevel(depth, FetchLevel.ENTITY_AND_CHILDREN);

        return getTaxonomy(taxonomyIdOrName, outputEnum, callback, prettyPrint, fetchLevel);
    }

    @GET
    @Produces(MediaType.APPLICATION_XML)
    public Response getTaxonomiesAsXML(@QueryParam("cmsQuery") String cmsQuery,
            @QueryParam("offset") Integer offset, @QueryParam("limit") Integer limit,
            @QueryParam("orderBy") String orderBy, @QueryParam("output") String output,
            @QueryParam("callback") String callback, @QueryParam("prettyPrint") String prettyPrint,
            @QueryParam("depth") String depth) {

        // URL-based negotiation overrides any Accept header sent by the client
        //i.e. if the url specifies the desired response type in the "output" parameter this method
        // will return the media type specified in "output" request parameter.
        Output outputEnum = Output.XML;
        if (StringUtils.isNotBlank(output)) {
            outputEnum = Output.valueOf(output.toUpperCase());
        }

        boolean prettyPrintEnabled = ContentApiUtils.isPrettyPrintEnabled(prettyPrint);

        FetchLevel fetchLevel = ContentApiUtils.getFetchLevel(depth, FetchLevel.ENTITY);

        return retrieveTaxonomies(cmsQuery, offset, limit, orderBy, outputEnum, callback, prettyPrintEnabled,
                fetchLevel);
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Response getTaxonomiesAsJson(@QueryParam("cmsQuery") String cmsQuery,
            @QueryParam("offset") Integer offset, @QueryParam("limit") Integer limit,
            @QueryParam("orderBy") String orderBy, @QueryParam("output") String output,
            @QueryParam("callback") String callback, @QueryParam("prettyPrint") String prettyPrint,
            @QueryParam("depth") String depth) {

        // URL-based negotiation overrides any Accept header sent by the client
        //i.e. if the url specifies the desired response type in the "output" parameter this method
        // will return the media type specified in "output" request parameter.
        Output outputEnum = Output.JSON;
        if (StringUtils.isNotBlank(output)) {
            outputEnum = Output.valueOf(output.toUpperCase());
        }

        boolean prettyPrintEnabled = ContentApiUtils.isPrettyPrintEnabled(prettyPrint);

        FetchLevel fetchLevel = ContentApiUtils.getFetchLevel(depth, FetchLevel.ENTITY);

        return retrieveTaxonomies(cmsQuery, offset, limit, orderBy, outputEnum, callback, prettyPrintEnabled,
                fetchLevel);
    }

    @GET
    @Produces("*/*")
    public Response getTaxonomies(@QueryParam("cmsQuery") String cmsQuery, @QueryParam("offset") Integer offset,
            @QueryParam("limit") Integer limit, @QueryParam("orderBy") String orderBy,
            @QueryParam("output") String output, @QueryParam("callback") String callback,
            @QueryParam("prettyPrint") String prettyPrint, @QueryParam("depth") String depth) {

        Output outputEnum = Output.XML;
        if (StringUtils.isNotBlank(output)) {
            outputEnum = Output.valueOf(output.toUpperCase());
        }

        boolean prettyPrintEnabled = ContentApiUtils.isPrettyPrintEnabled(prettyPrint);

        FetchLevel fetchLevel = ContentApiUtils.getFetchLevel(depth, FetchLevel.ENTITY);

        return retrieveTaxonomies(cmsQuery, offset, limit, orderBy, outputEnum, callback, prettyPrintEnabled,
                fetchLevel);
    }

    // **** THE FOLLOWING THREE METHODS SUPPORT RETRIEVING THE TAXONOMY_INSTANCE TOPICS THROUGH THE TaxonomyResource ****
    // **** TOPICS CAN BE ALSO RETRIEVED THROUGH THE TopicResource ****
    // **** READ THE COMMENTS THAT FOLLOW FOR AN EXPLANATION ****
    //
    // BE AWARE! the taxonomyIdOrName is not actually required to retrieve a topic since topic ids or system names are unique across all taxonomies.
    // However since the "taxonomyIdOrName" is provided it should exist and additionally 
    // the provided "topicPathWithIdsOrNames" should exist inside the taxonomy in order to get back your topic.
    // In other words we traverse the provided path from the taxonomy down to the last topic in the path. 
    // So the TaxonomyResource is recommended if you want to traverse/browse taxonomies and their topics going from node to node. 
    // The alternative, easier and more efficient way to directly get topics is to use the "TopicResource"
    // So why do we support this type of resource path for retrieving topics since you can get them directly through the "TopicResource"?. 
    // The answer is because it is natural and most users expect to be able to ask for topics while traversing a taxonomy through the Taxonomy Resource.
    // Imagine a user that implements an AJAX tree for browsing through the topics of the taxonomy. 
    // The URL "/taxonomy" brings back all available taxonomies and then the URL "/taxonomy/{taxonomyIdOrSystemName}" 
    // brings back the requested taxonomy with its root topics 
    // Then the URL "/taxonomy/{taxonomyIdOrSystemName}/{rootTopicIdOrSystemName}" 
    // brings back the requested topic and its child topics. 
    // In the same manner the
    // "/taxonomy/{taxonomyIdOrSystemName}/{rootTopicIdOrSystemName}/{childTopicIdOrSystemName}" brings back the child topic of the root topic and so on.   
    @GET
    @Produces("*/*")
    @Path("/{taxonomyIdOrName: " + CmsConstants.UUID_OR_SYSTEM_NAME_REG_EXP_FOR_RESTEASY + "}"
            + "/{topicPathWithIdsOrNames: " + CmsConstants.TOPIC_PATH_WITH_UUIDS_OR_SYSTEM_NAMES_REG_EXP + "}")
    public Response getTopicInTaxonomy(@PathParam("taxonomyIdOrName") String taxonomyIdOrName,
            @PathParam("topicPathWithIdsOrNames") String topicPathWithIdsOrNames,
            @QueryParam("output") String output, @QueryParam("callback") String callback,
            @QueryParam("prettyPrint") String prettyPrint) {

        /*if (output == null)
        {
           return getTopicInTaxonomyInternal(taxonomyIdOrName, topicPathWithIdsOrNames, Output.XML, callback);
        }*/

        Output outputEnum = ContentApiUtils.getOutputType(output, Output.XML);

        boolean isPrettyPrintEnabled = ContentApiUtils.isPrettyPrintEnabled(prettyPrint);

        return getTopicInTaxonomyInternal(taxonomyIdOrName, topicPathWithIdsOrNames, outputEnum, callback,
                isPrettyPrintEnabled);

    }

    @GET
    @Produces({ MediaType.APPLICATION_JSON })
    @Path("/{taxonomyIdOrName: " + CmsConstants.UUID_OR_SYSTEM_NAME_REG_EXP_FOR_RESTEASY + "}"
            + "/{topicPathWithIdsOrNames: " + CmsConstants.TOPIC_PATH_WITH_UUIDS_OR_SYSTEM_NAMES_REG_EXP + "}")
    public Response getTopicInTaxonomyAsJson(@PathParam("taxonomyIdOrName") String taxonomyIdOrName,
            @PathParam("topicPathWithIdsOrNames") String topicPathWithIdsOrNames,
            @QueryParam("output") String output, @QueryParam("callback") String callback,
            @QueryParam("prettyPrint") String prettyPrint) {

        // URL-based negotiation overrides any Accept header sent by the client
        //i.e. if the url specifies the desired response type in the "output" parameter this method
        // will return the media type specified in "output" request parameter.
        /*Output outputEnum = Output.JSON;
        if (StringUtils.isNotBlank(output)) {
           outputEnum = Output.valueOf(output.toUpperCase());
        }*/

        Output outputEnum = ContentApiUtils.getOutputType(output, Output.JSON);

        boolean isPrettyPrintEnabled = ContentApiUtils.isPrettyPrintEnabled(prettyPrint);

        return getTopicInTaxonomyInternal(taxonomyIdOrName, topicPathWithIdsOrNames, outputEnum, callback,
                isPrettyPrintEnabled);
    }

    @GET
    @Produces(MediaType.APPLICATION_XML)
    @Path("/{taxonomyIdOrName: " + CmsConstants.UUID_OR_SYSTEM_NAME_REG_EXP_FOR_RESTEASY + "}"
            + "/{topicPathWithIdsOrNames: " + CmsConstants.TOPIC_PATH_WITH_UUIDS_OR_SYSTEM_NAMES_REG_EXP + "}")
    public Response getTopicInTaxonomyAsXml(@PathParam("taxonomyIdOrName") String taxonomyIdOrName,
            @PathParam("topicPathWithIdsOrNames") String topicPathWithIdsOrNames,
            @QueryParam("output") String output, @QueryParam("callback") String callback,
            @QueryParam("prettyPrint") String prettyPrint) {

        // URL-based negotiation overrides any Accept header sent by the client
        //i.e. if the url specifies the desired response type in the "output" parameter this method
        // will return the media type specified in "output" request parameter.
        /*Output outputEnum = Output.XML;
        if (StringUtils.isNotBlank(output)) {
           outputEnum = Output.valueOf(output.toUpperCase());
        }*/

        Output outputEnum = ContentApiUtils.getOutputType(output, Output.XML);

        boolean isPrettyPrintEnabled = ContentApiUtils.isPrettyPrintEnabled(prettyPrint);

        return getTopicInTaxonomyInternal(taxonomyIdOrName, topicPathWithIdsOrNames, outputEnum, callback,
                isPrettyPrintEnabled);
    }

    @POST
    public Response postTaxonomy(String requestContent) {
        return saveTaxonomySource(requestContent, HttpMethod.POST, true);
    }

    @PUT
    @Path("/{taxonomyIdOrName: " + CmsConstants.UUID_OR_SYSTEM_NAME_REG_EXP_FOR_RESTEASY + "}")
    public Response putTaxonomyByIdOrName(@PathParam("taxonomyIdOrName") String taxonomyIdOrName,
            String requestContent) {

        if (StringUtils.isBlank(taxonomyIdOrName)) {
            logger.warn("Use HTTP PUT to save taxonomy {} but no id or name was provided ", requestContent);
            throw new WebApplicationException(HttpURLConnection.HTTP_BAD_REQUEST);
        }

        return saveTaxonomyByIdOrName(taxonomyIdOrName, requestContent, HttpMethod.PUT);
    }

    @DELETE
    @Path("/{taxonomyIdOrName:" + CmsConstants.UUID_OR_SYSTEM_NAME_REG_EXP_FOR_RESTEASY + "}")
    public Response deleteTaxonomy(@PathParam("taxonomyIdOrName") String taxonomyIdOrName) {
        if (StringUtils.isEmpty(taxonomyIdOrName)) {
            throw new WebApplicationException(Response.Status.BAD_REQUEST);
        }
        try {
            boolean taxonomyDeleted = astroboaClient.getTaxonomyService().deleteTaxonomyTree(taxonomyIdOrName);
            return ContentApiUtils.createResponseForHTTPDelete(taxonomyDeleted, taxonomyIdOrName);
        } catch (CmsUnauthorizedAccessException e) {
            throw new WebApplicationException(Response.Status.UNAUTHORIZED);
        } catch (Exception e) {
            logger.error("", e);
            throw new WebApplicationException(Response.Status.BAD_REQUEST);
        }
    }

    private Response saveTaxonomyByIdOrName(@PathParam("taxonomyIdOrName") String taxonomyIdOrName,
            String requestContent, String httpMethod) {

        //Import from xml or json. Taxonomy will not be saved
        ImportConfiguration configuration = ImportConfiguration.taxonomy().persist(PersistMode.DO_NOT_PERSIST)
                .build();

        Taxonomy taxonomyToBeSaved = astroboaClient.getImportService().importTaxonomy(requestContent,
                configuration);

        //Bring taxonomy from repository
        Taxonomy existedTaxonomy = astroboaClient.getTaxonomyService().getTaxonomy(taxonomyIdOrName,
                ResourceRepresentationType.TAXONOMY_INSTANCE, FetchLevel.ENTITY, false);

        boolean taxonomyIdHasBeenProvided = CmsConstants.UUIDPattern.matcher(taxonomyIdOrName).matches();

        boolean entityIsNew = existedTaxonomy == null;

        if (taxonomyIdHasBeenProvided) {
            if (taxonomyToBeSaved.getId() == null) {
                taxonomyToBeSaved.setId(taxonomyIdOrName);
            }
        } else {
            if (taxonomyToBeSaved.getName() == null) {
                taxonomyToBeSaved.setName(taxonomyIdOrName);
            }
        }

        if (existedTaxonomy != null) {

            //Taxonomy exists in repository.
            //Check to see if an id is provided in the payload
            if (taxonomyToBeSaved.getId() == null) {
                taxonomyToBeSaved.setId(existedTaxonomy.getId());
            } else {
                if (!StringUtils.equals(existedTaxonomy.getId(), taxonomyToBeSaved.getId())) {
                    logger.warn(
                            "Try to {} taxonomy {} which corresponds to an existed taxonomy in repository with id {} but payload contains a different id {}",
                            new Object[] { httpMethod, taxonomyIdOrName, existedTaxonomy.getId(),
                                    taxonomyToBeSaved.getId() });
                    throw new WebApplicationException(HttpURLConnection.HTTP_BAD_REQUEST);
                }
            }

        } else {
            //A new taxonomy will be created.
            //Check to see if system name is provided in the payload
            if (taxonomyToBeSaved.getName() != null && !taxonomyIdHasBeenProvided
                    && !StringUtils.equals(taxonomyIdOrName, taxonomyToBeSaved.getName())) {
                logger.warn("Try to {} taxonomy with name {} but payload contains a different name {}",
                        new Object[] { httpMethod, taxonomyIdOrName, taxonomyToBeSaved.getName() });
                throw new WebApplicationException(HttpURLConnection.HTTP_BAD_REQUEST);
            }
        }

        //Produce xml representation of imported taxonomy and continue with save
        return saveTaxonomySource(taxonomyToBeSaved.xml(false), httpMethod, entityIsNew);
    }

    private Response saveTaxonomySource(String taxonomySource, String httpMethod, boolean entityIsNew) {

        logger.debug("Want to save a new taxonomy {}", taxonomySource);

        try {

            ImportConfiguration configuration = ImportConfiguration.taxonomy()
                    .persist(PersistMode.PERSIST_ENTITY_TREE).build();

            Taxonomy taxonomy = astroboaClient.getImportService().importTaxonomy(taxonomySource, configuration);

            return ContentApiUtils.createResponseForPutOrPostOfACmsEntity(taxonomy, httpMethod, taxonomySource,
                    entityIsNew);

        } catch (CmsUnauthorizedAccessException e) {
            throw new WebApplicationException(HttpURLConnection.HTTP_UNAUTHORIZED);
        } catch (Exception e) {
            logger.error("", e);
            throw new WebApplicationException(HttpURLConnection.HTTP_NOT_FOUND);
        }
    }

    private Response getTopicInTaxonomyInternal(String taxonomyIdOrName, String topicPathWithIdsOrSystemNames,
            Output output, String callback, boolean prettyPrint) {

        try {

            Topic topic = findTopicByTaxonomyIdOrNameAndTopicPathWithIdsOrNames(taxonomyIdOrName,
                    topicPathWithIdsOrSystemNames);

            if (topic == null) {
                throw new WebApplicationException(HttpURLConnection.HTTP_NOT_FOUND);
            }

            // Lazy load topic children so they will be rendered in XML or JSON response
            topic.getChildren();

            StringBuilder topicAsXMLOrJSON = new StringBuilder();

            switch (output) {
            case XML: {
                if (StringUtils.isBlank(callback)) {
                    topicAsXMLOrJSON.append(topic.xml(prettyPrint));
                } else {
                    ContentApiUtils.generateXMLP(topicAsXMLOrJSON, topic.xml(prettyPrint), callback);
                }
                break;
            }
            case JSON:
                if (StringUtils.isBlank(callback)) {
                    topicAsXMLOrJSON.append(topic.json(prettyPrint));
                } else {
                    ContentApiUtils.generateXMLP(topicAsXMLOrJSON, topic.json(prettyPrint), callback);
                }
                break;
            }

            return ContentApiUtils.createResponse(topicAsXMLOrJSON, output, callback, null);

        } catch (Exception e) {
            logger.error("Taxonomy IdOrName: " + taxonomyIdOrName + ", Topic Path with Ids Or Names: "
                    + topicPathWithIdsOrSystemNames, e);
            throw new WebApplicationException(HttpURLConnection.HTTP_BAD_REQUEST);
        }
    }

    private Response getTaxonomy(String taxonomyIdOrName, Output output, String callback, String prettyPrint,
            FetchLevel fetchLevel) {

        if (StringUtils.isBlank(taxonomyIdOrName)) {
            logger.warn("No Taxonomy Name provided");
            throw new WebApplicationException(HttpURLConnection.HTTP_NOT_FOUND);
        }

        try {
            String taxonomyXmlorJson = retrieveTaxonomyXMLorJSONByIdOrSystemName(taxonomyIdOrName, output,
                    prettyPrint, fetchLevel);

            StringBuilder resourceRepresentation = new StringBuilder();

            if (StringUtils.isBlank(callback)) {
                resourceRepresentation.append(taxonomyXmlorJson);
            } else {
                switch (output) {
                case XML: {
                    ContentApiUtils.generateXMLP(resourceRepresentation, taxonomyXmlorJson, callback);
                    break;
                }
                case JSON:
                    ContentApiUtils.generateJSONP(resourceRepresentation, taxonomyXmlorJson, callback);
                    break;
                default: {
                    ContentApiUtils.generateXMLP(resourceRepresentation, taxonomyXmlorJson, callback);
                    break;
                }
                }

            }

            return ContentApiUtils.createResponse(resourceRepresentation, output, callback, null);
        } catch (Exception e) {
            logger.error("Taxonomy IdOrName: " + taxonomyIdOrName, e);
            throw new WebApplicationException(HttpURLConnection.HTTP_BAD_REQUEST);
        }

    }

    private Response retrieveTaxonomies(String cmsQuery, Integer offset, Integer limit, String orderBy,
            Output output, String callback, boolean prettyPrint, FetchLevel fetchLevel) {

        try {

            if (output == null) {
                output = Output.XML;
            }

            if (fetchLevel == null) {
                fetchLevel = FetchLevel.ENTITY;
            }

            StringBuilder resourceRepresentation = new StringBuilder();

            //List<Taxonomy> taxonomies = new ArrayList<Taxonomy>();

            if (!StringUtils.isBlank(cmsQuery)) {
                throw new WebApplicationException(HttpURLConnection.HTTP_NOT_IMPLEMENTED);
            }

            switch (output) {
            case XML: {
                String resourceCollectionAsXML = astroboaClient.getTaxonomyService()
                        .getAllTaxonomies(ResourceRepresentationType.XML, fetchLevel, prettyPrint);

                if (StringUtils.isBlank(callback)) {
                    resourceRepresentation.append(resourceCollectionAsXML);
                } else {
                    ContentApiUtils.generateXMLP(resourceRepresentation, resourceCollectionAsXML, callback);
                }
                break;
            }
            case JSON:
                String resourceCollectionAsJSON = astroboaClient.getTaxonomyService()
                        .getAllTaxonomies(ResourceRepresentationType.JSON, fetchLevel, prettyPrint);

                if (StringUtils.isBlank(callback)) {
                    resourceRepresentation.append(resourceCollectionAsJSON);
                } else {
                    ContentApiUtils.generateJSONP(resourceRepresentation, resourceCollectionAsJSON, callback);
                }
                break;
            }

            return ContentApiUtils.createResponse(resourceRepresentation, output, callback, null);

        } catch (Exception e) {
            logger.error("Cms query " + cmsQuery, e);
            throw new WebApplicationException(HttpURLConnection.HTTP_BAD_REQUEST);
        }
    }

    private String retrieveTaxonomyXMLorJSONByIdOrSystemName(String taxonomyIdOrName, Output output,
            String prettyPrint, FetchLevel fetchLevel) {

        if (StringUtils.isBlank(taxonomyIdOrName)) {
            logger.warn("The provided Taxonomy IdOrName {} is Blank ", taxonomyIdOrName);
            throw new WebApplicationException(HttpURLConnection.HTTP_NOT_FOUND);
        }

        //Default output is XML
        if (output == null) {
            output = Output.XML;
        }

        //Default fetch level is ENTITY_CHILDREN
        if (fetchLevel == null) {
            fetchLevel = FetchLevel.ENTITY_AND_CHILDREN;
        }

        boolean prettyPrintEnabled = ContentApiUtils.isPrettyPrintEnabled(prettyPrint);

        switch (output) {
        case XML: {
            String taxonomyXML = astroboaClient.getTaxonomyService().getTaxonomy(taxonomyIdOrName,
                    ResourceRepresentationType.XML, fetchLevel, prettyPrintEnabled);

            if (StringUtils.isBlank(taxonomyXML)) {
                throw new WebApplicationException(HttpURLConnection.HTTP_NOT_FOUND);
            }
            return taxonomyXML;
        }
        case JSON: {
            String taxonomyJSON = astroboaClient.getTaxonomyService().getTaxonomy(taxonomyIdOrName,
                    ResourceRepresentationType.JSON, fetchLevel, prettyPrintEnabled);

            if (StringUtils.isBlank(taxonomyJSON)) {
                throw new WebApplicationException(HttpURLConnection.HTTP_NOT_FOUND);
            }
            return taxonomyJSON;

        }
        default: {
            String taxonomyXML = astroboaClient.getTaxonomyService().getTaxonomy(taxonomyIdOrName,
                    ResourceRepresentationType.XML, fetchLevel, prettyPrintEnabled);

            if (StringUtils.isBlank(taxonomyXML)) {
                throw new WebApplicationException(HttpURLConnection.HTTP_NOT_FOUND);
            }
            return taxonomyXML;
        }
        }
    }

    /*private void transformTaxonomiesToXML(List<Taxonomy> taxonomies, StringBuilder resourceCollectionAsXML) {
       resourceCollectionAsXML.append("<resourceCollection>");
           
       for (Taxonomy taxonomy : taxonomies) {
     resourceCollectionAsXML
        .append(taxonomy.xml().substring(55));
       }
           
       resourceCollectionAsXML.append("</resourceCollection>");
    }
        
    private void transformTaxonomiesToJSON(List<Taxonomy> taxonomies, StringBuilder resourceCollectionAsJSON) {
       resourceCollectionAsJSON
     .append("{")
     .append("\"total\":").append("\"").append(taxonomies.size()).append("\"");
           
       if (taxonomies.size() > 0) {   
     resourceCollectionAsJSON.append(",")
     .append("\"resourceRepresentation\":").append("[");
     for (Taxonomy taxonomy : taxonomies) {
        resourceCollectionAsJSON.append(taxonomy.json())
           .append(",");
     }
     resourceCollectionAsJSON.append("]");
       }
       resourceCollectionAsJSON.append("}");
    }*/

    private Topic findTopicByTaxonomyIdOrNameAndTopicPathWithIdsOrNames(String taxonomyIdOrName,
            String topicPathWithIdsOrNames) {

        if (StringUtils.isBlank(topicPathWithIdsOrNames)) {
            logger.warn("The provided topic path is blank. NULL will be returned");
            return null;
        }

        if (StringUtils.isBlank(taxonomyIdOrName)) {
            logger.warn("The provided taxonomy id or name is blank. NULL will be returned");
            return null;
        }

        // split topic path to its components
        String[] topicPathComponents = topicPathWithIdsOrNames.split("/");

        TopicCriteria finalTopicCriteria = null;
        TopicCriteria parentTopicCriteria = null;
        TopicCriteria rootTopicCriteria = null;

        for (String topicIdOrName : topicPathComponents) {

            TopicCriteria topicCriteria = CmsCriteriaFactory.newTopicCriteria();
            if (CmsConstants.UUIDPattern.matcher(topicIdOrName).matches()) {
                topicCriteria.addIdEqualsCriterion(topicIdOrName);
            } else {
                topicCriteria.addNameEqualsCriterion(topicIdOrName);
            }
            topicCriteria.searchInDirectAncestorOnly();

            if (rootTopicCriteria == null) {
                rootTopicCriteria = topicCriteria;
                parentTopicCriteria = topicCriteria;
            } else {
                topicCriteria.setAncestorCriteria(parentTopicCriteria);

                parentTopicCriteria = topicCriteria;
            }

            finalTopicCriteria = topicCriteria;
        }

        //Finally add taxonomy criteria for the rootTopic
        if (CmsConstants.UUIDPattern.matcher(taxonomyIdOrName).matches()) {
            Taxonomy taxonomy = astroboaClient.getCmsRepositoryEntityFactory().newTaxonomy();
            taxonomy.setId(taxonomyIdOrName);
            rootTopicCriteria.addTaxonomyCriterion(taxonomy);
        } else {
            rootTopicCriteria.addTaxonomyNameEqualsCriterion(taxonomyIdOrName);
        }

        CmsOutcome<Topic> topicsFound = astroboaClient.getTopicService().searchTopics(finalTopicCriteria,
                ResourceRepresentationType.TOPIC_LIST);
        if (CollectionUtils.isNotEmpty(topicsFound.getResults())) {
            Topic firstTopic = topicsFound.getResults().get(0);
            // if more than one topics correspond to the same name then we choose the first one but we generate a warning
            if (topicsFound.getResults().size() > 1)
                logger.warn(
                        "More than one topics correspond to taxonomyIdOrName:topicPathWithIdsOrNames: {}:{}. The first from  list will be returned. Topic id and names should be unique across all taxonomies. Please inform your support team about this bug !!",
                        taxonomyIdOrName, topicPathWithIdsOrNames);
            return firstTopic;
        } else {
            logger.info("The provided taxonomyIdOrName:topicPathWithIdsOrNames: {}:{} does not exist.",
                    taxonomyIdOrName, topicPathWithIdsOrNames);
            return null;
        }

    }
}