package org.axway.grapes.server.webapp.resources;
import com.google.common.collect.Lists;
import com.yammer.dropwizard.auth.Auth;
import org.axway.grapes.commons.api.ServerAPI;
import org.axway.grapes.server.config.GrapesServerConfig;
import org.axway.grapes.server.core.ModuleHandler;
import org.axway.grapes.server.db.RepositoryHandler;
import org.axway.grapes.server.db.datamodel.DbCredential;
import org.axway.grapes.server.db.datamodel.DbProduct;
import org.axway.grapes.server.webapp.views.ListView;
import org.axway.grapes.server.webapp.views.ProductView;
import org.eclipse.jetty.http.HttpStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Product Resource
*
* <p>This server resource handles all the request about products.<br/>
* This resource extends DepManViews to holds its own documentation.
* The documentation is available in ProductResourceDocumentation.ftl file.</p>
* @author jdcoffre
*/
@Path(ServerAPI.PRODUCT_RESOURCE)
public class ProductResource extends AbstractResource {
private static final Logger LOG = LoggerFactory.getLogger(ProductResource.class);
public ProductResource(final RepositoryHandler repositoryHandler, final GrapesServerConfig configuration) {
super(repositoryHandler, "ProductResourceDocumentation.ftl", configuration);
}
/**
* Handle product posts when the server got a request POST /product & MIME that contains an organization.
*
* @param productName String Product's name to add to Grapes database
* @return Response An acknowledgment:<br/>- 400 if the MIME is malformed<br/>- 409 if product is already existing<br/>- 500 if internal error<br/>- 201 if ok
*/
@POST
public Response createProduct(@Auth final DbCredential credential, final String productName){
if(!credential.getRoles().contains(DbCredential.AvailableRoles.DATA_UPDATER)){
throw new WebApplicationException(Response.status(Response.Status.UNAUTHORIZED).build());
}
LOG.info("Got a create product request.");
if(productName == null || productName.isEmpty()){
throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST).entity("Product name should neither be null nor empty.").build());
}
final DbProduct dbProduct = new DbProduct();
dbProduct.setName(productName);
getProductHandler().create(dbProduct);
return Response.ok().status(HttpStatus.CREATED_201).build();
}
/**
* Return the list of available product name.
* This method is call via GET <dm_url>/product/names
*
* @return Response A list of product name in HTML or JSON
*/
@GET
@Produces({MediaType.TEXT_HTML, MediaType.APPLICATION_JSON})
@Path(ServerAPI.GET_NAMES)
public Response getNames(){
LOG.info("Got a get product names request.");
final ListView view = new ListView("Product Ids list", "Products");
final List<String> names = getProductHandler().getProductNames();
Collections.sort(names);
view.addAll(names);
return Response.ok(view).build();
}
/**
* Returns a product
*
* @param name String
* @return Response A product in HTML
*/
@GET
@Produces(MediaType.TEXT_HTML)
@Path("/{name}")
public Response get(@PathParam("name") final String name){
LOG.info("Got a get product request.");
final DbProduct dbProduct = getProductHandler().getProduct(name);
final ProductView view = new ProductView(dbProduct);
return Response.ok(view).build();
}
/**
* Delete a product
*
* @param credential DbCredential
* @param name String product name
* @return Response
*/
@DELETE
@Path("/{name}")
public Response delete(@Auth final DbCredential credential, @PathParam("name") final String name){
if(!credential.getRoles().contains(DbCredential.AvailableRoles.DATA_DELETER)){
throw new WebApplicationException(Response.status(Response.Status.UNAUTHORIZED).build());
}
LOG.info("Got a delete organization request.");
getProductHandler().deleteProduct(name);
return Response.ok("done").build();
}
/**
* Get the project configured list of module names
*
* @return Response
*/
@GET
@Path("/{name}" + ServerAPI.GET_MODULES)
@Produces(MediaType.APPLICATION_JSON)
public Response getModuleNames(@PathParam("name") final String name){
LOG.info("Got a get module names for organization " + name +".");
final DbProduct dbProduct = getProductHandler().getProduct(name);
return Response.ok(dbProduct.getModules()).build();
}
/**
* Sets a list of module names to a product
*
* @param credential DbCredential
* @param name String product name
* @param moduleNames List<String>
* @return Response
*/
@POST
@Path("/{name}" + ServerAPI.GET_MODULES)
public Response setModuleNames(@Auth final DbCredential credential, @PathParam("name") final String name, final List<String> moduleNames){
if(!credential.getRoles().contains(DbCredential.AvailableRoles.DATA_UPDATER)){
throw new WebApplicationException(Response.status(Response.Status.UNAUTHORIZED).build());
}
LOG.info("Got a set module names request for product " + name +".");
if(moduleNames == null){
throw new WebApplicationException(Response.serverError().status(HttpStatus.BAD_REQUEST_400)
.entity("Query content should contains a list of module names.").build());
}
Collections.sort(moduleNames);
getProductHandler().setProductModules(name, moduleNames);
return Response.ok().build();
}
/**
* Returns the list of existing deliveries of a product
*
* @param name String product name
* @return Response
*/
@GET
@Path("/{name}" + ServerAPI.GET_DELIVERIES)
@Produces(MediaType.APPLICATION_JSON)
public Response getDeliveries(@PathParam("name") final String name){
LOG.info("Got a get deliveries request for product " + name +".");
final DbProduct dbProduct = getProductHandler().getProduct(name);
final List<String> deliveryNames = Lists.newArrayList(dbProduct.getDeliveries().keySet());
Collections.sort(deliveryNames);
return Response.ok(deliveryNames).build();
}
/**
* Create a product delivery
*
* @param credential DbCredential
* @param name String product name
* @param deliveryName String
* @return Response
*/
@POST
@Path("/{name}" + ServerAPI.GET_DELIVERIES)
public Response createNewDelivery(@Auth final DbCredential credential, @PathParam("name") final String name, final String deliveryName){
if(!credential.getRoles().contains(DbCredential.AvailableRoles.DATA_UPDATER)){
throw new WebApplicationException(Response.status(Response.Status.UNAUTHORIZED).build());
}
LOG.info("Got a create delivery request for product " + name +".");
if(deliveryName == null || deliveryName.isEmpty()){
throw new WebApplicationException(Response.serverError().status(HttpStatus.BAD_REQUEST_400)
.entity("Query content should contains the name of the new delivery.").build());
}
final DbProduct dbProduct = getProductHandler().getProduct(name);
if(dbProduct.getDeliveries().containsKey(deliveryName)){
throw new WebApplicationException(Response.serverError().status(HttpStatus.CONFLICT_409)
.entity("Delivery " + deliveryName + " already exist for product "+ name + ".").build());
}
dbProduct.getDeliveries().put(deliveryName, new ArrayList<String>());
getProductHandler().update(dbProduct);
return Response.ok().status(Response.Status.CREATED).build();
}
/**
* Returns the list of module ids embedded inside a delivery
*
* @param name String product name
* @param delivery String delivery name
* @return Response
*/
@GET
@Path("/{name}" + ServerAPI.GET_DELIVERIES+"/{delivery}")
@Produces(MediaType.APPLICATION_JSON)
public Response getDelivery(@PathParam("name") final String name, @PathParam("delivery") final String delivery){
LOG.info("Got a get delivery request for product " + name +".");
final DbProduct dbProduct = getProductHandler().getProduct(name);
final List<String> modules = dbProduct.getDeliveries().get(delivery);
if(modules == null){
throw new WebApplicationException(Response.serverError().status(HttpStatus.NOT_FOUND_404)
.entity("Delivery " + delivery + " does not exist for product "+ name + ".").build());
}
Collections.sort(modules);
return Response.ok(modules).build();
}
/**
* Delete a delivery
*
* @param credential DbCredential
* @param name String product name
* @param delivery String delivery name
* @return Response
*/
@DELETE
@Path("/{name}" + ServerAPI.GET_DELIVERIES+"/{delivery}")
@Produces(MediaType.APPLICATION_JSON)
public Response deleteDelivery(@Auth final DbCredential credential, @PathParam("name") final String name, @PathParam("delivery") final String delivery){
if(!credential.getRoles().contains(DbCredential.AvailableRoles.DATA_DELETER)){
throw new WebApplicationException(Response.status(Response.Status.UNAUTHORIZED).build());
}
LOG.info("Got a delete delivery request for product " + name +".");
final DbProduct dbProduct = getProductHandler().getProduct(name);
if(! dbProduct.getDeliveries().containsKey(delivery)){
throw new WebApplicationException(Response.serverError().status(HttpStatus.NOT_FOUND_404)
.entity("Delivery " + delivery + " does not exist for product "+ name + ".").build());
}
dbProduct.getDeliveries().remove(delivery);
getProductHandler().update(dbProduct);
return Response.ok().build();
}
/**
* Sets the exhaustive list of modules that are embedded in a delivery
*
* @param credential DbCredential
* @param name String product name
* @param delivery String delivery name
* @param modules List<String> list of modules Ids
* @return Response
*/
@POST
@Path("/{name}" + ServerAPI.GET_DELIVERIES+"/{delivery}")
@Produces(MediaType.APPLICATION_JSON)
public Response setDelivery(@Auth final DbCredential credential, @PathParam("name") final String name, @PathParam("delivery") final String delivery, final List<String> modules){
if(!credential.getRoles().contains(DbCredential.AvailableRoles.DATA_UPDATER)){
throw new WebApplicationException(Response.status(Response.Status.UNAUTHORIZED).build());
}
LOG.info("Got a set delivery modules request for product " + name +".");
final DbProduct dbProduct = getProductHandler().getProduct(name);
if(dbProduct.getDeliveries().get(delivery) == null){
throw new WebApplicationException(Response.serverError().status(HttpStatus.NOT_FOUND_404)
.entity("Delivery " + delivery + " does not exist for product "+ name + ".").build());
}
// Check that modules exists
final ModuleHandler moduleHandler = getModuleHandler();
for(String moduleId: modules){
moduleHandler.getModule(moduleId);
}
Collections.sort(modules);
dbProduct.getDeliveries().put(delivery, modules);
getProductHandler().update(dbProduct);
return Response.ok().status(Response.Status.CREATED).build();
}
}