package org.gcube.application.cms.sdi.plugins; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.bson.Document; import org.gcube.application.cms.plugins.IndexerPluginInterface; import org.gcube.application.cms.plugins.faults.IndexingException; import org.gcube.application.cms.plugins.faults.InitializationException; import org.gcube.application.cms.plugins.faults.InvalidPluginRequestException; import org.gcube.application.cms.plugins.faults.InvalidProfileException; import org.gcube.application.cms.plugins.model.PluginDescriptor; import org.gcube.application.cms.plugins.reports.IndexDocumentReport; import org.gcube.application.cms.plugins.reports.InitializationReport; import org.gcube.application.cms.plugins.reports.Report; import org.gcube.application.cms.plugins.requests.IndexDocumentRequest; import org.gcube.application.cms.sdi.engine.PostgisIndexer; import org.gcube.application.cms.sdi.engine.PostgisTable; 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.cms.plugins.model.ComparableVersion; import org.gcube.application.geoportal.common.model.document.ProfiledDocument; import org.gcube.application.geoportal.common.model.document.filesets.GCubeSDILayer; import org.gcube.application.geoportal.common.model.document.spatial.SpatialReference; import org.gcube.application.geoportal.common.model.profile.Profile; import java.util.ArrayList; import java.util.List; @Slf4j public class SDIIndexerPlugin extends SDIAbstractPlugin implements IndexerPluginInterface { @Data private static class MappingObject{ private String name; private String type; private String path; public void validate () throws InvalidProfileException { if(name==null) throw new InvalidProfileException("Invalid mapping "+this+" : name is null"); if(type==null) throw new InvalidProfileException("Invalid mapping "+this+" : type is null"); if(path==null) throw new InvalidProfileException("Invalid mapping "+this+" : path is null"); } } static final PluginDescriptor DESCRIPTOR=new PluginDescriptor("SDI-Indexer-Plugin", PluginDescriptor.BaseTypes.INDEXER); static { DESCRIPTOR.setDescription("SDI Indexer. " + "Manage Centroids layers."); DESCRIPTOR.setVersion(new ComparableVersion("1.0.0")); } @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 * - centroidRecord (OPT) * * @param request * @return */ @Override public IndexDocumentReport index(IndexDocumentRequest request) throws InvalidPluginRequestException { log.info("Indexer {} : Performing {} ",this.getDescriptor().getId(),request); ProfiledDocument profiledDocument=request.getDocument(); Profile profile = request.getProfile(); Document requestArguments=request.getCallParameters(); IndexDocumentReport report= new IndexDocumentReport(request); try{ // ********* INIT INDEX // TODO CACHE PostgisIndexer indexer = new PostgisIndexer(sdiCache.getObject(),profile,postgisCache.getObject()); Document profileConfiguration =getConfigurationFromProfile(profile).getConfiguration(); log.debug("Profile Configuration is {} ",profileConfiguration); // SCHEMA log.debug("Profile {} : Evaluating Index schema.. ",profile.getId()); List fields = new ArrayList<>(); // TODO From Profile fields.add(new PostgisTable.Field("geom", PostgisTable.FieldType.GEOMETRY)); fields.add(new PostgisTable.Field("projectid", PostgisTable.FieldType.TEXT)); List mappingObjs= profileConfiguration.get("explicitFieldMapping",List.class); log.trace("Loading mappings from profile.. "); List mappingObjects= new ArrayList<>(); if(mappingObjs!=null){ for (Object mappingObj : mappingObjs) { log.trace("Mapping is {} ",mappingObj); MappingObject m = Serialization.convert(mappingObj,MappingObject.class); m.validate(); fields.add(new PostgisTable.Field(m.getName(), PostgisTable.FieldType.valueOf(m.getType()))); } } indexer.initIndex(requestArguments.getString("indexName"), fields, requestArguments.getString("workspace"), requestArguments.getString("indexName")); // ************* PREPARE RECORD JSONPathWrapper documentNavigator=new JSONPathWrapper(Serialization.write(profiledDocument)); Document centroidDoc = new Document(); if(requestArguments.containsKey("centroidRecord")) centroidDoc.putAll(requestArguments.get("centroidRecords",Document.class)); // DEFAULT VALUES centroidDoc.put("projectid",profiledDocument.getId()); // ********************** EVALAUTE POSITION log.debug("indexing Profile {} : Evaluating Centroid... ",profile.getId()); if(profiledDocument.getSpatialReference()!=null){ log.debug("Using user defined spatial reference "+profiledDocument.getSpatialReference()); //TODO USE GEOJSON Position throw new Exception("Not yet implemented"); }else { log.debug("Profile {} : Getting evaluation paths from profile.. ",profile.getId()); List bboxEvaluationPaths = profileConfiguration.get("bboxEvaluation",List.class); if(bboxEvaluationPaths==null || bboxEvaluationPaths.isEmpty()) throw new Exception("Missing configuration bboxEvaluation"); GCubeSDILayer.BBOX toSet = null; for(Object pathObj : bboxEvaluationPaths){ log.debug("Profile {} : Evaluating path {} ",profile.getId(),pathObj); List bboxObjects = documentNavigator.getByPath(pathObj.toString()); log.debug("Profile {} : Evaluating path {} .. results {} ",profile.getId(),pathObj,bboxObjects); for(Object bboxObject : bboxObjects) { log.info("Matched path {}, value is {} ",pathObj.toString(),bboxObject); GCubeSDILayer.BBOX box = Serialization.convert(bboxObject, GCubeSDILayer.BBOX.class); if(toSet == null) toSet = box; if(box.getMaxX()>toSet.getMaxX()) toSet.setMaxX(box.getMaxX()); if(box.getMaxY()>toSet.getMaxY()) toSet.setMaxY(box.getMaxY()); if(box.getMinX() foundValues = documentNavigator.getByPath(m.getPath()); Object toSetValue=null; if(!foundValues.isEmpty()) toSetValue=foundValues.get(0); log.trace("Setting {} = {} in centroid doc ",m.getName(),toSetValue); centroidDoc.put(m.getName(),foundValues.get(0)); } log.info("Inserting Centroid {} into {} ",centroidDoc.toJson(),indexer); indexer.insert(centroidDoc); // TODO GEOJSON report.setToSetSpatialReference(new SpatialReference()); 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; } } }