Package org.candlepin.resource

Source Code of org.candlepin.resource.ProductResource

/**
* Copyright (c) 2009 - 2012 Red Hat, Inc.
*
* This software is licensed to you under the GNU General Public License,
* version 2 (GPLv2). There is NO WARRANTY for this software, express or
* implied, including the implied warranties of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
* along with this software; if not, see
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
*
* Red Hat trademarks are not licensed under GPLv2. No permission is
* granted to use or replicate Red Hat trademarks that are incorporated
* in this software or its documentation.
*/
package org.candlepin.resource;

import org.candlepin.auth.interceptor.SecurityHole;
import org.candlepin.auth.interceptor.Verify;
import org.candlepin.common.exceptions.BadRequestException;
import org.candlepin.common.exceptions.NotFoundException;
import org.candlepin.model.Content;
import org.candlepin.model.ContentCurator;
import org.candlepin.model.Owner;
import org.candlepin.model.OwnerCurator;
import org.candlepin.model.Product;
import org.candlepin.model.ProductCertificate;
import org.candlepin.model.ProductContent;
import org.candlepin.model.Statistic;
import org.candlepin.model.StatisticCurator;
import org.candlepin.pinsetter.tasks.RefreshPoolsForProductJob;
import org.candlepin.resource.util.ResourceDateParser;
import org.candlepin.service.ProductServiceAdapter;

import com.google.inject.Inject;

import org.quartz.JobDetail;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xnap.commons.i18n.I18n;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
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.core.MediaType;

/**
* API Gateway into /product
*
* @version $Rev$
*/
@Path("/products")
public class ProductResource {

    private static Logger log = LoggerFactory.getLogger(ProductResource.class);
    private ProductServiceAdapter prodAdapter;
    private ContentCurator contentCurator;
    private StatisticCurator statisticCurator;
    private OwnerCurator ownerCurator;
    private I18n i18n;

    /**
     * default ctor
     *
     * @param prodAdapter
     *            Product Adapter used to interact with multiple services.
     */
    @Inject
    public ProductResource(ProductServiceAdapter prodAdapter,
                           StatisticCurator statisticCurator,
                           ContentCurator contentCurator,
                           OwnerCurator ownerCurator,
                           I18n i18n) {
        this.prodAdapter = prodAdapter;
        this.contentCurator = contentCurator;
        this.statisticCurator = statisticCurator;
        this.ownerCurator = ownerCurator;
        this.i18n = i18n;
    }

    /**
     * Retrieves a list of Products
     *
     * @param productIds if specified, the list of product ids to return product info for
     * @return a list of Product objects
     * @httpcode 200
     */
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public List<Product> list(@QueryParam("product") List<String> productIds) {
        return productIds.isEmpty() ?
            prodAdapter.getProducts() :
            prodAdapter.getProductsByIds(productIds);
    }

    /**
     * Retrieves a single Product
     * <p>
     * <pre>
     * {
     *   "id" : "product_id",
     *   "name" : "product_name",
     *   "multiplier" : 1,
     *   "attributes" : [ {
     *     "name" : "version",
     *     "value" : "1.0",
     *     "created" : [date],
     *     "updated" : [date]
     *   } ],
     *   "productContent" : [ ],
     *   "dependentProductIds" : [ ],
     *   "href" : "/products/product_id",
     *   "created" : [date],
     *   "updated" : [date]
     * }
     * </pre>
     *
     * @param pid uuid of the product sought.
     * @return a Product object
     * @httpcode 404
     * @httpcode 200
     */
    @GET
    @Path("/{product_uuid}")
    @Produces(MediaType.APPLICATION_JSON)
    @SecurityHole
    public Product getProduct(@PathParam("product_uuid") String pid) {
        Product toReturn = prodAdapter.getProductById(pid);

        if (toReturn != null) {
            return toReturn;
        }

        throw new NotFoundException(
            i18n.tr("Product with UUID ''{0}'' could not be found.", pid));
    }

