diff --git a/pom.xml b/pom.xml index b133e98..ea59427 100644 --- a/pom.xml +++ b/pom.xml @@ -128,6 +128,11 @@ 2.23.2 test + + org.glassfish.jersey.ext + jersey-bean-validation + 2.23.2 + diff --git a/src/main/java/org/gcube/data_catalogue/grsf_publish_ws/json/input/Common.java b/src/main/java/org/gcube/data_catalogue/grsf_publish_ws/json/input/Common.java index 222b38b..ff061cb 100644 --- a/src/main/java/org/gcube/data_catalogue/grsf_publish_ws/json/input/Common.java +++ b/src/main/java/org/gcube/data_catalogue/grsf_publish_ws/json/input/Common.java @@ -4,10 +4,12 @@ import java.util.HashMap; import java.util.List; 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.Group; 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 com.fasterxml.jackson.annotation.JsonIgnoreProperties; @@ -17,13 +19,15 @@ import com.fasterxml.jackson.annotation.JsonProperty; * Information that both Stock and Fishery must contain * @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 { @JsonProperty("description") private String description; @JsonProperty("license_id") + @NotNull(message="license_id cannot be null") + @Size(min=2, message="license_id cannot be empty") private String license; // filled automatically by the service @@ -48,13 +52,16 @@ public class Common { private String catchesOrLandings; @JsonProperty("database_sources") - @Group @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 databaseSources; @JsonProperty("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 sourceOfInformation; @JsonProperty("data_owner") @CustomField(key="Data owner") @@ -66,27 +73,33 @@ public class Common { @CustomField(key="Type") private Type type; - @JsonProperty("resources") - private List resources; - @JsonProperty("extras") private Map extras = new HashMap<>(); - // @JsonProperty("spatial") - // @CustomField(key="Spatial") - // private String spatial; - public Common() { 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, Long version, String authorContact, String maintainer, String maintainerContact, String catchesOrLandings, - Source databaseSources, String sourceOfInformation, - String dataOwner, Type type, - List resources, Map extras, - String spatial) { + List databaseSources, List sourceOfInformation, + String dataOwner, Type type, Map extras) { super(); this.description = description; this.license = license; @@ -100,19 +113,9 @@ public class Common { this.sourceOfInformation = sourceOfInformation; this.dataOwner = dataOwner; this.type = type; - this.resources = resources; this.extras = extras; - // this.spatial = spatial; } - // public String getSpatial() { - // return spatial; - // } - // - // public void setSpatial(String spatial) { - // this.spatial = spatial; - // } - public String getDescription() { return description; } @@ -177,19 +180,19 @@ public class Common { this.catchesOrLandings = catchesOrLandings; } - public Source getDatabaseSources() { + public List getDatabaseSources() { return databaseSources; } - public void setDatabaseSources(Source databaseSources) { + public void setDatabaseSources(List databaseSources) { this.databaseSources = databaseSources; } - public String getSourceOfInformation() { + public List getSourceOfInformation() { return sourceOfInformation; } - public void setSourceOfInformation(String sourceOfInformation) { + public void setSourceOfInformation(List sourceOfInformation) { this.sourceOfInformation = sourceOfInformation; } @@ -209,14 +212,6 @@ public class Common { this.type = type; } - public List getResources() { - return resources; - } - - public void setResources(List resources) { - this.resources = resources; - } - public void setExtras(Map extras) { this.extras = extras; } @@ -234,8 +229,8 @@ public class Common { + ", catchesOrLandings=" + catchesOrLandings + ", databaseSources=" + databaseSources + ", sourceOfInformation=" + sourceOfInformation - + ", dataOwner=" + dataOwner + ", type=" + type - + ", resources=" + resources + ", extras=" + extras + "]"; + + ", dataOwner=" + dataOwner + ", type=" + type + ", extras=" + + extras + "]"; } - + } diff --git a/src/main/java/org/gcube/data_catalogue/grsf_publish_ws/json/input/DatabaseSource.java b/src/main/java/org/gcube/data_catalogue/grsf_publish_ws/json/input/DatabaseSource.java new file mode 100644 index 0000000..4e31973 --- /dev/null +++ b/src/main/java/org/gcube/data_catalogue/grsf_publish_ws/json/input/DatabaseSource.java @@ -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 + "]"; + } +} diff --git a/src/main/java/org/gcube/data_catalogue/grsf_publish_ws/json/input/FisheryRecord.java b/src/main/java/org/gcube/data_catalogue/grsf_publish_ws/json/input/FisheryRecord.java index 08c0de1..816d290 100644 --- a/src/main/java/org/gcube/data_catalogue/grsf_publish_ws/json/input/FisheryRecord.java +++ b/src/main/java/org/gcube/data_catalogue/grsf_publish_ws/json/input/FisheryRecord.java @@ -1,5 +1,8 @@ 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.Group; 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{ @JsonProperty("fishery_name") + @NotNull(message="fishery_name cannot be null") + @Size(min=1, message="fishery_name cannot be empty") private String fisheryName; @JsonProperty("fishery_id") @@ -61,6 +66,7 @@ public class FisheryRecord extends Common{ @JsonProperty("status") @CustomField(key="Status") @Group + @NotNull(message="status cannot be null") private Status status; @JsonProperty("environment") diff --git a/src/main/java/org/gcube/data_catalogue/grsf_publish_ws/json/input/Resource.java b/src/main/java/org/gcube/data_catalogue/grsf_publish_ws/json/input/Resource.java index f6fe4bd..8523f1d 100644 --- a/src/main/java/org/gcube/data_catalogue/grsf_publish_ws/json/input/Resource.java +++ b/src/main/java/org/gcube/data_catalogue/grsf_publish_ws/json/input/Resource.java @@ -1,5 +1,8 @@ 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.JsonProperty; @@ -11,12 +14,16 @@ import com.fasterxml.jackson.annotation.JsonProperty; public class Resource { @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; @JsonProperty("description") private String description; @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; public Resource() { diff --git a/src/main/java/org/gcube/data_catalogue/grsf_publish_ws/json/input/StockRecord.java b/src/main/java/org/gcube/data_catalogue/grsf_publish_ws/json/input/StockRecord.java index c4bb7fe..39a58c6 100644 --- a/src/main/java/org/gcube/data_catalogue/grsf_publish_ws/json/input/StockRecord.java +++ b/src/main/java/org/gcube/data_catalogue/grsf_publish_ws/json/input/StockRecord.java @@ -1,5 +1,8 @@ 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.Group; 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{ @JsonProperty("stock_name") + @NotNull(message="stock_name cannot be null") + @Size(min=2, message="stock_name cannot be empty") private String stockName; @JsonProperty("stock_id") @@ -24,11 +29,15 @@ public class StockRecord extends Common{ @JsonProperty("species_scientific_name") @Tag + @NotNull(message="species_scientific_name cannot be null") + @Size(min=1, message="species_scientific_name cannot be empty") @CustomField(key="Species scientific name") private String speciesScientificName; @JsonProperty("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; @JsonProperty("exploiting_fishery") @@ -75,6 +84,7 @@ public class StockRecord extends Common{ @JsonProperty("status") @Tag + @NotNull(message="status cannot be null") @CustomField(key="Status") private Status status; diff --git a/src/main/java/org/gcube/data_catalogue/grsf_publish_ws/json/output/ResponseCreationBean.java b/src/main/java/org/gcube/data_catalogue/grsf_publish_ws/json/output/ResponseCreationBean.java index b103fc3..f0eec62 100644 --- a/src/main/java/org/gcube/data_catalogue/grsf_publish_ws/json/output/ResponseCreationBean.java +++ b/src/main/java/org/gcube/data_catalogue/grsf_publish_ws/json/output/ResponseCreationBean.java @@ -1,5 +1,7 @@ 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. @@ -7,16 +9,28 @@ package org.gcube.data_catalogue.grsf_publish_ws.json.output; */ public class ResponseCreationBean { + @JsonProperty("id") private String id; + + @JsonProperty("dataset_url") + String datasetUrl; + + @JsonProperty("error") private String error; // in case of error public ResponseCreationBean() { super(); } - public ResponseCreationBean(String id, String error) { + /** + * @param id + * @param datasetUrl + * @param error + */ + public ResponseCreationBean(String id, String datasetUrl, String error) { super(); this.id = id; + this.datasetUrl = datasetUrl; this.error = error; } @@ -28,6 +42,14 @@ public class ResponseCreationBean { this.id = id; } + public String getDatasetUrl() { + return datasetUrl; + } + + public void setDatasetUrl(String datasetUrl) { + this.datasetUrl = datasetUrl; + } + public String getError() { return error; } @@ -38,6 +60,8 @@ public class ResponseCreationBean { @Override public String toString() { - return "ResponseCreationBean [id=" + id + ", error=" + error + "]"; + return "ResponseCreationBean [id=" + id + ", datasetUrl=" + datasetUrl + + ", error=" + error + "]"; } + } diff --git a/src/main/java/org/gcube/data_catalogue/grsf_publish_ws/services/GrsfPublisherFisheryService.java b/src/main/java/org/gcube/data_catalogue/grsf_publish_ws/services/GrsfPublisherFisheryService.java index 71497b2..8cd27e6 100644 --- a/src/main/java/org/gcube/data_catalogue/grsf_publish_ws/services/GrsfPublisherFisheryService.java +++ b/src/main/java/org/gcube/data_catalogue/grsf_publish_ws/services/GrsfPublisherFisheryService.java @@ -21,7 +21,6 @@ import org.gcube.common.authorization.library.provider.SecurityTokenProvider; import org.gcube.common.authorization.library.utils.Caller; 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.Resource; 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.HelperMethods; @@ -91,6 +90,19 @@ public class GrsfPublisherFisheryService { Status status = Status.INTERNAL_SERVER_ERROR; 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{ // 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 String futureTitle = record.getFisheryName(); + String fishingArea = record.getFishingArea(); + String jurisdictionArea = record.getJurisdictionArea(); if(!HelperMethods.isValid(futureTitle)){ status = Status.BAD_REQUEST; 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 '_', '-'"); + }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{ logger.debug("Checking if such name [" + futureTitle + "]doesn't exist yet..."); @@ -178,19 +198,8 @@ public class GrsfPublisherFisheryService { }else{ - // evaluate the resources TODO - List resourcesRecord = record.getResources(); - List resources = null; - if(resourcesRecord != null && !resourcesRecord.isEmpty()){ - resources = new ArrayList(); - 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"); - } - } + // evaluate the resources + List resources = HelperMethods.getResourcesFromBean(record, username); // 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; @@ -219,7 +228,7 @@ public class GrsfPublisherFisheryService { tags, customFields, resources, - setPublic); // TODO + setPublic); if(id != null){ @@ -227,6 +236,7 @@ public class GrsfPublisherFisheryService { responseBean.setId(id); status = Status.CREATED; responseBean.setError(null); + responseBean.setDatasetUrl(catalogue.getCatalogueUrl() + "/dataset/" + futureName); if(!groups.isEmpty()){ logger.info("Launching thread for association to the list of groups " + groups); diff --git a/src/main/java/org/gcube/data_catalogue/grsf_publish_ws/services/GrsfPublisherStockService.java b/src/main/java/org/gcube/data_catalogue/grsf_publish_ws/services/GrsfPublisherStockService.java index 5f20a2e..ce0cbd2 100644 --- a/src/main/java/org/gcube/data_catalogue/grsf_publish_ws/services/GrsfPublisherStockService.java +++ b/src/main/java/org/gcube/data_catalogue/grsf_publish_ws/services/GrsfPublisherStockService.java @@ -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.utils.Caller; 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.output.ResponseCreationBean; import org.gcube.data_catalogue.grsf_publish_ws.utils.AssociationToGroupThread; import org.gcube.data_catalogue.grsf_publish_ws.utils.HelperMethods; 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.utils.UtilMethods; import org.slf4j.LoggerFactory; @@ -90,6 +88,19 @@ public class GrsfPublisherStockService { ResponseCreationBean responseBean = new ResponseCreationBean(); Status status = Status.INTERNAL_SERVER_ERROR; 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{ @@ -179,18 +190,18 @@ public class GrsfPublisherStockService { }else{ // evaluate the resources TODO - List resourcesRecord = record.getResources(); - List resources = null; - if(resourcesRecord != null && !resourcesRecord.isEmpty()){ - resources = new ArrayList(); - 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"); - } - } + // List resourcesRecord = record.getResources(); + // List resources = null; + // if(resourcesRecord != null && !resourcesRecord.isEmpty()){ + // resources = new ArrayList(); + // 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 @@ -219,7 +230,7 @@ public class GrsfPublisherStockService { license, tags, customFields, - resources, + null, setPublic); // TODO if(id != null){ @@ -228,6 +239,7 @@ public class GrsfPublisherStockService { responseBean.setId(id); status = Status.CREATED; responseBean.setError(null); + responseBean.setDatasetUrl(catalogue.getCatalogueUrl() + "/dataset/" + futureName); if(!groups.isEmpty()){ logger.info("Launching thread for association to the list of groups " + groups); diff --git a/src/main/java/org/gcube/data_catalogue/grsf_publish_ws/utils/HelperMethods.java b/src/main/java/org/gcube/data_catalogue/grsf_publish_ws/utils/HelperMethods.java index 940d740..3068e3e 100644 --- a/src/main/java/org/gcube/data_catalogue/grsf_publish_ws/utils/HelperMethods.java +++ b/src/main/java/org/gcube/data_catalogue/grsf_publish_ws/utils/HelperMethods.java @@ -4,21 +4,34 @@ import java.beans.PropertyDescriptor; import java.io.BufferedReader; import java.io.InputStreamReader; import java.lang.reflect.Field; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; 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.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.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.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.datacatalogue.ckanutillibrary.DataCatalogue; import org.gcube.datacatalogue.ckanutillibrary.DataCatalogueFactory; import org.gcube.datacatalogue.ckanutillibrary.DataCatalogueImpl; +import org.gcube.datacatalogue.ckanutillibrary.models.ResourceBean; import org.slf4j.LoggerFactory; import eu.trentorise.opendata.jackan.internal.org.apache.http.HttpResponse; @@ -116,7 +129,9 @@ public abstract class HelperMethods { if(f != null){ // 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){ @@ -126,6 +141,18 @@ public abstract class HelperMethods { } } while((current = current.getSuperclass())!=null); + + // now parse also the Database Sources field + List 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> violations = validator.validate(record); + for (ConstraintViolation 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 databaseSources = record.getDatabaseSources(); + for (DatabaseSource databaseSource : databaseSources) { + Set> violationsDatabaseSourcesBean = validator.validate(databaseSource); + for (ConstraintViolation 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 sourcesOfInformation = record.getSourceOfInformation(); + for (Resource sourceOfinformation : sourcesOfInformation) { + Set> violationsSourceOfinformationsBean = validator.validate(sourceOfinformation); + for (ConstraintViolation 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 getResourcesFromBean(FisheryRecord record, String username) { + List toReturn = new ArrayList(); + + List databaseSources = record.getDatabaseSources(); + List 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; + } + } diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index cc9da5c..80dfcd8 100644 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -28,7 +28,7 @@ Scope of pending products PendingContext - + /gcube/devNext/NextNext @@ -36,7 +36,7 @@ Scope of confirmed products ConfirmedContext - + /gcube/devNext/NextNext diff --git a/src/test/java/org/gcube/data_catalogue/grsf_publish_ws/JJerseyTest.java b/src/test/java/org/gcube/data_catalogue/grsf_publish_ws/JJerseyTest.java index 1d02c5b..0249144 100644 --- a/src/test/java/org/gcube/data_catalogue/grsf_publish_ws/JJerseyTest.java +++ b/src/test/java/org/gcube/data_catalogue/grsf_publish_ws/JJerseyTest.java @@ -1,15 +1,18 @@ package org.gcube.data_catalogue.grsf_publish_ws; +import java.util.ArrayList; + import javax.ws.rs.client.Entity; import javax.ws.rs.core.Application; import javax.ws.rs.core.MediaType; 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.Resource; 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.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.Type; import org.glassfish.jersey.server.ResourceConfig; @@ -29,8 +32,11 @@ public class JJerseyTest extends JerseyTest{ FisheryRecord recordFishery = new FisheryRecord(); recordFishery.setAuthor("Costantino Perciante"); recordFishery.setAuthorContact("costantino.perciante@isti.cnr.it"); + recordFishery.setLicense("a caso una lincense"); + recordFishery.setDataOwner("data owner"); recordFishery.setType(Type.Fishing_Description); - recordFishery.setDatabaseSources(Source.FIRMS); + recordFishery.setDatabaseSources(new ArrayList(1)); + recordFishery.setSourceOfInformation(new ArrayList(1)); recordFishery.setStatus(Status.Pending); Response res = target("fishery").path("/publish-product").request().post(Entity.entity(recordFishery, MediaType.APPLICATION_JSON)); System.out.println("Result is " + res.readEntity(String.class)); @@ -42,7 +48,7 @@ public class JJerseyTest extends JerseyTest{ stock.setAuthor("Costantino Perciante"); stock.setAuthorContact("costantino.perciante@isti.cnr.it"); stock.setType(Type.Fishing_Description); - stock.setDatabaseSources(Source.FIRMS); + stock.setDatabaseSources(null); stock.setStatus(Status.Pending); Response res = target("stock").path("/publish-product").request().post(Entity.entity(stock, MediaType.APPLICATION_JSON)); diff --git a/src/test/java/org/gcube/data_catalogue/grsf_publish_ws/JTests.java b/src/test/java/org/gcube/data_catalogue/grsf_publish_ws/JTests.java index fb613f2..c9c1817 100644 --- a/src/test/java/org/gcube/data_catalogue/grsf_publish_ws/JTests.java +++ b/src/test/java/org/gcube/data_catalogue/grsf_publish_ws/JTests.java @@ -11,10 +11,18 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; 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.Group; 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.StockRecord; 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.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.client.methods.HttpGet; import eu.trentorise.opendata.jackan.internal.org.apache.http.impl.client.CloseableHttpClient; @@ -39,7 +45,7 @@ public class JTests { FisheryRecord recordFishery = new FisheryRecord(); recordFishery.setType(Type.Fishing_Description); - recordFishery.setDatabaseSources(Source.FIRMS); + recordFishery.setDatabaseSources(new ArrayList()); recordFishery.setStatus(Status.Pending); List tags = new ArrayList(); @@ -116,24 +122,54 @@ public class JTests { //@Test public void testJSONMapping() throws IOException{ - StockRecord recordFishery = new StockRecord(); - recordFishery.setType(Type.Fishing_Description); - recordFishery.setDatabaseSources(Source.FIRMS); - recordFishery.setAuthor("Costantino Perciante"); - recordFishery.setMaintainer("Costantino Perciante"); - recordFishery.setAuthorContact("costantino.perciante@isti.cnr.it"); - recordFishery.setStatus(Status.Pending); - recordFishery.setVersion(new Long(1)); + StockRecord recordStock = new StockRecord(); + recordStock.setType(Type.Fishing_Description); + ArrayList list = new ArrayList(); + list.add(new DatabaseSource("http", null, Source.onDeserialize("s"))); + recordStock.setDatabaseSources(list); + recordStock.setAuthor("Costantino Perciante"); + recordStock.setMaintainer("Costantino Perciante"); + 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 - String jsonInString = mapper.writeValueAsString(recordFishery); - System.out.println(jsonInString); + Set> violations = validator.validate((Common)recordStock); + for (ConstraintViolation constraintViolation : violations) { + System.out.println("Violation is about " + constraintViolation.getPropertyPath() + ", message error is " + constraintViolation.getMessage()); + } - // JSON back to object - StockRecord converted = mapper.readValue(jsonInString, recordFishery.getClass()); - System.out.println(converted); + // check database_sources and source_of_information (they are not null nor empty at this point) + List databaseSources = recordStock.getDatabaseSources(); + for (DatabaseSource databaseSource : databaseSources) { + Set> violationsDatabaseSourcesBean = validator.validate(databaseSource); + for (ConstraintViolation constraintViolation : violationsDatabaseSourcesBean) { + System.out.println("Violation is about " + constraintViolation.getPropertyPath() + ", message error is " + constraintViolation.getMessage()); + + } + } + + // List sourcesOfInformation = recordStock.getSourceOfInformation(); + // for (Resource sourceOfinformation : sourcesOfInformation) { + // Set> violationsSourceOfinformationsBean = validator.validate(sourceOfinformation); + // for (ConstraintViolation 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