X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=gis%2Fruntime%2Forg.argeo.gis.geotools%2Fsrc%2Fmain%2Fjava%2Forg%2Fargeo%2Fgeotools%2Fjcr%2FGeoJcrIndex.java;fp=gis%2Fruntime%2Forg.argeo.gis.geotools%2Fsrc%2Fmain%2Fjava%2Forg%2Fargeo%2Fgeotools%2Fjcr%2FGeoJcrIndex.java;h=0000000000000000000000000000000000000000;hb=93854671977f419c5a2c1f2d343fd063450168db;hp=b9281b8229d1c9e19d1df22ebc1ea62e46fd4773;hpb=c3be9f8db8a79e159d6a057758dfc7f3580efc2d;p=lgpl%2Fargeo-commons.git diff --git a/gis/runtime/org.argeo.gis.geotools/src/main/java/org/argeo/geotools/jcr/GeoJcrIndex.java b/gis/runtime/org.argeo.gis.geotools/src/main/java/org/argeo/geotools/jcr/GeoJcrIndex.java deleted file mode 100644 index b9281b822..000000000 --- a/gis/runtime/org.argeo.gis.geotools/src/main/java/org/argeo/geotools/jcr/GeoJcrIndex.java +++ /dev/null @@ -1,314 +0,0 @@ -package org.argeo.geotools.jcr; - -import java.io.IOException; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.Executor; - -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.observation.Event; -import javax.jcr.observation.EventIterator; -import javax.jcr.observation.EventListener; -import javax.jcr.observation.ObservationManager; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.ArgeoException; -import org.argeo.geotools.GeoToolsUtils; -import org.argeo.jcr.JcrUtils; -import org.argeo.jcr.gis.GisNames; -import org.argeo.jcr.gis.GisTypes; -import org.argeo.jts.jcr.JtsJcrUtils; -import org.geotools.data.DataStore; -import org.geotools.data.DefaultTransaction; -import org.geotools.data.FeatureStore; -import org.geotools.data.Transaction; -import org.geotools.feature.FeatureCollection; -import org.geotools.feature.FeatureCollections; -import org.geotools.feature.simple.SimpleFeatureBuilder; -import org.geotools.feature.simple.SimpleFeatureTypeBuilder; -import org.geotools.filter.FilterFactoryImpl; -import org.geotools.referencing.CRS; -import org.opengis.feature.simple.SimpleFeature; -import org.opengis.feature.simple.SimpleFeatureType; -import org.opengis.filter.FilterFactory2; -import org.opengis.filter.identity.FeatureId; -import org.opengis.referencing.FactoryException; -import org.opengis.referencing.NoSuchAuthorityCodeException; -import org.opengis.referencing.crs.CoordinateReferenceSystem; - -import com.vividsolutions.jts.geom.Geometry; -import com.vividsolutions.jts.geom.Point; -import com.vividsolutions.jts.geom.Polygon; - -/** Index JCR nodes containing or referencing GIS data. */ -public class GeoJcrIndex implements EventListener, GisNames, GisTypes { - // PostGIS convention - final static String DEFAULT_GEOM_NAME = "the_geom"; - - private final static Log log = LogFactory.getLog(GeoJcrIndex.class); - - private DataStore dataStore; - private Session session; - private Executor systemExecutionService; - - private String crs = "EPSG:4326"; - - /** The key is the workspace */ - private Map> geoJcrIndexes = Collections - .synchronizedMap(new HashMap>()); - - // TODO: use common factory finder? - private FilterFactory2 ff = new FilterFactoryImpl(); - - /** Expects to execute with system authentication */ - public void init() { - if (systemExecutionService != null)// legacy - systemExecutionService.execute(new Runnable() { - public void run() { - initGeoJcrIndex(); - } - }); - else - initGeoJcrIndex(); - } - - protected void initGeoJcrIndex() { - try { - // create GIS schema - SimpleFeatureType indexType = getWorkspaceGeoJcrIndexType(session - .getWorkspace().getName()); - GeoToolsUtils.createSchemaIfNeeded(dataStore, indexType); - - // register JCR listeners - ObservationManager om = session.getWorkspace() - .getObservationManager(); - om.addEventListener(this, Event.NODE_ADDED | Event.NODE_REMOVED, - "/", true, null, null, false); - - // FIXME: use a different listener for properties since it resets - // the filter - // om.addEventListener(this, Event.PROPERTY_CHANGED, "/", - // true, null, new String[] { GIS_LOCATED }, false); - - } catch (RepositoryException e) { - throw new ArgeoException("Cannot initialize GeoJcr index", e); - } - } - - public void dispose() { - } - - public void onEvent(final EventIterator events) { - final FeatureCollection toAdd = FeatureCollections - .newCollection(); - final Set toRemove = new HashSet(); - - // execute with system authentication so that JCR can be read - systemExecutionService.execute(new Runnable() { - public void run() { - while (events.hasNext()) { - Event event = events.nextEvent(); - try { - Integer eventType = event.getType(); - if (Event.NODE_ADDED == eventType) { - Node node = session.getNodeByIdentifier(event - .getIdentifier()); - if (node.isNodeType(GIS_INDEXED)) { - SimpleFeature feature = mapNodeToFeature(node, - getGeoJcrIndex().getSchema()); - toAdd.add(feature); - } - } else if (Event.NODE_REMOVED == eventType) { - // we have no way to check whether the node was - // actually - // geoindexed without querying the index, this is - // therefore - // more optimal to create a filter with all ideas - // and apply - // a remove later on - String id = event.getIdentifier(); - toRemove.add(ff.featureId(id)); - } else if (Event.PROPERTY_CHANGED == eventType) { - // TODO: monitor changes to SRS, BBOX AND CENTROID - } - } catch (Exception e) { - log.error("Cannot process event " + event, e); - } - } - } - }); - - // TODO: this may be more optimal to persist in one single - // transaction, - // but we will loose modifications on all nodes if a single one - // fails - try { - Transaction transaction = new DefaultTransaction(); - getGeoJcrIndex().setTransaction(transaction); - try { - // points - getGeoJcrIndex().addFeatures(toAdd); - if (toRemove.size() != 0) - getGeoJcrIndex().removeFeatures(ff.id(toRemove)); - transaction.commit(); - } catch (Exception e) { - transaction.rollback(); - throw new ArgeoException("Cannot persist changes", e); - } finally { - transaction.close(); - } - } catch (ArgeoException e) { - throw e; - } catch (IOException e) { - throw new ArgeoException("Unexpected issue with the transaction", e); - } - } - - protected FeatureStore getGeoJcrIndex() { - String workspaceName = session.getWorkspace().getName(); - if (!geoJcrIndexes.containsKey(workspaceName)) { - SimpleFeatureType indexType = getWorkspaceGeoJcrIndexType(workspaceName); - FeatureStore geoIndex = GeoToolsUtils - .getFeatureStore(dataStore, indexType.getName()); - geoJcrIndexes.put(workspaceName, geoIndex); - } - return geoJcrIndexes.get(workspaceName); - } - - protected SimpleFeatureType getWorkspaceGeoJcrIndexType(String workspaceName) { - - SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder(); - builder.setNamespaceURI(GIS_NAMESPACE); - builder.setName(workspaceName + "_geojcr_index"); - try { - builder.setCRS(CRS.decode(crs)); - } catch (Exception e) { - throw new ArgeoException("Cannot set CRS " + crs, e); - } - - builder.setDefaultGeometry(JcrUtils.normalize(GIS_BBOX)); - builder.add(JcrUtils.normalize(GIS_BBOX), Polygon.class); - builder.add(JcrUtils.normalize(GIS_CENTROID), Point.class); - - builder.add(JcrUtils.normalize("jcr:uuid"), String.class); - builder.add(JcrUtils.normalize("jcr:path"), String.class); - builder.add(JcrUtils.normalize("jcr:primaryType"), String.class); - // mix:lastModified - builder.add(JcrUtils.normalize("jcr:lastModified"), Date.class); - builder.add(JcrUtils.normalize("jcr:lastModifiedBy"), String.class); - - return builder.buildFeatureType(); - } - - protected SimpleFeature mapNodeToFeature(Node node, SimpleFeatureType type) { - try { - SimpleFeatureBuilder builder = new SimpleFeatureBuilder(type); - - Node locatedNode; - if (node.isNodeType(GIS_LOCATED)) { - locatedNode = node; - } else if (node.isNodeType(GIS_INDEXED)) { - locatedNode = findLocatedParent(node); - } else { - throw new ArgeoException("Unsupported node " + node); - } - - // TODO: reproject to the feature store SRS - Polygon bbox = (Polygon) JtsJcrUtils.readWkb(locatedNode - .getProperty(GIS_BBOX)); - builder.set(JcrUtils.normalize(GIS_BBOX), bbox); - Point centroid = (Point) JtsJcrUtils.readWkb(locatedNode - .getProperty(GIS_CENTROID)); - builder.set(JcrUtils.normalize(GIS_CENTROID), centroid); - - builder.set(JcrUtils.normalize("jcr:uuid"), node.getIdentifier()); - builder.set(JcrUtils.normalize("jcr:path"), node.getPath()); - builder.set(JcrUtils.normalize("jcr:primaryType"), node - .getPrimaryNodeType().getName()); - if (node.hasProperty(Property.JCR_LAST_MODIFIED)) - builder.set(JcrUtils.normalize("jcr:lastModified"), node - .getProperty(Property.JCR_LAST_MODIFIED).getDate() - .getTime()); - if (node.hasProperty(Property.JCR_LAST_MODIFIED_BY)) - builder.set(JcrUtils.normalize("jcr:lastModifiedBy"), node - .getProperty(Property.JCR_LAST_MODIFIED_BY).getString()); - return builder.buildFeature(node.getIdentifier()); - } catch (RepositoryException e) { - throw new ArgeoException("Cannot map " + node + " to " + type, e); - } - } - - protected Node findLocatedParent(Node child) { - try { - if (child.getParent().isNodeType(GIS_LOCATED)) - return child.getParent(); - else - return findLocatedParent(child.getParent()); - } catch (Exception e) { - // also if child is root node - throw new ArgeoException("Cannot find located parent", e); - } - } - - /** Returns the node as a point in the CRS of the related feature store. */ - protected Geometry reproject(CoordinateReferenceSystem crs, - Geometry geometry, CoordinateReferenceSystem targetCrs) { - // transform if not same CRS - // FIXME: there is certainly a more standard way to reproject - if (!targetCrs.getIdentifiers().contains(crs.getName())) { - throw new ArgeoException("Reprojection not yet supported"); - // MathTransform transform; - // try { - // transform = CRS.findMathTransform(nodeCrs, featureStoreCrs); - // if (geometry instanceof Point) { - // Point point = (Point) geometry; - // DirectPosition2D pos = new DirectPosition2D(nodeCrs, - // point.getX(), point.getY()); - // DirectPosition targetPos = transform.transform(pos, null); - // return geometryFactory.createPoint(new Coordinate(targetPos - // .getCoordinate()[0], targetPos.getCoordinate()[1])); - // } else if (geometry instanceof Polygon) { - // Polygon polygon = (Polygon) geometry; - // List coordinates = new ArrayList(); - // for (Coordinate coo : polygon.getExteriorRing()) { - // DirectPosition pos = new DirectPosition2D(nodeCrs, - // coo.x, coo.y); - // DirectPosition targetPos = transform.transform(pos, - // null); - // // coordinates.add(o) - // } - // LinearRing ring = geometryFactory - // .createLinearRing(coordinates - // .toArray(new Coordinate[coordinates.size()])); - // return geometryFactory.createPolygon(ring, null); - // } - // } catch (Exception e) { - // throw new ArgeoException("Cannot transform from " + nodeCrs - // + " to " + featureStoreCrs, e); - // } - } else { - return geometry; - } - } - - public void setDataStore(DataStore dataStore) { - this.dataStore = dataStore; - } - - public void setSession(Session session) { - this.session = session; - } - - public void setSystemExecutionService(Executor systemExecutionService) { - this.systemExecutionService = systemExecutionService; - } - -}