gcat/src/main/java/org/gcube/gcat/configuration/isproxies/impl/FacetBasedISConfigurationPr...

519 lines
24 KiB
Java

package org.gcube.gcat.configuration.isproxies.impl;
import java.io.File;
import java.io.FileReader;
import java.net.URL;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import javax.ws.rs.InternalServerErrorException;
import org.gcube.com.fasterxml.jackson.core.JsonProcessingException;
import org.gcube.com.fasterxml.jackson.databind.JsonNode;
import org.gcube.com.fasterxml.jackson.databind.ObjectMapper;
import org.gcube.com.fasterxml.jackson.databind.node.ObjectNode;
import org.gcube.gcat.api.configuration.CatalogueConfiguration;
import org.gcube.gcat.configuration.isproxies.ISConfigurationProxy;
import org.gcube.gcat.configuration.service.FacetBasedISServiceCatalogueConfiguration;
import org.gcube.gcat.configuration.service.ServiceCKANDB;
import org.gcube.gcat.configuration.service.ServiceCatalogueConfiguration;
import org.gcube.informationsystem.model.impl.properties.PropagationConstraintImpl;
import org.gcube.informationsystem.model.impl.relations.ConsistsOfImpl;
import org.gcube.informationsystem.model.reference.entities.Entity;
import org.gcube.informationsystem.model.reference.properties.Encrypted;
import org.gcube.informationsystem.model.reference.properties.PropagationConstraint;
import org.gcube.informationsystem.model.reference.properties.PropagationConstraint.AddConstraint;
import org.gcube.informationsystem.model.reference.properties.PropagationConstraint.DeleteConstraint;
import org.gcube.informationsystem.model.reference.properties.PropagationConstraint.RemoveConstraint;
import org.gcube.informationsystem.model.reference.relations.ConsistsOf;
import org.gcube.informationsystem.queries.templates.reference.entities.QueryTemplate;
import org.gcube.informationsystem.resourceregistry.api.exceptions.NotFoundException;
import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException;
import org.gcube.informationsystem.resourceregistry.api.exceptions.types.SchemaViolationException;
import org.gcube.informationsystem.resourceregistry.client.ResourceRegistryClient;
import org.gcube.informationsystem.resourceregistry.client.ResourceRegistryClientFactory;
import org.gcube.informationsystem.resourceregistry.publisher.ResourceRegistryPublisher;
import org.gcube.informationsystem.resourceregistry.publisher.ResourceRegistryPublisherFactory;
import org.gcube.informationsystem.resourceregistry.queries.templates.ResourceRegistryQueryTemplateClient;
import org.gcube.informationsystem.resourceregistry.queries.templates.ResourceRegistryQueryTemplateClientFactory;
import org.gcube.informationsystem.serialization.ElementMapper;
import org.gcube.resourcemanagement.model.impl.entities.facets.SimpleFacetImpl;
import org.gcube.resourcemanagement.model.impl.entities.resources.EServiceImpl;
import org.gcube.resourcemanagement.model.impl.relations.isrelatedto.CallsForImpl;
import org.gcube.resourcemanagement.model.reference.entities.facets.AccessPointFacet;
import org.gcube.resourcemanagement.model.reference.entities.facets.SimpleFacet;
import org.gcube.resourcemanagement.model.reference.entities.resources.Configuration;
import org.gcube.resourcemanagement.model.reference.entities.resources.EService;
import org.gcube.resourcemanagement.model.reference.entities.resources.VirtualService;
import org.gcube.resourcemanagement.model.reference.relations.isrelatedto.CallsFor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Luca Frosini (ISTI - CNR)
*/
public class FacetBasedISConfigurationProxy extends ISConfigurationProxy<SimpleFacet> {
private static Logger logger = LoggerFactory.getLogger(FacetBasedISConfigurationProxy.class);
public final String QUERY_TEMPLATE_DIRECTORY_NAME = "query-template";
public final String GCAT_ESERVICE_UUID_VARNAME = "$uuid";
public final String GET_CALLS_FOR_QUERY_TEMPLATE_FILENAME = "01-get-calls-for-query-template.json";
public final String QUERY_DIRECTORY_NAME = "query";
public final String GET_CATALOGUE_VIRTUAL_SERVICE_FILENAME = "01-get-catalogue-virtual-service.json";
public final String GET_GCAT_CONFIGURATION_FILENAME = "02-get-gcat-configuration.json";
public final String GET_SIMPLE_FACET_OF_GCAT_CONFIGURATION_FILENAME = "03-get-simple-facet-of-gcat-configuration.json";
public final String GET_ACCESS_POINT_FACET_OF_CKAN_SERVICE_FILENAME = "05-get-access-point-facet-of-ckan-service.json";
public final String GET_ACCESS_POINT_FACET_OF_POSTGRES_CKAN_DB_FILENAME = "07-get-access-point-facet-of-postgres-ckan-db.json";
public final String GET_ACCESS_POINT_FACET_OF_SOLR_SERVICE_FILENAME = "09-get-access-point-facet-of-solr-service.json";
protected QueryTemplate queryTemplate;
public QueryTemplate getQueryTemplateFromFile(String queryTemplateFilename) throws Exception {
File queryTemplateFile = getJsonQueryTemplateFromFile(queryTemplateFilename);
FileReader fileReader = new FileReader(queryTemplateFile);
QueryTemplate queryTemplate = ElementMapper.unmarshal(QueryTemplate.class, fileReader);
return queryTemplate;
}
public QueryTemplate installQueryTemplate() throws Exception {
/*
* Going to create/update the query template.
* No need to test if exists and/or if is the last version.
*/
queryTemplate = rrqtc.update(queryTemplate);
return queryTemplate;
}
protected File getBaseDirectory(String directoryName) {
URL directoryURL = FacetBasedISConfigurationProxy.class.getClassLoader().getResource(directoryName);
File directory = new File(directoryURL.getPath());
return directory;
}
protected File getFile(String directoryName, String filename) throws Exception {
File directory = getBaseDirectory(directoryName);
return new File(directory, filename);
}
protected File getJsonQueryTemplateFromFile(String filename) throws Exception {
return getFile(QUERY_TEMPLATE_DIRECTORY_NAME, filename);
}
protected File getJsonQueryFromFile(String filename) throws Exception {
return getFile(QUERY_DIRECTORY_NAME, filename);
}
//
// Configuration
// ----------------------
// IsCustomizedBy | |
// -----------------> | gcat-configuration |
// / | |
// / ----------------------
// EService VirtualService /
// ------------ -----------------------------
// | | CallsFor | |
// | gcat | ------------> | catalogue-virtual-service |
// | | | |
// ------------ -----------------------------
// \ EService
// \ --------------------
// \ Uses | |
// \ ------------------> | postgres-ckan-db |
// \ / | |
// \ EService / --------------------
// \ -----------------
// \ CallsFor | |
// -------------> | ckan |
// | |
// ----------------- EService
// \ --------------------
// \ Uses | |
// ------------------> | solr |
// | |
// --------------------
/*
* Some resources are not needed to be queried and maintained.
* Leaving comment to remember that is not an error
* protected Configuration configuration;
*
* public static final String GET_CKAN_SERVICE_FILENAME = "04-get-ckan-service.json";
* protected EService ckanService;
*
* public static final String GET_POSTGRES_CKAN_DB_FILENAME = "06-get-postgres-ckan-db.json";
* protected EService solrService;
*
* public static final String GET_SOLR_SERVICE_FILENAME = "08-get-solr-service.json";
* protected EService ckanDB;
*
*/
protected final ObjectMapper objectMapper;
protected final ResourceRegistryClient resourceRegistryClient;
protected final ResourceRegistryPublisher resourceRegistryPublisher;
protected final ResourceRegistryQueryTemplateClient rrqtc;
/*
* We need to keep this resource because we want to create
* an IsRelatedTo relation
* i.e. EService(gcat) --CallsFor--> VirtualService(catalogue-virtual-service)
*/
protected VirtualService virtualService;
protected SimpleFacet configurationSimpleFacet;
protected String gcatEServiceID;
public FacetBasedISConfigurationProxy(String context) {
super(context);
resourceRegistryClient = ResourceRegistryClientFactory.create();
resourceRegistryPublisher = ResourceRegistryPublisherFactory.create();
rrqtc = ResourceRegistryQueryTemplateClientFactory.create();
try {
queryTemplate = getQueryTemplateFromFile(GET_CALLS_FOR_QUERY_TEMPLATE_FILENAME);
}catch(Exception e) {
throw new RuntimeException(FacetBasedISConfigurationProxy.class.getSimpleName() + " cannot be used", e);
}
objectMapper = new ObjectMapper();
}
public VirtualService getVirtualService() {
if(virtualService==null) {
virtualService = queryVirtualService();
}
return virtualService;
}
public void setGcatEServiceID(String gcatEServiceID) {
this.gcatEServiceID = gcatEServiceID;
}
public List<CallsFor<EService, VirtualService>> getCallsForToVirtualService() throws Exception {
ResourceRegistryQueryTemplateClient rrqtc = ResourceRegistryQueryTemplateClientFactory.create();
ObjectNode objectNode = objectMapper.createObjectNode();
objectNode.put(GCAT_ESERVICE_UUID_VARNAME, gcatEServiceID);
List<CallsFor<EService, VirtualService>> callsForList = rrqtc.run(queryTemplate.getName(), objectNode);
return callsForList;
}
public List<CallsFor<EService, VirtualService>> deleteCallsForToVirtualService(List<CallsFor<EService, VirtualService>> callsForList) throws SchemaViolationException, NotFoundException, ResourceRegistryException {
for(CallsFor<EService, VirtualService> cf : callsForList) {
resourceRegistryPublisher.delete(cf);
}
return callsForList;
}
public List<CallsFor<EService, VirtualService>> deleteCallsForToVirtualService() throws Exception {
List<CallsFor<EService, VirtualService>> callsForList = getCallsForToVirtualService();
return deleteCallsForToVirtualService(callsForList);
}
public CallsFor<EService, VirtualService> createCallsForToVirtualService() throws Exception {
List<CallsFor<EService, VirtualService>> callsForList = getCallsForToVirtualService();
CallsFor<EService, VirtualService> callsFor = null;
int size = callsForList.size();
UUID gcatEServiceUUID = UUID.fromString(gcatEServiceID);
if(size>1) {
logger.warn("There are {} instances of {} relation beetween gcat Eservice with UUID {} and the {} (catalogue-virtual-service). This is very strange because there should be only one. We are going to delete them and recreated a new one.",
callsForList.size(), CallsFor.NAME, gcatEServiceID, VirtualService.NAME);
logger.trace("{} relation instances that are going to be deleted are {}",
CallsFor.NAME, ElementMapper.marshal(callsForList));
deleteCallsForToVirtualService(callsForList);
size = 0;
}
if(size==0) {
logger.info("Going to create {} between {} (gcat with UUID={}) and the {}",
CallsFor.NAME, EService.NAME, gcatEServiceID, VirtualService.NAME);
PropagationConstraint propagationConstraint = new PropagationConstraintImpl();
propagationConstraint.setAddConstraint(AddConstraint.unpropagate);
propagationConstraint.setRemoveConstraint(RemoveConstraint.keep);
propagationConstraint.setDeleteConstraint(DeleteConstraint.keep);
EService gcatEService = new EServiceImpl();
gcatEService.setID(gcatEServiceUUID);
VirtualService virtualService = queryVirtualService();
callsFor = new CallsForImpl<EService, VirtualService>(gcatEService, virtualService, propagationConstraint);
callsFor = resourceRegistryPublisher.create(callsFor);
}else if(size==1){
callsFor = callsForList.get(0);
logger.info("{} between {} (gcat with UUID={}) and the {} exists.\n{}",
CallsFor.NAME, EService.NAME, gcatEServiceID, VirtualService.NAME, ElementMapper.marshal(callsFor));
}
return callsFor;
}
protected List<Entity> queryListOfEntities(String query) throws Exception {
logger.trace("Going to request the following query:\n{}", query);
String result = resourceRegistryClient.jsonQuery(query);
logger.trace("The query:\n{}\nproduced the following result:\n{}", query, result);
List<Entity> entities = ElementMapper.unmarshalList(Entity.class, result);
return entities;
}
protected JsonNode getQuery(File jsonQueryFile) throws Exception {
JsonNode query = objectMapper.readTree(jsonQueryFile);
return query;
}
protected <E extends Entity> E getUniqueEntity(List<E> entities, String originalQuery) throws JsonProcessingException {
int size = entities.size();
if(entities==null || size==0) {
String message = String.format("No instance found with query:\n%s", originalQuery);
logger.error(message);
throw new InternalServerErrorException(message);
}
if(size>1) {
String message = String.format(
"Too many instances found (i.e. expected 1, found %d) with query:\n%s\nthe obtained result is:\n%s",
size, originalQuery, ElementMapper.marshal(entities));
logger.error(message);
throw new InternalServerErrorException(message);
}
return entities.get(0);
}
protected Entity queryEntity(String filename) throws Exception{
File jsonQueryFile = getJsonQueryFromFile(filename);
JsonNode query = getQuery(jsonQueryFile);
String jsonQueryAsString = objectMapper.writeValueAsString(query);
List<Entity> entities = queryListOfEntities(jsonQueryAsString);
return getUniqueEntity(entities, jsonQueryAsString);
}
protected VirtualService queryVirtualService() throws InternalServerErrorException {
try {
VirtualService virtualService = (VirtualService) queryEntity(GET_CATALOGUE_VIRTUAL_SERVICE_FILENAME);
return virtualService;
}catch (Exception e) {
throw new InternalServerErrorException(e);
}
}
protected Configuration queryGcatConfiguration() throws Exception {
Configuration configuration = (Configuration) queryEntity(GET_GCAT_CONFIGURATION_FILENAME);
return configuration;
}
protected SimpleFacet queryConfigurationSimpleFacet() throws Exception {
SimpleFacet configurationSimpleFacet = (SimpleFacet) queryEntity(GET_SIMPLE_FACET_OF_GCAT_CONFIGURATION_FILENAME);
return configurationSimpleFacet;
}
protected AccessPointFacet queryCkanServiceAccessPointFacet() throws Exception {
AccessPointFacet accessPointFacet = (AccessPointFacet) queryEntity(GET_ACCESS_POINT_FACET_OF_CKAN_SERVICE_FILENAME);
return accessPointFacet;
}
protected AccessPointFacet queryPostgresCkanDBAccessPointFacet() throws Exception {
AccessPointFacet accessPointFacet = (AccessPointFacet) queryEntity(GET_ACCESS_POINT_FACET_OF_POSTGRES_CKAN_DB_FILENAME);
return accessPointFacet;
}
public AccessPointFacet querySolrServiceAccessPointFacet() throws Exception {
AccessPointFacet accessPointFacet = (AccessPointFacet) queryEntity(GET_ACCESS_POINT_FACET_OF_SOLR_SERVICE_FILENAME);
return accessPointFacet;
}
protected ServiceCatalogueConfiguration setConfigurationInfoFromSimpleFacet(SimpleFacet configurationSimpleFacet, ServiceCatalogueConfiguration catalogueConfiguration) throws Exception {
if(configurationSimpleFacet.getID()!=null) {
catalogueConfiguration.setID(configurationSimpleFacet.getID().toString());
}
catalogueConfiguration.setModerationEnabled((boolean) configurationSimpleFacet.getAdditionalProperty(CatalogueConfiguration.MODERATION_ENABLED_KEY));
catalogueConfiguration.setNotificationToUsersEnabled((boolean) configurationSimpleFacet.getAdditionalProperty(CatalogueConfiguration.NOTIFICATION_TO_USER_ENABLED_KEY));
catalogueConfiguration.setSocialPostEnabled((boolean) configurationSimpleFacet.getAdditionalProperty(CatalogueConfiguration.SOCIAL_POST_ENABLED_KEY));
catalogueConfiguration.setDefaultOrganization((String) configurationSimpleFacet.getAdditionalProperty(CatalogueConfiguration.DEFAULT_ORGANIZATION_KEY));
Object supportedOrganizationsObj = configurationSimpleFacet.getAdditionalProperty(CatalogueConfiguration.SUPPORTED_ORGANIZATIONS_KEY);
boolean forceUpdate = false;
if(supportedOrganizationsObj!=null && supportedOrganizationsObj instanceof Collection) {
@SuppressWarnings("unchecked")
Set<String> supportedOrganizations = new HashSet<String>((Collection<String>) supportedOrganizationsObj);
catalogueConfiguration.setSupportedOrganizations(supportedOrganizations);
}else {
Set<String> supportedOrganizations = new HashSet<>();
supportedOrganizations.add(catalogueConfiguration.getDefaultOrganization());
configurationSimpleFacet.setAdditionalProperty(CatalogueConfiguration.SUPPORTED_ORGANIZATIONS_KEY, supportedOrganizations);
forceUpdate = true;
catalogueConfiguration.setSupportedOrganizations(supportedOrganizations);
}
Map<String,Object> additionalProperties = new HashMap<>(configurationSimpleFacet.getAdditionalProperties());
for(String key : additionalProperties.keySet()) {
if(!CatalogueConfiguration.KNOWN_PROPERTIES.contains(key)) {
if(key.startsWith("@")) {
continue;
}
Object value = additionalProperties.get(key);
catalogueConfiguration.setAdditionalProperty(key, value);
}
}
if(forceUpdate) {
updateOnIS();
}
return catalogueConfiguration;
}
public ServiceCatalogueConfiguration setCkanServiceInfo(ServiceCatalogueConfiguration catalogueConfiguration) throws Exception {
AccessPointFacet ckanServiceAccessPointFacet = queryCkanServiceAccessPointFacet();
catalogueConfiguration.setCkanURL(ckanServiceAccessPointFacet.getEndpoint().toString());
Encrypted encrypted = (Encrypted) ckanServiceAccessPointFacet.getAdditionalProperty(CatalogueConfiguration.SYS_ADMIN_TOKEN_KEY);
String encryptedPassword = encrypted.getValue();
catalogueConfiguration.setSysAdminToken(encryptedPassword);
return catalogueConfiguration;
}
public ServiceCatalogueConfiguration setCkanDBInfo(ServiceCatalogueConfiguration catalogueConfiguration) throws Exception {
AccessPointFacet postgresCkanDBAccessPointFacet = queryPostgresCkanDBAccessPointFacet();
ServiceCKANDB ckanDB = new ServiceCKANDB();
String ckanDbURL = postgresCkanDBAccessPointFacet.getEndpoint().toString();
ckanDB.setUrl(ckanDbURL);
Encrypted encrypted = (Encrypted) postgresCkanDBAccessPointFacet.getAdditionalProperty(ServiceCKANDB.PASSWORD_KEY);
String encryptedPassword = encrypted.getValue();
ckanDB.setEncryptedPassword(encryptedPassword);
String username = (String) postgresCkanDBAccessPointFacet.getAdditionalProperty(ServiceCKANDB.USERNAME_KEY);
ckanDB.setUsername(username);
catalogueConfiguration.setCkanDB(ckanDB);
return catalogueConfiguration;
}
public ServiceCatalogueConfiguration setSolrServiceInfo(ServiceCatalogueConfiguration catalogueConfiguration) throws Exception {
AccessPointFacet solrServiceAccessPointFacet = querySolrServiceAccessPointFacet();
String solrURL = solrServiceAccessPointFacet.getEndpoint().toString();
catalogueConfiguration.setSolrURL(solrURL);
return catalogueConfiguration;
}
protected SimpleFacet getSimpleFacetFromConfiguration(ServiceCatalogueConfiguration catalogueConfiguration) {
SimpleFacet simpleFacet = new SimpleFacetImpl();
if(catalogueConfiguration.getID()!=null) {
UUID uuid = null;
try {
uuid = UUID.fromString(catalogueConfiguration.getID());
simpleFacet.setID(uuid);
}catch (Exception e) {
}
}
simpleFacet.setAdditionalProperty(CatalogueConfiguration.MODERATION_ENABLED_KEY, catalogueConfiguration.isModerationEnabled());
simpleFacet.setAdditionalProperty(CatalogueConfiguration.NOTIFICATION_TO_USER_ENABLED_KEY, catalogueConfiguration.isNotificationToUsersEnabled());
simpleFacet.setAdditionalProperty(CatalogueConfiguration.SOCIAL_POST_ENABLED_KEY, catalogueConfiguration.isSocialPostEnabled());
simpleFacet.setAdditionalProperty(CatalogueConfiguration.DEFAULT_ORGANIZATION_KEY, catalogueConfiguration.getDefaultOrganization());
simpleFacet.setAdditionalProperty(CatalogueConfiguration.SUPPORTED_ORGANIZATIONS_KEY, catalogueConfiguration.getSupportedOrganizations());
Map<String,Object> additionalProperties = new HashMap<>(catalogueConfiguration.getAdditionalProperties());
for(String key : additionalProperties.keySet()) {
if(!CatalogueConfiguration.KNOWN_PROPERTIES.contains(key)) {
Object value = additionalProperties.get(key);
simpleFacet.setAdditionalProperty(key, value);
}
}
return simpleFacet;
}
@Override
protected ServiceCatalogueConfiguration readFromIS() {
try {
catalogueConfiguration = new FacetBasedISServiceCatalogueConfiguration(context, this);
configurationSimpleFacet = getISResource();
if(configurationSimpleFacet==null) {
configurationSimpleFacet = getSimpleFacetFromConfiguration(catalogueConfiguration);
}else {
catalogueConfiguration = setConfigurationInfoFromSimpleFacet(configurationSimpleFacet, catalogueConfiguration);
}
catalogueConfiguration = setCkanServiceInfo(catalogueConfiguration);
catalogueConfiguration = setCkanDBInfo(catalogueConfiguration);
catalogueConfiguration = setSolrServiceInfo(catalogueConfiguration);
}catch (InternalServerErrorException e) {
throw e;
}catch (Exception e) {
throw new InternalServerErrorException(e);
}
return catalogueConfiguration;
}
@Override
public void delete() {
SimpleFacet simpleFacet = getISResource();
if(simpleFacet!=null) {
try {
resourceRegistryPublisher.delete(simpleFacet);
} catch (Exception e) {
throw new InternalServerErrorException("Unable to delete SimpleFacet with UUID " + simpleFacet.getID().toString(), e);
}
}
}
@Override
protected ServiceCatalogueConfiguration createOnIS() throws Exception {
UUID uuid = configurationSimpleFacet.getID();
if(uuid==null) {
Configuration gcatConfiguration = queryGcatConfiguration();
ConsistsOf<Configuration, SimpleFacet> co = new ConsistsOfImpl<>(gcatConfiguration, configurationSimpleFacet);
co = resourceRegistryPublisher.create(co);
configurationSimpleFacet = co.getTarget();
setConfigurationInfoFromSimpleFacet(configurationSimpleFacet, catalogueConfiguration);
}
return catalogueConfiguration;
}
@Override
protected SimpleFacet getISResource() {
if(configurationSimpleFacet==null) {
try {
configurationSimpleFacet = queryConfigurationSimpleFacet();
}catch (Exception e) {
return null;
}
}
return configurationSimpleFacet;
}
@Override
protected ServiceCatalogueConfiguration updateOnIS() throws Exception {
if(configurationSimpleFacet.getID()!=null) {
configurationSimpleFacet = getSimpleFacetFromConfiguration(catalogueConfiguration);
configurationSimpleFacet = resourceRegistryPublisher.update(configurationSimpleFacet);
setConfigurationInfoFromSimpleFacet(configurationSimpleFacet, catalogueConfiguration);
}
return catalogueConfiguration;
}
}