From 389d168637baac3b946d95dade62029acd517fba Mon Sep 17 00:00:00 2001 From: Luca Frosini Date: Tue, 7 Mar 2023 15:19:21 +0100 Subject: [PATCH] Defined REST interface --- pom.xml | 2 +- .../grsf/publisher/annotation/PATCH.java | 17 ++ .../grsf/publisher/annotation/PURGE.java | 17 ++ .../gcube/grsf/publisher/record/Fishery.java | 4 +- .../gcube/grsf/publisher/record/Record.java | 76 ++++++++- .../gcube/grsf/publisher/record/Stock.java | 4 +- .../publisher/record/TraceabilityUnit.java | 1 - .../grsf/publisher/rest/BaseRESTAPIs.java | 106 ++++++++++++- .../grsf/publisher/rest/FisheryRESTAPIs.java | 149 +++++++++++++++++- .../grsf/publisher/rest/StockRESTAPIs.java | 130 +++++++++++++-- .../rest/TraceabilityUnitRESTAPIs.java | 149 +++++++++++++++++- 11 files changed, 629 insertions(+), 26 deletions(-) create mode 100644 src/main/java/org/gcube/grsf/publisher/annotation/PATCH.java create mode 100644 src/main/java/org/gcube/grsf/publisher/annotation/PURGE.java diff --git a/pom.xml b/pom.xml index 83fbfe1..8ca03af 100644 --- a/pom.xml +++ b/pom.xml @@ -65,7 +65,7 @@ org.gcube.data-catalogue gcat-api - [2.3.2, 3.0.0-SNAPSHOT) + [2.3.2-SNAPSHOT, 3.0.0-SNAPSHOT) org.glassfish.jersey.containers diff --git a/src/main/java/org/gcube/grsf/publisher/annotation/PATCH.java b/src/main/java/org/gcube/grsf/publisher/annotation/PATCH.java new file mode 100644 index 0000000..3329741 --- /dev/null +++ b/src/main/java/org/gcube/grsf/publisher/annotation/PATCH.java @@ -0,0 +1,17 @@ +package org.gcube.grsf.publisher.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import javax.ws.rs.HttpMethod; + +/** + * @author Luca Frosini (ISTI - CNR) + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@HttpMethod("PATCH") +public @interface PATCH { +} \ No newline at end of file diff --git a/src/main/java/org/gcube/grsf/publisher/annotation/PURGE.java b/src/main/java/org/gcube/grsf/publisher/annotation/PURGE.java new file mode 100644 index 0000000..ded8fa5 --- /dev/null +++ b/src/main/java/org/gcube/grsf/publisher/annotation/PURGE.java @@ -0,0 +1,17 @@ +package org.gcube.grsf.publisher.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import javax.ws.rs.HttpMethod; + +/** + * @author Luca Frosini (ISTI - CNR) + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@HttpMethod("PURGE") +public @interface PURGE { +} \ No newline at end of file diff --git a/src/main/java/org/gcube/grsf/publisher/record/Fishery.java b/src/main/java/org/gcube/grsf/publisher/record/Fishery.java index 7342747..f3d236b 100644 --- a/src/main/java/org/gcube/grsf/publisher/record/Fishery.java +++ b/src/main/java/org/gcube/grsf/publisher/record/Fishery.java @@ -1,6 +1,5 @@ package org.gcube.grsf.publisher.record; -import org.gcube.com.fasterxml.jackson.databind.JsonNode; import org.gcube.com.fasterxml.jackson.databind.node.TextNode; /** @@ -8,8 +7,7 @@ import org.gcube.com.fasterxml.jackson.databind.node.TextNode; */ public class Fishery extends Record { - public Fishery(JsonNode jsonNode) { - super(jsonNode); + public Fishery() { TextNode textNode = new TextNode("Fishery"); addProperty(SOURCE_KEY, textNode); } diff --git a/src/main/java/org/gcube/grsf/publisher/record/Record.java b/src/main/java/org/gcube/grsf/publisher/record/Record.java index 42d6c19..8614eb4 100644 --- a/src/main/java/org/gcube/grsf/publisher/record/Record.java +++ b/src/main/java/org/gcube/grsf/publisher/record/Record.java @@ -6,6 +6,9 @@ import java.util.Iterator; import java.util.Map; import java.util.Set; +import javax.ws.rs.InternalServerErrorException; +import javax.ws.rs.core.UriInfo; + import org.gcube.com.fasterxml.jackson.databind.JsonNode; import org.gcube.com.fasterxml.jackson.databind.ObjectMapper; import org.gcube.grsf.publisher.record.property.Property; @@ -22,6 +25,10 @@ public class Record { public static final String DOMAIN_KEY = "Domain"; public static final String SOURCE_KEY = "Source"; + protected UriInfo uriInfo; + + protected String id; + protected ObjectMapper objectMapper; protected JsonNode jsonNode; @@ -30,9 +37,8 @@ public class Record { protected Set tags; protected Set resources; - public Record(JsonNode jsonNode) { + public Record() { this.objectMapper = new ObjectMapper(); - this.jsonNode = jsonNode; this.properties = new HashMap<>(); this.groups = new HashSet<>(); this.tags = new HashSet<>(); @@ -51,6 +57,18 @@ public class Record { this.tags.add(tag); } + public void setId(String id) { + this.id = id; + } + + public String getId() { + return this.id; + } + + public void setUriInfo(UriInfo uriInfo) { + this.uriInfo = uriInfo; + } + public void elaborate() { Iterator iterator = jsonNode.fieldNames(); while(iterator.hasNext()) { @@ -70,5 +88,59 @@ public class Record { } } + + public String list(int limit, int offset) { + // TODO + return null; + } + + public String create(String json) { + try { + this.jsonNode = objectMapper.readTree(json); + } catch (Exception e) { + throw new InternalServerErrorException(e); + } + elaborate(); + // TODO + return null; + } + + public String update(String json) { + try { + this.jsonNode = objectMapper.readTree(json); + } catch (Exception e) { + throw new InternalServerErrorException(e); + } + elaborate(); + // TODO + return null; + } + + public String patch(String json) { + try { + this.jsonNode = objectMapper.readTree(json); + } catch (Exception e) { + throw new InternalServerErrorException(e); + } + elaborate(); + // TODO + return null; + } + + public void delete(Boolean purge) { + // TODO + } + + public String read() { + // TODO + return null; + } + + + + public int count() { + // TODO + return 0; + } } diff --git a/src/main/java/org/gcube/grsf/publisher/record/Stock.java b/src/main/java/org/gcube/grsf/publisher/record/Stock.java index 5ba8420..4e6241e 100644 --- a/src/main/java/org/gcube/grsf/publisher/record/Stock.java +++ b/src/main/java/org/gcube/grsf/publisher/record/Stock.java @@ -1,6 +1,5 @@ package org.gcube.grsf.publisher.record; -import org.gcube.com.fasterxml.jackson.databind.JsonNode; import org.gcube.com.fasterxml.jackson.databind.node.TextNode; /** @@ -8,8 +7,7 @@ import org.gcube.com.fasterxml.jackson.databind.node.TextNode; */ public class Stock extends Record { - public Stock (JsonNode jsonNode) { - super(jsonNode); + public Stock () { TextNode textNode = new TextNode("Stock"); addProperty(SOURCE_KEY, textNode); } diff --git a/src/main/java/org/gcube/grsf/publisher/record/TraceabilityUnit.java b/src/main/java/org/gcube/grsf/publisher/record/TraceabilityUnit.java index d4f2bfe..630794a 100644 --- a/src/main/java/org/gcube/grsf/publisher/record/TraceabilityUnit.java +++ b/src/main/java/org/gcube/grsf/publisher/record/TraceabilityUnit.java @@ -9,7 +9,6 @@ import org.gcube.com.fasterxml.jackson.databind.node.TextNode; public class TraceabilityUnit extends Record { public TraceabilityUnit(JsonNode jsonNode) { - super(jsonNode); TextNode textNode = new TextNode("Traceability Unit"); addProperty(SOURCE_KEY, textNode); } diff --git a/src/main/java/org/gcube/grsf/publisher/rest/BaseRESTAPIs.java b/src/main/java/org/gcube/grsf/publisher/rest/BaseRESTAPIs.java index 313b5f3..473d6b1 100644 --- a/src/main/java/org/gcube/grsf/publisher/rest/BaseRESTAPIs.java +++ b/src/main/java/org/gcube/grsf/publisher/rest/BaseRESTAPIs.java @@ -1,11 +1,17 @@ package org.gcube.grsf.publisher.rest; +import javax.ws.rs.InternalServerErrorException; +import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Context; import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.ResponseBuilder; +import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.UriInfo; import org.gcube.common.authorization.library.provider.CalledMethodProvider; +import org.gcube.gcat.api.GCatConstants; +import org.gcube.grsf.publisher.record.Record; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -18,7 +24,7 @@ import com.webcohesion.enunciate.metadata.rs.RequestHeaders; @RequestHeaders ({ @RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources") }) -public class BaseRESTAPIs { +public class BaseRESTAPIs { private final Logger logger = LoggerFactory.getLogger(this.getClass()); @@ -30,6 +36,17 @@ public class BaseRESTAPIs { protected static final String LOCATION_HEADER = "Location"; + protected final String COLLECTION_PARAMETER; + protected final String ID_PARAMETER; + protected final Class reference; + + public BaseRESTAPIs(String collectionName, String recordID, Class reference) { + this.COLLECTION_PARAMETER = collectionName; + this.ID_PARAMETER = recordID; + this.reference = reference; + } + + protected void setCalledMethod(String method) { CalledMethodProvider.instance.set(method); logger.info("{}", uriInfo.getAbsolutePath()); @@ -40,5 +57,92 @@ public class BaseRESTAPIs { String.format("%s/%s", uriInfo.getAbsolutePath().toString(), id)); } + + protected R getInstance() { + try { + R record = reference.newInstance(); + record.setUriInfo(uriInfo); + return record; + } catch (WebApplicationException e) { + throw e; + } catch(Exception e) { + throw new InternalServerErrorException(e); + } + } + + public String list(int limit, int offset) { + setCalledMethod("GET /" + COLLECTION_PARAMETER); + R record = getInstance(); + return record.list(limit, offset); + } + + public Response create(String json) { + setCalledMethod("POST /" + COLLECTION_PARAMETER); + R record = getInstance(); + String ret = record.create(json); + + ResponseBuilder responseBuilder = Response.status(Status.CREATED).entity(ret); + responseBuilder = addLocation(responseBuilder, record.getId()); + return responseBuilder.type(GCatConstants.APPLICATION_JSON_CHARSET_UTF_8).build(); + } + + public String read(String id) { + setCalledMethod("GET /" + COLLECTION_PARAMETER + "/{" + ID_PARAMETER + "}"); + Record record = getInstance(); + record.setId(id); + return record.read(); + } + + public String update(String id, String json) { + setCalledMethod("PUT /" + COLLECTION_PARAMETER + "/{" + ID_PARAMETER + "}"); + Record record = getInstance(); + record.setId(id); + return record.update(json); + } + + public String patch(String id, String json) { + setCalledMethod("PATCH /" + COLLECTION_PARAMETER + "/{" + ID_PARAMETER + "}"); + Record record = getInstance(); + record.setId(id); + return record.patch(json); + } + + public Response delete(String id) { + return delete(id, false); + } + + public Response delete(String id, Boolean purge) { + if(purge) { + setCalledMethod("PURGE /" + COLLECTION_PARAMETER + "/{" + ID_PARAMETER + "}"); + } else { + setCalledMethod("DELETE /" + COLLECTION_PARAMETER + "/{" + ID_PARAMETER + "}"); + } + Record record = getInstance(); + record.setId(id); + record.delete(purge); + return Response.status(Status.NO_CONTENT).build(); + } + + public Response purge(String id) { + return delete(id, true); + } + + protected String createCountJson(int count) { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("{\""); + stringBuilder.append(GCatConstants.COUNT_KEY); + stringBuilder.append("\":"); + stringBuilder.append(count); + stringBuilder.append("}"); + return stringBuilder.toString(); + } + + protected String resultAsJsonAPI(String data) { + StringBuffer stringBuffer = new StringBuffer(); + stringBuffer.append("{ \"data\":"); + stringBuffer.append(data); + stringBuffer.append("}"); + return stringBuffer.toString(); + } } diff --git a/src/main/java/org/gcube/grsf/publisher/rest/FisheryRESTAPIs.java b/src/main/java/org/gcube/grsf/publisher/rest/FisheryRESTAPIs.java index e54c333..6174dc1 100644 --- a/src/main/java/org/gcube/grsf/publisher/rest/FisheryRESTAPIs.java +++ b/src/main/java/org/gcube/grsf/publisher/rest/FisheryRESTAPIs.java @@ -1,16 +1,161 @@ package org.gcube.grsf.publisher.rest; +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.MultivaluedMap; +import javax.ws.rs.core.Response; + +import org.gcube.gcat.api.GCatConstants; +import org.gcube.grsf.publisher.annotation.PATCH; +import org.gcube.grsf.publisher.annotation.PURGE; +import org.gcube.grsf.publisher.record.Fishery; + +import com.webcohesion.enunciate.metadata.rs.ResponseCode; +import com.webcohesion.enunciate.metadata.rs.StatusCodes; /** * @author Luca Frosini (ISTI - CNR) */ -@Path("fishery/{source}/") -public class FisheryRESTAPIs extends BaseRESTAPIs { +@Path(FisheryRESTAPIs.COLLECTION_PATH + "/") +public class FisheryRESTAPIs extends BaseRESTAPIs { @PathParam("source") protected String source; + public static final String COLLECTION_PATH = "fishery/{source}"; + public static final String RECORD_ID_PARAMETER = "fishery_record_id"; + + public FisheryRESTAPIs() { + super(COLLECTION_PATH, RECORD_ID_PARAMETER, Fishery.class); + } + + /** + * @pathExample /fishery/grsf + */ + @GET + @Produces(GCatConstants.APPLICATION_JSON_CHARSET_UTF_8) + @StatusCodes ({ + @ResponseCode ( code = 200, condition = "The request succeeded.") + }) + public String list(@QueryParam(GCatConstants.LIMIT_QUERY_PARAMETER) @DefaultValue("10") int limit, + @QueryParam(GCatConstants.OFFSET_QUERY_PARAMETER) @DefaultValue("0") int offset) { + Boolean countOnly = false; + MultivaluedMap queryParameters = uriInfo.getQueryParameters(); + if(queryParameters.containsKey(GCatConstants.COUNT_QUERY_PARAMETER)) { + countOnly = Boolean.parseBoolean(queryParameters.get(GCatConstants.COUNT_QUERY_PARAMETER).get(0)); + } + + String ret = null; + + if(countOnly) { + setCalledMethod("GET /" + COLLECTION_PARAMETER); + Fishery fishery = getInstance(); + int size = fishery.count(); + ret = createCountJson(size); + }else { + ret = super.list(limit, offset); + } + + String accept = httpHeaders.getHeaderString("Accept"); + if(accept!=null && accept.contains(GCatConstants.APPLICATION_JSON_API)) { + return resultAsJsonAPI(ret); + } + return ret; + + } + + /** + * @pathExample /fishery/grsf + */ + @POST + @Consumes(GCatConstants.APPLICATION_JSON_CHARSET_UTF_8) + @Produces(GCatConstants.APPLICATION_JSON_CHARSET_UTF_8) + @StatusCodes ({ + @ResponseCode ( code = 201, condition = "The stock record has been created successfully.") + }) + public Response create(String json) { + return super.create(json); + } + + /** + * @pathExample /fishery/grsf/bc26e8d0-6ab3-4547-9922-d40407fc5dbd + */ + @GET + @Path("/{" + RECORD_ID_PARAMETER + "}") + @Produces(GCatConstants.APPLICATION_JSON_CHARSET_UTF_8) + @StatusCodes ({ + @ResponseCode ( code = 200, condition = "The stock record exists.") + }) + @Override + public String read(@PathParam(RECORD_ID_PARAMETER) String id) { + return super.read(id); + } + + /** + * @pathExample /fishery/grsf/bc26e8d0-6ab3-4547-9922-d40407fc5dbd + */ + @PUT + @Path("/{" + RECORD_ID_PARAMETER + "}") + @Consumes(GCatConstants.APPLICATION_JSON_CHARSET_UTF_8) + @Produces(GCatConstants.APPLICATION_JSON_CHARSET_UTF_8) + @StatusCodes ({ + @ResponseCode ( code = 200, condition = "The stock record has been updated successfully.") + }) + @Override + public String update(@PathParam(RECORD_ID_PARAMETER) String id, String json) { + return super.update(id, json); + } + + /** + * @pathExample /fishery/grsf/bc26e8d0-6ab3-4547-9922-d40407fc5dbd + */ + @PATCH + @Path("/{" + RECORD_ID_PARAMETER + "}") + @Consumes(GCatConstants.APPLICATION_JSON_CHARSET_UTF_8) + @Produces(GCatConstants.APPLICATION_JSON_CHARSET_UTF_8) + @StatusCodes ({ + @ResponseCode ( code = 200, condition = "The stock record has been patched successfully.") + }) + @Override + public String patch(@PathParam(RECORD_ID_PARAMETER) String id, String json) { + return super.patch(id, json); + } + + /** + * @pathExample /fishery/grsf/bc26e8d0-6ab3-4547-9922-d40407fc5dbd + */ + @DELETE + @Path("/{" + RECORD_ID_PARAMETER + "}") + @StatusCodes ({ + @ResponseCode ( code = 204, condition = "The stock record has been deleted successfully."), + @ResponseCode ( code = 404, condition = "The stock record was not found.") + }) + @Override + public Response delete(@PathParam(RECORD_ID_PARAMETER) String id, + @QueryParam(GCatConstants.PURGE_QUERY_PARAMETER) @DefaultValue("false") Boolean purge) { + return super.delete(id, purge); + } + + /** + * @pathExample /fishery/grsf/bc26e8d0-6ab3-4547-9922-d40407fc5dbd + */ + @PURGE + @Path("/{" + RECORD_ID_PARAMETER + "}") + @StatusCodes ({ + @ResponseCode ( code = 204, condition = "The stock record has been purged successfully."), + @ResponseCode ( code = 404, condition = "The stock record was not found.") + }) + @Override + public Response purge(@PathParam(RECORD_ID_PARAMETER) String id) { + return super.purge(id); + } } diff --git a/src/main/java/org/gcube/grsf/publisher/rest/StockRESTAPIs.java b/src/main/java/org/gcube/grsf/publisher/rest/StockRESTAPIs.java index 71ff8bb..97c6ab9 100644 --- a/src/main/java/org/gcube/grsf/publisher/rest/StockRESTAPIs.java +++ b/src/main/java/org/gcube/grsf/publisher/rest/StockRESTAPIs.java @@ -1,16 +1,22 @@ package org.gcube.grsf.publisher.rest; 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; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response; import org.gcube.gcat.api.GCatConstants; +import org.gcube.grsf.publisher.annotation.PATCH; +import org.gcube.grsf.publisher.annotation.PURGE; +import org.gcube.grsf.publisher.record.Stock; import com.webcohesion.enunciate.metadata.rs.ResponseCode; import com.webcohesion.enunciate.metadata.rs.StatusCodes; @@ -18,12 +24,22 @@ import com.webcohesion.enunciate.metadata.rs.StatusCodes; /** * @author Luca Frosini (ISTI - CNR) */ -@Path("stock/{source}/") -public class StockRESTAPIs extends BaseRESTAPIs { +@Path(StockRESTAPIs.COLLECTION_PATH + "/") +public class StockRESTAPIs extends BaseRESTAPIs { @PathParam("source") protected String source; + public static final String COLLECTION_PATH = "stock/{source}"; + public static final String RECORD_ID_PARAMETER = "stock_record_id"; + + public StockRESTAPIs() { + super(COLLECTION_PATH, RECORD_ID_PARAMETER, Stock.class); + } + + /** + * @pathExample /stock/grsf + */ @GET @Produces(GCatConstants.APPLICATION_JSON_CHARSET_UTF_8) @StatusCodes ({ @@ -31,23 +47,115 @@ public class StockRESTAPIs extends BaseRESTAPIs { }) public String list(@QueryParam(GCatConstants.LIMIT_QUERY_PARAMETER) @DefaultValue("10") int limit, @QueryParam(GCatConstants.OFFSET_QUERY_PARAMETER) @DefaultValue("0") int offset) { + Boolean countOnly = false; + MultivaluedMap queryParameters = uriInfo.getQueryParameters(); + if(queryParameters.containsKey(GCatConstants.COUNT_QUERY_PARAMETER)) { + countOnly = Boolean.parseBoolean(queryParameters.get(GCatConstants.COUNT_QUERY_PARAMETER).get(0)); + } - return null; + String ret = null; + + if(countOnly) { + setCalledMethod("GET /" + COLLECTION_PARAMETER); + Stock stock = getInstance(); + int size = stock.count(); + ret = createCountJson(size); + }else { + ret = super.list(limit, offset); + } + + String accept = httpHeaders.getHeaderString("Accept"); + if(accept!=null && accept.contains(GCatConstants.APPLICATION_JSON_API)) { + return resultAsJsonAPI(ret); + } + return ret; } + /** + * @pathExample /stock/grsf + */ @POST - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - public void create(String jsonString) { - + @Consumes(GCatConstants.APPLICATION_JSON_CHARSET_UTF_8) + @Produces(GCatConstants.APPLICATION_JSON_CHARSET_UTF_8) + @StatusCodes ({ + @ResponseCode ( code = 201, condition = "The stock record has been created successfully.") + }) + public Response create(String json) { + return super.create(json); } + /** + * @pathExample /stock/grsf/866a479a-643a-4c21-bbcd-a3a73f28ea50 + */ @GET - @Produces(MediaType.APPLICATION_JSON) - public String read() { - return null; + @Path("/{" + RECORD_ID_PARAMETER + "}") + @Produces(GCatConstants.APPLICATION_JSON_CHARSET_UTF_8) + @StatusCodes ({ + @ResponseCode ( code = 200, condition = "The stock record exists.") + }) + @Override + public String read(@PathParam(RECORD_ID_PARAMETER) String id) { + return super.read(id); } + /** + * @pathExample /stock/grsf/866a479a-643a-4c21-bbcd-a3a73f28ea50 + */ + @PUT + @Path("/{" + RECORD_ID_PARAMETER + "}") + @Consumes(GCatConstants.APPLICATION_JSON_CHARSET_UTF_8) + @Produces(GCatConstants.APPLICATION_JSON_CHARSET_UTF_8) + @StatusCodes ({ + @ResponseCode ( code = 200, condition = "The stock record has been updated successfully.") + }) + @Override + public String update(@PathParam(RECORD_ID_PARAMETER) String id, String json) { + return super.update(id, json); + } + + /** + * @pathExample /stock/grsf/866a479a-643a-4c21-bbcd-a3a73f28ea50 + */ + @PATCH + @Path("/{" + RECORD_ID_PARAMETER + "}") + @Consumes(GCatConstants.APPLICATION_JSON_CHARSET_UTF_8) + @Produces(GCatConstants.APPLICATION_JSON_CHARSET_UTF_8) + @StatusCodes ({ + @ResponseCode ( code = 200, condition = "The stock record has been patched successfully.") + }) + @Override + public String patch(@PathParam(RECORD_ID_PARAMETER) String id, String json) { + return super.patch(id, json); + } + + /** + * @pathExample /stock/grsf/866a479a-643a-4c21-bbcd-a3a73f28ea50 + */ + @DELETE + @Path("/{" + RECORD_ID_PARAMETER + "}") + @StatusCodes ({ + @ResponseCode ( code = 204, condition = "The stock record has been deleted successfully."), + @ResponseCode ( code = 404, condition = "The stock record was not found.") + }) + @Override + public Response delete(@PathParam(RECORD_ID_PARAMETER) String id, + @QueryParam(GCatConstants.PURGE_QUERY_PARAMETER) @DefaultValue("false") Boolean purge) { + return super.delete(id, purge); + } + + /** + * @pathExample /stock/grsf/866a479a-643a-4c21-bbcd-a3a73f28ea50 + */ + @PURGE + @Path("/{" + RECORD_ID_PARAMETER + "}") + @StatusCodes ({ + @ResponseCode ( code = 204, condition = "The stock record has been purged successfully."), + @ResponseCode ( code = 404, condition = "The stock record was not found.") + }) + @Override + public Response purge(@PathParam(RECORD_ID_PARAMETER) String id) { + return super.purge(id); + } } diff --git a/src/main/java/org/gcube/grsf/publisher/rest/TraceabilityUnitRESTAPIs.java b/src/main/java/org/gcube/grsf/publisher/rest/TraceabilityUnitRESTAPIs.java index 447f437..3670cec 100644 --- a/src/main/java/org/gcube/grsf/publisher/rest/TraceabilityUnitRESTAPIs.java +++ b/src/main/java/org/gcube/grsf/publisher/rest/TraceabilityUnitRESTAPIs.java @@ -1,13 +1,158 @@ package org.gcube.grsf.publisher.rest; +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.MultivaluedMap; +import javax.ws.rs.core.Response; + +import org.gcube.gcat.api.GCatConstants; +import org.gcube.grsf.publisher.annotation.PATCH; +import org.gcube.grsf.publisher.annotation.PURGE; +import org.gcube.grsf.publisher.record.TraceabilityUnit; + +import com.webcohesion.enunciate.metadata.rs.ResponseCode; +import com.webcohesion.enunciate.metadata.rs.StatusCodes; /** * @author Luca Frosini (ISTI - CNR) */ -@Path("traceability-unit/") -public class TraceabilityUnitRESTAPIs { +@Path(TraceabilityUnitRESTAPIs.COLLECTION_PATH + "/") +public class TraceabilityUnitRESTAPIs extends BaseRESTAPIs{ + public static final String COLLECTION_PATH = "traceability-unit"; + public static final String RECORD_ID_PARAMETER = "traceability_unit_record_id"; + public TraceabilityUnitRESTAPIs() { + super(COLLECTION_PATH, RECORD_ID_PARAMETER, TraceabilityUnit.class); + } + + /** + * @pathExample /traceability-unit + */ + @GET + @Produces(GCatConstants.APPLICATION_JSON_CHARSET_UTF_8) + @StatusCodes ({ + @ResponseCode ( code = 200, condition = "The request succeeded.") + }) + public String list(@QueryParam(GCatConstants.LIMIT_QUERY_PARAMETER) @DefaultValue("10") int limit, + @QueryParam(GCatConstants.OFFSET_QUERY_PARAMETER) @DefaultValue("0") int offset) { + Boolean countOnly = false; + MultivaluedMap queryParameters = uriInfo.getQueryParameters(); + if(queryParameters.containsKey(GCatConstants.COUNT_QUERY_PARAMETER)) { + countOnly = Boolean.parseBoolean(queryParameters.get(GCatConstants.COUNT_QUERY_PARAMETER).get(0)); + } + + String ret = null; + + if(countOnly) { + setCalledMethod("GET /" + COLLECTION_PARAMETER); + TraceabilityUnit traceabilityUnit = getInstance(); + int size = traceabilityUnit.count(); + ret = createCountJson(size); + }else { + ret = super.list(limit, offset); + } + + String accept = httpHeaders.getHeaderString("Accept"); + if(accept!=null && accept.contains(GCatConstants.APPLICATION_JSON_API)) { + return resultAsJsonAPI(ret); + } + return ret; + + } + + /** + * @pathExample /traceability-unit + */ + @POST + @Consumes(GCatConstants.APPLICATION_JSON_CHARSET_UTF_8) + @Produces(GCatConstants.APPLICATION_JSON_CHARSET_UTF_8) + @StatusCodes ({ + @ResponseCode ( code = 201, condition = "The stock record has been created successfully.") + }) + public Response create(String json) { + return super.create(json); + } + + /** + * @pathExample /traceability-unit/004d6fd2-3e49-4246-b321-f768efdaa7b6 + */ + @GET + @Path("/{" + RECORD_ID_PARAMETER + "}") + @Produces(GCatConstants.APPLICATION_JSON_CHARSET_UTF_8) + @StatusCodes ({ + @ResponseCode ( code = 200, condition = "The stock record exists.") + }) + @Override + public String read(@PathParam(RECORD_ID_PARAMETER) String id) { + return super.read(id); + } + + /** + * @pathExample /traceability-unit/004d6fd2-3e49-4246-b321-f768efdaa7b6 + */ + @PUT + @Path("/{" + RECORD_ID_PARAMETER + "}") + @Consumes(GCatConstants.APPLICATION_JSON_CHARSET_UTF_8) + @Produces(GCatConstants.APPLICATION_JSON_CHARSET_UTF_8) + @StatusCodes ({ + @ResponseCode ( code = 200, condition = "The stock record has been updated successfully.") + }) + @Override + public String update(@PathParam(RECORD_ID_PARAMETER) String id, String json) { + return super.update(id, json); + } + + /** + * @pathExample /traceability-unit/004d6fd2-3e49-4246-b321-f768efdaa7b6 + */ + @PATCH + @Path("/{" + RECORD_ID_PARAMETER + "}") + @Consumes(GCatConstants.APPLICATION_JSON_CHARSET_UTF_8) + @Produces(GCatConstants.APPLICATION_JSON_CHARSET_UTF_8) + @StatusCodes ({ + @ResponseCode ( code = 200, condition = "The stock record has been patched successfully.") + }) + @Override + public String patch(@PathParam(RECORD_ID_PARAMETER) String id, String json) { + return super.patch(id, json); + } + + /** + * @pathExample /traceability-unit/004d6fd2-3e49-4246-b321-f768efdaa7b6 + */ + @DELETE + @Path("/{" + RECORD_ID_PARAMETER + "}") + @StatusCodes ({ + @ResponseCode ( code = 204, condition = "The stock record has been deleted successfully."), + @ResponseCode ( code = 404, condition = "The stock record was not found.") + }) + @Override + public Response delete(@PathParam(RECORD_ID_PARAMETER) String id, + @QueryParam(GCatConstants.PURGE_QUERY_PARAMETER) @DefaultValue("false") Boolean purge) { + return super.delete(id, purge); + } + + /** + * @pathExample /traceability-unit/004d6fd2-3e49-4246-b321-f768efdaa7b6 + */ + @PURGE + @Path("/{" + RECORD_ID_PARAMETER + "}") + @StatusCodes ({ + @ResponseCode ( code = 204, condition = "The stock record has been purged successfully."), + @ResponseCode ( code = 404, condition = "The stock record was not found.") + }) + @Override + public Response purge(@PathParam(RECORD_ID_PARAMETER) String id) { + return super.purge(id); + } }