Package org.apache.wink.example.history.resources

Source Code of org.apache.wink.example.history.resources.DefectsResource

/*******************************************************************************
* 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.history.resources;

import java.io.IOException;
import java.net.URI;
import java.util.Collection;
import java.util.List;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.MatrixParam;
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.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.PathSegment;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.core.Response.Status;

import org.apache.wink.common.annotations.Workspace;
import org.apache.wink.common.http.HttpStatus;
import org.apache.wink.example.history.legacy.DataStore;
import org.apache.wink.example.history.legacy.DefectBean;
import org.apache.wink.server.utils.LinkBuilders;

/**
* A sample application for managing defects of a defect tracking application.
* The defects are managed in an in-memory store, while also maintaining the
* history of every defect. The complete history of a defect is available, as
* well as the individual revision of each defect.
*/
@Workspace(workspaceTitle = "QA Defects", collectionTitle = "Defects")
@Path("defects")
public class DefectsResource {

    public static final String REVISION           = "rev";
    public static final String DEFECT_VAR         = "defect";
    public static final String DEFECT_URL         = "{" + DEFECT_VAR + "}";
    public static final String DEFECT_HISTORY_URL = DEFECT_URL + "/history";

    /**
     * Handles GET requests for returning a list of the latest revision of
     * existing defects.
     * <ul>
     * <em>Examples of requests:</em>
     * <li><code>/defects</code> - returns a list of defects in a format
     * specified by the <code>Accept</code> header
     * <li><code>/defects?alt=application/atom+xml</code> - returns an Atom feed
     * representation. Each defect is represented by Atom entry.
     * <li><code>/defects?alt=application/json</code> - returns a Json
     * representation
     * <li><code>/defects?alt=application/json&callback=getDefects</code> -
     * returns Json representation wrapped in javascript function
     * <code>getDefects</code>
     * </ul>
     *
     * @return DefectsAsset with the list of defects
     */
    @GET
    @Produces( {MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON})
    public DefectsAsset getDefects(@Context LinkBuilders linkProcessor, @Context UriInfo uriInfo) {
        // create data object (populated with store data)
        DataStore store = DataStore.getInstance();
        Collection<DefectBean> defects = store.getDefects();
        return new DefectsAsset(defects);
    }

    /**
     * Handles POST requests for creating a new defect. The server side decides
     * about the new resource URI (Location header) and returns a status code
     * 201 (created). The defect can be received as an Atom entry with xml
     * content (application/atom+xml) or just xml (application/xml), and can be
     * returned as Atom entry, Json or xml.
     * <p>
     * If the defect already existed and was previously deleted, it is
     * undeleted. If the defect is a new defect, the Id must be left blank.
     *
     * @return response with a "created" status code and the created defect
     *         asset
     */
    @POST
    @Consumes( {MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_XML})
    @Produces( {MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON,
        MediaType.APPLICATION_XML})
    public Response createDefect(DefectAsset asset,
                                 @Context LinkBuilders linkProcessor,
                                 @Context UriInfo uriInfo) {

        // if content was not sent => there is no meaning for the defect, throw
        // exception.
        DefectBean defect = asset.getDefect();
        if (defect == null) {
            throw new WebApplicationException(
                                              new RuntimeException(
                                                                   "The content of the defect is missing"),
                                              Response.Status.BAD_REQUEST);
        }

        DataStore store = DataStore.getInstance();
        if (defect.getId() != null) {
            // undelete operation
            if (!store.isDefectDeleted(defect.getId())) {
                // the defect was already undeleted!
                // it's a conflict!
                return Response.status(Status.CONFLICT).build();
            }
            // this is undelete operation, there is no need to populate new id
        } else {
            // this is a new defect so generate an id
            defect.setId(store.getDefectUniqueId());
        }

        // validate that the user didn't send deleted=true by mistake
        defect.setDeleted(false);

        // add defect legacy bean to the memory store
        store.putDefect(defect.getId(), defect);

        URI location = uriInfo.getAbsolutePathBuilder().segment(defect.getId()).build();
        return Response.created(location).entity(asset).build();
    }

    /**
     * <p>
     * Handles GET requests for a single defect.
     * <ul>
     * <em>Examples of handled URIs:</em>
     * <li><code>/defects/3</code> - returns a defect in a format specified by
     * the <code>Accept</code> header
     * <li><code>/defects/3?alt=application/atom%2Bxml</code> - returns a defect
     * as an Atom entry, where xml of defect is serialized in the
     * <code>atom:content</code> element
     * <li><code>/defects/3?alt=application/json</code> - returns javascript
     * (JSon) format
     * <li><code>/defects/3?alt=application/json&callback=getDefect</code> -
     * returns javascript (JSon) format wrapped in javascript function getDefect
     * <li><code>/defects/3?alt=application/xml</code> - returns serialization
     * of defect into XML
     * </ul>
     * <p>
     * A specific revision of the defect can be retrieved by specifying the
     * "rev" matrix parameter adjacent to the defect id on the uri, like so:
     * <code>/defects/3;rev=1</code>. If no revision is specified then the
     * latest revision is returned.
     *
     * @return DefectAsset with the requested defect
     */
    @Path(DEFECT_URL)
    @GET
    @Produces( {MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON,
        MediaType.APPLICATION_XML})
    public DefectAsset getDefect(@PathParam(DEFECT_VAR) PathSegment segment,
                                 @MatrixParam(REVISION) @DefaultValue("-1") int defectRevision) {

        // create data object (populated with store data)
        DataStore store = DataStore.getInstance();
        String defectId = segment.getPath();
        DefectBean defect = store.getDefect(defectId);
        if (defectRevision != -1) {
            // get specific revision
            // even if the defect was deleted, it is returned
            defect = store.getDefect(defectId, defectRevision);
        }
        if (defect == null) {
            throw new WebApplicationException(new RuntimeException("Defect " + defectId
                + " not found"), Response.Status.NOT_FOUND);
        }

        DefectAsset asset = new DefectAsset(defect);
        asset.setEditable(!store.isDefectDeleted(defectId));
        return asset;
    }

