From c4629e78be03ea15d81109f1d48007cd46a75b94 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Thu, 8 Feb 2024 15:00:19 +0100 Subject: [PATCH 1/5] Added method update item [#26640] --- CHANGELOG.md | 6 ++ pom.xml | 4 +- .../utillibrary/server/DataCatalogue.java | 30 ++++++++++ .../utillibrary/server/DataCatalogueImpl.java | 55 ++++++++++++++++++- .../server/utils/CKANConveter.java | 4 +- .../utillibrary/test/ContextTest.java | 13 ++++- .../test/TestDataCatalogueCMS.java | 2 - .../test/TestDataCatalogueLib.java | 42 ++++++++------ 8 files changed, 128 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 736f133..19095da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [v1.4.0-SNAPSHOT] - 2024-02-08 + +**Enhancements** + +- Added method update item [#26640] + ## [v1.3.0] - 2023-02-06 **Enhancements** diff --git a/pom.xml b/pom.xml index 976a77a..4f26798 100644 --- a/pom.xml +++ b/pom.xml @@ -6,13 +6,13 @@ maven-parent org.gcube.tools - 1.1.0 + 1.2.0 org.gcube.datacatalogue catalogue-util-library - 1.3.0 + 1.4.0-SNAPSHOT Ckan utility library Utility library to retrieve users information, organizations information and so on from the ckan d4science datacatalogue diff --git a/src/main/java/org/gcube/datacatalogue/utillibrary/server/DataCatalogue.java b/src/main/java/org/gcube/datacatalogue/utillibrary/server/DataCatalogue.java index 5250398..d60d482 100644 --- a/src/main/java/org/gcube/datacatalogue/utillibrary/server/DataCatalogue.java +++ b/src/main/java/org/gcube/datacatalogue/utillibrary/server/DataCatalogue.java @@ -331,6 +331,36 @@ public interface DataCatalogue { String description, String licenseId, List tags, Map> customFieldsMultiple, List resources, boolean setPublic, boolean setSearchable, boolean socialPost) throws Exception; + + + /** + * Update ckan dataset multiple custom fields. + * + * @param username the username + * @param title the title + * @param name the name + * @param organizationName the organization name + * @param author the author + * @param authorMail the author mail + * @param maintainer the maintainer + * @param maintainerMail the maintainer mail + * @param version the version + * @param description the description + * @param licenseId the license id + * @param tags the tags + * @param customFieldsMultiple the custom fields multiple + * @param resources the resources + * @param setPublic the set public + * @param setSearchable the set searchable + * @param socialPost the social post + * @return the string + * @throws Exception the exception + */ + String updateCkanDatasetMultipleCustomFields(String username, String title, String name, String organizationName, + String author, String authorMail, String maintainer, String maintainerMail, long version, + String description, String licenseId, List tags, Map> customFieldsMultiple, + List resources, boolean setPublic, boolean setSearchable, boolean socialPost) + throws Exception; /** * Add a resource described by the bean to the dataset id into diff --git a/src/main/java/org/gcube/datacatalogue/utillibrary/server/DataCatalogueImpl.java b/src/main/java/org/gcube/datacatalogue/utillibrary/server/DataCatalogueImpl.java index a5e664e..2e044aa 100644 --- a/src/main/java/org/gcube/datacatalogue/utillibrary/server/DataCatalogueImpl.java +++ b/src/main/java/org/gcube/datacatalogue/utillibrary/server/DataCatalogueImpl.java @@ -866,7 +866,7 @@ public class DataCatalogueImpl implements DataCatalogue { // in order to avoid errors, the username is always converted String ckanUsername = CatalogueUtilMethods.fromUsernameToCKanUsername(username); - LOG.debug("username: "+username + " converted to ckanUsername: "+ckanUsername); + LOG.debug("username: " + username + " converted to ckanUsername: " + ckanUsername); // check in the hashmap first if (apiKeysMap.containsKey(ckanUsername)) { @@ -1305,7 +1305,7 @@ public class DataCatalogueImpl implements DataCatalogue { if (jsonValueDataset != null) { CkanDataset toCkanDataset = MarshUnmarshCkanObject.toCkanDataset(jsonValueDataset, METHOD.TO_READ); - LOG.info("Dataset with name " + toCkanDataset.getName() + " has been created correctly"); + LOG.info("Dataset with name " + toCkanDataset.getName() + " has been correctly created"); return toCkanDataset.getId(); } } catch (Exception e) { @@ -1320,6 +1320,57 @@ public class DataCatalogueImpl implements DataCatalogue { return null; } + @Override + public String updateCkanDatasetMultipleCustomFields(String username, String title, String name, + String organizationName, String author, String authorMail, String maintainer, String maintainerMail, + long version, String description, String licenseId, List tags, + Map> customFieldsMultiple, List resources, boolean setPublic, + boolean setSearchable, boolean socialPost) throws Exception { + LOG.info("Called updateCkanDatasetMultipleCustomFields"); + + // checks (minimum) + checkNotNull(username); + // checkNotNull(organizationNameOrId); + // checkArgument(!organizationNameOrId.isEmpty()); + checkArgument(!(title == null && name == null || title.isEmpty() && name.isEmpty()), + "Name and Title cannot be empty/null at the same time!"); + + GcubeContext gcubeContext = null; + try { + + gcubeContext = GCubeUtils.detectAndSetTheOrgNameContext(organizationName, username, true); + + String toPassOrganizationToGcat = null; // Not needed to pass this information to gCat, never. + // String ckanUsername = getUserFromApiKey(apiKey).getName(); + LOG.debug("The visibility parameter passed is (isPublic): " + setPublic); + CkanDataset dataset = CKANConveter.toCkanDataset(ckanCaller, username, title, name, + toPassOrganizationToGcat, author, authorMail, maintainer, maintainerMail, version, description, + licenseId, tags, null, customFieldsMultiple, resources, setPublic, setSearchable); + + LOG.debug("The isPriv property into dataset is: " + dataset.isPriv()); + // trying to create by gCat + String jsonValueDataset = MarshUnmarshCkanObject.toJsonValueDataset(dataset, METHOD.TO_CREATE); + LOG.info("Serialized dataset to update is: " + jsonValueDataset); + jsonValueDataset = gCatCaller.updateDataset(name, jsonValueDataset); + LOG.debug("Updated dataset is: " + jsonValueDataset); + + if (jsonValueDataset != null) { + CkanDataset toCkanDataset = MarshUnmarshCkanObject.toCkanDataset(jsonValueDataset, METHOD.TO_READ); + LOG.info("Dataset with name " + toCkanDataset.getName() + " has been correctly updated"); + return toCkanDataset.getId(); + } + } catch (Exception e) { + LOG.error("Error on updating the dataset: ", e); + throw e; + } finally { + + if (gcubeContext != null) + GCubeUtils.revertToSourceContext(gcubeContext); + } + + return null; + } + /** * Refresh dataset. * diff --git a/src/main/java/org/gcube/datacatalogue/utillibrary/server/utils/CKANConveter.java b/src/main/java/org/gcube/datacatalogue/utillibrary/server/utils/CKANConveter.java index 5e79e01..4b104df 100644 --- a/src/main/java/org/gcube/datacatalogue/utillibrary/server/utils/CKANConveter.java +++ b/src/main/java/org/gcube/datacatalogue/utillibrary/server/utils/CKANConveter.java @@ -68,8 +68,10 @@ public class CKANConveter { String ckanUsername = CatalogueUtilMethods.fromUsernameToCKanUsername(username); String nameToUse = name; - if(nameToUse == null) + //Applying normalize function if and only if the paramenter 'name' is null + if(nameToUse == null) { nameToUse = CatalogueUtilMethods.fromProductTitleToName(title); + } LOG.debug("Name of the dataset is going to be " + nameToUse + ". Title is going to be " + title); diff --git a/src/test/java/org/gcube/datacatalogue/utillibrary/test/ContextTest.java b/src/test/java/org/gcube/datacatalogue/utillibrary/test/ContextTest.java index 82abe9f..af885c7 100644 --- a/src/test/java/org/gcube/datacatalogue/utillibrary/test/ContextTest.java +++ b/src/test/java/org/gcube/datacatalogue/utillibrary/test/ContextTest.java @@ -27,9 +27,16 @@ public class ContextTest { protected static Properties properties; protected static final String PROPERTIES_FILENAME = "token.properties"; - public static final String ROOT = "/gcube"; - public static final String VO = ROOT + "/devsec"; - public static final String VRE = VO + "/devVRE"; +// public static final String ROOT = "/gcube"; +// public static final String VO = ROOT + "/devsec"; +// public static final String VRE = VO + "/devVRE"; + + + public static final String ROOT = "/d4science.research-infrastructures.eu"; + public static final String VO = ROOT + "/D4OS"; + public static final String VRE = VO + "/Blue-Cloud2026Project"; + + public static final String scope = VRE; static { properties = new Properties(); diff --git a/src/test/java/org/gcube/datacatalogue/utillibrary/test/TestDataCatalogueCMS.java b/src/test/java/org/gcube/datacatalogue/utillibrary/test/TestDataCatalogueCMS.java index d34c9a5..860bfa9 100644 --- a/src/test/java/org/gcube/datacatalogue/utillibrary/test/TestDataCatalogueCMS.java +++ b/src/test/java/org/gcube/datacatalogue/utillibrary/test/TestDataCatalogueCMS.java @@ -14,8 +14,6 @@ import org.gcube.datacatalogue.utillibrary.server.cms.CatalogueContentModeratorS import org.gcube.datacatalogue.utillibrary.shared.ItemStatus; import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanDataset; import org.gcube.gcat.client.Item; -import org.junit.Before; -import org.junit.Test; import org.slf4j.LoggerFactory; /** diff --git a/src/test/java/org/gcube/datacatalogue/utillibrary/test/TestDataCatalogueLib.java b/src/test/java/org/gcube/datacatalogue/utillibrary/test/TestDataCatalogueLib.java index 7eb0b57..5d0672c 100644 --- a/src/test/java/org/gcube/datacatalogue/utillibrary/test/TestDataCatalogueLib.java +++ b/src/test/java/org/gcube/datacatalogue/utillibrary/test/TestDataCatalogueLib.java @@ -7,7 +7,6 @@ import java.util.List; import java.util.Map; import java.util.Random; -import org.gcube.common.authorization.library.provider.SecurityTokenProvider; import org.gcube.common.scope.api.ScopeProvider; import org.gcube.datacatalogue.utillibrary.ckan.MarshUnmarshCkanObject; import org.gcube.datacatalogue.utillibrary.ckan.MarshUnmarshCkanObject.METHOD; @@ -28,12 +27,12 @@ import org.slf4j.LoggerFactory; * * @author Francesco Mangiacrapa at ISTI-CNR Pisa (Italy) Jun 1, 2020 */ -public class TestDataCatalogueLib { +public class TestDataCatalogueLib extends ContextTest{ private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(TestDataCatalogueLib.class); private DataCatalogueFactory factory; - private String scope = "/gcube/devsec/devVRE"; + //private String scope = "/gcube/devsec/devVRE"; // private String scope = "/gcube"; // private String scope = "/pred4s/preprod/preVRE"; // private String scope = @@ -42,7 +41,7 @@ public class TestDataCatalogueLib { // "/d4science.research-infrastructures.eu/gCubeApps/BiodiversityLab"; // private String testUser = "costantino_perciante"; private String testUser = "francesco.mangiacrapa"; - private String authorizationToken = ""; + //private String authorizationToken = ""; String subjectId = "aa_father4"; String objectId = "bb_son4"; String productName = "adatasetcreatedbycatalogue-util-library-873805063"; @@ -52,7 +51,7 @@ public class TestDataCatalogueLib { * * @throws Exception the exception */ - // @Before + @Before public void before() throws Exception { factory = DataCatalogueFactory.getFactory(); } @@ -124,10 +123,17 @@ public class TestDataCatalogueLib { */ //@Test public void getDataset() throws Exception { + + String datasetname = "blue-cloud_2026_-_a_federated_european_fair_and_open_research_ecosystem_for_oceans_seas_coastal_and"; + DataCatalogueImpl instance = factory.getUtilsPerScope(scope); String username = testUser; - CkanDataset dataset = instance.getDataset("my_first_restful_transaction_model_private", username); + CkanDataset dataset = instance.getDataset(datasetname, username); LOG.debug("Got dataset: " + dataset.getName() + ", with id: " + dataset.getId()); + LOG.debug("Got getAuthor: " + dataset.getAuthor()); + LOG.debug("Got getAuthorEmail: " + dataset.getAuthorEmail()); + LOG.debug("Got getMantainer: " + dataset.getMaintainer()); + LOG.debug("Got getMaintainerEmail: " + dataset.getMaintainerEmail()); } /** @@ -236,8 +242,8 @@ public class TestDataCatalogueLib { try { - ScopeProvider.instance.set(scope); - SecurityTokenProvider.instance.set(authorizationToken); +// ScopeProvider.instance.set(scope); +// SecurityTokenProvider.instance.set(authorizationToken); DataCatalogueImpl instance = factory.getUtilsPerScope(scope); String licenseId = instance.getLicenses().get(0).getId(); @@ -282,8 +288,8 @@ public class TestDataCatalogueLib { // @Test public void createGroup() throws Exception { - ScopeProvider.instance.set(scope); - SecurityTokenProvider.instance.set(authorizationToken); +// ScopeProvider.instance.set(scope); +// SecurityTokenProvider.instance.set(authorizationToken); DataCatalogueImpl instance = factory.getUtilsPerScope(scope); int random = new Random().nextInt(); @@ -296,8 +302,8 @@ public class TestDataCatalogueLib { // @Test public void addResource() throws Exception { - ScopeProvider.instance.set(scope); - SecurityTokenProvider.instance.set(authorizationToken); +// ScopeProvider.instance.set(scope); +// SecurityTokenProvider.instance.set(authorizationToken); DataCatalogueImpl instance = factory.getUtilsPerScope(scope); CkanDataset dataset = instance.getDataset(productName, testUser); @@ -312,8 +318,8 @@ public class TestDataCatalogueLib { // @Test public void deleteResource() throws Exception { - ScopeProvider.instance.set(scope); - SecurityTokenProvider.instance.set(authorizationToken); +// ScopeProvider.instance.set(scope); +// SecurityTokenProvider.instance.set(authorizationToken); DataCatalogueImpl instance = factory.getUtilsPerScope(scope); String resourceId = "ce7295cf-47db-4faf-901f-4fec2d3fae7a"; @@ -325,8 +331,8 @@ public class TestDataCatalogueLib { // @Test public void patchFieldsForDataset() throws Exception { - ScopeProvider.instance.set(scope); - SecurityTokenProvider.instance.set(authorizationToken); +// ScopeProvider.instance.set(scope); +// SecurityTokenProvider.instance.set(authorizationToken); DataCatalogueImpl instance = factory.getUtilsPerScope(scope); Map customFieldsToChange = new HashMap(); @@ -337,8 +343,8 @@ public class TestDataCatalogueLib { // @Test public void getUrlProduct() throws Exception { - ScopeProvider.instance.set(scope); - SecurityTokenProvider.instance.set(authorizationToken); +// ScopeProvider.instance.set(scope); +// SecurityTokenProvider.instance.set(authorizationToken); DataCatalogueImpl instance = factory.getUtilsPerScope(scope); String datasetName = productName; From 3d9080ed810782e8f2e73a8aaf6e1a63ba334ebd Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Thu, 8 Feb 2024 17:53:31 +0100 Subject: [PATCH 2/5] Added method getListExtrasAsHashMap - D4Science model compliant --- CHANGELOG.md | 1 + .../shared/jackan/model/CkanDatasetBase.java | 767 +++++++++--------- 2 files changed, 393 insertions(+), 375 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 19095da..aad5d7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm **Enhancements** - Added method update item [#26640] +- Added method getListExtrasAsHashMap - D4Science model compliant ## [v1.3.0] - 2023-02-06 diff --git a/src/main/java/org/gcube/datacatalogue/utillibrary/shared/jackan/model/CkanDatasetBase.java b/src/main/java/org/gcube/datacatalogue/utillibrary/shared/jackan/model/CkanDatasetBase.java index a202966..1974eaf 100644 --- a/src/main/java/org/gcube/datacatalogue/utillibrary/shared/jackan/model/CkanDatasetBase.java +++ b/src/main/java/org/gcube/datacatalogue/utillibrary/shared/jackan/model/CkanDatasetBase.java @@ -30,17 +30,15 @@ import org.gcube.com.fasterxml.jackson.annotation.JsonAnySetter; import org.gcube.com.fasterxml.jackson.annotation.JsonIgnore; import org.gcube.com.fasterxml.jackson.annotation.JsonProperty; - - /** * A Ckan Dataset, which in turn holds Ckan Resources. * * In Ckan terminology it is also known as 'package'. * - * {@link CkanDatasetBase} holds fields that can be sent when - * creating - * a dataset,, while {@link CkanDataset} holds more fields that can be - * returned with searches. + * {@link CkanDatasetBase} holds fields that can be sent when creating a dataset,, while {@link CkanDataset} holds more + * fields that can be returned with searches. * * This class initializes nothing to fully preserve all we get from ckan. In * practice, all fields of retrieved resources can be null except maybe @@ -51,148 +49,148 @@ import org.gcube.com.fasterxml.jackson.annotation.JsonProperty; */ public class CkanDatasetBase { - private String author; - private String authorEmail; - private List extras; - private List groups; - private String id; - private String licenseId; - private String maintainer; - private String maintainerEmail; - private String name; - private String notes; - private String ownerOrg; - private List relationshipsAsObject; - private List relationshipsAsSubject; - private List resources; - private CkanState state; - private List tags; - private String title; - private String type; - private String url; - private String version; - - private Boolean priv; + private String author; + private String authorEmail; + private List extras; + private List groups; + private String id; + private String licenseId; + private String maintainer; + private String maintainerEmail; + private String name; + private String notes; + private String ownerOrg; + private List relationshipsAsObject; + private List relationshipsAsSubject; + private List resources; + private CkanState state; + private List tags; + private String title; + private String type; + private String url; + private String version; - /** - * Custom CKAN instances might sometimes gift us with properties that don't - * end up in extras. They will end up here. - */ - @Nullable - private Map others; + private Boolean priv; - public CkanDatasetBase() { - } + /** + * Custom CKAN instances might sometimes gift us with properties that don't end + * up in extras. They will end up here. + */ + @Nullable + private Map others; - /** - * Constructor with the minimal set of attributes required to successfully - * create a dataset on the server. - * - * @param name the dataset name (contains no spaces and has dashes as - * separators, i.e. "limestone-pavement-orders") - */ - public CkanDatasetBase(String name) { - this(); - this.name = name; - } + public CkanDatasetBase() { + } - /** - * CKAN instances might have - * - * custom data schemas that force presence of custom properties among - * 'regular' ones. In this case, they go to 'others' field. Note that to - * further complicate things there is also an {@link #getExtras() extras} - * field. - * - * @see #putOthers(java.lang.String, java.lang.Object) - */ - @JsonAnyGetter - @Nullable - public Map getOthers() { - return others; - } + /** + * Constructor with the minimal set of attributes required to successfully + * create a dataset on the server. + * + * @param name the dataset name (contains no spaces and has dashes as + * separators, i.e. "limestone-pavement-orders") + */ + public CkanDatasetBase(String name) { + this(); + this.name = name; + } - /** - * @see #getOthers() - * @see #putOthers(java.lang.String, java.lang.Object) - */ - public void setOthers(@Nullable Map others) { - this.others = others; - } + /** + * CKAN instances might have custom + * data schemas that force presence of custom properties among 'regular' + * ones. In this case, they go to 'others' field. Note that to further + * complicate things there is also an {@link #getExtras() extras} field. + * + * @see #putOthers(java.lang.String, java.lang.Object) + */ + @JsonAnyGetter + @Nullable + public Map getOthers() { + return others; + } - /** - * See {@link #getOthers()} - * - * @see #setOthers(java.util.Map) - */ - @JsonAnySetter - public void putOthers(String name, Object value) { - if (others == null) { - others = new HashMap<>(); - } - others.put(name, value); - } + /** + * @see #getOthers() + * @see #putOthers(java.lang.String, java.lang.Object) + */ + public void setOthers(@Nullable Map others) { + this.others = others; + } - public String getAuthor() { - return author; - } + /** + * See {@link #getOthers()} + * + * @see #setOthers(java.util.Map) + */ + @JsonAnySetter + public void putOthers(String name, Object value) { + if (others == null) { + others = new HashMap<>(); + } + others.put(name, value); + } - public void setAuthor(String author) { - this.author = author; - } + public String getAuthor() { + return author; + } - public String getAuthorEmail() { - return authorEmail; - } + public void setAuthor(String author) { + this.author = author; + } - public void setAuthorEmail(String authorEmail) { - this.authorEmail = authorEmail; - } + public String getAuthorEmail() { + return authorEmail; + } - /** - * Notice that if the dataset was obtained with a - * {@link eu.trentorise.opendata.jackan.CkanClient#getDataset(java.lang.String)} call, the returned group - * won't have all the params you would get with a - * {@link eu.trentorise.opendata.jackan.CkanClient#getGroup(java.lang.String)} call. - */ - public List getGroups() { - return groups; - } + public void setAuthorEmail(String authorEmail) { + this.authorEmail = authorEmail; + } - public void setGroups(List groups) { - this.groups = groups; - } + /** + * Notice that if the dataset was obtained with a + * {@link eu.trentorise.opendata.jackan.CkanClient#getDataset(java.lang.String)} + * call, the returned group won't have all the params you would get with a + * {@link eu.trentorise.opendata.jackan.CkanClient#getGroup(java.lang.String)} + * call. + */ + public List getGroups() { + return groups; + } - /** - * Adds CkanGroups - * - * @param ckanGroups The CkanGroups elements - * - * @since 0.4.3 - */ - public void addGroups(CkanGroup... ckanGroups) { - if (this.groups == null) { - this.groups = new ArrayList<>(ckanGroups.length); - } - Collections.addAll(this.groups, ckanGroups); - } + public void setGroups(List groups) { + this.groups = groups; + } - /** - * Regular place where to put custom metadata. See also - * {@link #getOthers()}. Note also extras can be in CkanDataset but not in - * CkanResource. - */ - public List getExtras() { - return extras; - } + /** + * Adds CkanGroups + * + * @param ckanGroups The CkanGroups elements + * + * @since 0.4.3 + */ + public void addGroups(CkanGroup... ckanGroups) { + if (this.groups == null) { + this.groups = new ArrayList<>(ckanGroups.length); + } + Collections.addAll(this.groups, ckanGroups); + } - /** - * See {@link #getExtras()} - */ - public void setExtras(List extras) { - this.extras = extras; - } + /** + * Regular place where to put custom metadata. See also {@link #getOthers()}. + * Note also extras can be in CkanDataset but not in CkanResource. + */ + public List getExtras() { + return extras; + } + /** + * See {@link #getExtras()} + */ + public void setExtras(List extras) { + this.extras = extras; + } + + /** * Always returns a non-null map (which might be empty) */ @@ -207,285 +205,306 @@ public class CkanDatasetBase { return hm; } - /** - * Adds CkanExtras - * - * @param extras The CkanExtra elements - * - * @since 0.4.3 - */ - public void addExtras(CkanPair... extras) { - if (this.extras == null) { - this.extras = new ArrayList<>(extras.length); - } - Collections.addAll(this.extras, extras); - } + /** + * Always returns a non-null map (which might be empty) + * + * updated by Francesco Mangiacrapa at ISTI-CNR + * + * The D4Science model accepts extra fields with multiple keys + */ + @JsonIgnore + public Map> getListExtrasAsHashMap() { + HashMap> hm = new HashMap<>(); + if (extras != null) { + for (CkanPair cp : extras) { - /** - * Returns the alphanumerical id, i.e. - * "c4577b8f-5603-4098-917e-da03e8ddf461" - */ - public String getId() { - return id; - } + List list = hm.get(cp.getKey()); + if (list == null) + list = new ArrayList(); - /** - * Sets the alphanumerical id, i.e. "c4577b8f-5603-4098-917e-da03e8ddf461" - */ - public void setId(String id) { - this.id = id; - } + list.add(cp.getValue()); + hm.put(cp.getKey(), list); + } + } + return hm; + } - /** - * The license id (i.e. 'cc-zero') - */ - public String getLicenseId() { - return licenseId; - } + /** + * Adds CkanExtras + * + * @param extras The CkanExtra elements + * + * @since 0.4.3 + */ + public void addExtras(CkanPair... extras) { + if (this.extras == null) { + this.extras = new ArrayList<>(extras.length); + } + Collections.addAll(this.extras, extras); + } - /** - * The license id (i.e. 'cc-zero') - */ - public void setLicenseId(String licenseId) { - this.licenseId = licenseId; - } + /** + * Returns the alphanumerical id, i.e. "c4577b8f-5603-4098-917e-da03e8ddf461" + */ + public String getId() { + return id; + } - public String getMaintainer() { - return maintainer; - } + /** + * Sets the alphanumerical id, i.e. "c4577b8f-5603-4098-917e-da03e8ddf461" + */ + public void setId(String id) { + this.id = id; + } - public void setMaintainer(String maintainer) { - this.maintainer = maintainer; - } + /** + * The license id (i.e. 'cc-zero') + */ + public String getLicenseId() { + return licenseId; + } - public String getMaintainerEmail() { - return maintainerEmail; - } + /** + * The license id (i.e. 'cc-zero') + */ + public void setLicenseId(String licenseId) { + this.licenseId = licenseId; + } - public void setMaintainerEmail(String maintainerEmail) { - this.maintainerEmail = maintainerEmail; - } + public String getMaintainer() { + return maintainer; + } - /** - * The dataset name (contains no spaces and has dashes as separators, i.e. - * "limestone-pavement-orders") - */ - public String getName() { - return name; - } + public void setMaintainer(String maintainer) { + this.maintainer = maintainer; + } - /** - * The dataset name. Name must not contain spaces and have dashes as - * separators, i.e. "limestone-pavement-orders" - * - */ - public void setName(String name) { - this.name = name; - } + public String getMaintainerEmail() { + return maintainerEmail; + } - /** - * A description of the dataset. See also - * {@link CkanDataset#getNotesRendered()} Note CkanResource has instead a - * field called {@link CkanResourceBase#getDescription() description}. - */ - public String getNotes() { - return notes; - } + public void setMaintainerEmail(String maintainerEmail) { + this.maintainerEmail = maintainerEmail; + } - /** - * A description of the dataset. See also - * {@link CkanDataset#getNotesRendered()} Note CkanResource has instead a - * field called {@link CkanResourceBase#getDescription() description}. - */ - public void setNotes(String notes) { - this.notes = notes; - } + /** + * The dataset name (contains no spaces and has dashes as separators, i.e. + * "limestone-pavement-orders") + */ + public String getName() { + return name; + } - /** - * The owner organization alphanunmerical id, like - * "b112ed55-01b7-4ca4-8385-f66d6168efcc". - */ - public String getOwnerOrg() { - return ownerOrg; - } + /** + * The dataset name. Name must not contain spaces and have dashes as separators, + * i.e. "limestone-pavement-orders" + * + */ + public void setName(String name) { + this.name = name; + } - /** - * The owner organization alphanunmerical id, like - * "b112ed55-01b7-4ca4-8385-f66d6168efcc". - */ - public void setOwnerOrg(String ownerOrg) { - this.ownerOrg = ownerOrg; - } + /** + * A description of the dataset. See also {@link CkanDataset#getNotesRendered()} + * Note CkanResource has instead a field called + * {@link CkanResourceBase#getDescription() description}. + */ + public String getNotes() { + return notes; + } - public List getRelationshipsAsObject() { - return relationshipsAsObject; - } + /** + * A description of the dataset. See also {@link CkanDataset#getNotesRendered()} + * Note CkanResource has instead a field called + * {@link CkanResourceBase#getDescription() description}. + */ + public void setNotes(String notes) { + this.notes = notes; + } - public void setRelationshipsAsObject(List relationshipsAsObject) { - this.relationshipsAsObject = relationshipsAsObject; - } + /** + * The owner organization alphanunmerical id, like + * "b112ed55-01b7-4ca4-8385-f66d6168efcc". + */ + public String getOwnerOrg() { + return ownerOrg; + } - public List getRelationshipsAsSubject() { - return relationshipsAsSubject; - } + /** + * The owner organization alphanunmerical id, like + * "b112ed55-01b7-4ca4-8385-f66d6168efcc". + */ + public void setOwnerOrg(String ownerOrg) { + this.ownerOrg = ownerOrg; + } - public void setRelationshipsAsSubject(List relationshipsAsSubject) { - this.relationshipsAsSubject = relationshipsAsSubject; - } + public List getRelationshipsAsObject() { + return relationshipsAsObject; + } - public List getResources() { - return this.resources; - } + public void setRelationshipsAsObject(List relationshipsAsObject) { + this.relationshipsAsObject = relationshipsAsObject; + } - public void setResources(List resources) { - this.resources = resources; - } + public List getRelationshipsAsSubject() { + return relationshipsAsSubject; + } - /** - * Adds CkanResources - * - * @param resources The CkanResources elements - * - * @since 0.4.3 - */ - public void addCkanResources(CkanResource... resources) { - if (this.resources == null) { - this.resources = new ArrayList<>(resources.length); - } - Collections.addAll(this.resources, resources); - } + public void setRelationshipsAsSubject(List relationshipsAsSubject) { + this.relationshipsAsSubject = relationshipsAsSubject; + } - /** - * The current state of the dataset, e.g. 'active' or 'deleted', only active - * datasets show up in search results and other lists of datasets, this - * parameter will be ignored if you are not authorized to change the state - * of the dataset (optional, default: 'active') - */ - public CkanState getState() { - return state; - } + public List getResources() { + return this.resources; + } - /** - * The current state of the dataset, e.g. 'active' or 'deleted', only active - * datasets show up in search results and other lists of datasets, this - * parameter will be ignored if you are not authorized to change the state - * of the dataset (optional, default: 'active') - */ - public void setState(CkanState state) { - this.state = state; - } + public void setResources(List resources) { + this.resources = resources; + } - public List getTags() { - return tags; - } + /** + * Adds CkanResources + * + * @param resources The CkanResources elements + * + * @since 0.4.3 + */ + public void addCkanResources(CkanResource... resources) { + if (this.resources == null) { + this.resources = new ArrayList<>(resources.length); + } + Collections.addAll(this.resources, resources); + } - public void setTags(List tags) { - this.tags = tags; - } + /** + * The current state of the dataset, e.g. 'active' or 'deleted', only active + * datasets show up in search results and other lists of datasets, this + * parameter will be ignored if you are not authorized to change the state of + * the dataset (optional, default: 'active') + */ + public CkanState getState() { + return state; + } - /** - * Adds CkanTag - * - * @param tags The CkanTags elements - * - * @since 0.4.3 - */ - public void addTags(CkanTag... tags) { - if (this.tags == null) { - this.tags = new ArrayList<>(tags.length); - } - Collections.addAll(this.tags, tags); - } + /** + * The current state of the dataset, e.g. 'active' or 'deleted', only active + * datasets show up in search results and other lists of datasets, this + * parameter will be ignored if you are not authorized to change the state of + * the dataset (optional, default: 'active') + */ + public void setState(CkanState state) { + this.state = state; + } - /** - * The title, like "Hospitals of Trento" - */ - public String getTitle() { - return title; - } + public List getTags() { + return tags; + } - /** - * The title, like "Hospitals of Trento" - */ - public void setTitle(String title) { - this.title = title; - } + public void setTags(List tags) { + this.tags = tags; + } - /** - * The type of the dataset (optional), IDatasetForm plugins associate - * themselves with different dataset types and provide custom dataset - * handling behaviour for these types - */ - public String getType() { - return type; - } + /** + * Adds CkanTag + * + * @param tags The CkanTags elements + * + * @since 0.4.3 + */ + public void addTags(CkanTag... tags) { + if (this.tags == null) { + this.tags = new ArrayList<>(tags.length); + } + Collections.addAll(this.tags, tags); + } - /** - * The type of the dataset (optional), IDatasetForm plugins associate - * themselves with different dataset types and provide custom dataset - * handling behaviour for these types - */ - public void setType(String type) { - this.type = type; - } + /** + * The title, like "Hospitals of Trento" + */ + public String getTitle() { + return title; + } - /** - * Should be the landing page on original data provider website describing - * the dataset. - */ - public String getUrl() { - return url; - } + /** + * The title, like "Hospitals of Trento" + */ + public void setTitle(String title) { + this.title = title; + } - /** - * Should be the landing page on original data provider website describing - * the dataset. - */ - public void setUrl(String url) { - this.url = url; - } + /** + * The type of the dataset (optional), IDatasetForm plugins associate themselves + * with different dataset types and provide custom dataset handling behaviour + * for these types + */ + public String getType() { + return type; + } - public String getVersion() { - return version; - } + /** + * The type of the dataset (optional), IDatasetForm plugins associate themselves + * with different dataset types and provide custom dataset handling behaviour + * for these types + */ + public void setType(String type) { + this.type = type; + } - public void setVersion(String version) { - this.version = version; - } + /** + * Should be the landing page on original data provider website describing the + * dataset. + */ + public String getUrl() { + return url; + } - /** - * Returns the id if non-empty, the name otherwise - */ - @Nullable - public String idOrName() { - return isNotEmpty(getId()) ? getId() : getName(); - } + /** + * Should be the landing page on original data provider website describing the + * dataset. + */ + public void setUrl(String url) { + this.url = url; + } - /** - * Returns the name if non-empty, the id otherwise - */ - @Nullable - public String nameOrId() { + public String getVersion() { + return version; + } - return isNotEmpty(getName()) ? getName() : getId(); - } - - /** - * Actually it is named "private" in the CKAN API. Appears in dataset - * searches. - */ - @JsonProperty("private") - public Boolean isPriv() { - return priv; - } + public void setVersion(String version) { + this.version = version; + } - /** - * Actually it is named "private" in the CKAN API. Appears in dataset - * searches. - */ - public void setPriv(Boolean priv) { - this.priv = priv; - } + /** + * Returns the id if non-empty, the name otherwise + */ + @Nullable + public String idOrName() { + return isNotEmpty(getId()) ? getId() : getName(); + } + + /** + * Returns the name if non-empty, the id otherwise + */ + @Nullable + public String nameOrId() { + + return isNotEmpty(getName()) ? getName() : getId(); + } + + /** + * Actually it is named "private" in the CKAN API. Appears in dataset searches. + */ + @JsonProperty("private") + public Boolean isPriv() { + return priv; + } + + /** + * Actually it is named "private" in the CKAN API. Appears in dataset searches. + */ + public void setPriv(Boolean priv) { + this.priv = priv; + } @Override public String toString() { @@ -537,7 +556,5 @@ public class CkanDatasetBase { builder.append("]"); return builder.toString(); } - - } \ No newline at end of file From 618c4a48c24882475a630d9128c4fe72d00586a6 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Fri, 9 Feb 2024 10:30:59 +0100 Subject: [PATCH 3/5] updated comment --- .../utillibrary/shared/jackan/model/CkanDatasetBase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/gcube/datacatalogue/utillibrary/shared/jackan/model/CkanDatasetBase.java b/src/main/java/org/gcube/datacatalogue/utillibrary/shared/jackan/model/CkanDatasetBase.java index 1974eaf..7910183 100644 --- a/src/main/java/org/gcube/datacatalogue/utillibrary/shared/jackan/model/CkanDatasetBase.java +++ b/src/main/java/org/gcube/datacatalogue/utillibrary/shared/jackan/model/CkanDatasetBase.java @@ -208,7 +208,7 @@ public class CkanDatasetBase { /** * Always returns a non-null map (which might be empty) * - * updated by Francesco Mangiacrapa at ISTI-CNR + * added by Francesco Mangiacrapa at ISTI-CNR * * The D4Science model accepts extra fields with multiple keys */ From ee82656541215db560bc36eda0646e99d0f8a183 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Mon, 12 Feb 2024 16:12:08 +0100 Subject: [PATCH 4/5] Added method: addResource --- .../utillibrary/server/DataCatalogue.java | 14 +++++ .../utillibrary/server/DataCatalogueImpl.java | 54 ++++++++++++++----- 2 files changed, 54 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/gcube/datacatalogue/utillibrary/server/DataCatalogue.java b/src/main/java/org/gcube/datacatalogue/utillibrary/server/DataCatalogue.java index d60d482..cd9bd9c 100644 --- a/src/main/java/org/gcube/datacatalogue/utillibrary/server/DataCatalogue.java +++ b/src/main/java/org/gcube/datacatalogue/utillibrary/server/DataCatalogue.java @@ -10,6 +10,7 @@ import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanDataset; import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanGroup; import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanLicense; import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanOrganization; +import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanResource; /** * The Interface DataCatalogue. @@ -373,6 +374,19 @@ public interface DataCatalogue { * @throws Exception the exception */ String addResourceToDataset(ResourceBean resourceBean, String organizationName, String username) throws Exception; + + + /** + * Adds the resource. + * + * @param resourceBean the resource bean + * @param datasetId the dataset id + * @param organizationName the organization name + * @param username the username + * @return the ckan resource + * @throws Exception the exception + */ + CkanResource addResource(ResourceBean resourceBean, String datasetId, String organizationName, String username) throws Exception; /** * Remove the resource with id resourceId from dataset in which it is. diff --git a/src/main/java/org/gcube/datacatalogue/utillibrary/server/DataCatalogueImpl.java b/src/main/java/org/gcube/datacatalogue/utillibrary/server/DataCatalogueImpl.java index 2e044aa..df99bf0 100644 --- a/src/main/java/org/gcube/datacatalogue/utillibrary/server/DataCatalogueImpl.java +++ b/src/main/java/org/gcube/datacatalogue/utillibrary/server/DataCatalogueImpl.java @@ -1513,22 +1513,37 @@ public class DataCatalogueImpl implements DataCatalogue { throws Exception { LOG.info("Called addResourceToDataset by this bean " + resourceBean); + CkanResource resource = createResource(resourceBean, organizationName, username); + if (resource != null) + return resource.getId(); + return null; + } + + /** + * Adds the resource to dataset. + * + * @param resourceBean the resource bean + * @param organizationName the organization name + * @param username the username + * @return the string + * @throws Exception the exception + */ + @Override + public CkanResource addResource(ResourceBean resourceBean, String datasetId, String organizationName, + String username) throws Exception { + LOG.info("Called addResource by this bean " + resourceBean.getName() + ", datasetId: " + datasetId); + + resourceBean.setDatasetId(datasetId); + return createResource(resourceBean, organizationName, username); + } + + private CkanResource createResource(ResourceBean resourceBean, String organizationName, String username) + throws Exception { + // checks checkNotNull(resourceBean); checkNotNull(resourceBean.getUrl()); - // Commented since #21259 - /* - * boolean isAccessibleURL = false; try { isAccessibleURL = - * CatalogueUtilMethods.resourceExists(resourceBean.getUrl()); } catch - * (Exception e) { throw new Exception("It seems the resource at this url " + - * resourceBean.getUrl()+" is not reachable. Error: "+e.getMessage()); } - * - * if(!isAccessibleURL){ throw new - * Exception("It seems there is no resource at this url " + - * resourceBean.getUrl()); } - */ - GcubeContext gcubeContext = null; try { @@ -1547,7 +1562,7 @@ public class DataCatalogueImpl implements DataCatalogue { if (createdRes != null) { LOG.info("Resource with id: " + createdRes.getId() + ", name: " + createdRes.getName() + " added correclty"); - return createdRes.getId(); + return createdRes; } } catch (Exception e) { LOG.error("Unable to add the resource " + resourceBean, e); @@ -1558,6 +1573,7 @@ public class DataCatalogueImpl implements DataCatalogue { } return null; + } /** @@ -1584,7 +1600,17 @@ public class DataCatalogueImpl implements DataCatalogue { GcubeContext gcubeContext = null; try { - CkanResource theResource = ckanCaller.getResource(resourceId); + CkanResource theResource = null; + // Using CKAN API KEY TO READ THE RESOURCE + if (username != null && !username.isEmpty()) { + LOG.info("username found. Calling the " + ExtendCkanClient.class.getSimpleName()); + String apiKey = getApiKeyFromUsername(username); + ExtendCkanClient client = new ExtendCkanClient(CKAN_CATALOGUE_URL, apiKey); + theResource = client.getResource(resourceId); + } else { + // GUEST MODE - NO API + theResource = ckanCaller.getResource(resourceId); + } CkanDataset theDataset = getDataset(theResource.getPackageId(), username); From ea8bc0c46ccb8cd2b0730eec0d3378fbf46a8cf5 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Mon, 19 Feb 2024 15:59:28 +0100 Subject: [PATCH 5/5] - Added method deleteDataset [#26793] --- CHANGELOG.md | 2 + .../utillibrary/server/DataCatalogue.java | 54 +++++++++-------- .../utillibrary/server/DataCatalogueImpl.java | 59 +++++++++++++++++++ 3 files changed, 92 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aad5d7b..9694977 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,8 +9,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm **Enhancements** - Added method update item [#26640] +- Added method deleteDataset [#26793] - Added method getListExtrasAsHashMap - D4Science model compliant + ## [v1.3.0] - 2023-02-06 **Enhancements** diff --git a/src/main/java/org/gcube/datacatalogue/utillibrary/server/DataCatalogue.java b/src/main/java/org/gcube/datacatalogue/utillibrary/server/DataCatalogue.java index cd9bd9c..426e369 100644 --- a/src/main/java/org/gcube/datacatalogue/utillibrary/server/DataCatalogue.java +++ b/src/main/java/org/gcube/datacatalogue/utillibrary/server/DataCatalogue.java @@ -332,28 +332,27 @@ public interface DataCatalogue { String description, String licenseId, List tags, Map> customFieldsMultiple, List resources, boolean setPublic, boolean setSearchable, boolean socialPost) throws Exception; - /** * Update ckan dataset multiple custom fields. * - * @param username the username - * @param title the title - * @param name the name - * @param organizationName the organization name - * @param author the author - * @param authorMail the author mail - * @param maintainer the maintainer - * @param maintainerMail the maintainer mail - * @param version the version - * @param description the description - * @param licenseId the license id - * @param tags the tags + * @param username the username + * @param title the title + * @param name the name + * @param organizationName the organization name + * @param author the author + * @param authorMail the author mail + * @param maintainer the maintainer + * @param maintainerMail the maintainer mail + * @param version the version + * @param description the description + * @param licenseId the license id + * @param tags the tags * @param customFieldsMultiple the custom fields multiple - * @param resources the resources - * @param setPublic the set public - * @param setSearchable the set searchable - * @param socialPost the social post + * @param resources the resources + * @param setPublic the set public + * @param setSearchable the set searchable + * @param socialPost the social post * @return the string * @throws Exception the exception */ @@ -374,19 +373,19 @@ public interface DataCatalogue { * @throws Exception the exception */ String addResourceToDataset(ResourceBean resourceBean, String organizationName, String username) throws Exception; - - + /** * Adds the resource. * - * @param resourceBean the resource bean - * @param datasetId the dataset id + * @param resourceBean the resource bean + * @param datasetId the dataset id * @param organizationName the organization name - * @param username the username + * @param username the username * @return the ckan resource * @throws Exception the exception */ - CkanResource addResource(ResourceBean resourceBean, String datasetId, String organizationName, String username) throws Exception; + CkanResource addResource(ResourceBean resourceBean, String datasetId, String organizationName, String username) + throws Exception; /** * Remove the resource with id resourceId from dataset in which it is. @@ -463,6 +462,15 @@ public interface DataCatalogue { */ String refreshDataset(String datasetName) throws Exception; + /** + * Delete dataset. + * + * @param datasetName the dataset name + * @return true, if successful + * @throws Exception the exception + */ + boolean deleteDataset(String datasetName) throws Exception; + /** * Patch a product with product id productId by using the couples in * customFieldsToChange. NOTE: only the specified custom fields will be changed. diff --git a/src/main/java/org/gcube/datacatalogue/utillibrary/server/DataCatalogueImpl.java b/src/main/java/org/gcube/datacatalogue/utillibrary/server/DataCatalogueImpl.java index df99bf0..4e33479 100644 --- a/src/main/java/org/gcube/datacatalogue/utillibrary/server/DataCatalogueImpl.java +++ b/src/main/java/org/gcube/datacatalogue/utillibrary/server/DataCatalogueImpl.java @@ -1320,6 +1320,29 @@ public class DataCatalogueImpl implements DataCatalogue { return null; } + /** + * Update ckan dataset multiple custom fields. + * + * @param username the username + * @param title the title + * @param name the name + * @param organizationName the organization name + * @param author the author + * @param authorMail the author mail + * @param maintainer the maintainer + * @param maintainerMail the maintainer mail + * @param version the version + * @param description the description + * @param licenseId the license id + * @param tags the tags + * @param customFieldsMultiple the custom fields multiple + * @param resources the resources + * @param setPublic the set public + * @param setSearchable the set searchable + * @param socialPost the social post + * @return the string + * @throws Exception the exception + */ @Override public String updateCkanDatasetMultipleCustomFields(String username, String title, String name, String organizationName, String author, String authorMail, String maintainer, String maintainerMail, @@ -1411,6 +1434,32 @@ public class DataCatalogueImpl implements DataCatalogue { return null; } + /** + * Delete dataset. + * + * @param datasetName the dataset name + * @return true, if successful + * @throws Exception the exception + */ + @Override + public boolean deleteDataset(String datasetName) throws Exception { + LOG.info("Called deleteDataset"); + + checkNotNull(datasetName); + boolean deleted = false; + try { + + gCatCaller.deleteItem(datasetName, true); + deleted = true; + LOG.info("Deleted the dataset: {} ", datasetName); + return deleted; + + } catch (Exception e) { + LOG.error("Error on deleting the dataset: ", e); + throw e; + } + } + /** * Patch fields for dataset. * @@ -1523,6 +1572,7 @@ public class DataCatalogueImpl implements DataCatalogue { * Adds the resource to dataset. * * @param resourceBean the resource bean + * @param datasetId the dataset id * @param organizationName the organization name * @param username the username * @return the string @@ -1537,6 +1587,15 @@ public class DataCatalogueImpl implements DataCatalogue { return createResource(resourceBean, organizationName, username); } + /** + * Creates the resource. + * + * @param resourceBean the resource bean + * @param organizationName the organization name + * @param username the username + * @return the ckan resource + * @throws Exception the exception + */ private CkanResource createResource(ResourceBean resourceBean, String organizationName, String username) throws Exception {