Java tutorial
/* * 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; } } }