code has been updated to according the requests in ticket #5567, unfortunately ckan doesn't support extras with duplicated keys, as it is(the ticket #5650 has been opened for this issue)

git-svn-id: https://svn.d4science.research-infrastructures.eu/gcube/trunk/data-catalogue/grsf-publisher-ws@133911 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
Costantino Perciante 2016-11-04 15:26:19 +00:00
parent f2b47b9e0a
commit 6e1c4d3bac
13 changed files with 298 additions and 240 deletions

View File

@ -12,7 +12,5 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface CkanResource {
boolean inspect() default false;
}

View File

@ -16,6 +16,7 @@ import javax.ws.rs.ext.Provider;
import org.gcube.common.authorization.library.AuthorizationEntry;
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.portal.PortalContext;
import org.gcube.common.scope.api.ScopeProvider;
@ -81,6 +82,7 @@ public class RequestsAuthAccountingFilter implements ContainerRequestFilter{
logger.debug("Setting scope " + ae.getContext());
AuthorizationProvider.instance.set(new Caller(ae.getClientInfo(), ae.getQualifier()));
ScopeProvider.instance.set(ae.getContext());
SecurityTokenProvider.instance.set(tokenInHeader);
logger.info("Authorization entry set in thread local");
return;
}else
@ -92,6 +94,7 @@ public class RequestsAuthAccountingFilter implements ContainerRequestFilter{
logger.debug("Setting scope " + ae.getContext());
AuthorizationProvider.instance.set(new Caller(ae.getClientInfo(), ae.getQualifier()));
ScopeProvider.instance.set(ae.getContext());
SecurityTokenProvider.instance.set(tokenAsQueryParameter);
logger.info("Authorization entry set in thread local");
return;
}else
@ -132,7 +135,7 @@ public class RequestsAuthAccountingFilter implements ContainerRequestFilter{
boolean isJson(ContainerRequestContext request) {
// define rules when to read body
return request.getMediaType().toString().contains("application/json");
return request.getMediaType().toString().contains(MediaType.APPLICATION_JSON);
}
}

View File

