2016-10-08 20:46:17 +02:00
package org.gcube.data_catalogue.grsf_publish_ws.services ;
2016-11-04 16:26:19 +01:00
import java.net.URLEncoder ;
2016-10-10 18:50:11 +02:00
import java.util.ArrayList ;
import java.util.HashMap ;
import java.util.List ;
import java.util.Map ;
2016-10-09 16:06:45 +02:00
2016-10-10 18:50:11 +02:00
import javax.servlet.ServletContext ;
2016-10-14 18:44:34 +02:00
import javax.validation.Valid ;
2016-10-15 22:34:57 +02:00
import javax.validation.ValidationException ;
import javax.validation.constraints.NotNull ;
2016-10-08 20:46:17 +02:00
import javax.ws.rs.Consumes ;
2016-10-14 18:44:34 +02:00
import javax.ws.rs.DELETE ;
2016-10-10 18:50:11 +02:00
import javax.ws.rs.GET ;
2016-10-08 20:46:17 +02:00
import javax.ws.rs.POST ;
import javax.ws.rs.Path ;
import javax.ws.rs.Produces ;
2016-10-10 18:50:11 +02:00
import javax.ws.rs.core.Context ;
2016-10-08 20:46:17 +02:00
import javax.ws.rs.core.MediaType ;
import javax.ws.rs.core.Response ;
2016-10-09 16:06:45 +02:00
import javax.ws.rs.core.Response.Status ;
2016-10-08 20:46:17 +02:00
2016-10-10 18:50:11 +02:00
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 ;
2016-10-14 18:44:34 +02:00
import org.gcube.data_catalogue.grsf_publish_ws.json.input.DeleteProductBean ;
2016-10-08 20:46:17 +02:00
import org.gcube.data_catalogue.grsf_publish_ws.json.input.FisheryRecord ;
2016-10-09 16:06:45 +02:00
import org.gcube.data_catalogue.grsf_publish_ws.json.output.ResponseCreationBean ;
2016-10-10 18:50:11 +02:00
import org.gcube.data_catalogue.grsf_publish_ws.utils.HelperMethods ;
2016-11-24 17:53:50 +01:00
import org.gcube.data_catalogue.grsf_publish_ws.utils.threads.AssociationToGroupThread ;
import org.gcube.data_catalogue.grsf_publish_ws.utils.threads.ManageTimeSeriesThread ;
2016-10-10 18:50:11 +02:00
import org.gcube.datacatalogue.ckanutillibrary.DataCatalogue ;
import org.gcube.datacatalogue.ckanutillibrary.models.ResourceBean ;
import org.gcube.datacatalogue.ckanutillibrary.models.RolesCkanGroupOrOrg ;
2016-10-08 20:46:17 +02:00
import org.slf4j.LoggerFactory ;
2016-10-14 18:44:34 +02:00
import eu.trentorise.opendata.jackan.model.CkanDataset ;
2016-10-08 20:46:17 +02:00
/ * *
* Fishery web service methods
* @author Costantino Perciante at ISTI - CNR
* /
@Path ( " fishery/ " )
public class GrsfPublisherFisheryService {
2016-10-11 11:39:25 +02:00
private static final String DEFAULT_FISHERY_LICENSE = " CC-BY-SA-4.0 " ;
2016-10-18 10:42:12 +02:00
private static final String THIS_TYPE = " Fishery " ;
2016-10-11 11:39:25 +02:00
2016-10-10 18:50:11 +02:00
// the context
@Context
ServletContext contextServlet ;
2016-10-09 16:06:45 +02:00
2016-10-08 20:46:17 +02:00
// Logger
private static final org . slf4j . Logger logger = LoggerFactory . getLogger ( GrsfPublisherFisheryService . class ) ;
2016-10-11 11:39:25 +02:00
2016-10-10 18:50:11 +02:00
@GET
@Path ( " hello " )
@Produces ( MediaType . TEXT_PLAIN )
public Response hello ( ) {
return Response . ok ( " Hello.. Fishery service is here " ) . build ( ) ;
}
2016-10-11 11:39:25 +02:00
@GET
@Path ( " get-licenses " )
@Produces ( MediaType . APPLICATION_JSON )
public Response getLicenses ( ) {
// since are equals for stock and fishery, we just retrieve them all
Map < String , String > licenses = new HashMap < String , String > ( ) ;
Status status ;
try {
2016-11-06 21:21:11 +01:00
licenses = HelperMethods . getLicenses ( HelperMethods . getDataCatalogueRunningInstance ( ScopeProvider . instance . get ( ) ) ) ;
2016-10-11 11:39:25 +02:00
status = Status . OK ;
} catch ( Exception e ) {
logger . error ( " Failed to retrieve the list of licenses " ) ;
status = Status . INTERNAL_SERVER_ERROR ;
}
return Response . status ( status ) . entity ( licenses ) . build ( ) ;
}
2016-10-09 16:06:45 +02:00
2016-10-08 20:46:17 +02:00
@POST
@Path ( " publish-product " )
@Consumes ( MediaType . APPLICATION_JSON )
@Produces ( MediaType . APPLICATION_JSON )
2016-10-15 22:34:57 +02:00
public Response publishFishery (
2016-11-06 21:21:11 +01:00
@NotNull ( message = " record cannot be null " )
@Valid FisheryRecord record )
throws ValidationException {
2016-10-09 16:06:45 +02:00
2016-10-10 18:50:11 +02:00
// retrieve context and username
Caller caller = AuthorizationProvider . instance . get ( ) ;
String username = caller . getClient ( ) . getId ( ) ;
String context = ScopeProvider . instance . get ( ) ;
2016-11-04 16:26:19 +01:00
String token = SecurityTokenProvider . instance . get ( ) ;
2016-10-10 18:50:11 +02:00
logger . info ( " Incoming request for creating a fishery record = " + record ) ;
2016-11-06 21:21:11 +01:00
logger . info ( " Request comes from user " + username + " in context " + context ) ;
2016-10-10 18:50:11 +02:00
ResponseCreationBean responseBean = new ResponseCreationBean ( ) ;
Status status = Status . INTERNAL_SERVER_ERROR ;
String id = " " ;
2016-11-06 21:21:11 +01:00
2016-10-10 18:50:11 +02:00
try {
// determine the organization in which this product should be put
String contextInWhichPublish = HelperMethods . getContextFromStatus ( record . getStatus ( ) , contextServlet ) ;
if ( contextInWhichPublish = = null | | ! contextInWhichPublish . equals ( context ) ) {
// stop, this value must be defined
status = Status . BAD_REQUEST ;
throw new IllegalArgumentException ( " Status attribute is not defined or the Token you are using is not correct to perform such request! " ) ;
} else {
DataCatalogue catalogue = HelperMethods . getDataCatalogueRunningInstance ( context ) ;
if ( catalogue = = null ) {
status = Status . INTERNAL_SERVER_ERROR ;
throw new Exception ( " There was a problem while serving your request " ) ;
} else {
// check the user has editor/admin role into the org
String organization = HelperMethods . retrieveOrgNameFromScope ( contextInWhichPublish ) ;
2016-11-22 12:54:41 +01:00
String role = catalogue . getRoleOfUserInOrganization ( username , organization , catalogue . getApiKeyFromUsername ( username ) ) ;
logger . info ( " ***************************Role of the user " + username + " is " + role ) ;
if ( ! role . equalsIgnoreCase ( RolesCkanGroupOrOrg . ADMIN . toString ( ) ) ) {
2016-10-10 18:50:11 +02:00
status = Status . FORBIDDEN ;
2016-10-18 11:51:55 +02:00
throw new Exception ( " You are not authorized to create a product. Please check you have the Catalogue-admin role! " ) ;
2016-10-10 18:50:11 +02:00
}
2016-11-06 21:21:11 +01:00
// The name of the product will be the uuid of the kb. The title will be the fishery's fishery_name. Fishery has also the constraint that
// fishing area and jurisdiction area cannot be empty at the same time
2016-11-04 16:26:19 +01:00
String futureName = record . getUuid ( ) ;
2016-10-10 18:50:11 +02:00
String futureTitle = record . getFisheryName ( ) ;
2016-10-13 11:46:42 +02:00
String fishingArea = record . getFishingArea ( ) ;
String jurisdictionArea = record . getJurisdictionArea ( ) ;
2016-11-06 21:21:11 +01:00
if ( ! HelperMethods . isNameValid ( futureName ) ) {
2016-10-10 18:50:11 +02:00
status = Status . BAD_REQUEST ;
throw new Exception ( " The name requested for the product is not correct! It should contain only alphanumeric characters, and symbols like '.' or '_', '-' " ) ;
2016-10-13 11:46:42 +02:00
} else if ( ( fishingArea = = null | | fishingArea . isEmpty ( ) ) & & ( jurisdictionArea = = null | | jurisdictionArea . isEmpty ( ) ) ) {
status = Status . BAD_REQUEST ;
throw new Exception ( " fishing_area and jurisdiction_area cannot be null/empty at the same time! " ) ;
2016-10-10 18:50:11 +02:00
} else {
2016-11-04 16:26:19 +01:00
logger . debug ( " Checking if such name [ " + futureName + " ] doesn't exist yet... " ) ;
2016-10-10 18:50:11 +02:00
boolean alreadyExist = catalogue . existProductWithNameOrId ( futureName ) ;
if ( alreadyExist ) {
logger . debug ( " A product with name " + futureName + " already exists " ) ;
2016-10-14 15:20:10 +02:00
status = Status . CONFLICT ;
2016-11-06 21:21:11 +01:00
throw new Exception ( " A product with name " + futureName + " already exists " ) ;
2016-10-10 18:50:11 +02:00
} else {
2016-11-06 21:21:11 +01:00
2016-11-04 16:26:19 +01:00
// set the type
record . setProductType ( THIS_TYPE ) ;
2016-10-10 18:50:11 +02:00
// evaluate the tags of the product
List < String > tags = new ArrayList < String > ( ) ;
HelperMethods . getTags ( tags , record ) ;
// evaluate the groups
List < String > groups = new ArrayList < String > ( ) ;
HelperMethods . getGroups ( groups , record ) ;
// evaluate the custom fields
2016-10-27 11:40:19 +02:00
Map < String , List < String > > customFields = new HashMap < String , List < String > > ( ) ;
2016-10-10 18:50:11 +02:00
if ( record . getExtras ( ) ! = null )
customFields = record . getExtras ( ) ;
// automatically retrieve the other ones
HelperMethods . getExtras ( customFields , record ) ;
// retrieve the user's email and fullname
2016-11-04 16:26:19 +01:00
String authorMail = HelperMethods . getUserEmail ( context , token ) ;
String authorFullname = HelperMethods . getUserFullname ( context , token ) ;
2016-10-10 18:50:11 +02:00
if ( authorMail = = null | | authorFullname = = null ) {
logger . debug ( " Author fullname or mail missing, cannot continue " ) ;
status = Status . INTERNAL_SERVER_ERROR ;
throw new Exception ( " Sorry but there was not possible to retrieve your fullname/email! " ) ;
} else {
2016-10-13 11:46:42 +02:00
// evaluate the resources
2016-11-01 22:35:52 +01:00
List < ResourceBean > resources = HelperMethods . getResourcesFromBean ( record , username , tags , groups ) ;
2016-10-10 18:50:11 +02:00
2016-10-11 11:39:25 +02:00
// check the license id
String license = null ;
if ( record . getLicense ( ) = = null | | record . getLicense ( ) . isEmpty ( ) )
license = DEFAULT_FISHERY_LICENSE ;
else
2016-11-06 21:21:11 +01:00
if ( HelperMethods . existsLicenseId ( record . getLicense ( ) , catalogue ) )
2016-10-11 11:39:25 +02:00
license = record . getLicense ( ) ;
else throw new Exception ( " Please check the license id! " ) ;
2016-10-15 22:34:57 +02:00
2016-10-13 15:34:47 +02:00
long version = record . getVersion ( ) = = null ? 1 : record . getVersion ( ) ;
2016-10-11 11:39:25 +02:00
2016-10-10 18:50:11 +02:00
// create the product
2016-10-27 11:40:19 +02:00
id = catalogue . createCKanDatasetMultipleCustomFields (
2016-10-10 18:50:11 +02:00
catalogue . getApiKeyFromUsername ( username ) ,
futureTitle ,
2016-11-04 16:26:19 +01:00
futureName ,
2016-10-10 18:50:11 +02:00
organization ,
authorFullname ,
authorMail ,
record . getMaintainer ( ) ,
record . getMaintainerContact ( ) ,
2016-10-13 15:34:47 +02:00
version ,
2016-10-10 18:50:11 +02:00
record . getDescription ( ) ,
2016-10-11 11:39:25 +02:00
license ,
2016-10-10 18:50:11 +02:00
tags ,
customFields ,
resources ,
2016-11-06 21:21:11 +01:00
false ) ;
2016-10-10 18:50:11 +02:00
if ( id ! = null ) {
logger . info ( " Product created! Id is " + id ) ;
responseBean . setId ( id ) ;
status = Status . CREATED ;
responseBean . setError ( null ) ;
2016-11-04 16:26:19 +01:00
responseBean . setProductUrl ( catalogue . getPortletUrl ( ) + " ? " + URLEncoder . encode ( " path=/dataset/ " + futureName , " UTF-8 " ) ) ;
responseBean . setKbUuid ( record . getUuid ( ) ) ;
2016-11-24 17:53:50 +01:00
2016-10-10 18:50:11 +02:00
if ( ! groups . isEmpty ( ) ) {
logger . info ( " Launching thread for association to the list of groups " + groups ) ;
2016-11-25 18:25:23 +01:00
AssociationToGroupThread threadGroups = new AssociationToGroupThread ( groups , id , organization , username , catalogue ) ;
threadGroups . start ( ) ;
logger . info ( " Waiting association thread to die.. " ) ;
threadGroups . join ( ) ;
logger . debug ( " Ok, it died " ) ;
2016-10-10 18:50:11 +02:00
}
2016-11-25 18:25:23 +01:00
// manage time series
logger . info ( " Launching thread for time series handling " ) ;
new ManageTimeSeriesThread ( record , futureName , username , catalogue , ScopeProvider . instance . get ( ) ) . start ( ) ;
2016-10-10 18:50:11 +02:00
}
}
}
}
}
}
} catch ( Exception e ) {
logger . error ( " Failed to create fishery record " , e ) ;
responseBean . setError ( e . getMessage ( ) ) ;
}
2016-10-09 16:06:45 +02:00
2016-10-10 18:50:11 +02:00
return Response . status ( status ) . entity ( responseBean ) . build ( ) ;
2016-10-08 20:46:17 +02:00
}
2016-10-15 22:34:57 +02:00
2016-10-14 18:44:34 +02:00
@DELETE
@Path ( " delete-product " )
@Consumes ( MediaType . APPLICATION_JSON )
@Produces ( MediaType . APPLICATION_JSON )
2016-11-06 21:21:11 +01:00
public Response deleteFishery (
@NotNull ( message = " input value is missing " )
@Valid DeleteProductBean recordToDelete ) throws ValidationException {
2016-10-14 18:44:34 +02:00
// retrieve context and username
Caller caller = AuthorizationProvider . instance . get ( ) ;
String username = caller . getClient ( ) . getId ( ) ;
String context = ScopeProvider . instance . get ( ) ;
ResponseCreationBean responseBean = new ResponseCreationBean ( ) ;
Status status = Status . INTERNAL_SERVER_ERROR ;
2016-10-15 22:34:57 +02:00
// check it is a fishery ...
2016-10-14 18:44:34 +02:00
logger . info ( " Received call to delete product with id " + recordToDelete . getId ( ) + " , checking if it is a fishery " ) ;
try {
DataCatalogue catalogue = HelperMethods . getDataCatalogueRunningInstance ( context ) ;
if ( catalogue = = null ) {
status = Status . INTERNAL_SERVER_ERROR ;
throw new Exception ( " There was a problem while serving your request " ) ;
}
// retrieve the catalogue instance
CkanDataset fisheryInCkan = catalogue . getDataset ( recordToDelete . getId ( ) , catalogue . getApiKeyFromUsername ( username ) ) ;
if ( fisheryInCkan = = null ) {
status = Status . NOT_FOUND ;
throw new Exception ( " There was a problem while serving your request. This product was not found " ) ;
}
2016-11-06 21:21:11 +01:00
2016-10-15 22:34:57 +02:00
// get extras and check there is the field Fishery Name that is mandatory for fishery
2016-10-14 18:44:34 +02:00
if ( fisheryInCkan . getExtrasAsHashMap ( ) . containsKey ( " Fishery Name " ) ) {
logger . warn ( " Ok, this is a fishery, removing it " ) ;
boolean deleted = catalogue . deleteProduct ( fisheryInCkan . getId ( ) , catalogue . getApiKeyFromUsername ( username ) , true ) ;
if ( deleted ) {
logger . info ( " Stock DELETED AND PURGED! " ) ;
status = Status . OK ;
responseBean . setId ( fisheryInCkan . getId ( ) ) ;
}
else {
status = Status . INTERNAL_SERVER_ERROR ;
throw new Exception ( " Request failed, sorry " ) ;
}
} else {
status = Status . BAD_REQUEST ;
throw new Exception ( " The id you are using doesn't belong to a Fishery product! " ) ;
}
} catch ( Exception e ) {
logger . error ( " Failed to delete this " ) ;
status = Status . INTERNAL_SERVER_ERROR ;
responseBean . setError ( e . getMessage ( ) ) ;
}
return Response . status ( status ) . entity ( responseBean ) . build ( ) ;
}
2016-10-08 20:46:17 +02:00
}