    /**
     * Handles a GET request for the history of a defect. The history can be
     * requested as an Atom feed or as Json. <em>Examples of handled URIs:</em>
     * <li><code>/defects/3/history</code> - returns a defect in a format
     * specified by the <code>Accept</code> header <li>
     * <code>/defects/3/history?alt=application/atom%2Bxml</code> - returns the
     * history as an Atom feed <li>
     * <code>/defects/3/history?alt=application/json</code> - returns the
     * history as Json <li>
     * <code>/defects/3/history?alt=application/json&callback=getDefect</code> -
     * returns the history as Json wrapped in a javascript
     * <code>getDefect</code> method
     *
     * @param segement
     * @return
     */
    @Path(DEFECT_HISTORY_URL)
    @GET
    @Produces( {MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON})
    public DefectsAsset getDefectHistory(@PathParam(DEFECT_VAR) PathSegment segement) {
        // create data object (populated with store data)
        DataStore store = DataStore.getInstance();
        String defectId = segement.getPath();
        // get the history of the defect
        List<DefectBean> defectHistory = store.getDefectHistory(defectId);
        if (defectHistory.isEmpty()) {
            throw new WebApplicationException(new RuntimeException("Defect " + defectId
                + " not found"), Response.Status.NOT_FOUND);
        }
        return new DefectsAsset(defectHistory, true);
    }

    /**
     * <p>
     * Handles PUT requests for updating a defect. It updates an existing defect
     * with data received in the request body.
     * <p>
     * The defect being updated can be sent as an Atom entry with xml content
     * (application/atom+xml) or just xml (application/xml).
     * <p>
     * The <code>defectRevision</code> parameter of the method exists to make
     * sure that no revision was specified in the update request.
     *
     * @return DefectAsset with the updated defect
     */
    @Path(DEFECT_URL)
    @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,
                                    @PathParam(DEFECT_VAR) PathSegment segement,
                                    @MatrixParam(REVISION) @DefaultValue("-1") int defectRevision)
        throws IOException {

        if (defectRevision != -1) {
            // it's impossible to update a specific revision
            throw new WebApplicationException(HttpStatus.METHOD_NOT_ALLOWED.getCode());
        }

        // obtain data object from the memory store
        // if the defect was deleted, it cannot be updated anymore.
        DataStore store = DataStore.getInstance();
        String defectId = segement.getPath();
        DefectBean defect = store.getDefect(defectId);
        if (defect == null) {
            throw new WebApplicationException(new RuntimeException("Defect " + defectId
                + " not found"), Response.Status.NOT_FOUND);
        }

        // validate that user didn't send deleted flag, since it will mark
        // defect as deleted.
        // to delete a defect, DELETE http method should be used
        defect = asset.getDefect();
        defect.setDeleted(false);

        // set Id in the asset for cases that element <id> is missing
        // in the request body
        defect.setId(defectId);

        // update defect legacy bean to the memory store
        store.putDefect(defectId, defect);

        return asset;
    }

    /**
     * Handles DELETE requests for deleting an existing defect.
     * <p>
     * The <code>defectRevision</code> parameter of the method exists to make
     * sure that no revision was specified in the delete request.
     *
     * @return DefectAsset with the deleted defect
     */
    @Path(DEFECT_URL)
    @DELETE
    @Produces( {MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON,
        MediaType.APPLICATION_XML})
    public Object deleteDocument(@PathParam(DEFECT_VAR) PathSegment segement,
                                 @MatrixParam(REVISION) @DefaultValue("-1") int defectRevision) {
        if (defectRevision != -1) {
            // it's impossible to update a specific revision
            throw new WebApplicationException(HttpStatus.METHOD_NOT_ALLOWED.getCode());
        }

        // obtain data object from memory store
        // if the object was already deleted, null will be returned
        DataStore store = DataStore.getInstance();
        String defectId = segement.getPath();
        DefectBean defect = store.getDefect(defectId);
        if (defect == null) {
            throw new WebApplicationException(new RuntimeException("Defect " + defectId
                + " not found"), Response.Status.NOT_FOUND);
        }

        // remove defect legacy bean from memory store
        store.deleteDefect(defectId);

        return new DefectAsset(defect);
    }
}
TOP

Related Classes of org.apache.wink.example.history.resources.DefectsResource

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.