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