Several improvements:

- added checks using annotations and validator for bean validations
- DatabaseSources and SourceOfInformation are now list of resources
- notations have been added according the model on the wiki page(GCube_Data_Catalogue_for_GRSF)

git-svn-id: https://svn.d4science.research-infrastructures.eu/gcube/trunk/data-catalogue/grsf-publisher-ws@133160 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
Costantino Perciante 2016-10-13 09:46:42 +00:00
parent 9d435d4f26
commit 0c4f135002
13 changed files with 378 additions and 97 deletions

View File

@ -128,6 +128,11 @@
<version>2.23.2</version> <version>2.23.2</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-bean-validation</artifactId>
<version>2.23.2</version>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -4,10 +4,12 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.CustomField; import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.CustomField;
import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.Group; import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.Group;
import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.Tag; import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.Tag;
import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Source;
import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Type; import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Type;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@ -17,13 +19,15 @@ import com.fasterxml.jackson.annotation.JsonProperty;
* Information that both Stock and Fishery must contain * Information that both Stock and Fishery must contain
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it) * @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
*/ */
@JsonIgnoreProperties(value = {"author", "author_contact"}, ignoreUnknown = true) // ignore in serialization/deserialization @JsonIgnoreProperties(value = {"author", "author_contact", "authorContact"}, ignoreUnknown = true) // ignore in serialization/deserialization
public class Common { public class Common {
@JsonProperty("description") @JsonProperty("description")
private String description; private String description;
@JsonProperty("license_id") @JsonProperty("license_id")
@NotNull(message="license_id cannot be null")
@Size(min=2, message="license_id cannot be empty")
private String license; private String license;
// filled automatically by the service // filled automatically by the service
@ -48,13 +52,16 @@ public class Common {
private String catchesOrLandings; private String catchesOrLandings;
@JsonProperty("database_sources") @JsonProperty("database_sources")
@Group
@CustomField(key="Database sources") @CustomField(key="Database sources")
private Source databaseSources; @NotNull(message="database_source cannot be null")
@Size(min=1, message="database_source cannot be empty")
private List<DatabaseSource> databaseSources;
@JsonProperty("source_of_information") @JsonProperty("source_of_information")
@CustomField(key="Source of information") @CustomField(key="Source of information")
private String sourceOfInformation; @NotNull(message="source_of_information cannot be null")
@Size(min=1, message="source_of_information cannot be empty")
private List<Resource> sourceOfInformation;
@JsonProperty("data_owner") @JsonProperty("data_owner")
@CustomField(key="Data owner") @CustomField(key="Data owner")
@ -66,27 +73,33 @@ public class Common {
@CustomField(key="Type") @CustomField(key="Type")
private Type type; private Type type;
@JsonProperty("resources")
private List<Resource> resources;
@JsonProperty("extras") @JsonProperty("extras")
private Map<String, String> extras = new HashMap<>(); private Map<String, String> extras = new HashMap<>();
// @JsonProperty("spatial")
// @CustomField(key="Spatial")
// private String spatial;
public Common() { public Common() {
super(); super();
} }
/**
* @param description
* @param license
* @param author
* @param version
* @param authorContact
* @param maintainer
* @param maintainerContact
* @param catchesOrLandings
* @param databaseSources
* @param sourceOfInformation
* @param dataOwner
* @param type
* @param extras
*/
public Common(String description, String license, String author, public Common(String description, String license, String author,
Long version, String authorContact, String maintainer, Long version, String authorContact, String maintainer,
String maintainerContact, String catchesOrLandings, String maintainerContact, String catchesOrLandings,
Source databaseSources, String sourceOfInformation, List<DatabaseSource> databaseSources, List<Resource> sourceOfInformation,
String dataOwner, Type type, String dataOwner, Type type, Map<String, String> extras) {
List<Resource> resources, Map<String, String> extras,
String spatial) {
super(); super();
this.description = description; this.description = description;
this.license = license; this.license = license;
@ -100,19 +113,9 @@ public class Common {
this.sourceOfInformation = sourceOfInformation; this.sourceOfInformation = sourceOfInformation;
this.dataOwner = dataOwner; this.dataOwner = dataOwner;
this.type = type; this.type = type;
this.resources = resources;
this.extras = extras; this.extras = extras;
// this.spatial = spatial;
} }
// public String getSpatial() {
// return spatial;
// }
//
// public void setSpatial(String spatial) {
// this.spatial = spatial;
// }
public String getDescription() { public String getDescription() {
return description; return description;
} }
@ -177,19 +180,19 @@ public class Common {
this.catchesOrLandings = catchesOrLandings; this.catchesOrLandings = catchesOrLandings;
} }
public Source getDatabaseSources() { public List<DatabaseSource> getDatabaseSources() {
return databaseSources; return databaseSources;
} }
public void setDatabaseSources(Source databaseSources) { public void setDatabaseSources(List<DatabaseSource> databaseSources) {
this.databaseSources = databaseSources; this.databaseSources = databaseSources;
} }
public String getSourceOfInformation() { public List<Resource> getSourceOfInformation() {
return sourceOfInformation; return sourceOfInformation;
} }
public void setSourceOfInformation(String sourceOfInformation) { public void setSourceOfInformation(List<Resource> sourceOfInformation) {
this.sourceOfInformation = sourceOfInformation; this.sourceOfInformation = sourceOfInformation;
} }
@ -209,14 +212,6 @@ public class Common {
this.type = type; this.type = type;
} }
public List<Resource> getResources() {
return resources;
}
public void setResources(List<Resource> resources) {
this.resources = resources;
}
public void setExtras(Map<String, String> extras) { public void setExtras(Map<String, String> extras) {
this.extras = extras; this.extras = extras;
} }
@ -234,8 +229,8 @@ public class Common {
+ ", catchesOrLandings=" + catchesOrLandings + ", catchesOrLandings=" + catchesOrLandings
+ ", databaseSources=" + databaseSources + ", databaseSources=" + databaseSources
+ ", sourceOfInformation=" + sourceOfInformation + ", sourceOfInformation=" + sourceOfInformation
+ ", dataOwner=" + dataOwner + ", type=" + type + ", dataOwner=" + dataOwner + ", type=" + type + ", extras="
+ ", resources=" + resources + ", extras=" + extras + "]"; + extras + "]";
} }
} }

