/******************************************************************************* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *******************************************************************************/ package org.apache.wink.example.qadefect.resources; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.util.Collection; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; 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.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.wink.common.annotations.Workspace; import org.apache.wink.common.internal.utils.MediaTypeUtils; import org.apache.wink.common.internal.utils.OpenSearchUtils; import org.apache.wink.common.model.opensearch.OpenSearchDescription; import org.apache.wink.common.model.opensearch.OpenSearchImage; import org.apache.wink.common.model.opensearch.OpenSearchParameter; import org.apache.wink.common.model.opensearch.OpenSearchQuery; import org.apache.wink.common.model.opensearch.OpenSearchUrl; import org.apache.wink.example.qadefect.legacy.DataStore; import org.apache.wink.example.qadefect.legacy.DefectBean; import org.apache.wink.example.qadefect.utils.SearchMap; import org.apache.wink.server.utils.LinkBuilders; @Workspace(workspaceTitle = "QA Defects", collectionTitle = "Defects") @Path(DefectsResource.DEFECTS_PATH) public class DefectsResource { private static final Logger logger = LoggerFactory .getLogger(DefectsResource.class); public static final String DEFECTS_PATH = "defects"; public static final String DEFECT_VAR = "defect"; public static final String DEFECT_PATH = "{" + DEFECT_VAR + "}"; public static final String DEFECT_ATTACHMENT_PATH = DEFECT_PATH + "/attachment"; public static final String SEVERIIY = "severity"; public static final String ASSIGNED_TO = "assignedTo"; public static final String URN_ASSIGNED_TO = "urn:hp:defect:assignedTo"; public static final String URN_SEVERIIY = "urn:hp:defect:severity"; public static final String FTS = "q"; @GET @Produces( {MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_HTML, "text/csv"}) public DefectsAsset getDefects(@QueryParam(FTS) String query, @QueryParam(SEVERIIY) String severity, @QueryParam(ASSIGNED_TO) String assignedTo) { DataStore store = DataStore.getInstance(); // fill search parameters // the parameters may be absent, the SearchMap will do the filtering SearchMap searchParameters = new SearchMap(); searchParameters.put(FTS, query); searchParameters.put(SEVERIIY, severity); searchParameters.put(ASSIGNED_TO, assignedTo); // get the defects that match the search criteria Collection<DefectBean> defects = store.getDefects(searchParameters); return new DefectsAsset(defects); } /** * Add OpenSearch representation to this defect collection resource. * OpenSearch description document describes search infrastructure * interface. (see <a href="http://www.opensearch.org/">OpenSearch</a>) */ @GET @Produces(MediaTypeUtils.OPENSEARCH) public OpenSearchDescription getOpenSearch(@Context UriInfo info) { String baseUri = info.getAbsolutePath().toString(); OpenSearchDescription openSearchDescription = new OpenSearchDescription(); openSearchDescription.setShortName("HP Defect Manager search engine"); openSearchDescription.setDescription("You can search defects in HP Defect Manager"); openSearchDescription.setLongName("HP Defect Manager search engine"); openSearchDescription.setContact("john.smith@example.com"); openSearchDescription.setDeveloper("John Smith"); openSearchDescription.addLanguage("en-US"); openSearchDescription.setTags("defect bug"); openSearchDescription.addInputEncoding("UTF-8"); openSearchDescription.addOutputEncoding("UTF-8"); // set OpenSearch URL parameters OpenSearchParameter severityParameter = new OpenSearchParameter(SEVERIIY, URN_SEVERIIY, false); OpenSearchParameter ftsParameter = new OpenSearchParameter(FTS, OpenSearchParameter.OpenSearchParams.searchTerms .toString(), false); OpenSearchParameter assignedToParameter = new OpenSearchParameter(ASSIGNED_TO, URN_ASSIGNED_TO, false); // create Search URL & populate search parameters for browsers OpenSearchUrl openSearchUrlForBrowsers = new OpenSearchUrl(); openSearchUrlForBrowsers.addOpenSearchParameter(ftsParameter); openSearchUrlForBrowsers.setType(MediaType.TEXT_HTML); // create Search URL & populate search parameters OpenSearchUrl openSearchUrl = new OpenSearchUrl(); openSearchUrl.addOpenSearchParameter(severityParameter); openSearchUrl.addOpenSearchParameter(ftsParameter); openSearchUrl.addOpenSearchParameter(assignedToParameter); openSearchUrl.setType(MediaType.TEXT_HTML); // create open search base uri StringBuilder openSearchUrlBuilder = new StringBuilder(baseUri); openSearchUrl.setBaseUri(openSearchUrlBuilder.toString()); openSearchUrlForBrowsers.setBaseUri(openSearchUrlBuilder.toString()); // add URLs to OpenSearch openSearchDescription.addUrl(openSearchUrlForBrowsers); openSearchDescription.addUrl(openSearchUrl); // add OpenSearch Query element OpenSearchQuery openSearchQuery = new OpenSearchQuery(); openSearchQuery.setRole(OpenSearchQuery.QueryRole.example.toString()); openSearchQuery.setSearchTerms("Search Terms"); openSearchDescription.addQuery(openSearchQuery); // add OpenSearch Images OpenSearchImage openSearchImage; openSearchImage = OpenSearchUtils.createOpenSearchImage(MediaTypeUtils.IMAGE_JPEG, openSearchUrlBuilder .toString() + "splash.jpg"); openSearchDescription.addNewImage(openSearchImage); return openSearchDescription; } @POST @Consumes({"text/csv"}) @Produces( {MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) public Response createDefects(DefectsAsset defects, @Context LinkBuilders linkProcessor, @Context UriInfo uriInfo) { // add the defects to the defects store DataStore store = DataStore.getInstance(); String id = null; for (DefectBean defect : defects.getDefects()) { id = store.getDefectUniqueId(); defect.setId(id); store.putDefect(id, defect); } // return the created defects and set the status code to created (201) URI location = uriInfo.getAbsolutePathBuilder().segment(id).build(); return Response.created(location).entity(defects).build(); } @POST @Consumes( {MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) @Produces( {MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) public Response createDefect(DefectAsset asset, @Context UriInfo uriInfo) throws IOException, Exception { // if content was not sent => there is no meaning for the defect, throw // exception. if (asset.getDefect() == null) { logger.error("The content of the defect is missing"); throw new WebApplicationException(Response.Status.BAD_REQUEST); } // add the defect to the defects store and set it a new ID DataStore store = DataStore.getInstance(); String id = store.getDefectUniqueId(); DefectBean defect = asset.getDefect(); defect.setId(id); store.putDefect(id, defect); // return the defect and set the status code to created (201) URI location = uriInfo.getAbsolutePathBuilder().segment(id).build(); return Response.created(location).entity(asset).build(); } @Path(DEFECT_PATH) @GET @Produces( {MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_HTML}) public DefectAsset getDefect(@PathParam("defect") String defectId) { // fetch the defect bean from the store, throw 404 in case it does not // exist DataStore store = DataStore.getInstance(); DefectBean defect = store.getDefect(defectId); if (defect == null) { logger.info("Defect {} does not exist", defectId); throw new WebApplicationException(Response.Status.NOT_FOUND); } return new DefectAsset(defect); } /** * <p> * This method is handling GET requests for specific defects' attachment. * <ul> * <em>Examples of handled URIs:</em> * <li><code>/defects/1/attachment</code> - returns defects' attachment in * JPEG format. * * @param defectId defect id * @return resource of defects' attachment */ @Path(DEFECT_ATTACHMENT_PATH) @GET @Produces( {MediaTypeUtils.IMAGE_JPEG}) public InputStream getDefectAttachement(@PathParam("defect") String defectId) { DataStore store = DataStore.getInstance(); // create data object (populated with store data) DefectBean defect = store.getDefect(defectId); if (defect == null) { logger.info("Defect {} does not exist", defectId); throw new WebApplicationException(Response.Status.NOT_FOUND); } String path = defect.getPathToAttachment(); if (path == null) { throw new WebApplicationException(Response.Status.NOT_FOUND); } InputStream attachmentStream = this.getClass().getResourceAsStream("../representation/" + path); return attachmentStream; } @Path(DEFECT_PATH) @PUT @Consumes( {MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_XML}) @Produces( {MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) public DefectAsset updateDefect(DefectAsset asset, @Context LinkBuilders linkProcessor, @PathParam("defect") String defectId) { DataStore store = DataStore.getInstance(); // verify Defect exist in the store, return 404 otherwise DefectBean bean = store.getDefect(defectId); if (bean == null) { logger.info("Defect {} does not exist", defectId); throw new WebApplicationException(Response.Status.NOT_FOUND); } // set Id in the resources data for cases that element <id> is missing // in the request body DefectBean defect = asset.getDefect(); defect.setId(defectId); // update defect legacy bean to the store store.putDefect(defectId, defect); return asset; } @Path(DEFECT_PATH) @DELETE @Produces( {MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) public DefectAsset deleteDefect(@PathParam("defect") String defectId) { DataStore store = DataStore.getInstance(); DefectBean defect = store.getDefect(defectId); store.removeDefect(defectId); return new DefectAsset(defect); } }