    /**
     * Retreives a Certificate for a Product
     *
     * @return a ProductCertificate object
     * @httpcode 404
     * @httpcode 200
     */
    @GET
    @Path("/{product_uuid}/certificate")
    @Produces(MediaType.APPLICATION_JSON)
    @SecurityHole
    public ProductCertificate getProductCertificate(
        @PathParam("product_uuid") String productId) {

        Product product = prodAdapter.getProductById(productId);

        if (product == null) {
            throw new NotFoundException(
                i18n.tr("Product with UUID ''{0}'' could not be found.", productId));
        }

        return prodAdapter.getProductCertificate(product);
    }

    /**
     * Creates a Product
     * <p>
     * Returns either the new created Product or the Product that already existed.
     *
     * @param product
     * @return a Product object
     * @httpcode 200
     */
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public Product createProduct(Product product) {
        return prodAdapter.createProduct(product);
    }

    /**
     * Updates a Product
     *
     * @return a Product object
     * @httpcode 400
     * @httpcode 200
     */
    @PUT
    @Path("/{product_uuid}")
    @Produces(MediaType.APPLICATION_JSON)
    public Product updateProduct(
        @PathParam("product_uuid") @Verify(Product.class) String productId,
        Product product) {
        Product toUpdate = getProduct(productId);

        if (performProductUpdates(toUpdate, product)) {
            this.prodAdapter.mergeProduct(toUpdate);
        }

        return toUpdate;
    }

    protected boolean performProductUpdates(Product existing, Product incoming) {
        boolean changesMade = false;

        if (incoming.getName() != null && !existing.getName().equals(incoming.getName()) &&
            !incoming.getName().isEmpty()) {

            log.debug("Updating product name");
            changesMade = true;
            existing.setName(incoming.getName());
        }

        if (incoming.getAttributes() != null &&
            !existing.getAttributes().equals(incoming.getAttributes())) {

            log.debug("Updating product attributes");

            // clear and addall here instead of replacing instance so there are no
            // dangling memory references
            existing.getAttributes().clear();
            existing.getAttributes().addAll(incoming.getAttributes());
            changesMade = true;
        }

        if (incoming.getDependentProductIds() != null &&
            !existing.getDependentProductIds().equals(incoming.getDependentProductIds())) {

            log.debug("Updating dependent product ids");

            // clear and addall here instead of replacing instance so there are no
            // dangling memory references
            existing.getDependentProductIds().clear();
            existing.getDependentProductIds().addAll(incoming.getDependentProductIds());
            changesMade = true;
        }

        if (incoming.getMultiplier() != null &&
            existing.getMultiplier().longValue() != incoming.getMultiplier().longValue()) {

            log.debug("Updating product multiplier");
            changesMade = true;
            existing.setMultiplier(incoming.getMultiplier());
        }

        // not calling setHref() it's a no op and pointless to call.

        return changesMade;
    }

    /**
     * Adds Content to a Product
     * <p>
     * Batch mode
     *
     * @return a Product object
     * @httpcode 200
     */
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    @Path("/{product_uuid}/batch_content")
    public Product addBatchContent(@PathParam("product_uuid") String pid,
                              Map<String, Boolean> contentMap) {
        Product product = prodAdapter.getProductById(pid);
        for (Entry<String, Boolean> entry : contentMap.entrySet()) {
            Content content = contentCurator.find(entry.getKey());
            ProductContent productContent = new ProductContent(product, content,
                entry.getValue());
            product.getProductContent().add(productContent);
        }
        return prodAdapter.getProductById((product.getId()));
    }

    /**
     * Adds Content to a Product
     * <p>
     * Single mode
     *
     * @return a Product object
     * @httpcode 200
     */
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Path("/{product_uuid}/content/{content_id}")
    public Product addContent(@PathParam("product_uuid") String pid,
                              @PathParam("content_id") String contentId,
                              @QueryParam("enabled") Boolean enabled) {
        Product product = prodAdapter.getProductById(pid);
        Content content = contentCurator.find(contentId);

        ProductContent productContent = new ProductContent(product, content, enabled);
        product.getProductContent().add(productContent);
        return prodAdapter.getProductById((product.getId()));
    }

