Package org.apache.wink.example.locking.resources

Source Code of org.apache.wink.example.locking.resources.DefectResource

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

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collection;
import java.util.Date;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
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.EntityTag;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.Response.Status;

import org.apache.wink.common.annotations.Workspace;
import org.apache.wink.example.locking.legacy.DefectBean;
import org.apache.wink.example.locking.legacy.DefectsBean;
import org.apache.wink.example.locking.store.DataStore;

/**
* <p>
* This example demonstrates usage of Preconditions to create an <a
* href="http://en.wikipedia.org/wiki/Optimistic_concurrency_control">Optimistic
* Concurrency Control</a> functionality.
*/
@Path("defects")
@Workspace(workspaceTitle = "QA Defects", collectionTitle = "Defects")
public class DefectResource {

    public static final String DEFECT     = "defect";
    public static final String DEFECT_URL = "/{" + DEFECT + "}";

    /**
     * memory store
     */
    private DataStore          store      = DataStore.getInstance();

    /**
     * Returns the collection of defects.
     * <p>
     * If the store wasn't modified from the last call, the method returns 304
     * (NOT_MODIFIED).
     */
    @GET
    @Produces(MediaType.APPLICATION_XML)
    public Response getDefectsCollection(@Context Request request) {

        // verify that the store was modified since the last call
        Date lastModifiedIgnoreMillis = store.getLastModifiedIgnoreMillis();
        ResponseBuilder precondition = request.evaluatePreconditions(lastModifiedIgnoreMillis);
        if (precondition != null) {
            // the collection wasn't modified, 304 will be returned
            return precondition.build();
        }

        // the collection was modified, retrieve it from the store
        Collection<DefectBean> defects = store.getDefects();

        // return the collection and add its last modified date on the response
        return Response.ok(new DefectsBean(defects)).lastModified(lastModifiedIgnoreMillis).build();
    }

    /**
     * Returns a single defect.
     * <p>
     * If the defect with the given id doesn't exist in the store, 404 NOT_FOUND
     * is returned
     * <p>
     * If IF_NONE_MATCH header present, the defect will be returned only if it
     * was modified since the previous call.
     */
    @GET
    @Path(DEFECT_URL)
    @Produces(MediaType.APPLICATION_XML)
    public Response getDefect(@Context Request request, @PathParam(DEFECT) String defectId) {

        // get defect from the store
        DefectBean bean = store.getDefect(defectId);
        if (bean == null) {
            // defect was not found
            return Response.status(Status.NOT_FOUND).build();
        }

        // create defect's etag
        EntityTag defectBeanEtag = new EntityTag(String.valueOf(bean.hashCode()));

        // evaluate the precondition
        ResponseBuilder precondition = request.evaluatePreconditions(defectBeanEtag);
        if (precondition != null) {
            // defect was not modified, return 304
            return precondition.build();
        }

        // create response the defect and its entity tag
        return Response.ok(bean).tag(defectBeanEtag).build();
    }

    /**
     * Adds a new defect to the collection. The created defect is returned along
     * with its etag to the client.
     */
    @POST
    @Consumes(MediaType.APPLICATION_XML)
    @Produces(MediaType.APPLICATION_XML)
    public Response addDefect(@Context UriInfo uriInfo, DefectBean bean) throws IOException,
        URISyntaxException {

        // verify that bean was sent
        if (bean == null) {
            throw new WebApplicationException(Status.BAD_REQUEST);
        }

        // set unique Id in the new defect bean:
        // - Id in the input data is ignored, actually there should be no Id
        // there,
        bean.setId(store.getDefectUniqueId());

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

        // header Location (absolute URI) must exist on the response in case of
        // status code 201
        URI location = new URI(uriInfo.getAbsolutePath() + "/" + bean.getId());

        // create entity tag, so the Client can use it for OCC
        EntityTag entityTag = new EntityTag(String.valueOf(bean.hashCode()));

        return Response.status(Status.CREATED).entity(bean).location(location).tag(entityTag)
            .build();
    }

    /**
     * Updates defect.
     * <p>
     * The defect is updated only if the If-Match header is present and
     * evaluation of precondition succeeds. This is done to ensure the OCC.
     */
    @PUT
    @Path(DEFECT_URL)
    @Consumes(MediaType.APPLICATION_XML)
    @Produces(MediaType.APPLICATION_XML)
    public Response updateDefect(@Context Request request,
                                 @PathParam(DEFECT) String defectId,
                                 @HeaderParam(HttpHeaders.IF_MATCH) String ifMatchHeader,
                                 DefectBean updatedBean) throws IOException {

        if (ifMatchHeader == null) {
            // IF-MATCH header wasn't sent, cannot validate the precondition
            throw new WebApplicationException(Status.BAD_REQUEST);
        }

        // obtain data object from the memory store
        DefectBean bean = store.getDefect(defectId);
        if (bean == null) {
            // not found, return 404
            throw new WebApplicationException(Status.NOT_FOUND);
        }

        // create defect's etag
        EntityTag defectBeanEtag = new EntityTag(String.valueOf(bean.hashCode()));

        ResponseBuilder preconditions = request.evaluatePreconditions(defectBeanEtag);
        if (preconditions != null) {
            return preconditions.build();
        }

        updatedBean.setId(defectId);

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

        Response response =
            Response.ok(updatedBean).tag(new EntityTag(String.valueOf(updatedBean.hashCode())))
                .build();
        return response;
    }

    /**
     * Deletes defect.
     * <p>
     * The defect is deleted only if If-Match is present and valid to ensure
     * OCC.
     */
    @DELETE
    @Path(DEFECT_URL)
    @Produces(MediaType.APPLICATION_XML)
    public Object deleteDocument(@Context Request request,
                                 @PathParam(DEFECT) String defectId,
                                 @HeaderParam(HttpHeaders.IF_MATCH) String ifMatchHeader) {

        if (ifMatchHeader == null) {
            // IF-MATCH header wasn't sent, cannot validate the precondition
            throw new WebApplicationException(Status.BAD_REQUEST);
        }

        // obtain data object from memory store
        DefectBean bean = store.getDefect(defectId);
        if (bean == null) {
            // defect not found, return 404
            throw new WebApplicationException(Status.NOT_FOUND);
        }

        // create defect's etag
        EntityTag defectBeanEtag = new EntityTag(String.valueOf(bean.hashCode()), false);

        ResponseBuilder preconditions = request.evaluatePreconditions(defectBeanEtag);
        if (preconditions != null) {
            return preconditions.build();
        }

        return store.removeDefect(defectId);
    }

}
TOP

Related Classes of org.apache.wink.example.locking.resources.DefectResource

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.