diff --git a/src/main/java/org/gcube/gcat/persistence/ckan/CKANPackage.java b/src/main/java/org/gcube/gcat/persistence/ckan/CKANPackage.java index cc090da..9c2e376 100644 --- a/src/main/java/org/gcube/gcat/persistence/ckan/CKANPackage.java +++ b/src/main/java/org/gcube/gcat/persistence/ckan/CKANPackage.java @@ -11,14 +11,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.ws.rs.BadRequestException; -import javax.ws.rs.DELETE; import javax.ws.rs.ForbiddenException; -import javax.ws.rs.GET; -import javax.ws.rs.HEAD; 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.core.MultivaluedMap; 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.scope.impl.ScopeBean; import org.gcube.common.scope.impl.ScopeBean.Type; -import org.gcube.gcat.annotation.PURGE; import org.gcube.gcat.api.GCatConstants; import org.gcube.gcat.oldutils.Validator; import org.gcube.gcat.profile.MetadataUtility; @@ -241,9 +234,25 @@ public class CKANPackage extends CKAN { } 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) 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 if(objectNode.has(ID_KEY)) { @@ -265,15 +274,17 @@ public class CKANPackage extends CKAN { if(objectNode.has(LICENSE_KEY)) { licenseId = objectNode.get(LICENSE_KEY).asText(); } - if(licenseId == null || licenseId.isEmpty()) { + if(licenseId == null || licenseId.isEmpty() && !allowPartialInfo) { throw new BadRequestException( "You must specify a license identifier for the item. License list can be retrieved using licence collection"); } else { - try { - CKANLicense.checkLicenseId(licenseId); - } catch(Exception e) { - throw new BadRequestException( - "You must specify an existing license identifier for the item. License list can be retrieved using licence collection"); + if(licenseId!=null) { + try { + CKANLicense.checkLicenseId(licenseId); + } catch(Exception e) { + 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 @Override public String patch(String json) { - String[] moreAllowed = new String[] {HEAD.class.getSimpleName(), GET.class.getSimpleName(), - PUT.class.getSimpleName(), DELETE.class.getSimpleName(), PURGE.class.getSimpleName()}; - throw new NotAllowedException(OPTIONS.class.getSimpleName(), moreAllowed); + try { + JsonNode jsonNode = checkBaseInformation(json); + + read(); + + this.itemID = result.get(ID_KEY).asText(); + + Map 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 diff --git a/src/main/java/org/gcube/gcat/rest/Item.java b/src/main/java/org/gcube/gcat/rest/Item.java index 211896c..eea6314 100644 --- a/src/main/java/org/gcube/gcat/rest/Item.java +++ b/src/main/java/org/gcube/gcat/rest/Item.java @@ -16,6 +16,7 @@ import javax.ws.rs.core.Response; import javax.xml.ws.WebServiceException; import org.gcube.gcat.ResourceInitializer; +import org.gcube.gcat.annotation.PATCH; import org.gcube.gcat.annotation.PURGE; import org.gcube.gcat.api.GCatConstants; import org.gcube.gcat.persistence.ckan.CKANPackage; @@ -74,7 +75,6 @@ public class Item extends REST implements org.gcube.gcat.api.interf return super.update(id, json); } - /* @PATCH @Path("/{" + ITEM_ID_PARAMETER + "}") @Consumes(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8) @@ -83,7 +83,6 @@ public class Item extends REST implements org.gcube.gcat.api.interf public String patch(@PathParam(ITEM_ID_PARAMETER) String id, String json) { return super.patch(id, json); } - */ @DELETE @Path("/{" + ITEM_ID_PARAMETER + "}")