diff --git a/CHANGELOG.md b/CHANGELOG.md index c3c2592..84236f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm # Changelog for gCube Catalogue (gCat) Service +## [v2.0.0-SNAPSHOT] + +- Improved check on controlled vocabulary to match corner cases [#20742] +- Added PATCH method on Item collection [#19768] +- Switched JSON management to gcube-jackson [#19735] +- Added support to publish an item organizations not matching the current context [#19365] + ## [v1.4.5] - Removed 'owner_org' field from result when reading an item [#20919] diff --git a/pom.xml b/pom.xml index 846409a..c2db73e 100644 --- a/pom.xml +++ b/pom.xml @@ -9,10 +9,10 @@ - org.gcube.data-publishing + org.gcube.data-catalogue gcat war - 1.4.5 + 2.0.0-SNAPSHOT gCube Catalogue (gCat) Service This service allows any client to publish on the gCube Catalogue. @@ -21,7 +21,7 @@ UTF-8 ${project.basedir}${file.separator}src${file.separator}main${file.separator}webapp${file.separator}WEB-INF - DataPublishing + data-catalogue @@ -44,14 +44,36 @@ - org.gcube.data-publishing + org.gcube.data-catalogue gcat-api - [1.2.2, 2.0.0-SNAPSHOT) + [2.0.0-SNAPSHOT, 3.0.0-SNAPSHOT) org.slf4j slf4j-api + + org.gcube.information-system + information-system-model + provided + + + org.gcube.resource-management + gcube-model + provided + + + org.gcube.information-system + resource-registry-client + provided + + + org.gcube.information-system + resource-registry-publisher + provided + + + org.gcube.data-catalogue gcubedatacatalogue-metadata-discovery diff --git a/src/main/java/org/gcube/gcat/oldutils/Validator.java b/src/main/java/org/gcube/gcat/oldutils/Validator.java index 03545fc..c49250d 100644 --- a/src/main/java/org/gcube/gcat/oldutils/Validator.java +++ b/src/main/java/org/gcube/gcat/oldutils/Validator.java @@ -23,6 +23,7 @@ import org.gcube.datacatalogue.metadatadiscovery.bean.jaxb.MetadataField; import org.gcube.datacatalogue.metadatadiscovery.bean.jaxb.MetadataFormat; import org.gcube.datacatalogue.metadatadiscovery.bean.jaxb.MetadataGrouping; import org.gcube.datacatalogue.metadatadiscovery.bean.jaxb.MetadataTagging; +import org.gcube.datacatalogue.metadatadiscovery.bean.jaxb.MetadataVocabulary; import org.gcube.datacatalogue.metadatadiscovery.bean.jaxb.NamespaceCategory; import org.gcube.gcat.persistence.ckan.CKANGroup; import org.gcube.gcat.persistence.ckan.CKANPackage; @@ -354,9 +355,11 @@ public class Validator { // if there was no field with this key and it was not mandatory, just add an entry of the kind {"key": "key-value", "value" : ""}. // Sometimes it is important to view the field as empty. + /* if(fieldsFoundWithThisKey == 0 && !metadataField.getMandatory()) { toReturn.add(new CustomField(metadataFieldName, "", -1, -1)); } + */ return toReturn; @@ -480,7 +483,14 @@ public class Validator { DataType dataType = metadataField.getDataType(); String regex = metadataField.getValidator() != null ? metadataField.getValidator().getRegularExpression() : null; - boolean hasControlledVocabulary = metadataField.getVocabulary() != null; + boolean hasControlledVocabulary = false; + MetadataVocabulary metadataVocabulary = metadataField.getVocabulary(); + if(metadataVocabulary!=null) { + List vocabularyFields = metadataVocabulary.getVocabularyFields(); + if(vocabularyFields!=null && vocabularyFields.size()>0) { + hasControlledVocabulary = true; + } + } String value = fieldToValidate.getValue(); String key = fieldToValidate.getKey(); String defaultValue = metadataField.getDefaultValue(); @@ -581,7 +591,7 @@ public class Validator { case GeoJSON: try { - new ObjectMapper().readValue(fieldToValidate.getValue(), GeoJsonObject.class); + new com.fasterxml.jackson.databind.ObjectMapper().readValue(fieldToValidate.getValue(), GeoJsonObject.class); } catch(Exception e) { throw new BadRequestException("GeoJSON field with key '" + key + "' seems not valid!"); } diff --git a/src/main/java/org/gcube/gcat/persistence/ckan/CKAN.java b/src/main/java/org/gcube/gcat/persistence/ckan/CKAN.java index 0e2a99e..f19b274 100644 --- a/src/main/java/org/gcube/gcat/persistence/ckan/CKAN.java +++ b/src/main/java/org/gcube/gcat/persistence/ckan/CKAN.java @@ -129,6 +129,7 @@ public abstract class CKAN { throw new BadRequestException(e); } } + /** * Validate the CKAN response and return the diff --git a/src/main/java/org/gcube/gcat/persistence/ckan/CKANGroup.java b/src/main/java/org/gcube/gcat/persistence/ckan/CKANGroup.java index 9144968..08891c7 100644 --- a/src/main/java/org/gcube/gcat/persistence/ckan/CKANGroup.java +++ b/src/main/java/org/gcube/gcat/persistence/ckan/CKANGroup.java @@ -16,19 +16,19 @@ import org.gcube.com.fasterxml.jackson.databind.node.ObjectNode; */ public class CKANGroup extends CKAN { - // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.group_list + // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.get.group_list public static final String GROUP_LIST = CKAN.CKAN_API_PATH + "group_list"; - // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.create.group_create + // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.create.group_create public static final String GROUP_CREATE = CKAN.CKAN_API_PATH + "group_create"; - // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.group_show + // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.get.group_show public static final String GROUP_SHOW = CKAN.CKAN_API_PATH + "group_show"; - // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.update.group_update + // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.update.group_update public static final String GROUP_UPDATE = CKAN.CKAN_API_PATH + "group_update"; - // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.patch.group_patch + // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.patch.group_patch public static final String GROUP_PATCH = CKAN.CKAN_API_PATH + "group_patch"; - // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.delete.group_delete + // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.delete.group_delete public static final String GROUP_DELETE = CKAN.CKAN_API_PATH + "group_delete"; - // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.delete.group_purge + // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.delete.group_purge public static final String GROUP_PURGE = CKAN.CKAN_API_PATH + "group_purge"; public static final String GROUPS_KEY = "groups"; diff --git a/src/main/java/org/gcube/gcat/persistence/ckan/CKANLicense.java b/src/main/java/org/gcube/gcat/persistence/ckan/CKANLicense.java index f474d90..baffab7 100644 --- a/src/main/java/org/gcube/gcat/persistence/ckan/CKANLicense.java +++ b/src/main/java/org/gcube/gcat/persistence/ckan/CKANLicense.java @@ -8,7 +8,7 @@ import org.gcube.com.fasterxml.jackson.databind.node.ArrayNode; */ public class CKANLicense extends CKAN { - // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.license_list + // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.get.license_list public static final String LICENSES_LIST = CKAN.CKAN_API_PATH + "license_list"; public CKANLicense() { diff --git a/src/main/java/org/gcube/gcat/persistence/ckan/CKANOrganization.java b/src/main/java/org/gcube/gcat/persistence/ckan/CKANOrganization.java index dd1907f..d206d39 100644 --- a/src/main/java/org/gcube/gcat/persistence/ckan/CKANOrganization.java +++ b/src/main/java/org/gcube/gcat/persistence/ckan/CKANOrganization.java @@ -17,19 +17,19 @@ public class CKANOrganization extends CKAN { // CKAN Connector sanitize the Organization name as following //organizationName.replaceAll(" ", "_").replace(".", "_").toLowerCase() - // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.organization_list + // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.get.organization_list public static final String ORGANIZATION_LIST = CKAN.CKAN_API_PATH + "organization_list"; - // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.create.organization_create + // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.create.organization_create public static final String ORGANIZATION_CREATE = CKAN.CKAN_API_PATH + "organization_create"; - // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.organization_show + // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.get.organization_show public static final String ORGANIZATION_SHOW = CKAN.CKAN_API_PATH + "organization_show"; - // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.update.organization_update + // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.update.organization_update public static final String ORGANIZATION_UPDATE = CKAN.CKAN_API_PATH + "organization_update"; - // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.patch.organization_patch + // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.patch.organization_patch public static final String ORGANIZATION_PATCH = CKAN.CKAN_API_PATH + "organization_patch"; - // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.delete.organization_delete + // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.delete.organization_delete public static final String ORGANIZATION_DELETE = CKAN.CKAN_API_PATH + "organization_delete"; - // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.delete.organization_purge + // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.delete.organization_purge public static final String ORGANIZATION_PURGE = CKAN.CKAN_API_PATH + "organization_purge"; // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.create.organization_member_create 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 1111c19..0d65025 100644 --- a/src/main/java/org/gcube/gcat/persistence/ckan/CKANPackage.java +++ b/src/main/java/org/gcube/gcat/persistence/ckan/CKANPackage.java @@ -49,17 +49,17 @@ public class CKANPackage extends CKAN { */ // see https://docs.ckan.org/en/latest/api/index.html#ckan.logic.action.get.package_search public static final String ITEM_LIST = CKAN.CKAN_API_PATH + "package_search"; - // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.create.package_create + // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.create.package_create public static final String ITEM_CREATE = CKAN.CKAN_API_PATH + "package_create"; - // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.package_show + // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.get.package_show public static final String ITEM_SHOW = CKAN.CKAN_API_PATH + "package_show"; - // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.update.package_update + // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.update.package_update public static final String ITEM_UPDATE = CKAN.CKAN_API_PATH + "package_update"; - // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.patch.package_patch + // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.patch.package_patch public static final String ITEM_PATCH = CKAN.CKAN_API_PATH + "package_patch"; - // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.delete.package_delete + // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.delete.package_delete public static final String ITEM_DELETE = CKAN.CKAN_API_PATH + "package_delete"; - // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.delete.dataset_purge + // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.delete.dataset_purge public static final String ITEM_PURGE = CKAN.CKAN_API_PATH + "dataset_purge"; // limit in https://docs.ckan.org/en/latest/api/index.html#ckan.logic.action.get.package_search @@ -584,7 +584,7 @@ public class CKANPackage extends CKAN { } - // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.create.package_create + // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.create.package_create @Override public String create(String json) { try { @@ -631,7 +631,7 @@ public class CKANPackage extends CKAN { } } - // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.update.package_update + // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.update.package_update @Override public String update(String json) { try { @@ -704,7 +704,7 @@ public class CKANPackage extends CKAN { } } - // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.patch.package_patch + // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.patch.package_patch @Override public String patch(String json) { try { diff --git a/src/main/java/org/gcube/gcat/persistence/ckan/CKANResource.java b/src/main/java/org/gcube/gcat/persistence/ckan/CKANResource.java index 5badd46..0fc6144 100644 --- a/src/main/java/org/gcube/gcat/persistence/ckan/CKANResource.java +++ b/src/main/java/org/gcube/gcat/persistence/ckan/CKANResource.java @@ -36,15 +36,15 @@ public class CKANResource extends CKAN { private static final Logger logger = LoggerFactory.getLogger(CKANResource.class); - // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.create.resource_create + // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.create.resource_create public static final String RESOURCE_CREATE = CKAN.CKAN_API_PATH + "resource_create"; - // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.resource_show + // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.get.resource_show public static final String RESOURCE_SHOW = CKAN.CKAN_API_PATH + "resource_show"; - // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.update.resource_update + // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.update.resource_update public static final String RESOURCE_UPDATE = CKAN.CKAN_API_PATH + "resource_update"; - // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.patch.resource_patch + // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.patch.resource_patch public static final String RESOURCE_PATCH = CKAN.CKAN_API_PATH + "resource_patch"; - // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.delete.resource_delete + // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.delete.resource_delete public static final String RESOURCE_DELETE = CKAN.CKAN_API_PATH + "resource_delete"; protected static final String URL_KEY = "url"; diff --git a/src/main/java/org/gcube/gcat/persistence/ckan/CKANUser.java b/src/main/java/org/gcube/gcat/persistence/ckan/CKANUser.java index b91fbf9..1327a80 100644 --- a/src/main/java/org/gcube/gcat/persistence/ckan/CKANUser.java +++ b/src/main/java/org/gcube/gcat/persistence/ckan/CKANUser.java @@ -26,13 +26,13 @@ public class CKANUser extends CKAN { /* User Paths */ // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.get.user_list public static final String USER_LIST = CKAN.CKAN_API_PATH + "user_list"; - // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.create.user_create + // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.create.user_create public static final String USER_CREATE = CKAN.CKAN_API_PATH + "user_create"; - // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.user_show + // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.get.user_show public static final String USER_SHOW = CKAN.CKAN_API_PATH + "user_show"; - // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.update.user_update + // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.update.user_update public static final String USER_UPDATE = CKAN.CKAN_API_PATH + "user_update"; - // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.delete.user_delete + // see https://docs.ckan.org/en/latest/api/#ckan.logic.action.delete.user_delete public static final String USER_DELETE = CKAN.CKAN_API_PATH + "user_delete"; public static final String ADD_USER_TO_GROUP = CKAN.CKAN_API_PATH + "member_create"; diff --git a/src/main/java/org/gcube/gcat/profile/ResourceRegistryProfile.java b/src/main/java/org/gcube/gcat/profile/ResourceRegistryProfile.java new file mode 100644 index 0000000..f8a4bee --- /dev/null +++ b/src/main/java/org/gcube/gcat/profile/ResourceRegistryProfile.java @@ -0,0 +1,282 @@ +package org.gcube.gcat.profile; + +import java.io.StringWriter; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.ws.rs.InternalServerErrorException; +import javax.ws.rs.NotAuthorizedException; +import javax.ws.rs.NotFoundException; +import javax.ws.rs.WebApplicationException; + +import org.gcube.com.fasterxml.jackson.databind.ObjectMapper; +import org.gcube.com.fasterxml.jackson.databind.node.ArrayNode; +import org.gcube.common.resources.gcore.GenericResource; +import org.gcube.common.resources.gcore.Resources; +import org.gcube.datacatalogue.metadatadiscovery.reader.MetadataFormatDiscovery; +import org.gcube.datacatalogue.metadatadiscovery.reader.QueryForResourceUtil; +import org.gcube.gcat.persistence.ckan.CKANUser; +import org.gcube.gcat.persistence.ckan.CKANUser.Role; +import org.gcube.gcat.persistence.ckan.CKANUserCache; +import org.gcube.gcat.utils.Constants; +import org.gcube.informationsystem.publisher.RegistryPublisher; +import org.gcube.informationsystem.publisher.RegistryPublisherFactory; +import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException; +import org.gcube.informationsystem.resourceregistry.client.ResourceRegistryClient; +import org.gcube.informationsystem.resourceregistry.client.ResourceRegistryClientFactory; +import org.gcube.resourcemanagement.model.impl.entities.facets.SchemaFacetImpl; +import org.gcube.resourcemanagement.model.impl.entities.facets.SimpleFacetImpl; +import org.gcube.resourcemanagement.model.impl.entities.resources.ConfigurationImpl; +import org.gcube.resourcemanagement.model.reference.entities.facets.IdentifierFacet; +import org.gcube.resourcemanagement.model.reference.entities.facets.SchemaFacet; +import org.gcube.resourcemanagement.model.reference.entities.facets.SimpleFacet; +import org.gcube.resourcemanagement.model.reference.entities.resources.Configuration; +import org.gcube.resourcemanagement.model.reference.relations.consistsof.IsIdentifiedBy; +import org.gcube.resources.discovery.client.api.DiscoveryClient; +import org.gcube.resources.discovery.client.queries.api.Query; +import org.gcube.resources.discovery.client.queries.impl.QueryBox; +import org.gcube.resources.discovery.icclient.ICFactory; +import org.json.JSONObject; +import org.json.XML; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xml.sax.SAXException; + +public class ResourceRegistryProfile { + + public static int PRETTY_PRINT_INDENT_FACTOR = 4; + + public static final String PROFILE = "profile"; + public static final String PROFILE_SCHEMA = "profileSchema"; + + public static final String SCHEMA_URL_ADDRESS = "https://code-repo.d4science.org/gCubeSystem/gcubedatacatalogue-metadata-discovery/raw/branch/master/src/main/resources/org/gcube/datacatalogue/metadatadiscovery/Gdcmetadataprofilev3.xsd"; + public static final URL SCHEMA_URL; + + static { + try { + SCHEMA_URL = new URL(SCHEMA_URL_ADDRESS); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + } + + private static Logger logger = LoggerFactory.getLogger(ResourceRegistryProfile.class); + + protected ObjectMapper mapper; + + public ResourceRegistryProfile() { + mapper = new ObjectMapper(); + } + + public ObjectMapper getMapper() { + return mapper; + } + + public ArrayNode list() { + ArrayNode arrayNode = mapper.createArrayNode(); + + try { + Set names = (new MetadataUtility()).getProfilesNames(); + for(String name : names) { + arrayNode.add(name); + } + return arrayNode; + } catch(Exception e) { + throw new InternalServerErrorException(e); + } + } + + /* + * https://wiki.gcube-system.org/gcube/GCube_Model#Configuration + */ + protected Configuration instantiateConfiguration(String name, String xml) throws Exception { + Configuration configuration = new ConfigurationImpl(); + + /* + IdentifierFacet identifierFacet = new IdentifierFacetImpl(); + identifierFacet.setValue(name); + identifierFacet.setType(IdentificationType.STRING); + IsIdentifiedBy isIdentifiedBy = new IsIdentifiedByImpl(configuration, identifierFacet); + configuration.addFacet(isIdentifiedBy); + */ + + SimpleFacet profile = new SimpleFacetImpl(); + profile.setAdditionalProperty(PROFILE, xml); + configuration.addFacet(profile); + + SchemaFacet schemaFacet = new SchemaFacetImpl(); + schemaFacet.setName("gCube Item Profile"); + schemaFacet.setDescription("gCube Metadata Profile defines a Metadata schema XML-based for adding custom metadata fields."); + + /* + ValueSchema valueSchema = new ValueSchemaImpl(); + valueSchema.setSchema(SCHEMA_URL.toURI()); + valueSchema.setValue(DataCalogueMetadataFormatReader.getProfileSchemaString()); + schemaFacet.setSchema(valueSchema); + */ + + configuration.addFacet(schemaFacet); + + return configuration; + } + + + protected Configuration getConfiguration(String name) throws ResourceRegistryException { + ResourceRegistryClient resourceRegistryClient = ResourceRegistryClientFactory.create(); + Map map = new HashMap<>(); + map.put(IdentifierFacet.VALUE_PROPERTY, name); + List configurations = resourceRegistryClient.getFilteredResources(Configuration.class, IsIdentifiedBy.class, IdentifierFacet.class, false, map); + return configurations.get(0); + } + + /* + * TODO Check the Queries because the name in the Profile differs from the name in + * + * + */ + protected GenericResource instantiateGenericResource(String name, String xml) throws Exception { + GenericResource genericResource = new GenericResource(); + org.gcube.common.resources.gcore.GenericResource.Profile profile = genericResource.newProfile(); + profile.type(MetadataFormatDiscovery.DATA_CATALOGUE_METADATA_SECONDARY_TYPE); + profile.name(name); + profile.description("Profile create using " + Constants.CATALOGUE_NAME); + // appendXmlFragment(profile, xml); + profile.newBody(xml); + StringWriter stringWriter = new StringWriter(); + Resources.marshal(genericResource, stringWriter); + logger.debug("The generated {} is\n{}", GenericResource.class.getSimpleName(), stringWriter.toString()); + return genericResource; + } + + protected void createGenericResource(String name, String xml) throws Exception { + GenericResource genericResource = instantiateGenericResource(name, xml); + RegistryPublisher registryPublisher = RegistryPublisherFactory.create(); + genericResource = registryPublisher.create(genericResource); + StringWriter stringWriter = new StringWriter(); + Resources.marshal(genericResource, stringWriter); + logger.trace("The {} with ID {} has been created \n{}", GenericResource.class.getSimpleName(), + genericResource.id(), stringWriter.toString()); + } + + protected GenericResource getGenericResource(String name) { + String query = QueryForResourceUtil.getGcubeGenericQueryStringForSecondaryTypeAndName(name, + MetadataFormatDiscovery.DATA_CATALOGUE_METADATA_SECONDARY_TYPE); + Query q = new QueryBox(query); + DiscoveryClient client = ICFactory.clientFor(GenericResource.class); + List resources = client.submit(q); + + if(resources == null || resources.size() == 0) { + throw new InternalServerErrorException( + "No Resources with secondaryType '" + MetadataFormatDiscovery.DATA_CATALOGUE_METADATA_SECONDARY_TYPE + + "' and name '" + name + "' exists in the current context"); + } else { + if(resources.size() == 1) { + GenericResource genericResource = resources.get(0); + return genericResource; + } else { + throw new InternalServerErrorException("More than one Resource with secondaryType '" + + MetadataFormatDiscovery.DATA_CATALOGUE_METADATA_SECONDARY_TYPE + "' and name '" + name + + "' exists in the current context"); + } + } + } + + protected void updateGenericResource(String name, String xml) { + + GenericResource genericResource = getGenericResource(name); + logger.info("The {} with ID {} is going to be updated", GenericResource.class.getSimpleName(), + genericResource.id()); + + genericResource.profile().newBody(xml); + RegistryPublisher registryPublisher = RegistryPublisherFactory.create(); + registryPublisher.update(genericResource); + + StringWriter stringWriter = new StringWriter(); + Resources.marshal(genericResource, stringWriter); + logger.trace("The {} with ID {} has been updated to \n{}", GenericResource.class.getSimpleName(), + genericResource.id(), stringWriter.toString()); + + } + + protected void removeGenericResource(String name) { + GenericResource genericResource = getGenericResource(name); + RegistryPublisher registryPublisher = RegistryPublisherFactory.create(); + registryPublisher.remove(genericResource); + } + + public String read(String name, boolean xml) { + try { + String profile = (new MetadataUtility()).getMetadataFormat(name).getMetadataSource(); + if(profile != null) { + if(xml) { + return profile; + } else { + JSONObject xmlJSONObj = XML.toJSONObject(profile); + String jsonString = xmlJSONObj.toString(PRETTY_PRINT_INDENT_FACTOR); + return jsonString; + } + } else { + throw new NotFoundException("Profile with name " + name + " not found"); + } + } catch(WebApplicationException e) { + throw e; + } catch(Exception e) { + throw new InternalServerErrorException(e.getMessage()); + } + } + + public boolean createOrUpdate(String name, String xml) throws SAXException { + try { + CKANUser ckanUser = CKANUserCache.getCurrrentCKANUser(); + if(ckanUser.getRole().ordinal() createdGroup, Map groups, String name) throws JsonProcessingException, IOException { + if(createdGroup.contains(name)) { + return; + } + String sysAdminAPI = ""; // CKANUtility.getSysAdminAPI(); + CKANGroup ckanGroupToCreate = new CKANGroup(); + ckanGroupToCreate.setApiKey(sysAdminAPI); + ckanGroupToCreate.setName(name); + // ckanGroupToCreate.purge(); + ObjectMapper objectMapper = new ObjectMapper(); + JsonNode jsonNode = objectMapper.readTree(groups.get(name)); + ArrayNode array = (ArrayNode) jsonNode.get("groups"); + for(JsonNode node : array) { + String parentName = node.get("name").asText(); + if(!createdGroup.contains(parentName)) { + create(createdGroup, groups, parentName); + } + } + ckanGroupToCreate.create(groups.get(name)); + createdGroup.add(name); + } + + // @Test + public void createGRSFGroups() throws ObjectNotFound, Exception { + // Setting GRSF ADMIN token of grsf.publisher user to read groups + ContextTest.setContext(""); + String key = CKANUtility.getSysAdminAPI(); + List groupNames = listGroup(); + Map groups = new HashMap<>(); + for(String name : groupNames) { + CKANGroup ckanGroup = new CKANGroup(); + ckanGroup.setApiKey(key); + ckanGroup.setName(name); + String read = ckanGroup.read(); + groups.put(name, read); + } + + Set createdGroup = new HashSet<>(); + + // Setting GRSF_PRE token of grsf.publisher user to create groups + ContextTest.setContext(""); + for(String name : groupNames) { + create(createdGroup, groups, name); + } + + } } diff --git a/src/test/java/org/gcube/gcat/persistence/ckan/CKANPackageTest.java b/src/test/java/org/gcube/gcat/persistence/ckan/CKANPackageTest.java index a6b9911..62f9180 100644 --- a/src/test/java/org/gcube/gcat/persistence/ckan/CKANPackageTest.java +++ b/src/test/java/org/gcube/gcat/persistence/ckan/CKANPackageTest.java @@ -286,7 +286,7 @@ public class CKANPackageTest extends ContextTest { itemObjectNode.put(CKANPackage.LICENSE_KEY, LICENSE_VALUE); itemObjectNode.put(PRIVATE_KEY, false); itemObjectNode.put(NOTES_KEY, "A research of Luca Frosini"); - itemObjectNode.put(URL_KEY, "http://www.d4science.org"); + itemObjectNode.put(URL_KEY, "https://www.d4science.org"); itemObjectNode.put(CKANPackage.OWNER_ORG_KEY, ckanOrganizationName); ArrayNode tagArrayNode = itemObjectNode.putArray(CKANPackage.TAGS_KEY); @@ -307,10 +307,12 @@ public class CKANPackageTest extends ContextTest { typeNode.put(CKANPackage.EXTRAS_VALUE_KEY, EXTRAS_TYPE_VALUE_VALUE); extraArrayNode.add(typeNode); + /* ObjectNode modelNode = mapper.createObjectNode(); modelNode.put(CKANPackage.EXTRAS_KEY_KEY, "test"); modelNode.put(CKANPackage.EXTRAS_VALUE_KEY, "test 2.9°"); extraArrayNode.add(modelNode); + */ ObjectNode populationNode = mapper.createObjectNode(); populationNode.put(CKANPackage.EXTRAS_KEY_KEY, "Population"); @@ -328,7 +330,7 @@ public class CKANPackageTest extends ContextTest { @Test public void create() throws Exception { - ContextTest.setContextByName("/gcube/devNext/NextNext"); + ContextTest.setContextByName("/gcube/devsec/devVRE"); ObjectMapper mapper = new ObjectMapper(); createPackage(mapper); } @@ -428,14 +430,14 @@ public class CKANPackageTest extends ContextTest { public void testUpdate() { CKANPackage ckanPackage = new CKANPackage(); ckanPackage.setName("knime_workflow_with_joined_consumer_phase_and_dose_response_model"); - ckanPackage.update("{\"rating\":0.0,\"license_title\":\"Academic Free License 3.0\",\"maintainer\":\"\",\"relationships_as_object\":[],\"private\":false,\"maintainer_email\":\"\",\"num_tags\":5,\"id\":\"f4292d0e-c94f-4542-bfa3-25f78638fc1b\",\"metadata_created\":\"2020-01-07T16:40:16.987780\",\"owner_org\":\"3571cca5-b0ae-4dc6-b791-434a8e062ce5\",\"metadata_modified\":\"2020-02-03T14:24:59.221160\",\"author\":\"Buschhardt Tasja\",\"author_email\":\"tasja.buschhardt@bfr.bund.de\",\"state\":\"active\",\"version\":\"1\",\"license_id\":\"AFL-3.0\",\"type\":\"dataset\",\"resources\":[{\"cache_last_updated\":null,\"cache_url\":null,\"mimetype_inner\":null,\"hash\":\"\",\"description\":\"\",\"format\":\"knwf\",\"url\":\"https://data.d4science.net/g9QY\",\"created\":\"2019-09-16T20:49:02.168666\",\"state\":\"active\",\"package_id\":\"f4292d0e-c94f-4542-bfa3-25f78638fc1b\",\"last_modified\":null,\"mimetype\":null,\"url_type\":null,\"position\":0,\"revision_id\":\"a84a35ec-2786-4835-9f50-ad52202c4e33\",\"size\":null,\"datastore_active\":false,\"id\":\"0734b380-ea5d-4c99-be03-c38ff6ae6fbf\",\"resource_type\":null,\"name\":\"KNIME_WF_ICPMF11\"}],\"num_resources\":1,\"tags\":[{\"vocabulary_id\":null,\"state\":\"active\",\"display_name\":\"Campylobacter\",\"id\":\"84c76669-d135-4c5e-9e3a-b163689a10de\",\"name\":\"Campylobacter\"},{\"vocabulary_id\":null,\"state\":\"active\",\"display_name\":\"KNIME workflow\",\"id\":\"30bce4d2-fc45-46ab-8f8b-5da582fff3c3\",\"name\":\"KNIME workflow\"},{\"vocabulary_id\":null,\"state\":\"active\",\"display_name\":\"chicken meat\",\"id\":\"f1aac698-a865-4bf4-ac55-b53f8bf7ecac\",\"name\":\"chicken meat\"},{\"vocabulary_id\":null,\"state\":\"active\",\"display_name\":\"consumer phase model\",\"id\":\"9e6b2337-9ac0-4bfc-8e7f-4327c531bbec\",\"name\":\"consumer phase model\"},{\"vocabulary_id\":null,\"state\":\"active\",\"display_name\":\"dose response model\",\"id\":\"21311c09-a928-4a9a-83de-7ef98b257af5\",\"name\":\"dose response model\"}],\"groups\":[],\"creator_user_id\":\"7020f836-45f4-4ee8-9c65-e7504209644f\",\"relationships_as_subject\":[],\"name\":\"knime_workflow_with_joined_consumer_phase_and_dose_response_model\",\"isopen\":true,\"url\":\"\",\"notes\":\"This KNIME workflow shows how to use FSK-Lab to read, customise, run, \\r\\ncombine and change simulation settings for food safety models- specifically \\r\\nthis workflow exemplifies a joined consumer phase model for Campylobacter \\r\\nin chicken meat and a dose response model for Campylobacter\",\"title\":\"KNIME workflow with joined consumer phase and dose response model\",\"extras\":[{\"value\":\"\",\"key\":\"Author\"},{\"value\":\"http://data.d4science.org/ctlg/RAKIP_trial/knime_workflow_with_joined_consumer_phase_and_dose_response_model\",\"key\":\"Item URL\"},{\"value\":\"ResearchObject\",\"key\":\"system:type\"},{\"value\":\"{\\\"relatedIdentifierType\\\":\\\"URL\\\",\\\"relationType\\\":\\\"isReferencedBy\\\",\\\"link\\\":\\\"https://doi.org/10.5072/zenodo.488235\\\",\\\"zenodoId\\\":488235}\",\"key\":\"relatedIdentifier:Zenodo.DOI\"}],\"license_url\":\"http://www.opensource.org/licenses/AFL-3.0\",\"ratings_count\":0,\"organization\":{\"description\":\"\",\"title\":\"devVRE\",\"created\":\"2016-05-30T11:30:41.710079\",\"approval_status\":\"approved\",\"is_organization\":true,\"state\":\"active\",\"image_url\":\"\",\"revision_id\":\"7c8463df-ed3f-4d33-87d8-6c0bcbe30d5d\",\"type\":\"organization\",\"id\":\"3571cca5-b0ae-4dc6-b791-434a8e062ce5\",\"name\":\"devvre\"},\"revision_id\":\"9f51fa28-0732-46c9-a208-9a0e6da0cd2c\"}"); + ckanPackage.update("{\"rating\":0.0,\"license_title\":\"Academic Free License 3.0\",\"maintainer\":\"\",\"relationships_as_object\":[],\"private\":false,\"maintainer_email\":\"\",\"num_tags\":5,\"id\":\"f4292d0e-c94f-4542-bfa3-25f78638fc1b\",\"metadata_created\":\"2020-01-07T16:40:16.987780\",\"owner_org\":\"3571cca5-b0ae-4dc6-b791-434a8e062ce5\",\"metadata_modified\":\"2020-02-03T14:24:59.221160\",\"author\":\"Buschhardt Tasja\",\"author_email\":\"tasja.buschhardt@bfr.bund.de\",\"state\":\"active\",\"version\":\"1\",\"license_id\":\"AFL-3.0\",\"type\":\"dataset\",\"resources\":[{\"cache_last_updated\":null,\"cache_url\":null,\"mimetype_inner\":null,\"hash\":\"\",\"description\":\"\",\"format\":\"knwf\",\"url\":\"https://data.d4science.net/g9QY\",\"created\":\"2019-09-16T20:49:02.168666\",\"state\":\"active\",\"package_id\":\"f4292d0e-c94f-4542-bfa3-25f78638fc1b\",\"last_modified\":null,\"mimetype\":null,\"url_type\":null,\"position\":0,\"revision_id\":\"a84a35ec-2786-4835-9f50-ad52202c4e33\",\"size\":null,\"datastore_active\":false,\"id\":\"0734b380-ea5d-4c99-be03-c38ff6ae6fbf\",\"resource_type\":null,\"name\":\"KNIME_WF_ICPMF11\"}],\"num_resources\":1,\"tags\":[{\"vocabulary_id\":null,\"state\":\"active\",\"display_name\":\"Campylobacter\",\"id\":\"84c76669-d135-4c5e-9e3a-b163689a10de\",\"name\":\"Campylobacter\"},{\"vocabulary_id\":null,\"state\":\"active\",\"display_name\":\"KNIME workflow\",\"id\":\"30bce4d2-fc45-46ab-8f8b-5da582fff3c3\",\"name\":\"KNIME workflow\"},{\"vocabulary_id\":null,\"state\":\"active\",\"display_name\":\"chicken meat\",\"id\":\"f1aac698-a865-4bf4-ac55-b53f8bf7ecac\",\"name\":\"chicken meat\"},{\"vocabulary_id\":null,\"state\":\"active\",\"display_name\":\"consumer phase model\",\"id\":\"9e6b2337-9ac0-4bfc-8e7f-4327c531bbec\",\"name\":\"consumer phase model\"},{\"vocabulary_id\":null,\"state\":\"active\",\"display_name\":\"dose response model\",\"id\":\"21311c09-a928-4a9a-83de-7ef98b257af5\",\"name\":\"dose response model\"}],\"groups\":[],\"creator_user_id\":\"7020f836-45f4-4ee8-9c65-e7504209644f\",\"relationships_as_subject\":[],\"name\":\"knime_workflow_with_joined_consumer_phase_and_dose_response_model\",\"isopen\":true,\"url\":\"\",\"notes\":\"This KNIME workflow shows how to use FSK-Lab to read, customise, run, \\r\\ncombine and change simulation settings for food safety models- specifically \\r\\nthis workflow exemplifies a joined consumer phase model for Campylobacter \\r\\nin chicken meat and a dose response model for Campylobacter\",\"title\":\"KNIME workflow with joined consumer phase and dose response model\",\"extras\":[{\"value\":\"\",\"key\":\"Author\"},{\"value\":\"https://data.d4science.org/ctlg/RAKIP_trial/knime_workflow_with_joined_consumer_phase_and_dose_response_model\",\"key\":\"Item URL\"},{\"value\":\"ResearchObject\",\"key\":\"system:type\"},{\"value\":\"{\\\"relatedIdentifierType\\\":\\\"URL\\\",\\\"relationType\\\":\\\"isReferencedBy\\\",\\\"link\\\":\\\"https://doi.org/10.5072/zenodo.488235\\\",\\\"zenodoId\\\":488235}\",\"key\":\"relatedIdentifier:Zenodo.DOI\"}],\"license_url\":\"https://www.opensource.org/licenses/AFL-3.0\",\"ratings_count\":0,\"organization\":{\"description\":\"\",\"title\":\"devVRE\",\"created\":\"2016-05-30T11:30:41.710079\",\"approval_status\":\"approved\",\"is_organization\":true,\"state\":\"active\",\"image_url\":\"\",\"revision_id\":\"7c8463df-ed3f-4d33-87d8-6c0bcbe30d5d\",\"type\":\"organization\",\"id\":\"3571cca5-b0ae-4dc6-b791-434a8e062ce5\",\"name\":\"devvre\"},\"revision_id\":\"9f51fa28-0732-46c9-a208-9a0e6da0cd2c\"}"); } @Test public void testUpdate2() { CKANPackage ckanPackage = new CKANPackage(); ckanPackage.setName("vre_picture"); - ckanPackage.update("{\"rating\": 0.0, \"license_title\": \"Academic Free License 3.0\", \"maintainer\": \"Kerekes Kata\", \"relationships_as_object\": [], \"private\": false, \"maintainer_email\": \"kerekeska@nebih.gov.hu\", \"num_tags\": 1, \"id\": \"7731b70f-47ff-4b74-b943-188215e82d07\", \"metadata_created\": \"2020-01-07T16:40:24.822719\", \"owner_org\": \"3571cca5-b0ae-4dc6-b791-434a8e062ce5\", \"metadata_modified\": \"2020-02-03T15:16:42.596068\", \"author\": \"Kerekes Kata\", \"author_email\": \"kerekeska@nebih.gov.hu\", \"state\": \"active\", \"version\": \"1\", \"license_id\": \"AFL-3.0\", \"type\": \"dataset\", \"resources\": [{\"cache_last_updated\": null, \"cache_url\": null, \"mimetype_inner\": null, \"hash\": \"\", \"description\": \"\", \"format\": \"JPEG\", \"url\": \"https://goo.gl/SnwAM7\", \"created\": \"2019-04-01T13:24:40.738838\", \"state\": \"active\", \"package_id\": \"7731b70f-47ff-4b74-b943-188215e82d07\", \"last_modified\": null, \"mimetype\": \"image/jpeg\", \"url_type\": null, \"position\": 0, \"revision_id\": \"06d61000-a0c1-4155-ad2d-78ede56d6bb5\", \"size\": null, \"datastore_active\": false, \"id\": \"1de8851d-1385-47ae-9c93-6040d170a9cc\", \"resource_type\": null, \"name\": \"th.jpeg\"}], \"num_resources\": 1, \"tags\": [{\"vocabulary_id\": null, \"state\": \"active\", \"display_name\": \"DEMETER\", \"id\": \"4e05058b-a006-4dbf-94f5-277a30318323\", \"name\": \"DEMETER\"}], \"groups\": [], \"creator_user_id\": \"7020f836-45f4-4ee8-9c65-e7504209644f\", \"relationships_as_subject\": [], \"name\": \"vre_picture\", \"isopen\": true, \"url\": \"\", \"notes\": \"This is a nice picture of a VRE ;)\", \"title\": \"VRE picture\", \"extras\": [{\"value\": \"http://data.d4science.org/ctlg/DEMETER_trial/vre_picture\", \"key\": \"Item URL\"}, {\"value\": \"ResearchObject\", \"key\": \"system:type\"}], \"license_url\": \"http://www.opensource.org/licenses/AFL-3.0\", \"ratings_count\": 0, \"organization\": {\"description\": \"\", \"title\": \"devVRE\", \"created\": \"2016-05-30T11:30:41.710079\", \"approval_status\": \"approved\", \"is_organization\": true, \"state\": \"active\", \"image_url\": \"\", \"revision_id\": \"7c8463df-ed3f-4d33-87d8-6c0bcbe30d5d\", \"type\": \"organization\", \"id\": \"3571cca5-b0ae-4dc6-b791-434a8e062ce5\", \"name\": \"devvre\"}, \"revision_id\": \"bdb6169a-6268-43d6-b7e1-265c0c9e1a1c\"}"); + ckanPackage.update("{\"rating\": 0.0, \"license_title\": \"Academic Free License 3.0\", \"maintainer\": \"Kerekes Kata\", \"relationships_as_object\": [], \"private\": false, \"maintainer_email\": \"kerekeska@nebih.gov.hu\", \"num_tags\": 1, \"id\": \"7731b70f-47ff-4b74-b943-188215e82d07\", \"metadata_created\": \"2020-01-07T16:40:24.822719\", \"owner_org\": \"3571cca5-b0ae-4dc6-b791-434a8e062ce5\", \"metadata_modified\": \"2020-02-03T15:16:42.596068\", \"author\": \"Kerekes Kata\", \"author_email\": \"kerekeska@nebih.gov.hu\", \"state\": \"active\", \"version\": \"1\", \"license_id\": \"AFL-3.0\", \"type\": \"dataset\", \"resources\": [{\"cache_last_updated\": null, \"cache_url\": null, \"mimetype_inner\": null, \"hash\": \"\", \"description\": \"\", \"format\": \"JPEG\", \"url\": \"https://goo.gl/SnwAM7\", \"created\": \"2019-04-01T13:24:40.738838\", \"state\": \"active\", \"package_id\": \"7731b70f-47ff-4b74-b943-188215e82d07\", \"last_modified\": null, \"mimetype\": \"image/jpeg\", \"url_type\": null, \"position\": 0, \"revision_id\": \"06d61000-a0c1-4155-ad2d-78ede56d6bb5\", \"size\": null, \"datastore_active\": false, \"id\": \"1de8851d-1385-47ae-9c93-6040d170a9cc\", \"resource_type\": null, \"name\": \"th.jpeg\"}], \"num_resources\": 1, \"tags\": [{\"vocabulary_id\": null, \"state\": \"active\", \"display_name\": \"DEMETER\", \"id\": \"4e05058b-a006-4dbf-94f5-277a30318323\", \"name\": \"DEMETER\"}], \"groups\": [], \"creator_user_id\": \"7020f836-45f4-4ee8-9c65-e7504209644f\", \"relationships_as_subject\": [], \"name\": \"vre_picture\", \"isopen\": true, \"url\": \"\", \"notes\": \"This is a nice picture of a VRE ;)\", \"title\": \"VRE picture\", \"extras\": [{\"value\": \"https://data.d4science.org/ctlg/DEMETER_trial/vre_picture\", \"key\": \"Item URL\"}, {\"value\": \"ResearchObject\", \"key\": \"system:type\"}], \"license_url\": \"https://www.opensource.org/licenses/AFL-3.0\", \"ratings_count\": 0, \"organization\": {\"description\": \"\", \"title\": \"devVRE\", \"created\": \"2016-05-30T11:30:41.710079\", \"approval_status\": \"approved\", \"is_organization\": true, \"state\": \"active\", \"image_url\": \"\", \"revision_id\": \"7c8463df-ed3f-4d33-87d8-6c0bcbe30d5d\", \"type\": \"organization\", \"id\": \"3571cca5-b0ae-4dc6-b791-434a8e062ce5\", \"name\": \"devvre\"}, \"revision_id\": \"bdb6169a-6268-43d6-b7e1-265c0c9e1a1c\"}"); } /* diff --git a/src/test/java/org/gcube/gcat/social/SocialPostTest.java b/src/test/java/org/gcube/gcat/social/SocialPostTest.java index 47e44ca..e2daea2 100644 --- a/src/test/java/org/gcube/gcat/social/SocialPostTest.java +++ b/src/test/java/org/gcube/gcat/social/SocialPostTest.java @@ -25,7 +25,7 @@ public class SocialPostTest extends ContextTest { SocialPost socialService = new SocialPost(); socialService.setItemID(UUID.randomUUID().toString()); socialService.setItemTitle("Test Item"); - socialService.setItemURL("http://www.d4science.org"); + socialService.setItemURL("https://www.d4science.org"); List tags = new ArrayList<>(); tags.add("Test"); tags.add("ThisIsATest");