gcube-cms-suite/sdi-plugins/src/main/java/org/gcube/application/cms/sdi/plugins/SDIMaterializerPlugin.java

271 lines
12 KiB
Java
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package org.gcube.application.cms.sdi.plugins;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.bson.Document;
import org.gcube.application.cms.implementations.utils.UserUtils;
import org.gcube.application.cms.plugins.MaterializationPlugin;
import org.gcube.application.cms.plugins.faults.InitializationException;
import org.gcube.application.cms.plugins.faults.InvalidPluginRequestException;
import org.gcube.application.cms.plugins.faults.MaterializationException;
import org.gcube.application.cms.plugins.faults.ShutDownException;
import org.gcube.application.cms.plugins.implementations.AbstractPlugin;
import org.gcube.application.cms.plugins.reports.InitializationReport;
import org.gcube.application.cms.plugins.reports.MaterializationReport;
import org.gcube.application.cms.plugins.reports.Report;
import org.gcube.application.cms.plugins.requests.MaterializationRequest;
import org.gcube.application.cms.sdi.engine.SDIManagerWrapper;
import org.gcube.application.cms.sdi.faults.SDIInteractionException;
import org.gcube.application.cms.serialization.Serialization;
import org.gcube.application.geoportal.common.model.JSONPathWrapper;
import org.gcube.application.geoportal.common.model.document.Project;
import org.gcube.application.geoportal.common.model.document.filesets.Materialization;
import org.gcube.application.geoportal.common.model.document.filesets.RegisteredFileSet;
import org.gcube.application.geoportal.common.model.document.filesets.sdi.GCubeSDILayer;
import org.gcube.application.geoportal.common.model.plugins.MaterializerPluginDescriptor;
import org.gcube.application.geoportal.common.model.plugins.PluginDescriptor;
import org.gcube.application.geoportal.common.model.useCaseDescriptor.Field;
import org.gcube.application.geoportal.common.model.useCaseDescriptor.UseCaseDescriptor;
import com.vdurmont.semver4j.Semver;
import lombok.Data;
import lombok.Synchronized;
import lombok.extern.slf4j.Slf4j;
/**
* The Class SDIMaterializerPlugin.
*
* @author created by Fabio Sinibaldi
* @author new architect and maintainer - Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it
*
* Apr 28, 2023
*/
@Slf4j
public class SDIMaterializerPlugin extends AbstractPlugin implements MaterializationPlugin {
/**
* Instantiates a new materialization config.
*/
@Data
public static class MaterializationConfig{
private String schemaField;
private String documentPath;
}
Map<String, SDIManagerWrapper> sdiManagerMap=null;
/**
* Gets the SDI manager.
*
* @return the SDI manager
*/
private SDIManagerWrapper getSDIManager(){
String context = UserUtils.getCurrent().getContext();
log.debug("Getting SDIManagerWrapper from cache map for context {}");
return sdiManagerMap.get(context);
}
/**
* Inits the in context.
*
* @return the initialization report
* @throws InitializationException the initialization exception
*/
@Override
@Synchronized
public InitializationReport initInContext() throws InitializationException {
InitializationReport report = new InitializationReport();
try{
String context = UserUtils.getCurrent().getContext();
if(getSDIManager()==null) {
log.info("Initializing in " + context);
sdiManagerMap.put(context,new SDIManagerWrapper());
}
report.setStatus(Report.Status.OK);
report.putMessage("Initialized SDI Manager in "+context+" pointing to "+getSDIManager().getGeoserverHostName());
} catch (SDIInteractionException e) {
throw new InitializationException("Unable to initialize SDI Manager ",e);
}
return report;
}
/**
* Inits the.
*
* @return the initialization report
* @throws InitializationException the initialization exception
*/
@Override
@Synchronized
public InitializationReport init() throws InitializationException {
InitializationReport report = new InitializationReport();
sdiManagerMap=new HashMap<>();
report.setStatus(Report.Status.OK);
return report;
}
/**
* Shutdown.
*
* @throws ShutDownException the shut down exception
*/
@Override
public void shutdown() throws ShutDownException {
}
/**
* Expected params :
* -workspace MANDATORY
* -titleField.
*
* @param request the request
* @return the materialization report
* @throws MaterializationException the materialization exception
* @throws InvalidPluginRequestException the invalid plugin request exception
*/
@Override
public MaterializationReport materialize(MaterializationRequest request) throws MaterializationException, InvalidPluginRequestException {
log.info("Serving Materialize {} : request CallParameters {}, request Context {}: ",this.getDescriptor().getId(), request.getCallParameters(), request.getContext());
log.debug("Materialize request {}",request);
Project project =request.getDocument();
UseCaseDescriptor useCaseDescriptor = request.getUseCaseDescriptor();
Document requestArguments=Serialization.convert(request.getCallParameters(),Document.class);
MaterializationReport report= new MaterializationReport(request);
try{
Document profileConfiguration =getConfigurationFromProfile(useCaseDescriptor).getConfiguration();
log.debug("UseCaseDescriptor Configuration is {} ",profileConfiguration);
JSONPathWrapper documentNavigator=new JSONPathWrapper(project.getTheDocument().toJson());
JSONPathWrapper schemaNavigator=new JSONPathWrapper(useCaseDescriptor.getSchema().toJson());
for(Object fsConfigObj : profileConfiguration.get("registeredFileSetPaths", List.class)){
log.debug("Managing {} ",fsConfigObj);
MaterializationConfig fsConfig=Serialization.convert(fsConfigObj,MaterializationConfig.class);
List matchingFieldDefinitions =schemaNavigator.getByPath(fsConfig.getSchemaField());
if(matchingFieldDefinitions==null || matchingFieldDefinitions.isEmpty())
throw new MaterializationException("Invalid Field Definition path in configuration [NO MATCH] : "+
fsConfig.getSchemaField());
if(matchingFieldDefinitions.size()>1)
throw new MaterializationException("Invalid Field Definition path in configuration [MATCHES "+matchingFieldDefinitions.size()+"] : "+
fsConfig.getSchemaField());
Field f = Serialization.convert(matchingFieldDefinitions.get(0),Field.class);
// TODO Check if schema points to RegisteredFileSet
for(Object fsObject : documentNavigator.getByPath(fsConfig.getDocumentPath())){
RegisteredFileSet fs = Serialization.convert(fsObject,RegisteredFileSet.class);
log.debug("Found {} ",fs);
requestArguments.putIfAbsent("basePersistencePath", useCaseDescriptor.getId());
requestArguments.putIfAbsent("documentID", project.getId());
if(requestArguments.containsKey("titleField"))
requestArguments.putIfAbsent("layerTitle",fs.getString(requestArguments.getString("titleField")));
else requestArguments.putIfAbsent("layerTitle",fs.getUUID());
//Add FS uuid at ws_baseName
String ws = request.getMandatory("workspace")+"_"+ project.getId();
ws = ws.replaceAll("\\W","_");
log.trace("Escaped WS will be {} ",ws);
requestArguments.put("workspace",ws);
// Actually materializing
RegisteredFileSet obtained = getSDIManager().materializeLayer(fs,requestArguments);
log.debug("Obtained {} ",obtained);
documentNavigator.setElement("$..[?(@."+ RegisteredFileSet.UUID+" == '"+fs.getUUID()+"')]",obtained);
}
}
String finalDocument = documentNavigator.getValueCTX().jsonString();
log.debug("Final document after materialization is {} ",finalDocument);
report.setResultingDocument(Document.parse(finalDocument));
report.setStatus(Report.Status.OK);
}catch (SDIInteractionException e){
log.error("Unable to materialize "+request,e);
report.setStatus(Report.Status.ERROR);
report.putMessage(e.getMessage());
}catch (Throwable t){
log.error("Unable to materialize "+request,t);
report.setStatus(Report.Status.ERROR);
report.putMessage(t.getMessage());
}finally{
return report;
}
}
/**
* Expected parameters
* - fileSetPath.
*
* @param request the request
* @return the materialization report
* @throws MaterializationException the materialization exception
* @throws InvalidPluginRequestException the invalid plugin request exception
*/
@Override
public MaterializationReport dematerialize(MaterializationRequest request) throws MaterializationException, InvalidPluginRequestException {
log.info("Serving DeMaterialize {} : request CallParameters {}, request Context {}: ",this.getDescriptor().getId(), request.getCallParameters(), request.getContext());
log.debug("DeMaterialize request {}",request);
MaterializationReport report= new MaterializationReport(request);
try{
SDIManagerWrapper sdi=getSDIManager();
JSONPathWrapper wrapper = new JSONPathWrapper(request.getDocument().getTheDocument().toJson());
for(String s : wrapper.getMatchingPaths(request.getMandatory("fileSetPath"))){
log.debug("Found matching {} ",s);
RegisteredFileSet registeredFileSet=Serialization.convert(wrapper.getByPath(s).get(0),RegisteredFileSet.class);
List<Object> toKeep = new ArrayList<>();
if(registeredFileSet.getMaterializations()!=null)
for(Object matObj : registeredFileSet.getMaterializations()){
Materialization mat = Serialization.convert(matObj,Materialization.class);
if(mat.getType().equals(GCubeSDILayer.GCUBE_SDY_LAYER_TYPE)) {
log.debug("Deleting Layer {} ",mat);
sdi.deleteLayer(Serialization.convert(matObj, GCubeSDILayer.class));
}else toKeep.add(matObj);
}
// Resetting remaining materializations
registeredFileSet.put(RegisteredFileSet.MATERIALIZATIONS,toKeep);
// Update FS in doc
wrapper.setElement(s,registeredFileSet);
}
// Resetting Document
report.setResultingDocument(Document.parse(wrapper.getValueCTX().jsonString()));
}catch (SDIInteractionException e){
log.error("Unable to materialize "+request,e);
report.setStatus(Report.Status.ERROR);
report.putMessage(e.getMessage());
}catch (Throwable t){
log.error("Unable to materialize "+request,t);
report.setStatus(Report.Status.ERROR);
report.putMessage(t.getMessage());
}finally{
return report;
}
}
static final PluginDescriptor DESCRIPTOR=new PluginDescriptor("SDI-Default-Materializer", MaterializerPluginDescriptor.MATERIALIZER);
static {
DESCRIPTOR.setDescription("SDI Materializer. " +
"This plugin materialize FileSets in gCube SDI.");
DESCRIPTOR.setVersion(new Semver("1.0.0"));
}
/**
* Gets the descriptor.
*
* @return the descriptor
*/
@Override
public PluginDescriptor getDescriptor() {
return DESCRIPTOR;
}
}