Merge remote-tracking branch 'origin/feature/20225'

This commit is contained in:
Luca Frosini 2021-04-14 15:07:14 +02:00
commit 6cab331db0
14 changed files with 426 additions and 47 deletions

View File

@ -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]

32
pom.xml
View File

@ -9,10 +9,10 @@
<relativePath />
</parent>
<groupId>org.gcube.data-publishing</groupId>
<groupId>org.gcube.data-catalogue</groupId>
<artifactId>gcat</artifactId>
<packaging>war</packaging>
<version>1.4.5</version>
<version>2.0.0-SNAPSHOT</version>
<name>gCube Catalogue (gCat) Service</name>
<description>
This service allows any client to publish on the gCube Catalogue.
@ -21,7 +21,7 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<webappDirectory>${project.basedir}${file.separator}src${file.separator}main${file.separator}webapp${file.separator}WEB-INF</webappDirectory>
<serviceClass>DataPublishing</serviceClass>
<serviceClass>data-catalogue</serviceClass>
</properties>
<scm>
@ -44,14 +44,36 @@
<dependencies>
<dependency>
<groupId>org.gcube.data-publishing</groupId>
<groupId>org.gcube.data-catalogue</groupId>
<artifactId>gcat-api</artifactId>
<version>[1.2.2, 2.0.0-SNAPSHOT)</version>
<version>[2.0.0-SNAPSHOT, 3.0.0-SNAPSHOT)</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.gcube.information-system</groupId>
<artifactId>information-system-model</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.gcube.resource-management</groupId>
<artifactId>gcube-model</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.gcube.information-system</groupId>
<artifactId>resource-registry-client</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.gcube.information-system</groupId>
<artifactId>resource-registry-publisher</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.gcube.data-catalogue</groupId>
<artifactId>gcubedatacatalogue-metadata-discovery</artifactId>

View File

@ -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<String> 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!");
}

View File

@ -129,6 +129,7 @@ public abstract class CKAN {
throw new BadRequestException(e);
}
}
/**
* Validate the CKAN response and return the

View File

@ -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";

View File

@ -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() {

View File

@ -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

View File

@ -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 {

View File

@ -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";

View File

@ -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";

View File

@ -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<String> 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<Configuration, IdentifierFacet> isIdentifiedBy = new IsIdentifiedByImpl<Configuration, IdentifierFacet>(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<String, String> map = new HashMap<>();
map.put(IdentifierFacet.VALUE_PROPERTY, name);
List<Configuration> 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
* <metadataformat type="Dataset">
*
*/
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<GenericResource> client = ICFactory.clientFor(GenericResource.class);
List<GenericResource> 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()<Role.ADMIN.ordinal()) {
throw new NotAuthorizedException("You are not authorized to manage profiles, only Catalogue Editor can manipulate profiles.");
}
MetadataUtility metadataUtility = new MetadataUtility();
metadataUtility.validateProfile(xml);
if(metadataUtility.getMetadataFormat(name) == null) {
createGenericResource(name, xml);
return true;
} else {
updateGenericResource(name, xml);
return false;
}
} catch(WebApplicationException e) {
throw e;
} catch(SAXException e) {
throw e;
} catch(Exception e) {
throw new InternalServerErrorException(e);
} finally {
// TOOD Actually Cache has been removed. Remove the following code if it will not be re-introduced
// Cleaning the cache
// MetadataUtility.clearCache();
}
}
public boolean delete(String name) {
try {
CKANUser ckanUser = CKANUserCache.getCurrrentCKANUser();
if(ckanUser.getRole().ordinal()<Role.EDITOR.ordinal()) {
throw new NotAuthorizedException("You are not authorized to manage profiles, only Catalogue Editor can manipulate profiles.");
}
MetadataUtility metadataUtility = new MetadataUtility();
if(metadataUtility.getMetadataFormat(name) == null) {
throw new NotFoundException("Profile with name " + name + " not found");
} else {
removeGenericResource(name);
return true;
}
} catch(WebApplicationException e) {
throw e;
} catch(Exception e) {
throw new InternalServerErrorException(e.getMessage());
} finally {
// Cleaning the cache
// MetadataUtility.clearCache();
}
}
}

View File

@ -1,15 +1,23 @@
package org.gcube.gcat.persistence.ckan;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.gcube.com.fasterxml.jackson.core.JsonProcessingException;
import org.gcube.com.fasterxml.jackson.databind.JsonNode;
import org.gcube.com.fasterxml.jackson.databind.ObjectMapper;
import org.gcube.com.fasterxml.jackson.databind.node.ArrayNode;
import org.gcube.common.authorization.client.exceptions.ObjectNotFound;
import org.gcube.gcat.ContextTest;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.gcube.com.fasterxml.jackson.databind.ObjectMapper;
public class CKANGroupTest extends ContextTest {
private static Logger logger = LoggerFactory.getLogger(CKANGroupTest.class);
@ -76,4 +84,51 @@ public class CKANGroupTest extends ContextTest {
ckanGroup.delete(true);
}
}
private void create(Set<String> createdGroup, Map<String, String> 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<String> groupNames = listGroup();
Map<String, String> 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<String> createdGroup = new HashSet<>();
// Setting GRSF_PRE token of grsf.publisher user to create groups
ContextTest.setContext("");
for(String name : groupNames) {
create(createdGroup, groups, name);
}
}
}

View File

@ -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\"}");
}
/*

View File

@ -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<String> tags = new ArrayList<>();
tags.add("Test");
tags.add("ThisIsATest");