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

325 lines
13 KiB
Java
Raw Normal View History

2022-02-18 18:11:12 +01:00
package org.gcube.application.cms.sdi.plugins;
2022-04-01 19:11:11 +02:00
import com.vdurmont.semver4j.Semver;
2022-02-18 18:11:12 +01:00
import lombok.extern.slf4j.Slf4j;
import org.bson.Document;
import org.gcube.application.cms.plugins.IndexerPluginInterface;
2022-03-04 11:30:31 +01:00
import org.gcube.application.cms.plugins.faults.IndexingException;
2022-02-18 18:11:12 +01:00
import org.gcube.application.cms.plugins.faults.InitializationException;
2022-03-04 11:30:31 +01:00
import org.gcube.application.cms.plugins.faults.InvalidPluginRequestException;
2022-02-24 18:09:30 +01:00
import org.gcube.application.cms.plugins.faults.InvalidProfileException;
2022-02-18 18:11:12 +01:00
import org.gcube.application.cms.plugins.reports.IndexDocumentReport;
import org.gcube.application.cms.plugins.reports.InitializationReport;
import org.gcube.application.cms.plugins.reports.Report;
2022-03-11 18:11:32 +01:00
import org.gcube.application.cms.plugins.requests.BaseRequest;
2022-02-18 18:11:12 +01:00
import org.gcube.application.cms.plugins.requests.IndexDocumentRequest;
2022-11-09 16:55:39 +01:00
import org.gcube.application.cms.sdi.Constants;
2022-10-27 16:04:13 +02:00
import org.gcube.application.cms.sdi.engine.DBConstants;
2022-02-18 18:11:12 +01:00
import org.gcube.application.cms.sdi.engine.PostgisIndexer;
import org.gcube.application.cms.sdi.engine.PostgisTable;
2022-09-26 16:11:20 +02:00
import org.gcube.application.cms.sdi.engine.bboxes.BBOXByCoordinatePaths;
import org.gcube.application.cms.sdi.engine.bboxes.BBOXEvaluator;
import org.gcube.application.cms.sdi.engine.bboxes.BBOXPathScanner;
2022-02-18 18:11:12 +01:00
import org.gcube.application.cms.sdi.faults.SDIInteractionException;
2022-11-09 16:55:39 +01:00
import org.gcube.application.cms.sdi.model.MappingObject;
2022-02-18 18:11:12 +01:00
import org.gcube.application.cms.serialization.Serialization;
import org.gcube.application.geoportal.common.model.JSONPathWrapper;
2022-03-11 18:11:32 +01:00
import org.gcube.application.geoportal.common.model.configuration.Index;
2022-03-04 14:23:20 +01:00
import org.gcube.application.geoportal.common.model.document.Project;
2022-03-30 12:57:14 +02:00
import org.gcube.application.geoportal.common.model.document.filesets.sdi.GCubeSDILayer;
2022-09-26 16:11:20 +02:00
import org.gcube.application.geoportal.common.model.document.identification.IdentificationReference;
import org.gcube.application.geoportal.common.model.document.identification.SpatialReference;
import org.gcube.application.geoportal.common.model.plugins.IndexerPluginDescriptor;
import org.gcube.application.geoportal.common.model.plugins.PluginDescriptor;
2022-03-11 18:11:32 +01:00
import org.gcube.application.geoportal.common.model.rest.ConfigurationException;
2022-03-04 14:23:20 +01:00
import org.gcube.application.geoportal.common.model.useCaseDescriptor.UseCaseDescriptor;
2022-05-06 12:45:18 +02:00
import org.geojson.Crs;
2022-03-07 17:59:06 +01:00
import org.geojson.GeoJsonObject;
import org.geojson.LngLatAlt;
import org.geojson.Point;
2022-02-23 17:13:22 +01:00
2022-03-11 18:11:32 +01:00
import java.sql.SQLException;
2022-02-24 18:09:30 +01:00
import java.util.ArrayList;
2022-10-24 17:45:13 +02:00
import java.util.Collection;
2022-02-18 18:11:12 +01:00
import java.util.List;
@Slf4j
public class SDIIndexerPlugin extends SDIAbstractPlugin implements IndexerPluginInterface {
2022-02-24 18:09:30 +01:00
2022-11-09 16:55:39 +01:00
static final PluginDescriptor DESCRIPTOR=new PluginDescriptor(Constants.INDEXER_PLUGIN_ID,
IndexerPluginDescriptor.INDEXER);
2022-02-18 18:11:12 +01:00
2022-05-03 18:07:18 +02:00
static final ArrayList<BBOXEvaluator> BBOX_EVALUATORS=new ArrayList<>();
2022-02-18 18:11:12 +01:00
static {
DESCRIPTOR.setDescription("SDI Indexer. " +
"Manage Centroids layers.");
2022-04-01 19:11:11 +02:00
DESCRIPTOR.setVersion(new Semver("1.0.0"));
2022-05-03 18:07:18 +02:00
BBOX_EVALUATORS.add(new BBOXPathScanner());
BBOX_EVALUATORS.add(new BBOXByCoordinatePaths());
2022-02-18 18:11:12 +01:00
}
@Override
public PluginDescriptor getDescriptor() {
return DESCRIPTOR;
}
@Override
public InitializationReport initInContext() throws InitializationException {
InitializationReport report = new InitializationReport();
report.setStatus(Report.Status.OK);
return report;
}
/**
* Expected parameters :
* - indexName (unique)
* - workspace
2022-03-04 11:30:31 +01:00
* - centroidRecord (OPT)
2022-02-18 18:11:12 +01:00
*
* @param request
* @return
*/
@Override
2022-03-04 11:30:31 +01:00
public IndexDocumentReport index(IndexDocumentRequest request) throws InvalidPluginRequestException {
2022-02-18 18:11:12 +01:00
2022-03-30 12:57:14 +02:00
log.info("Indexer {} : Serving Index Request {} ",this.getDescriptor().getId(),request);
2022-02-18 18:11:12 +01:00
2022-03-04 14:23:20 +01:00
Project project =request.getDocument();
UseCaseDescriptor useCaseDescriptor = request.getUseCaseDescriptor();
2022-02-18 18:11:12 +01:00
Document requestArguments=request.getCallParameters();
2022-02-23 17:13:22 +01:00
IndexDocumentReport report= new IndexDocumentReport(request);
2022-02-18 18:11:12 +01:00
2022-02-24 18:09:30 +01:00
2022-02-18 18:11:12 +01:00
try{
// ********* INIT INDEX
// TODO CACHE
2022-03-11 18:11:32 +01:00
PostgisIndexer indexer = getIndexer(useCaseDescriptor,requestArguments);
2022-02-18 18:11:12 +01:00
2022-03-04 14:23:20 +01:00
Document profileConfiguration =getConfigurationFromProfile(useCaseDescriptor).getConfiguration();
log.debug("UseCaseDescriptor Configuration is {} ",profileConfiguration);
2022-02-18 18:11:12 +01:00
// ************* PREPARE RECORD
2022-03-04 14:23:20 +01:00
JSONPathWrapper documentNavigator=new JSONPathWrapper(Serialization.write(project));
2022-02-18 18:11:12 +01:00
2022-03-04 11:30:31 +01:00
Document centroidDoc = new Document();
if(requestArguments.containsKey("centroidRecord"))
centroidDoc.putAll(requestArguments.get("centroidRecords",Document.class));
2022-02-18 18:11:12 +01:00
// DEFAULT VALUES
2022-10-27 16:04:13 +02:00
centroidDoc.put(DBConstants.Defaults.PROJECT_ID, project.getId());
centroidDoc.put(DBConstants.Defaults.DISPLAYED,true);
2022-02-18 18:11:12 +01:00
// ********************** EVALAUTE POSITION
2022-03-04 14:23:20 +01:00
log.debug("indexing UseCaseDescriptor {} : Evaluating Centroid... ", useCaseDescriptor.getId());
2022-04-11 17:23:27 +02:00
SpatialReference reference =null;
List<IdentificationReference> refs=project.getIdentificationReferenceByType(SpatialReference.SPATIAL_REFERENCE_TYPE);
if(!refs.isEmpty()){
2022-03-07 17:59:06 +01:00
2022-04-11 17:23:27 +02:00
// Use existing Reference
2022-03-07 17:59:06 +01:00
2022-04-11 17:23:27 +02:00
reference = Serialization.convert(refs.get(0), SpatialReference.class);
2022-03-07 17:59:06 +01:00
2022-05-05 14:15:39 +02:00
log.debug("Using already defined spatial reference " + reference);
2022-03-07 17:59:06 +01:00
2022-04-11 17:23:27 +02:00
GeoJsonObject object = Serialization.convert(reference.getGeoJson(), GeoJsonObject.class);
2022-03-07 17:59:06 +01:00
2022-04-11 17:23:27 +02:00
GCubeSDILayer.BBOX bbox = GCubeSDILayer.BBOX.fromGeoJSON(object.getBbox());
log.info("Found declared BBOX {} ", bbox);
2022-10-18 18:00:34 +02:00
Double pointX = (bbox.getMaxX() + bbox.getMinX())/2;
Double pointY = (bbox.getMaxY() + bbox.getMinY())/2;
2022-04-11 17:23:27 +02:00
String wkt = String.format("POINT (%1$f %2$f) ",
pointX, pointY);
2022-03-07 17:59:06 +01:00
2022-04-11 17:23:27 +02:00
centroidDoc.put("geom", wkt);
} else{
// unable to use current Spatial reference, try evaluating it
2022-03-04 14:23:20 +01:00
log.debug("UseCaseDescriptor {} : Getting evaluation paths from useCaseDescriptor.. ", useCaseDescriptor.getId());
2022-04-11 17:23:27 +02:00
2022-05-03 18:07:18 +02:00
// for each configuration option try until found
2022-04-11 17:23:27 +02:00
GCubeSDILayer.BBOX toSet = null;
2022-05-03 18:07:18 +02:00
for(BBOXEvaluator evaluator : BBOX_EVALUATORS){
log.trace("UCD {}, Project {}. Evaluating BBOX with {}",useCaseDescriptor.getId(),project.getId(),evaluator);
try{
if(evaluator.isConfigured(profileConfiguration)){
toSet=evaluator.evaluate(profileConfiguration,useCaseDescriptor,documentNavigator);
if(toSet!=null) {
log.info("UCD {}, Project {}. Evaluated BBOX {} with method {}",
useCaseDescriptor.getId(),project.getId(),toSet,evaluator);
break;
}
}
}catch (Throwable t){
log.warn("UCD {}, Project {}. Exception with {}",
useCaseDescriptor.getId(),project.getId(),evaluator,t);
2022-02-18 18:11:12 +01:00
}
}
2022-05-03 18:07:18 +02:00
if(toSet== null)
throw new IndexingException("No BBOX has been evaluated from project");
2022-03-04 11:30:31 +01:00
2022-10-18 18:00:34 +02:00
Double pointX=(toSet.getMaxX()+toSet.getMinX())/2;
Double pointY = (toSet.getMaxY()+toSet.getMinY())/2;
2022-02-18 18:11:12 +01:00
log.info("Evaluated BBOX {} ",toSet);
2022-03-04 11:30:31 +01:00
String wkt = String .format("POINT (%1$f %2$f) ",
2022-03-07 17:59:06 +01:00
pointX, pointY);
2022-05-06 12:45:18 +02:00
//TODO support altitude
Double pointZ= 0d;
2022-02-18 18:11:12 +01:00
2022-03-04 11:30:31 +01:00
centroidDoc.put("geom",wkt);
2022-02-18 18:11:12 +01:00
2022-05-06 12:45:18 +02:00
Point point = new Point();
point.setCoordinates(new LngLatAlt(pointX,pointY,pointZ));
point.setBbox(toSet.asGeoJSONArray());
2022-03-07 17:59:06 +01:00
2022-05-06 12:45:18 +02:00
//TODO Manage CRS
point.setCrs(new Crs());
reference = new SpatialReference(Serialization.asDocument(point));
log.info("UCD {} project {}, Setting Spatial Reference {} ",useCaseDescriptor.getId(),project.getId(),Serialization.write(reference));
2022-04-11 17:23:27 +02:00
report.addIdentificationReference(reference);
2022-02-18 18:11:12 +01:00
}
2022-03-04 14:23:20 +01:00
//*********** Additional Values from useCaseDescriptor
2022-02-18 18:11:12 +01:00
2022-03-04 11:30:31 +01:00
log.info("Setting additional values to centroid from mappings ..");
2022-03-11 18:11:32 +01:00
for(MappingObject m : getMappings(useCaseDescriptor)){
2022-03-04 11:30:31 +01:00
List<Object> foundValues = documentNavigator.getByPath(m.getPath());
Object toSetValue=null;
2022-10-24 16:36:00 +02:00
if(!foundValues.isEmpty()) {
// NB CSV for multiple values
StringBuilder b=new StringBuilder();
2022-10-24 17:45:13 +02:00
foundValues.forEach(o-> {
// Parser returns list of list
if (o instanceof Collection) ((Collection<?>) o).forEach(v ->b.append(v + ","));
else b.append(o+",");
});
2022-10-24 16:36:00 +02:00
b.deleteCharAt(b.length()-1);
toSetValue = b.toString();
}
2022-03-04 11:30:31 +01:00
log.trace("Setting {} = {} in centroid doc ",m.getName(),toSetValue);
2022-10-24 16:15:38 +02:00
centroidDoc.put(m.getName(),toSetValue);
2022-03-04 11:30:31 +01:00
}
2022-02-18 18:11:12 +01:00
2022-11-04 17:48:53 +01:00
log.info("Inserting Centroid {} into {} ",Serialization.write(centroidDoc.toJson()),indexer);
2022-03-04 11:30:31 +01:00
indexer.insert(centroidDoc);
2022-02-18 18:11:12 +01:00
2022-11-04 17:48:53 +01:00
// Support to HIDE AND DISPLAY as requested by invoker
2022-10-27 17:18:47 +02:00
if(requestArguments.containsKey("_toHideIds")){
2022-11-04 17:48:53 +01:00
List<String> ids = Serialization.convert(requestArguments.get("_toHideIds"),List.class);
2022-10-27 17:18:47 +02:00
log.info("Requested to hide centroids {} ",ids);
indexer.updateIsVisible(false,ids);
}
2022-10-27 16:04:13 +02:00
2022-10-27 17:18:47 +02:00
if(requestArguments.containsKey("_toDisplayIds")){
2022-11-04 17:48:53 +01:00
List<String> ids = Serialization.convert(requestArguments.get("_toDisplayIds"),List.class);
2022-10-27 17:18:47 +02:00
log.info("Requested to hide centroids {} ",ids);
indexer.updateIsVisible(true,ids);
}
2022-10-27 16:04:13 +02:00
2022-02-18 18:11:12 +01:00
report.setStatus(Report.Status.OK);
}catch (SDIInteractionException e){
log.error("Unable to index "+request,e);
report.setStatus(Report.Status.ERROR);
report.putMessage(e.getMessage());
}catch (Throwable t){
log.error("Unable to index "+request,t);
report.setStatus(Report.Status.ERROR);
report.putMessage(t.getMessage());
}finally{
return report;
}
}
2022-11-09 16:55:39 +01:00
private List<MappingObject> getMappings(UseCaseDescriptor useCaseDescriptor) throws InvalidProfileException {
return MappingObject.getMappingsFromUCD(useCaseDescriptor, getDescriptor().getId());
}
2022-03-30 12:57:14 +02:00
@Override
public IndexDocumentReport deindex(IndexDocumentRequest request) throws InvalidPluginRequestException {
log.info("Indexer {} : Serving Index Request {} ",this.getDescriptor().getId(),request);
IndexDocumentReport report= new IndexDocumentReport(request);
try{
PostgisIndexer indexer = getIndexer(request.getUseCaseDescriptor(),request.getCallParameters());
2022-11-09 16:55:39 +01:00
indexer.removeByFieldValue(PostgisIndexer.StandardFields.PROJECT_ID,request.getDocument().getId());
2022-03-30 12:57:14 +02:00
}catch (SDIInteractionException e){
log.error("Unable to index "+request,e);
report.setStatus(Report.Status.ERROR);
report.putMessage(e.getMessage());
}catch (Throwable t){
log.error("Unable to index "+request,t);
report.setStatus(Report.Status.ERROR);
report.putMessage(t.getMessage());
}finally{
return report;
}
}
2022-03-17 17:54:00 +01:00
/**
* Expected parameters :
* workspace
* indexName
*
* @param request
* @return
* @throws ConfigurationException
*/
2022-03-11 18:11:32 +01:00
@Override
public Index getIndex(BaseRequest request) throws ConfigurationException {
try {
return getIndexer(request.getUseCaseDescriptor(), request.getCallParameters()).getIndexConfiguration();
}catch(Throwable t ){
throw new ConfigurationException("Unable to get Postgis index for ucd "+request.getUseCaseDescriptor().getId()+" in "+ request.getContext(),t);
}
}
// Inits index
// TODO CACHE
private PostgisIndexer getIndexer(UseCaseDescriptor ucd,Document params) throws ConfigurationException, SQLException, InvalidProfileException, SDIInteractionException {
PostgisIndexer indexer = new PostgisIndexer(sdiCache.getObject(), ucd, postgisCache.getObject());
List<MappingObject> mappingObjects = getMappings(ucd);
2022-11-09 16:55:39 +01:00
List<PostgisTable.Field> fields = PostgisTable.Field.fromMappings(mappingObjects);
2022-03-11 18:11:32 +01:00
indexer.initIndex(params.getString("indexName"),
fields,
params.getString("workspace"),
params.getString("indexName"));
return indexer;
}
2022-10-27 16:04:13 +02:00
2022-03-30 12:57:14 +02:00
2022-03-11 18:11:32 +01:00
2022-10-27 16:04:13 +02:00
2022-03-11 18:11:32 +01:00
2022-02-18 18:11:12 +01:00
}