View File

@ -0,0 +1,72 @@
package org.gcube.data_catalogue.grsf_publish_ws.json.input;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.Group;
import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Source;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* A resource object bean for the database source. The name description has a controlled vocabulary
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
*/
@JsonIgnoreProperties(ignoreUnknown = true) // ignore in serialization/deserialization
public class DatabaseSource {
@JsonProperty("url")
@NotNull(message="'url' attribute of database_source cannot be null")
@Size(min=1, message="'url' attribute of database_source cannot be empty")
private String url;
@JsonProperty("description")
private String description;
@JsonProperty("name")
@Group
@NotNull(message="'name' attribute of database_source is missing or wrong")
private Source name;
public DatabaseSource() {
super();
}
public DatabaseSource(String url, String description, Source name) {
super();
this.url = url;
this.description = description;
this.name = name;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Source getName() {
return name;
}
public void setName(Source name) {
this.name = name;
}
@Override
public String toString() {
return "DatabaseSource [url=" + url + ", description=" + description
+ ", name=" + name + "]";
}
}

View File

@ -1,5 +1,8 @@
package org.gcube.data_catalogue.grsf_publish_ws.json.input; package org.gcube.data_catalogue.grsf_publish_ws.json.input;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.CustomField; import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.CustomField;
import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.Group; import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.Group;
import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.Tag; import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.Tag;
@ -15,6 +18,8 @@ import com.fasterxml.jackson.annotation.JsonProperty;
public class FisheryRecord extends Common{ public class FisheryRecord extends Common{
@JsonProperty("fishery_name") @JsonProperty("fishery_name")
@NotNull(message="fishery_name cannot be null")
@Size(min=1, message="fishery_name cannot be empty")
private String fisheryName; private String fisheryName;
@JsonProperty("fishery_id") @JsonProperty("fishery_id")
@ -61,6 +66,7 @@ public class FisheryRecord extends Common{
@JsonProperty("status") @JsonProperty("status")
@CustomField(key="Status") @CustomField(key="Status")
@Group @Group
@NotNull(message="status cannot be null")
private Status status; private Status status;
@JsonProperty("environment") @JsonProperty("environment")

View File

@ -1,5 +1,8 @@
package org.gcube.data_catalogue.grsf_publish_ws.json.input; package org.gcube.data_catalogue.grsf_publish_ws.json.input;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
@ -11,12 +14,16 @@ import com.fasterxml.jackson.annotation.JsonProperty;
public class Resource { public class Resource {
@JsonProperty("url") @JsonProperty("url")
@NotNull(message="'url' field of a resource cannot be null")
@Size(min=1, message="'url' field of a resource cannot be empty")
private String url; private String url;
@JsonProperty("description") @JsonProperty("description")
private String description; private String description;
@JsonProperty("name") @JsonProperty("name")
@NotNull(message="'name' field of a resource cannot be null")
@Size(min=1, message="'name' field of a resource cannot be empty")
private String name; private String name;
public Resource() { public Resource() {

View File

@ -1,5 +1,8 @@
package org.gcube.data_catalogue.grsf_publish_ws.json.input; package org.gcube.data_catalogue.grsf_publish_ws.json.input;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.CustomField; import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.CustomField;
import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.Group; import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.Group;
import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.Tag; import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.Tag;
@ -16,6 +19,8 @@ import com.fasterxml.jackson.annotation.JsonProperty;
public class StockRecord extends Common{ public class StockRecord extends Common{
@JsonProperty("stock_name") @JsonProperty("stock_name")
@NotNull(message="stock_name cannot be null")
@Size(min=2, message="stock_name cannot be empty")
private String stockName; private String stockName;
@JsonProperty("stock_id") @JsonProperty("stock_id")
@ -24,11 +29,15 @@ public class StockRecord extends Common{
@JsonProperty("species_scientific_name") @JsonProperty("species_scientific_name")
@Tag @Tag
@NotNull(message="species_scientific_name cannot be null")
@Size(min=1, message="species_scientific_name cannot be empty")
@CustomField(key="Species scientific name") @CustomField(key="Species scientific name")
private String speciesScientificName; private String speciesScientificName;
@JsonProperty("assessment_distribution_area") @JsonProperty("assessment_distribution_area")
@CustomField(key="Assessment distribution area") @CustomField(key="Assessment distribution area")
@NotNull(message="area cannot be null")
@Size(min=1, message="area cannot be empty")
private String area; private String area;
@JsonProperty("exploiting_fishery") @JsonProperty("exploiting_fishery")
@ -75,6 +84,7 @@ public class StockRecord extends Common{
@JsonProperty("status") @JsonProperty("status")
@Tag @Tag
@NotNull(message="status cannot be null")
@CustomField(key="Status") @CustomField(key="Status")
private Status status; private Status status;

View File

@ -1,5 +1,7 @@
package org.gcube.data_catalogue.grsf_publish_ws.json.output; package org.gcube.data_catalogue.grsf_publish_ws.json.output;
import com.fasterxml.jackson.annotation.JsonProperty;
/** /**
* A bean used to reply to a product creation method. * A bean used to reply to a product creation method.
@ -7,16 +9,28 @@ package org.gcube.data_catalogue.grsf_publish_ws.json.output;
*/ */
public class ResponseCreationBean { public class ResponseCreationBean {
@JsonProperty("id")
private String id; private String id;
@JsonProperty("dataset_url")
String datasetUrl;
@JsonProperty("error")
private String error; // in case of error private String error; // in case of error
public ResponseCreationBean() { public ResponseCreationBean() {
super(); super();
} }
public ResponseCreationBean(String id, String error) { /**
* @param id
* @param datasetUrl
* @param error
*/
public ResponseCreationBean(String id, String datasetUrl, String error) {
super(); super();
this.id = id; this.id = id;
this.datasetUrl = datasetUrl;
this.error = error; this.error = error;
} }
@ -28,6 +42,14 @@ public class ResponseCreationBean {
this.id = id; this.id = id;
} }
public String getDatasetUrl() {
return datasetUrl;
}
public void setDatasetUrl(String datasetUrl) {
this.datasetUrl = datasetUrl;
}
public String getError() { public String getError() {
return error; return error;
} }
@ -38,6 +60,8 @@ public class ResponseCreationBean {
@Override @Override
public String toString() { public String toString() {
return "ResponseCreationBean [id=" + id + ", error=" + error + "]"; return "ResponseCreationBean [id=" + id + ", datasetUrl=" + datasetUrl
+ ", error=" + error + "]";
} }
} }

View File

@ -21,7 +21,6 @@ import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.common.authorization.library.utils.Caller; import org.gcube.common.authorization.library.utils.Caller;
import org.gcube.common.scope.api.ScopeProvider; import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.data_catalogue.grsf_publish_ws.json.input.FisheryRecord; import org.gcube.data_catalogue.grsf_publish_ws.json.input.FisheryRecord;
import org.gcube.data_catalogue.grsf_publish_ws.json.input.Resource;
import org.gcube.data_catalogue.grsf_publish_ws.json.output.ResponseCreationBean; import org.gcube.data_catalogue.grsf_publish_ws.json.output.ResponseCreationBean;
import org.gcube.data_catalogue.grsf_publish_ws.utils.AssociationToGroupThread; import org.gcube.data_catalogue.grsf_publish_ws.utils.AssociationToGroupThread;
import org.gcube.data_catalogue.grsf_publish_ws.utils.HelperMethods; import org.gcube.data_catalogue.grsf_publish_ws.utils.HelperMethods;
@ -91,6 +90,19 @@ public class GrsfPublisherFisheryService {
Status status = Status.INTERNAL_SERVER_ERROR; Status status = Status.INTERNAL_SERVER_ERROR;
String id = ""; String id = "";
// validate the bean
logger.debug("Start validating bean...");
Response responseAfterValidation = HelperMethods.validateBeanAndResources(record);
if(responseAfterValidation == null)
logger.debug("Bean validation successful");
else{
logger.warn("Bean validation failed");
return responseAfterValidation;
}
try{ try{
// determine the organization in which this product should be put // determine the organization in which this product should be put
@ -126,12 +138,20 @@ public class GrsfPublisherFisheryService {
// check the record has a name, at least // check the record has a name, at least
String futureTitle = record.getFisheryName(); String futureTitle = record.getFisheryName();
String fishingArea = record.getFishingArea();
String jurisdictionArea = record.getJurisdictionArea();
if(!HelperMethods.isValid(futureTitle)){ if(!HelperMethods.isValid(futureTitle)){
status = Status.BAD_REQUEST; status = Status.BAD_REQUEST;
responseBean.setId(null); responseBean.setId(null);
throw new Exception("The name requested for the product is not correct! It should contain only alphanumeric characters, and symbols like '.' or '_', '-'"); throw new Exception("The name requested for the product is not correct! It should contain only alphanumeric characters, and symbols like '.' or '_', '-'");
}else if((fishingArea == null || fishingArea.isEmpty()) && (jurisdictionArea == null || jurisdictionArea.isEmpty())){
status = Status.BAD_REQUEST;
responseBean.setId(null);
throw new Exception("fishing_area and jurisdiction_area cannot be null/empty at the same time!");
}else{ }else{
logger.debug("Checking if such name [" + futureTitle + "]doesn't exist yet..."); logger.debug("Checking if such name [" + futureTitle + "]doesn't exist yet...");
@ -178,19 +198,8 @@ public class GrsfPublisherFisheryService {
}else{ }else{
// evaluate the resources TODO // evaluate the resources
List<Resource> resourcesRecord = record.getResources(); List<ResourceBean> resources = HelperMethods.getResourcesFromBean(record, username);
List<ResourceBean> resources = null;
if(resourcesRecord != null && !resourcesRecord.isEmpty()){
resources = new ArrayList<ResourceBean>();
for (Resource res : resourcesRecord) {
logger.debug("Trying to add resource " + res);
if(res.getName() != null && res.getUrl() != null)
resources.add(new ResourceBean(res.getUrl(), res.getName(), res.getDescription(), null, username, null, null));
else
logger.warn("Unable to add resource because url or name is null");
}
}
// if confirmed, set to visible TODO anyway if it is confirmed we should another method // if confirmed, set to visible TODO anyway if it is confirmed we should another method
boolean setPublic = record.getStatus() == org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Status.Confirmed; boolean setPublic = record.getStatus() == org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Status.Confirmed;
@ -219,7 +228,7 @@ public class GrsfPublisherFisheryService {
tags, tags,
customFields, customFields,
resources, resources,
setPublic); // TODO setPublic);
if(id != null){ if(id != null){
@ -227,6 +236,7 @@ public class GrsfPublisherFisheryService {
responseBean.setId(id); responseBean.setId(id);
status = Status.CREATED; status = Status.CREATED;
responseBean.setError(null); responseBean.setError(null);
responseBean.setDatasetUrl(catalogue.getCatalogueUrl() + "/dataset/" + futureName);
if(!groups.isEmpty()){ if(!groups.isEmpty()){
logger.info("Launching thread for association to the list of groups " + groups); logger.info("Launching thread for association to the list of groups " + groups);

View File

@ -20,13 +20,11 @@ import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.authorization.library.provider.SecurityTokenProvider; import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.common.authorization.library.utils.Caller; import org.gcube.common.authorization.library.utils.Caller;
import org.gcube.common.scope.api.ScopeProvider; import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.data_catalogue.grsf_publish_ws.json.input.Resource;
import org.gcube.data_catalogue.grsf_publish_ws.json.input.StockRecord; import org.gcube.data_catalogue.grsf_publish_ws.json.input.StockRecord;
import org.gcube.data_catalogue.grsf_publish_ws.json.output.ResponseCreationBean; import org.gcube.data_catalogue.grsf_publish_ws.json.output.ResponseCreationBean;
import org.gcube.data_catalogue.grsf_publish_ws.utils.AssociationToGroupThread; import org.gcube.data_catalogue.grsf_publish_ws.utils.AssociationToGroupThread;
import org.gcube.data_catalogue.grsf_publish_ws.utils.HelperMethods; import org.gcube.data_catalogue.grsf_publish_ws.utils.HelperMethods;
import org.gcube.datacatalogue.ckanutillibrary.DataCatalogue; import org.gcube.datacatalogue.ckanutillibrary.DataCatalogue;
import org.gcube.datacatalogue.ckanutillibrary.models.ResourceBean;
import org.gcube.datacatalogue.ckanutillibrary.models.RolesCkanGroupOrOrg; import org.gcube.datacatalogue.ckanutillibrary.models.RolesCkanGroupOrOrg;
import org.gcube.datacatalogue.ckanutillibrary.utils.UtilMethods; import org.gcube.datacatalogue.ckanutillibrary.utils.UtilMethods;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -91,6 +89,19 @@ public class GrsfPublisherStockService {
Status status = Status.INTERNAL_SERVER_ERROR; Status status = Status.INTERNAL_SERVER_ERROR;
String id = ""; String id = "";
// validate the bean
logger.debug("Start validating bean...");
Response responseAfterValidation = HelperMethods.validateBeanAndResources(record);
if(responseAfterValidation == null)
logger.debug("Bean validation successful");
else{
logger.warn("Bean validation failed");
return responseAfterValidation;
}
try{ try{
// determine the organization in which this product should be put // determine the organization in which this product should be put
@ -179,18 +190,18 @@ public class GrsfPublisherStockService {
}else{ }else{
// evaluate the resources TODO // evaluate the resources TODO
List<Resource> resourcesRecord = record.getResources(); // List<Resource> resourcesRecord = record.getResources();
List<ResourceBean> resources = null; // List<ResourceBean> resources = null;
if(resourcesRecord != null && !resourcesRecord.isEmpty()){ // if(resourcesRecord != null && !resourcesRecord.isEmpty()){
resources = new ArrayList<ResourceBean>(); // resources = new ArrayList<ResourceBean>();
for (Resource res : resourcesRecord) { // for (Resource res : resourcesRecord) {
logger.debug("Trying to add resource " + res); // logger.debug("Trying to add resource " + res);
if(res.getName() != null && res.getUrl() != null) // if(res.getName() != null && res.getUrl() != null)
resources.add(new ResourceBean(res.getUrl(), res.getName(), res.getDescription(), null, username, null, null)); // resources.add(new ResourceBean(res.getUrl(), res.getName(), res.getDescription(), null, username, null, null));
else // else
logger.warn("Unable to add resource because url or name is null"); // logger.warn("Unable to add resource because url or name is null");
} // }
} // }
// if confirmed, set to visible TODO anyway if it is confirmed we should another method // if confirmed, set to visible TODO anyway if it is confirmed we should another method
@ -219,7 +230,7 @@ public class GrsfPublisherStockService {
license, license,
tags, tags,
customFields, customFields,
resources, null,
setPublic); // TODO setPublic); // TODO
if(id != null){ if(id != null){
@ -228,6 +239,7 @@ public class GrsfPublisherStockService {
responseBean.setId(id); responseBean.setId(id);
status = Status.CREATED; status = Status.CREATED;
responseBean.setError(null); responseBean.setError(null);
responseBean.setDatasetUrl(catalogue.getCatalogueUrl() + "/dataset/" + futureName);
if(!groups.isEmpty()){ if(!groups.isEmpty()){
logger.info("Launching thread for association to the list of groups " + groups); logger.info("Launching thread for association to the list of groups " + groups);

View File

@ -4,21 +4,34 @@ import java.beans.PropertyDescriptor;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import javax.servlet.ServletContext; import javax.servlet.ServletContext;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import javax.ws.rs.core.Response;
import org.gcube.common.scope.api.ScopeProvider; import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.CustomField; import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.CustomField;
import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.Group; import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.Group;
import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.Tag; import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.Tag;
import org.gcube.data_catalogue.grsf_publish_ws.json.input.Common; import org.gcube.data_catalogue.grsf_publish_ws.json.input.Common;
import org.gcube.data_catalogue.grsf_publish_ws.json.input.DatabaseSource;
import org.gcube.data_catalogue.grsf_publish_ws.json.input.FisheryRecord;
import org.gcube.data_catalogue.grsf_publish_ws.json.input.Resource;
import org.gcube.data_catalogue.grsf_publish_ws.json.output.ResponseCreationBean;
import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Source;
import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Status; import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Status;
import org.gcube.datacatalogue.ckanutillibrary.DataCatalogue; import org.gcube.datacatalogue.ckanutillibrary.DataCatalogue;
import org.gcube.datacatalogue.ckanutillibrary.DataCatalogueFactory; import org.gcube.datacatalogue.ckanutillibrary.DataCatalogueFactory;
import org.gcube.datacatalogue.ckanutillibrary.DataCatalogueImpl; import org.gcube.datacatalogue.ckanutillibrary.DataCatalogueImpl;
import org.gcube.datacatalogue.ckanutillibrary.models.ResourceBean;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import eu.trentorise.opendata.jackan.internal.org.apache.http.HttpResponse; import eu.trentorise.opendata.jackan.internal.org.apache.http.HttpResponse;
@ -116,7 +129,9 @@ public abstract class HelperMethods {
if(f != null){ if(f != null){
// also convert to the group name that should be on ckan // also convert to the group name that should be on ckan
groups.add(getGroupNameOnCkan(f.toString())); String groupName = getGroupNameOnCkan(f.toString());
if(!groups.contains(groupName))
groups.add(groupName);
} }
}catch(Exception e){ }catch(Exception e){
@ -126,6 +141,18 @@ public abstract class HelperMethods {
} }
} }
while((current = current.getSuperclass())!=null); while((current = current.getSuperclass())!=null);
// now parse also the Database Sources field
List<DatabaseSource> sources = record.getDatabaseSources();
for (DatabaseSource databaseSource : sources) {
logger.debug("Database source is " + databaseSource);
Source name = databaseSource.getName();
String groupName = getGroupNameOnCkan(name.toString());
if(!groups.contains(groupName))
groups.add(groupName);
}
} }
/** /**
@ -318,4 +345,75 @@ public abstract class HelperMethods {
} }
/**
* Validate a record along the database_sources and the source_of_information
* @param record
* @return
*/
public static Response validateBeanAndResources(Common record){
ResponseCreationBean responseBean = new ResponseCreationBean();
javax.ws.rs.core.Response.Status status = javax.ws.rs.core.Response.Status.BAD_REQUEST;
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Set<ConstraintViolation<Common>> violations = validator.validate(record);
for (ConstraintViolation<Common> constraintViolation : violations) {
logger.warn("Violation is about " + constraintViolation.getPropertyPath() + ", message error is " + constraintViolation.getMessage());
responseBean.setError(constraintViolation.getMessage());
return Response.status(status).entity(responseBean).build();
}
// check database_sources and source_of_information (they are not null nor empty at this point)
List<DatabaseSource> databaseSources = record.getDatabaseSources();
for (DatabaseSource databaseSource : databaseSources) {
Set<ConstraintViolation<DatabaseSource>> violationsDatabaseSourcesBean = validator.validate(databaseSource);
for (ConstraintViolation<DatabaseSource> constraintViolation : violationsDatabaseSourcesBean) {
logger.warn("Violation is about " + constraintViolation.getPropertyPath() + ", message error is " + constraintViolation.getMessage());
responseBean.setError(constraintViolation.getMessage());
return Response.status(status).entity(responseBean).build();
}
}
List<Resource> sourcesOfInformation = record.getSourceOfInformation();
for (Resource sourceOfinformation : sourcesOfInformation) {
Set<ConstraintViolation<Resource>> violationsSourceOfinformationsBean = validator.validate(sourceOfinformation);
for (ConstraintViolation<Resource> constraintViolation : violationsSourceOfinformationsBean) {
logger.warn("Violation is about " + constraintViolation.getPropertyPath() + ", message error is " + constraintViolation.getMessage());
responseBean.setError(constraintViolation.getMessage());
return Response.status(status).entity(responseBean).build();
}
}
return null;
}
/**
* Retrieve the ResourceBean given the record (extract resources from Database Sources and Source of Information)
* @param record
* @return
*/
public static List<ResourceBean> getResourcesFromBean(FisheryRecord record, String username) {
List<ResourceBean> toReturn = new ArrayList<ResourceBean>();
List<DatabaseSource> databaseSources = record.getDatabaseSources();
List<Resource> databaseOfInformation = record.getSourceOfInformation();
// transform database sources
for (DatabaseSource res : databaseSources) {
logger.debug("Adding resource " + res);
toReturn.add(new ResourceBean(res.getUrl(), res.getName().getOrigName(), res.getDescription(), null, username, null, null));
}
// just add source of information
for (Resource res : databaseOfInformation) {
logger.debug("Adding resource " + res);
toReturn.add(new ResourceBean(res.getUrl(), res.getName(), res.getDescription(), null, username, null, null));
}
logger.debug("Returning resources " + toReturn);
return toReturn;
}
} }

View File

@ -28,7 +28,7 @@
<description>Scope of pending products</description> <description>Scope of pending products</description>
<param-name>PendingContext</param-name> <param-name>PendingContext</param-name>
<!-- <param-value>/d4science.research-infrastructures.eu/FARM/GRSF</param-value> --> <!-- <param-value>/d4science.research-infrastructures.eu/FARM/GRSF</param-value> -->
<!-- <param-value>/gcube/devNext/NextNext</param-value> --> <param-value>/gcube/devNext/NextNext</param-value>
<!-- <param-value>/gcube/preprod/Dorne</param-value> --> <!-- <param-value>/gcube/preprod/Dorne</param-value> -->
</context-param> </context-param>
@ -36,7 +36,7 @@
<description>Scope of confirmed products</description> <description>Scope of confirmed products</description>
<param-name>ConfirmedContext</param-name> <param-name>ConfirmedContext</param-name>
<!-- <param-value>/d4science.research-infrastructures.eu/FARM/GRSFAccepted</param-value> --> <!-- <param-value>/d4science.research-infrastructures.eu/FARM/GRSFAccepted</param-value> -->
<!-- <param-value>/gcube/devNext/NextNext</param-value> --> <param-value>/gcube/devNext/NextNext</param-value>
<!-- <param-value>/gcube/preprod/Dorne</param-value> --> <!-- <param-value>/gcube/preprod/Dorne</param-value> -->
</context-param> </context-param>
</web-app> </web-app>

View File

@ -1,15 +1,18 @@
package org.gcube.data_catalogue.grsf_publish_ws; package org.gcube.data_catalogue.grsf_publish_ws;
import java.util.ArrayList;
import javax.ws.rs.client.Entity; import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Application; import javax.ws.rs.core.Application;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import org.gcube.data_catalogue.grsf_publish_ws.json.input.DatabaseSource;
import org.gcube.data_catalogue.grsf_publish_ws.json.input.FisheryRecord; import org.gcube.data_catalogue.grsf_publish_ws.json.input.FisheryRecord;
import org.gcube.data_catalogue.grsf_publish_ws.json.input.Resource;
import org.gcube.data_catalogue.grsf_publish_ws.json.input.StockRecord; import org.gcube.data_catalogue.grsf_publish_ws.json.input.StockRecord;
import org.gcube.data_catalogue.grsf_publish_ws.services.GrsfPublisherFisheryService; import org.gcube.data_catalogue.grsf_publish_ws.services.GrsfPublisherFisheryService;
import org.gcube.data_catalogue.grsf_publish_ws.services.GrsfPublisherStockService; import org.gcube.data_catalogue.grsf_publish_ws.services.GrsfPublisherStockService;
import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Source;
import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Status; import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Status;
import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Type; import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Type;
import org.glassfish.jersey.server.ResourceConfig; import org.glassfish.jersey.server.ResourceConfig;
@ -29,8 +32,11 @@ public class JJerseyTest extends JerseyTest{
FisheryRecord recordFishery = new FisheryRecord(); FisheryRecord recordFishery = new FisheryRecord();
recordFishery.setAuthor("Costantino Perciante"); recordFishery.setAuthor("Costantino Perciante");
recordFishery.setAuthorContact("costantino.perciante@isti.cnr.it"); recordFishery.setAuthorContact("costantino.perciante@isti.cnr.it");
recordFishery.setLicense("a caso una lincense");
recordFishery.setDataOwner("data owner");
recordFishery.setType(Type.Fishing_Description); recordFishery.setType(Type.Fishing_Description);
recordFishery.setDatabaseSources(Source.FIRMS); recordFishery.setDatabaseSources(new ArrayList<DatabaseSource>(1));
recordFishery.setSourceOfInformation(new ArrayList<Resource>(1));
recordFishery.setStatus(Status.Pending); recordFishery.setStatus(Status.Pending);
Response res = target("fishery").path("/publish-product").request().post(Entity.entity(recordFishery, MediaType.APPLICATION_JSON)); Response res = target("fishery").path("/publish-product").request().post(Entity.entity(recordFishery, MediaType.APPLICATION_JSON));
System.out.println("Result is " + res.readEntity(String.class)); System.out.println("Result is " + res.readEntity(String.class));
@ -42,7 +48,7 @@ public class JJerseyTest extends JerseyTest{
stock.setAuthor("Costantino Perciante"); stock.setAuthor("Costantino Perciante");
stock.setAuthorContact("costantino.perciante@isti.cnr.it"); stock.setAuthorContact("costantino.perciante@isti.cnr.it");
stock.setType(Type.Fishing_Description); stock.setType(Type.Fishing_Description);
stock.setDatabaseSources(Source.FIRMS); stock.setDatabaseSources(null);
stock.setStatus(Status.Pending); stock.setStatus(Status.Pending);
Response res = target("stock").path("/publish-product").request().post(Entity.entity(stock, MediaType.APPLICATION_JSON)); Response res = target("stock").path("/publish-product").request().post(Entity.entity(stock, MediaType.APPLICATION_JSON));

View File

@ -11,10 +11,18 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.CustomField; import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.CustomField;
import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.Group; import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.Group;
import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.Tag; import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.Tag;
import org.gcube.data_catalogue.grsf_publish_ws.json.input.Common;
import org.gcube.data_catalogue.grsf_publish_ws.json.input.DatabaseSource;
import org.gcube.data_catalogue.grsf_publish_ws.json.input.FisheryRecord; import org.gcube.data_catalogue.grsf_publish_ws.json.input.FisheryRecord;
import org.gcube.data_catalogue.grsf_publish_ws.json.input.StockRecord; import org.gcube.data_catalogue.grsf_publish_ws.json.input.StockRecord;
import org.gcube.data_catalogue.grsf_publish_ws.utils.HelperMethods; import org.gcube.data_catalogue.grsf_publish_ws.utils.HelperMethods;
@ -23,8 +31,6 @@ import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Source;
import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Status; import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Status;
import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Type; import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Type;
import com.fasterxml.jackson.databind.ObjectMapper;
import eu.trentorise.opendata.jackan.internal.org.apache.http.HttpResponse; import eu.trentorise.opendata.jackan.internal.org.apache.http.HttpResponse;
import eu.trentorise.opendata.jackan.internal.org.apache.http.client.methods.HttpGet; import eu.trentorise.opendata.jackan.internal.org.apache.http.client.methods.HttpGet;
import eu.trentorise.opendata.jackan.internal.org.apache.http.impl.client.CloseableHttpClient; import eu.trentorise.opendata.jackan.internal.org.apache.http.impl.client.CloseableHttpClient;
@ -39,7 +45,7 @@ public class JTests {
FisheryRecord recordFishery = new FisheryRecord(); FisheryRecord recordFishery = new FisheryRecord();
recordFishery.setType(Type.Fishing_Description); recordFishery.setType(Type.Fishing_Description);
recordFishery.setDatabaseSources(Source.FIRMS); recordFishery.setDatabaseSources(new ArrayList<DatabaseSource>());
recordFishery.setStatus(Status.Pending); recordFishery.setStatus(Status.Pending);
List<String> tags = new ArrayList<String>(); List<String> tags = new ArrayList<String>();
@ -116,24 +122,54 @@ public class JTests {
//@Test //@Test
public void testJSONMapping() throws IOException{ public void testJSONMapping() throws IOException{
StockRecord recordFishery = new StockRecord(); StockRecord recordStock = new StockRecord();
recordFishery.setType(Type.Fishing_Description); recordStock.setType(Type.Fishing_Description);
recordFishery.setDatabaseSources(Source.FIRMS); ArrayList<DatabaseSource> list = new ArrayList<DatabaseSource>();
recordFishery.setAuthor("Costantino Perciante"); list.add(new DatabaseSource("http", null, Source.onDeserialize("s")));
recordFishery.setMaintainer("Costantino Perciante"); recordStock.setDatabaseSources(list);
recordFishery.setAuthorContact("costantino.perciante@isti.cnr.it"); recordStock.setAuthor("Costantino Perciante");
recordFishery.setStatus(Status.Pending); recordStock.setMaintainer("Costantino Perciante");
recordFishery.setVersion(new Long(1)); recordStock.setAuthorContact("costantino.perciante@isti.cnr.it");
recordStock.setStatus(Status.Pending);
recordStock.setVersion(new Long(1));
ObjectMapper mapper = new ObjectMapper(); ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
//Object to JSON in String Set<ConstraintViolation<Common>> violations = validator.validate((Common)recordStock);
String jsonInString = mapper.writeValueAsString(recordFishery); for (ConstraintViolation<Common> constraintViolation : violations) {
System.out.println(jsonInString); System.out.println("Violation is about " + constraintViolation.getPropertyPath() + ", message error is " + constraintViolation.getMessage());
}
// JSON back to object // check database_sources and source_of_information (they are not null nor empty at this point)
StockRecord converted = mapper.readValue(jsonInString, recordFishery.getClass()); List<DatabaseSource> databaseSources = recordStock.getDatabaseSources();
System.out.println(converted); for (DatabaseSource databaseSource : databaseSources) {
Set<ConstraintViolation<DatabaseSource>> violationsDatabaseSourcesBean = validator.validate(databaseSource);
for (ConstraintViolation<DatabaseSource> constraintViolation : violationsDatabaseSourcesBean) {
System.out.println("Violation is about " + constraintViolation.getPropertyPath() + ", message error is " + constraintViolation.getMessage());
}
}
// List<Resource> sourcesOfInformation = recordStock.getSourceOfInformation();
// for (Resource sourceOfinformation : sourcesOfInformation) {
// Set<ConstraintViolation<Resource>> violationsSourceOfinformationsBean = validator.validate(sourceOfinformation);
// for (ConstraintViolation<Resource> constraintViolation : violationsSourceOfinformationsBean) {
// System.out.println("Violation is about " + constraintViolation.getPropertyPath() + ", message error is " + constraintViolation.getMessage());
// }
// }
//
//
// ObjectMapper mapper = new ObjectMapper();
//
// //Object to JSON in String
// String jsonInString = mapper.writeValueAsString(recordStock);
// System.out.println(jsonInString);
//
// // JSON back to object
// StockRecord converted = mapper.readValue(jsonInString, recordStock.getClass());
// System.out.println(converted);
} }
//@Test //@Test