    /**
     * Removes Content from a Product
     *
     * @httpcode 200
     */
    @DELETE
    @Produces(MediaType.APPLICATION_JSON)
    @Path("/{product_uuid}/content/{content_id}")
    public void removeContent(@PathParam("product_uuid") String pid,
                              @PathParam("content_id") String contentId) {
        prodAdapter.removeContent(pid, contentId);
    }

    /**
     * Removes a Product
     *
     * @httpcode 400
     * @httpcode 404
     * @httpcode 200
     */
    @DELETE
    @Produces(MediaType.APPLICATION_JSON)
    @Path("/{product_uuid}")
    public void deleteProduct(@PathParam("product_uuid") String pid) {
        Product product = prodAdapter.getProductById(pid);
        if (product == null) {
            throw new NotFoundException(
                i18n.tr("Product with UUID ''{0}'' could not be found.", pid));
        }
        if (prodAdapter.productHasSubscriptions(product)) {
            throw new BadRequestException(
                i18n.tr("Product with UUID ''{0}'' cannot be deleted " +
                    "while subscriptions exist.", pid));
        }

        prodAdapter.deleteProduct(product);
    }

    /**
     * Retrieves a list of Statistics for a Product
     *
     * @return a list of Statistic objects
     * @httpcode 400
     * @httpcode 200
     */
    @GET
    @Path("/{prod_id}/statistics")
    @Produces(MediaType.APPLICATION_JSON)
    public List<Statistic> getProductStats(@PathParam("prod_id") String id,
                            @QueryParam("from") String from,
                            @QueryParam("to") String to,
                            @QueryParam("days") String days) {

        return statisticCurator.getStatisticsByProduct(id, null,
                                ResourceDateParser.getFromDate(from, to, days),
                                ResourceDateParser.parseDateString(to));
    }

    /**
     * Retrieves a list of Statistics for a Product
     * <p>
     * By Statistic type
     *
     * @return a list of Statistic objects
     * @httpcode 400
     * @httpcode 200
     */
    @GET
    @Path("/{prod_id}/statistics/{vtype}")
    @Produces(MediaType.APPLICATION_JSON)
    public List<Statistic> getProductStats(@PathParam("prod_id") String id,
                            @PathParam("vtype") String valueType,
                            @QueryParam("from") String from,
                            @QueryParam("to") String to,
                            @QueryParam("days") String days) {

        return statisticCurator.getStatisticsByProduct(id, valueType,
                                ResourceDateParser.getFromDate(from, to, days),
                                ResourceDateParser.parseDateString(to));
    }

    /**
     * Retrieves a list of Owners by Product
     *
     * @return a list of Owner objects
     * @httpcode 200
     * @httpcode 400
     */
    @GET
    @Path("/owners")
    @Produces(MediaType.APPLICATION_JSON)
    public List<Owner> getActiveProductOwners(@QueryParam("product") String[] productIds) {
        List<String> ids = Arrays.asList(productIds);
        if (ids.isEmpty()) {
            throw new BadRequestException(i18n.tr("Must specify product ID."));
        }

        return ownerCurator.lookupOwnersByActiveProduct(ids);
    }

    /**
     * Refreshes Pools by Product
     *
     * @param pid
     * @param lazyRegen
     * @return a JobDetail object
     */
    @PUT
    @Path("/{product_uuid}/subscriptions")
    @Produces(MediaType.APPLICATION_JSON)
    public JobDetail refreshPoolsForProduct(
        @PathParam("product_uuid") String pid,
        @QueryParam("lazy_regen") @DefaultValue("true") Boolean lazyRegen) {

        Product product = prodAdapter.getProductById(pid);
        if (product == null) {
            throw new NotFoundException(
                i18n.tr("Product with UUID ''{0}'' could not be found.", pid));
        }

        return RefreshPoolsForProductJob.forProduct(product, lazyRegen);
    }
}
TOP

Related Classes of org.candlepin.resource.ProductResource

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.