@ -12,6 +12,7 @@ import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.CkanResource;
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.Status;
import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Type;
@ -22,7 +23,7 @@ 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", "extras"}, ignoreUnknown = true) // ignore in serialization/deserialization
@JsonIgnoreProperties(value = {"author", "author_contact", "extras", "product_type"}, ignoreUnknown = true) // ignore in serialization/deserialization
public class Common {
@JsonProperty("description")
@ -49,22 +50,23 @@ public class Common {
private String maintainerContact;
@JsonProperty("catches_or_landings")
@Valid
@CkanResource
private Resource catchesOrLandings;
@Valid
private Resource<String> catchesOrLandings;
@JsonProperty("database_sources")
@NotNull(message="database_source cannot be null")
@Size(min=1, message="database_source cannot be empty")
@CkanResource
@Valid
private List<DatabaseSource> databaseSources;
private List<Resource<Source>> databaseSources;
@JsonProperty("source_of_information")
@NotNull(message="source_of_information cannot be null")
@Size(min=1, message="source_of_information cannot be empty")
@CkanResource
@Valid
private List<Resource> sourceOfInformation;
private List<Resource<String>> sourceOfInformation;
@JsonProperty("data_owner")
@CustomField(key="Data owner")
@ -78,19 +80,20 @@ public class Common {
@JsonProperty("short_title")
@CustomField(key="Short Title")
@NotNull
@NotNull(message="short_title cannot be null")
@Size(min=1, message="short_title cannot be empty")
private String shortTitle;
@JsonProperty("uuid_knowledge_base")
@CustomField(key="UUID Knowledge Base")
@NotNull
@NotNull(message="uuid_knowledge_base cannot be null")
@Size(min=1, message="uuid_knowledge_base cannot be empty")
// This will be the identifier of the product!!
private String uuid;
@JsonProperty("traceability_flag")
@CustomField(key="Traceability Flag")
@NotNull
@NotNull(message="traceability_flag cannot be null")
private boolean traceabilityFlag;
@JsonProperty("extras")
@ -103,6 +106,12 @@ public class Common {
@NotNull(message="status cannot be null")
private Status status;
// automatically compiled
@JsonProperty("product_type")
@CustomField(key="Product type")
@Tag
private String productType;
public Common() {
super();
}
@ -124,14 +133,17 @@ public class Common {
* @param uuid
* @param traceabilityFlag
* @param extras
* @param status
* @param productType
*/
public Common(String description, String license, String author,
Long version, String authorContact, String maintainer,
String maintainerContact, Resource catchesOrLandings,
List<DatabaseSource> databaseSources,
List<Resource> sourceOfInformation, String dataOwner, Type type,
String shortTitle, String uuid, boolean traceabilityFlag,
Map<String, List<String>> extras) {
String maintainerContact, Resource<String> catchesOrLandings,
List<Resource<Source>> databaseSources,
List<Resource<String>> sourceOfInformation, String dataOwner,
Type type, String shortTitle, String uuid,
boolean traceabilityFlag, Map<String, List<String>> extras,
Status status, String productType) {
super();
this.description = description;
this.license = license;
@ -149,6 +161,16 @@ public class Common {
this.uuid = uuid;
this.traceabilityFlag = traceabilityFlag;
this.extras = extras;
this.status = status;
this.productType = productType;
}
public String getProductType() {
return productType;
}
public void setProductType(String productType) {
this.productType = productType;
}
public String getDescription() {
@ -207,27 +229,27 @@ public class Common {
this.maintainerContact = maintainerContact;
}
public Resource getCatchesOrLandings() {
public Resource<String> getCatchesOrLandings() {
return catchesOrLandings;
}
public void setCatchesOrLandings(Resource catchesOrLandings) {
public void setCatchesOrLandings(Resource<String> catchesOrLandings) {
this.catchesOrLandings = catchesOrLandings;
}
public List<DatabaseSource> getDatabaseSources() {
public List<Resource<Source>> getDatabaseSources() {
return databaseSources;
}
public void setDatabaseSources(List<DatabaseSource> databaseSources) {
public void setDatabaseSources(List<Resource<Source>> databaseSources) {
this.databaseSources = databaseSources;
}
public List<Resource> getSourceOfInformation() {
public List<Resource<String>> getSourceOfInformation() {
return sourceOfInformation;
}
public void setSourceOfInformation(List<Resource> sourceOfInformation) {
public void setSourceOfInformation(List<Resource<String>> sourceOfInformation) {
this.sourceOfInformation = sourceOfInformation;
}
@ -299,6 +321,7 @@ public class Common {
+ ", dataOwner=" + dataOwner + ", type=" + type
+ ", shortTitle=" + shortTitle + ", uuid=" + uuid
+ ", traceabilityFlag=" + traceabilityFlag + ", extras="
+ extras + "]";
+ extras + ", status=" + status + ", productType="
+ productType + "]";
}
}

View File

@ -1,74 +0,0 @@
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.custom_annotations.Tag;
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
@Tag
@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

@ -3,15 +3,17 @@ 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.utils.groups.Source;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* A resource object bean
* A resource object bean. The generic argument applies to the resource's name.
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
*/
@JsonIgnoreProperties(ignoreUnknown = true) // ignore in serialization/deserialization
public class Resource {
public class Resource<T> {
@JsonProperty("url")
@NotNull(message="'url' field of a resource cannot be null")
@ -23,14 +25,13 @@ public class Resource {
@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 T name;
public Resource() {
super();
}
public Resource(String url, String description, String name) {
public Resource(String url, String description, T name) {
super();
this.url = url;
this.description = description;
@ -53,18 +54,24 @@ public class Resource {
this.description = description;
}
public String getName() {
public T getName() {
return name;
}
public void setName(String name) {
public void setName(T name) {
this.name = name;
}
@Override
public String toString() {
return "Resource [url=" + url + ", description=" + description
+ ", name=" + name + "]";
// in case of @tag
Class<? extends Object> nameClass = name.getClass();
if(nameClass.equals(Source.class))
return name.toString();
else
return "Resource [url=" + url + ", description=" + description
+ ", name=" + name + "]";
}
}

View File

@ -6,10 +6,11 @@ import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.CkanResource;
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.Abundance_Level;
import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Exploitation_Rate;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
@ -61,18 +62,24 @@ public class StockRecord extends Common{
private String stateOfMarineResource;
@JsonProperty("exploitation_rate")
@Group
@CustomField(key="Exploitation Rate")
@Tag
@CkanResource(inspect=true)
@Valid
private Resource exploitationRate;
private List<TimeSeriesBean<Exploitation_Rate>> exploitationRate;
@JsonProperty("abundance_level")
@Group
@CustomField(key="Abundance Level")
@Tag
@CkanResource(inspect=true)
@Valid
private Resource abundanceLevel;
private List<TimeSeriesBean<Abundance_Level>> abundanceLevel;
@JsonProperty("exploitation_rate_for_grouping")
@Group
private Exploitation_Rate exploitationRateForGrouping;
@JsonProperty("abundance_level_for_grouping")
@Group
private Abundance_Level abundanceLevelForGrouping;
@JsonProperty("narrative_state_and_trend")
@CustomField(key="Narrative state and trend")
@ -96,8 +103,7 @@ public class StockRecord extends Common{
@JsonProperty("water_area")
@CustomField(key="Water Area")
private List<String> waterArea;// TODO check that multiple values are mapped to ckan
private List<String> waterArea;
public StockRecord() {
super();
@ -114,11 +120,12 @@ public class StockRecord extends Common{
* @param stateOfMarineResource
* @param exploitationRate
* @param abundanceLevel
* @param exploitationRateForGrouping
* @param abundanceLevelForGrouping
* @param narrativeStateAndTrend
* @param scientificAdvice
* @param reportingEntity
* @param reportingYear
* @param status
* @param stockUri
* @param waterArea
*/
@ -126,10 +133,13 @@ public class StockRecord extends Common{
String speciesScientificName, String area,
String exploitingFishery, String managementEntity,
String assessmentMethods, String stateOfMarineResource,
Resource exploitationRate, Resource abundanceLevel,
List<TimeSeriesBean<Exploitation_Rate>> exploitationRate,
List<TimeSeriesBean<Abundance_Level>> abundanceLevel,
Exploitation_Rate exploitationRateForGrouping,
Abundance_Level abundanceLevelForGrouping,
String narrativeStateAndTrend, String scientificAdvice,
String reportingEntity, Long reportingYear,
String stockUri, List<String> waterArea) {
String reportingEntity, Long reportingYear, String stockUri,
List<String> waterArea) {
super();
this.stockName = stockName;
this.stockID = stockID;
@ -141,6 +151,8 @@ public class StockRecord extends Common{
this.stateOfMarineResource = stateOfMarineResource;
this.exploitationRate = exploitationRate;
this.abundanceLevel = abundanceLevel;
this.exploitationRateForGrouping = exploitationRateForGrouping;
this.abundanceLevelForGrouping = abundanceLevelForGrouping;
this.narrativeStateAndTrend = narrativeStateAndTrend;
this.scientificAdvice = scientificAdvice;
this.reportingEntity = reportingEntity;
@ -149,6 +161,24 @@ public class StockRecord extends Common{
this.waterArea = waterArea;
}
public Exploitation_Rate getExploitationRateForGrouping() {
return exploitationRateForGrouping;
}
public void setExploitationRateForGrouping(
Exploitation_Rate exploitationRateForGrouping) {
this.exploitationRateForGrouping = exploitationRateForGrouping;
}
public Abundance_Level getAbundanceLevelForGrouping() {
return abundanceLevelForGrouping;
}
public void setAbundanceLevelForGrouping(
Abundance_Level abundanceLevelForGrouping) {
this.abundanceLevelForGrouping = abundanceLevelForGrouping;
}
public String getStockUri() {
return stockUri;
}
@ -229,19 +259,19 @@ public class StockRecord extends Common{
this.stateOfMarineResource = stateOfMarineResource;
}
public Resource getExploitationRate() {
public List<TimeSeriesBean<Exploitation_Rate>> getExploitationRate() {
return exploitationRate;
}
public void setExploitationRate(Resource exploitationRate) {
public void setExploitationRate(List<TimeSeriesBean<Exploitation_Rate>> exploitationRate) {
this.exploitationRate = exploitationRate;
}
public Resource getAbundanceLevel() {
public List<TimeSeriesBean<Abundance_Level>> getAbundanceLevel() {
return abundanceLevel;
}
public void setAbundanceLevel(Resource abundanceLevel) {
public void setAbundanceLevel(List<TimeSeriesBean<Abundance_Level>> abundanceLevel) {
this.abundanceLevel = abundanceLevel;
}
@ -287,10 +317,12 @@ public class StockRecord extends Common{
+ ", stateOfMarineResource=" + stateOfMarineResource
+ ", exploitationRate=" + exploitationRate
+ ", abundanceLevel=" + abundanceLevel
+ ", narrativeStateAndTrend=" + narrativeStateAndTrend
+ ", scientificAdvice=" + scientificAdvice
+ ", reportingEntity=" + reportingEntity + ", reportingYear="
+ reportingYear + ", stockUri=" + stockUri + ", waterArea="
+ waterArea + "]";
}
+ ", exploitationRateForGrouping="
+ exploitationRateForGrouping + ", abundanceLevelForGrouping="
+ abundanceLevelForGrouping + ", narrativeStateAndTrend="
+ narrativeStateAndTrend + ", scientificAdvice="
+ scientificAdvice + ", reportingEntity=" + reportingEntity
+ ", reportingYear=" + reportingYear + ", stockUri=" + stockUri
+ ", waterArea=" + waterArea + "]";
}
}

View File

@ -0,0 +1,70 @@
package org.gcube.data_catalogue.grsf_publish_ws.json.input;
import javax.validation.constraints.NotNull;
import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Abundance_Level;
import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Exploitation_Rate;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* A time series bean that contains couple <year, value>
* @author Costantino Perciante at ISTI-CNR
* (costantino.perciante@isti.cnr.it)
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class TimeSeriesBean<T> {
@JsonProperty("value")
@NotNull(message="value of a time series cannot be null")
private T value;
@JsonProperty("year")
@NotNull(message="year of a time series cannot be null")
private Long year;
/**
*
*/
public TimeSeriesBean() {
super();
}
/**
* @param value
* @param year
*/
public TimeSeriesBean(T value, Long year) {
super();
this.value = value;
this.year = year;
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
public Long getYear() {
return year;
}
public void setYear(Long year) {
this.year = year;
}
@Override
public String toString() {
Class<? extends Object> valueClass = value.getClass();
// when the value belongs to these classes annotated with @Tag..
if(valueClass.equals(Abundance_Level.class) || valueClass.equals(Exploitation_Rate.class))
return year + "-" + value;
else
return "TimeSeriesBean [value=" + value + ", year=" + year + "]";
}
}

View File

@ -11,6 +11,9 @@ public class ResponseCreationBean {
@JsonProperty("id")
private String id;
@JsonProperty("knowledge_base_id")
private String kbUuid; // the original uuid given by the KB
@JsonProperty("product_url")
String productUrl;
@ -24,12 +27,15 @@ public class ResponseCreationBean {
/**
* @param id
* @param kbUuid
* @param productUrl
* @param error
*/
public ResponseCreationBean(String id, String productUrl, String error) {
public ResponseCreationBean(String id, String kbUuid, String productUrl,
String error) {
super();
this.id = id;
this.kbUuid = kbUuid;
this.productUrl = productUrl;
this.error = error;
}
@ -42,10 +48,6 @@ public class ResponseCreationBean {
this.id = id;
}
public String getProducttUrl() {
return productUrl;
}
public void setProductUrl(String productUrl) {
this.productUrl = productUrl;
}
@ -58,10 +60,21 @@ public class ResponseCreationBean {
this.error = error;
}
@Override
public String toString() {
return "ResponseCreationBean [id=" + id + ", productUrl=" + productUrl
+ ", error=" + error + "]";
public String getKbUuid() {
return kbUuid;
}
public void setKbUuid(String kbUuid) {
this.kbUuid = kbUuid;
}
public String getProductUrl() {
return productUrl;
}
@Override
public String toString() {
return "ResponseCreationBean [id=" + id + ", kbUuid=" + kbUuid
+ ", productUrl=" + productUrl + ", error=" + error + "]";
}
}

View File

@ -1,7 +1,7 @@
package org.gcube.data_catalogue.grsf_publish_ws.services;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -33,7 +33,6 @@ 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;
import eu.trentorise.opendata.jackan.model.CkanDataset;
@ -92,6 +91,7 @@ public class GrsfPublisherFisheryService {
Caller caller = AuthorizationProvider.instance.get();
String username = caller.getClient().getId();
String context = ScopeProvider.instance.get();
String token = SecurityTokenProvider.instance.get();
logger.info("Incoming request for creating a fishery record = " + record);
logger.info("Request coming from user " + username + " in context " + context);
@ -133,11 +133,12 @@ public class GrsfPublisherFisheryService {
}
// check the record has a name, at least
// The name of the product will be the uuid of the kb. The title will be the fishery's fishery_name.
String futureName = record.getUuid();
String futureTitle = record.getFisheryName();
String fishingArea = record.getFishingArea();
String jurisdictionArea = record.getJurisdictionArea();
if(!HelperMethods.isValid(futureTitle)){
if(!HelperMethods.isValid(futureName)){
status = Status.BAD_REQUEST;
responseBean.setId(null);
@ -151,9 +152,7 @@ public class GrsfPublisherFisheryService {
}else{
logger.debug("Checking if such name [" + futureTitle + "]doesn't exist yet...");
String futureName = UtilMethods.fromProductTitleToName(futureTitle);
logger.info("Transformed name is " + futureName);
logger.debug("Checking if such name [" + futureName + "] doesn't exist yet...");
boolean alreadyExist = catalogue.existProductWithNameOrId(futureName);
if(alreadyExist){
@ -164,11 +163,13 @@ public class GrsfPublisherFisheryService {
throw new Exception("Sorry but a product with such name already exists!");
}else{
// set the type
record.setProductType(THIS_TYPE);
// evaluate the tags of the product
List<String> tags = new ArrayList<String>();
HelperMethods.getTags(tags, record);
tags.add(THIS_TYPE);
// evaluate the groups
List<String> groups = new ArrayList<String>();
@ -183,12 +184,9 @@ public class GrsfPublisherFisheryService {
// automatically retrieve the other ones
HelperMethods.getExtras(customFields, record);
// add the type
customFields.put(HelperMethods.PRODUCT_TYPE, Arrays.asList(THIS_TYPE));
// retrieve the user's email and fullname
String authorMail = HelperMethods.getUserEmail(context, SecurityTokenProvider.instance.get());
String authorFullname = HelperMethods.getUserFullname(context, SecurityTokenProvider.instance.get());
String authorMail = HelperMethods.getUserEmail(context, token);
String authorFullname = HelperMethods.getUserFullname(context, token);
if(authorMail == null || authorFullname == null){
@ -220,6 +218,7 @@ public class GrsfPublisherFisheryService {
id = catalogue.createCKanDatasetMultipleCustomFields(
catalogue.getApiKeyFromUsername(username),
futureTitle,
futureName,
organization,
authorFullname,
authorMail,
@ -239,7 +238,8 @@ public class GrsfPublisherFisheryService {
responseBean.setId(id);
status = Status.CREATED;
responseBean.setError(null);
responseBean.setProductUrl(catalogue.getPortletUrl() + "?path=/dataset/" + futureName);
responseBean.setProductUrl(catalogue.getPortletUrl() + "?" + URLEncoder.encode("path=/dataset/" + futureName, "UTF-8"));
responseBean.setKbUuid(record.getUuid());
if(!groups.isEmpty()){
logger.info("Launching thread for association to the list of groups " + groups);

View File

@ -1,7 +1,7 @@
package org.gcube.data_catalogue.grsf_publish_ws.services;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -33,7 +33,6 @@ 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;
import eu.trentorise.opendata.jackan.model.CkanDataset;
@ -92,6 +91,7 @@ public class GrsfPublisherStockService {
Caller caller = AuthorizationProvider.instance.get();
String username = caller.getClient().getId();
String context = ScopeProvider.instance.get();
String token = SecurityTokenProvider.instance.get();
logger.info("Incoming request for creating a stock record = " + record);
logger.info("Request coming from user " + username + " in context " + context);
@ -134,8 +134,9 @@ public class GrsfPublisherStockService {
}
// check the record has a name, at least
String futureName = record.getUuid();
String futureTitle = record.getStockName();
if(!HelperMethods.isValid(futureTitle)){
if(!HelperMethods.isValid(futureName)){
status = Status.BAD_REQUEST;
responseBean.setId(null);
@ -143,9 +144,7 @@ public class GrsfPublisherStockService {
}else{
logger.debug("Checking if such name [" + futureTitle + "] doesn't exist yet...");
String futureName = UtilMethods.fromProductTitleToName(futureTitle);
logger.info("Transformed name is " + futureName);
logger.debug("Checking if such name [" + futureName + "] doesn't exist yet...");
boolean alreadyExist = catalogue.existProductWithNameOrId(futureName);
if(alreadyExist){
@ -157,11 +156,13 @@ public class GrsfPublisherStockService {
}else{
// set the type
record.setProductType(THIS_TYPE);
// evaluate the tags of the product
List<String> tags = new ArrayList<String>();
HelperMethods.getTags(tags, record);
tags.add(THIS_TYPE);
// evaluate the groups
List<String> groups = new ArrayList<String>();
HelperMethods.getGroups(groups, record);
@ -174,20 +175,17 @@ public class GrsfPublisherStockService {
// automatically retrieve the other ones
HelperMethods.getExtras(customFields, record);
// add the type
customFields.put(HelperMethods.PRODUCT_TYPE, Arrays.asList(THIS_TYPE));
// retrieve the user's email and fullname
String authorMail = HelperMethods.getUserEmail(context, SecurityTokenProvider.instance.get());
String authorFullname = HelperMethods.getUserFullname(context, SecurityTokenProvider.instance.get());
String authorMail = HelperMethods.getUserEmail(context, token);
String authorFullname = HelperMethods.getUserFullname(context, token);
if(authorMail == null || authorFullname == null){
logger.debug("Author fullname or mail missing, cannot continue");
responseBean.setId(null);
status = Status.INTERNAL_SERVER_ERROR;
throw new Exception("Sorry but there was not possible to retrieve your fullname/email!");
throw new Exception("Sorry but was not possible to retrieve your fullname/email!");
}else{
@ -211,6 +209,7 @@ public class GrsfPublisherStockService {
id = catalogue.createCKanDatasetMultipleCustomFields(
catalogue.getApiKeyFromUsername(username),
futureTitle,
futureName,
organization,
authorFullname,
authorMail,
@ -230,7 +229,8 @@ public class GrsfPublisherStockService {
responseBean.setId(id);
status = Status.CREATED;
responseBean.setError(null);
responseBean.setProductUrl(catalogue.getPortletUrl() + "?path=/dataset/" + futureName);
responseBean.setProductUrl(catalogue.getPortletUrl() + "?" + URLEncoder.encode("path=/dataset/" + futureName, "UTF-8"));
responseBean.setKbUuid(record.getUuid());
if(!groups.isEmpty()){
logger.info("Launching thread for association to the list of groups " + groups);

View File

@ -5,7 +5,6 @@ import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -18,9 +17,7 @@ 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.Resource;
import org.gcube.data_catalogue.grsf_publish_ws.json.input.StockRecord;
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;
@ -47,7 +44,6 @@ public abstract class HelperMethods {
// to be retrieved from the web.xml
private static final String PENDING_CONTEX_KEY = "PendingContext";
private static final String CONFIRMED_CONTEX_KEY = "ConfirmedContext";
public static final String PRODUCT_TYPE = "Product type";
/**
* Convert a group name to its id on ckan
@ -73,7 +69,7 @@ public abstract class HelperMethods {
* @return
* @throws Exception
*/
public static DataCatalogue getDataCatalogueRunningInstance(String scope) throws Exception{
public static DataCatalogue getDataCatalogueRunningInstance(String scope){
try{
DataCatalogueImpl instance = DataCatalogueFactory.getFactory().getUtilsPerScope(scope);
@ -100,9 +96,22 @@ public abstract class HelperMethods {
Object f = new PropertyDescriptor(field.getName(), current).getReadMethod().invoke(record);
if(f != null){
if(f instanceof List<?>){
tags.add(f.toString().trim());
List asList = ((List) f);
logger.debug("The object annotated with @Tag is a list. Adding ... ");
for (Object object : asList) {
logger.debug(object.toString().trim());
tags.add(object.toString().trim());
}
}else{
logger.debug("The object annotated with @Tag is a simple one. Adding ... ");
logger.debug(f.toString().trim());
tags.add(f.toString().trim());
}
}
}catch(Exception e){
logger.error("Failed ot read value for field " + field.getName() + " skipping", e);
@ -111,16 +120,8 @@ public abstract class HelperMethods {
}
}
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);
String nameAsTag = databaseSource.getName().toString();
if(!tags.contains(nameAsTag))
tags.add(nameAsTag);
}
logger.info("Tags are " + tags);
}
/**
@ -151,19 +152,7 @@ public abstract class HelperMethods {
}
while((current = current.getSuperclass())!=null);
logger.debug("Groups is " + groups);
// 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().trim());
if(!groups.contains(groupName))
groups.add(groupName);
}
logger.info("Groups is " + groups);
}
/**
@ -181,15 +170,18 @@ public abstract class HelperMethods {
String keyField = field.getAnnotation(CustomField.class).key();
if(f != null){
if(f.getClass().isArray()){
if(Collection.class.isAssignableFrom(f.getClass())){
if(f instanceof List<?>){
logger.debug("The object " + field.getName() + " is a list and is annotated with @CustomField. Adding ...");
List asList = (List)f;
List<String> res = new ArrayList<String>();
for (Object object : asList) {
logger.debug(object.toString().trim());
res.add(object.toString().trim());
}
logger.debug("The object " + field.getName() + " is a collection");
List<String> res = (List<String>)f;
extras.put(keyField, res);
extras.put(keyField, res);
}else
logger.error("The object " + field.getName() + " cannot be convert to a list/array");
}else{
List<String> values = new ArrayList<String>();
if(extras.containsKey(keyField))
@ -206,6 +198,8 @@ public abstract class HelperMethods {
}
}
while((current = current.getSuperclass())!=null);
logger.info("Extras is " + extras);
}
/**
@ -269,8 +263,8 @@ public abstract class HelperMethods {
try(CloseableHttpClient client = HttpClientBuilder.create().build();){
String baseUrl = new ServiceEndPointReaderSocial(context).getBasePath();
String url = baseUrl.replace("http", "https") + "/users/getUserEmail?gcube-token=" + token;
logger.debug("Request url is " + baseUrl);
String url = baseUrl + "users/getUserEmail?gcube-token=" + token;
logger.debug("Request url is " + url);
HttpGet getRequest = new HttpGet(url);
HttpResponse response = client.execute(getRequest);
@ -310,7 +304,7 @@ public abstract class HelperMethods {
try(CloseableHttpClient client = HttpClientBuilder.create().build();){
String baseUrl = new ServiceEndPointReaderSocial(context).getBasePath();
String url = baseUrl.replace("http", "https") + "/users/getUserEmail?gcube-token=" + token;
String url = baseUrl + "users/getUserFullname?gcube-token=" + token;
logger.debug("Request url is " + url);
HttpGet getRequest = new HttpGet(url);
HttpResponse response = client.execute(getRequest);
@ -365,9 +359,16 @@ public abstract class HelperMethods {
*/
public static boolean existsLicenseId(String license) throws Exception {
Map<String, String> licenses = getLicenses();
return licenses.containsKey(license);
String scope = ScopeProvider.instance.get();
DataCatalogue catalogue = getDataCatalogueRunningInstance(scope);
List<CkanLicense> licenses = catalogue.getLicenses();
for (CkanLicense ckanLicense : licenses) {
if(ckanLicense.getId().equals(license))
return true;
}
return false;
}
/**
@ -380,15 +381,12 @@ public abstract class HelperMethods {
*/
public static List<ResourceBean> getResourcesFromBean(Common record, String username, List<String> tags, List<String> groups){
List<ResourceBean> toReturn = new ArrayList<ResourceBean>();
List<DatabaseSource> databaseSources = record.getDatabaseSources();
// 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));
List<Resource<Source>> databaseSources = record.getDatabaseSources();
for (Resource<Source> resource : databaseSources) {
toReturn.add(new ResourceBean(resource.getUrl(), resource.getName().toString(), resource.getDescription(), null, username, null, null));
}
Class<?> current = record.getClass();
do{
Field[] fields = current.getDeclaredFields();
@ -403,18 +401,15 @@ public abstract class HelperMethods {
List<Resource> listOfResources = (List<Resource>)f;
for (Resource resource : listOfResources) {
toReturn.add(new ResourceBean(resource.getUrl(), resource.getName(), resource.getDescription(), null, username, null, null));
toReturn.add(new ResourceBean(resource.getUrl(), resource.getName().toString(), resource.getDescription(), null, username, null, null));
}
}else{
Resource res = (Resource)f;
toReturn.add(new ResourceBean(res.getUrl(), res.getName(), res.getDescription(), null, username, null, null));
toReturn.add(new ResourceBean(res.getUrl(), res.getName().toString(), res.getDescription(), null, username, null, null));
}
// TODO handle groups/tags
}
}catch(Exception e){
logger.error("Failed ot read value for field " + field.getName() + " skipping", e);
@ -424,18 +419,7 @@ public abstract class HelperMethods {
}
while((current = current.getSuperclass())!=null);
logger.debug("Returning resources " + toReturn);
logger.info("Returning resources " + toReturn);
return toReturn;
}
/**
* Inspect a resource file at this url for finding out tags/groups of the object
* @param r
*/
public static void inspectResourceFile(Resource r){
// TODO
}
}

View File

@ -7,12 +7,12 @@ 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;
@ -35,8 +35,8 @@ public class JJerseyTest extends JerseyTest{
recordFishery.setLicense("a caso una lincense");
recordFishery.setDataOwner("data owner");
recordFishery.setType(Type.Fishing_Description);
recordFishery.setDatabaseSources(new ArrayList<DatabaseSource>(1));
recordFishery.setSourceOfInformation(new ArrayList<Resource>(1));
recordFishery.setDatabaseSources(new ArrayList<Resource<Source>>(1));
recordFishery.setSourceOfInformation(new ArrayList<Resource<String>>(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));

View File

@ -16,13 +16,15 @@ import java.util.Map;
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.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.utils.HelperMethods;
import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Abundance_Level;
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.junit.Test;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.core.JsonProcessingException;
@ -43,7 +45,7 @@ public class JTests {
FisheryRecord recordFishery = new FisheryRecord();
recordFishery.setType(Type.Fishing_Description);
recordFishery.setDatabaseSources(new ArrayList<DatabaseSource>());
recordFishery.setDatabaseSources(new ArrayList<Resource<Source>>());
recordFishery.setStatus(Status.Pending);
List<String> tags = new ArrayList<String>();
@ -117,7 +119,7 @@ public class JTests {
System.out.println(res.name());
}
//@Test
// @Test
public void testJSONMapping() throws IOException{
FisheryRecord record = new FisheryRecord();
@ -188,7 +190,7 @@ public class JTests {
ObjectMapper mapper = new ObjectMapper();
//Object to JSON in String
String jsonInString = mapper.writeValueAsString(record);
StockRecord jsonInString = mapper.readValue("{\n \"short_title\":\"Thunnus maccoyii SEAFO division D.1\",\n \"data_owner\":\"CCSBT\",\n \"narrative_state_and_trend\":\"<p>The 2014 assessment suggested that the SBT spawning biomass is at a very low fraction (9%) of its original biomass as well as below the level that could produce maximum sustainable yield. However, there has been some improvement since the 2011 stock assessment and the fishing mortality rate is below the level associated with MSY. &nbsp;The current TAC has been set using the management procedure adopted in 2011, which has a 70% probability of rebuilding to the interim target biomass level by 2035.<\\/p>\",\n \"database_sources\":[\n {\n \"name\":\"firms\",\n \"description\":\"unknown\",\n \"url\":\"unkown\"\n },\n {\n \"name\":\"fishsource\",\n \"description\":\"unknown\",\n \"url\":\"unkown\"\n }\n ],\n \"reporting_year\":2015,\n \"stock_name\":\"Southern Bluefin tuna - Global Name\",\n \"assessment_methods\":\"Survey index\",\n \"abundance_level\":[\n {\n \"year\":2014,\n \"value\":\"low abundance\"\n },\n {\n \"year\":2015,\n \"value\":\"intermediate abundance\"\n }\n ],\n \"abundance_level_for_grouping\":\"low abundance\",\n \"scientific_advice\":\"<p>Based on the results of the MP operation for 2015&ndash;17 in its 2013 meeting and the outcome of the review of exceptional circumstances in its 2015 meeting, the ESC recommended that there is no need to revise the Extended Commission&rsquo;s 2013 TAC decision regarding the TAC for 2016&ndash;17. The recommended annual TAC for the years 2016-2017 is 14,647.4t.<\\/p>\",\n \"type\":\"assessment unit\",\n \"stock_id\":\"Southern Bluefin tuna - Global Title\",\n \"uuid_knowledge_base\":\"c898163b-1dbe-4b97-ba4a-5a73e8b81db9\",\n \"traceability_flag\":true,\n \"water_area\":[\n \"SEAFO division B.1\",\n \"SEAFO division D.0\",\n \"Indian Ocean, East \\/ 57.6\",\n \"SEAFO division D.1\",\n \"Cape of Good Hope\",\n \"Indian Ocean, West \\/ 51.6\",\n \"Indian Ocean, West \\/ 51.7\"\n ],\n \"assessment_distribution_area\":\"an area\",\n \"stock_uri\":\"http:\\/\\/www.bluebridge.com\\/grsf\\/stock\\/c898163b-1dbe-4b97-ba4a-5a73e8b81db9\",\n \"exploiting_fishery\":\"Tunas and billfishes fishery\",\n \"exploitation_rate\":[\n {\n \"year\":2014,\n \"value\":\"moderate fishing mortality\"\n },\n {\n \"year\":2015,\n \"value\":\"high fishing mortality\"\n }\n ],\n \"exploitation_rate_for_grouping\":\"No or low fishing mortality\",\n \"state_of_marine_resource\":\"Overexploited\",\n \"species_scientific_name\":\"Thunnus maccoyii\",\n \"source_of_information\":[\n {\n \"name\":\"sourcename\",\n \"description\":\"unknown\",\n \"url\":\"https:\\/\\/www.ccsbt.org\\/userfiles\\/file\\/docs_english\\/meetings\\/meeting_reports\\/ccsbt_22\\/report_of_SC20.pdf\"\n },\n {\n \"name\":\"sourcename\",\n \"description\":\"unknown\",\n \"url\":\"https:\\/\\/www.ccsbt.org\\/userfiles\\/file\\/docs_english\\/meetings\\/meeting_reports\\/ccsbt_22\\/report_of_SC20-2.pdf\"\n }\n ],\n \"status\":\"pending\",\n \"catches_or_landings\":{\n \"name\":\"catches_or_landings_example\",\n \"description\":\"unknown\",\n \"url\":\"a url\"\n }\n}", StockRecord.class);
System.out.println(jsonInString);