Implementing patch method

This commit is contained in:
Luca Frosini 2020-11-30 19:44:15 +01:00
parent 36b59cf13c
commit 1733b66c05
2 changed files with 94 additions and 19 deletions

View File

@ -11,14 +11,8 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import javax.ws.rs.BadRequestException; import javax.ws.rs.BadRequestException;
import javax.ws.rs.DELETE;
import javax.ws.rs.ForbiddenException; import javax.ws.rs.ForbiddenException;
import javax.ws.rs.GET;
import javax.ws.rs.HEAD;
import javax.ws.rs.InternalServerErrorException; import javax.ws.rs.InternalServerErrorException;
import javax.ws.rs.NotAllowedException;
import javax.ws.rs.OPTIONS;
import javax.ws.rs.PUT;
import javax.ws.rs.WebApplicationException; import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.Response.Status;
@ -26,7 +20,6 @@ import javax.ws.rs.core.Response.Status;
import org.gcube.common.resources.gcore.GenericResource; import org.gcube.common.resources.gcore.GenericResource;
import org.gcube.common.scope.impl.ScopeBean; import org.gcube.common.scope.impl.ScopeBean;
import org.gcube.common.scope.impl.ScopeBean.Type; import org.gcube.common.scope.impl.ScopeBean.Type;
import org.gcube.gcat.annotation.PURGE;
import org.gcube.gcat.api.GCatConstants; import org.gcube.gcat.api.GCatConstants;
import org.gcube.gcat.oldutils.Validator; import org.gcube.gcat.oldutils.Validator;
import org.gcube.gcat.profile.MetadataUtility; import org.gcube.gcat.profile.MetadataUtility;
@ -241,9 +234,25 @@ public class CKANPackage extends CKAN {
} }
public ObjectNode checkBaseInformation(String json) throws Exception { public ObjectNode checkBaseInformation(String json) throws Exception {
return checkBaseInformation(json, false);
}
/**
* @param json The json to check
* @param allowPartialInfo used for patch method which provide only partial information (i.e. the info to patch)
* @return ObjectNode from json
* @throws Exception
*/
public ObjectNode checkBaseInformation(String json, boolean allowPartialInfo) throws Exception {
ObjectNode objectNode = (ObjectNode) mapper.readTree(json); ObjectNode objectNode = (ObjectNode) mapper.readTree(json);
objectNode = (ObjectNode) checkName(objectNode); try {
objectNode = (ObjectNode) checkName(objectNode);
}catch (Exception e) {
if(!allowPartialInfo) {
throw e;
}
}
// We need to enforce the itemID to properly manage resource persistence // We need to enforce the itemID to properly manage resource persistence
if(objectNode.has(ID_KEY)) { if(objectNode.has(ID_KEY)) {
@ -265,15 +274,17 @@ public class CKANPackage extends CKAN {
if(objectNode.has(LICENSE_KEY)) { if(objectNode.has(LICENSE_KEY)) {
licenseId = objectNode.get(LICENSE_KEY).asText(); licenseId = objectNode.get(LICENSE_KEY).asText();
} }
if(licenseId == null || licenseId.isEmpty()) { if(licenseId == null || licenseId.isEmpty() && !allowPartialInfo) {
throw new BadRequestException( throw new BadRequestException(
"You must specify a license identifier for the item. License list can be retrieved using licence collection"); "You must specify a license identifier for the item. License list can be retrieved using licence collection");
} else { } else {
try { if(licenseId!=null) {
CKANLicense.checkLicenseId(licenseId); try {
} catch(Exception e) { CKANLicense.checkLicenseId(licenseId);
throw new BadRequestException( } catch(Exception e) {
"You must specify an existing license identifier for the item. License list can be retrieved using licence collection"); throw new BadRequestException(
"You must specify an existing license identifier for the item. License list can be retrieved using licence collection");
}
} }
} }
@ -643,9 +654,74 @@ public class CKANPackage extends CKAN {
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.patch.package_patch // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.patch.package_patch
@Override @Override
public String patch(String json) { public String patch(String json) {
String[] moreAllowed = new String[] {HEAD.class.getSimpleName(), GET.class.getSimpleName(), try {
PUT.class.getSimpleName(), DELETE.class.getSimpleName(), PURGE.class.getSimpleName()}; JsonNode jsonNode = checkBaseInformation(json);
throw new NotAllowedException(OPTIONS.class.getSimpleName(), moreAllowed);
read();
this.itemID = result.get(ID_KEY).asText();
Map<String,CKANResource> originalResources = new HashMap<>();
ArrayNode originalResourcesarrayNode = (ArrayNode) result.get(RESOURCES_KEY);
if(originalResources != null) {
for(JsonNode resourceNode : originalResourcesarrayNode) {
CKANResource ckanResource = new CKANResource(itemID);
ckanResource.setPreviousRepresentation(resourceNode);
String resourceID = ckanResource.getResourceID();
originalResources.put(resourceID, ckanResource);
}
}
if(jsonNode.has(RESOURCES_KEY)) {
ArrayNode resourcesToBeSend = mapper.createArrayNode();
ArrayNode receivedResources = (ArrayNode) jsonNode.get(RESOURCES_KEY);
for(JsonNode resourceNode : receivedResources) {
CKANResource ckanResource = new CKANResource(itemID);
String resourceId = CKANResource.extractResourceID(resourceNode);
if(resourceId != null) {
if(originalResources.containsKey(resourceId)) {
ckanResource = originalResources.get(resourceId);
originalResources.remove(resourceId);
} else {
throw new BadRequestException(
"The content contains a resource with id " + resourceId + " which does not exists");
}
}
if(originalResources.get(resourceId) != null
&& (!originalResources.get(resourceId).getPreviousRepresentation().equals(resourceNode))) {
resourceNode = ckanResource.createOrUpdate(resourceNode);
}
resourcesToBeSend.add(resourceNode);
managedResources.add(ckanResource);
}
((ObjectNode) jsonNode).replace(RESOURCES_KEY, resourcesToBeSend);
}
addItemURLViaResolver(jsonNode);
sendPostRequest(ITEM_PATCH, getAsString(jsonNode));
for(String resourceId : originalResources.keySet()) {
CKANResource ckanResource = originalResources.get(resourceId);
ckanResource.deleteFile();
}
/*
// Adding Item URL via Resolver
URIResolver uriResolver = new URIResolver();
String catalogueItemURL = uriResolver.getCatalogueItemURL(name);
((ObjectNode) result).put(ITEM_URL_KEY, catalogueItemURL);
*/
return getAsString(result);
} catch(WebApplicationException e) {
rollbackManagedResources();
throw e;
} catch(Exception e) {
rollbackManagedResources();
throw new InternalServerErrorException(e);
}
} }
@Override @Override

View File

@ -16,6 +16,7 @@ import javax.ws.rs.core.Response;
import javax.xml.ws.WebServiceException; import javax.xml.ws.WebServiceException;
import org.gcube.gcat.ResourceInitializer; import org.gcube.gcat.ResourceInitializer;
import org.gcube.gcat.annotation.PATCH;
import org.gcube.gcat.annotation.PURGE; import org.gcube.gcat.annotation.PURGE;
import org.gcube.gcat.api.GCatConstants; import org.gcube.gcat.api.GCatConstants;
import org.gcube.gcat.persistence.ckan.CKANPackage; import org.gcube.gcat.persistence.ckan.CKANPackage;
@ -74,7 +75,6 @@ public class Item extends REST<CKANPackage> implements org.gcube.gcat.api.interf
return super.update(id, json); return super.update(id, json);
} }
/*
@PATCH @PATCH
@Path("/{" + ITEM_ID_PARAMETER + "}") @Path("/{" + ITEM_ID_PARAMETER + "}")
@Consumes(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8) @Consumes(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
@ -83,7 +83,6 @@ public class Item extends REST<CKANPackage> implements org.gcube.gcat.api.interf
public String patch(@PathParam(ITEM_ID_PARAMETER) String id, String json) { public String patch(@PathParam(ITEM_ID_PARAMETER) String id, String json) {
return super.patch(id, json); return super.patch(id, json);
} }
*/
@DELETE @DELETE
@Path("/{" + ITEM_ID_PARAMETER + "}") @Path("/{" + ITEM_ID_PARAMETER + "}")