]> git.argeo.org Git - lgpl/argeo-commons.git/blobdiff - gis/runtime/org.argeo.gis.geotools/src/main/java/org/argeo/geotools/jcr/SimpleGeoJcrMapper.java
Move Commons GIS to Connect
[lgpl/argeo-commons.git] / gis / runtime / org.argeo.gis.geotools / src / main / java / org / argeo / geotools / jcr / SimpleGeoJcrMapper.java
index d3661870546011cef32c9434f2afb785f2e6590c..27da93738e19fa93a0d816dce153b0664c57fd6f 100644 (file)
@@ -18,26 +18,40 @@ import org.argeo.ArgeoException;
 import org.argeo.geotools.GeoToolsConstants;
 import org.argeo.geotools.GeoToolsUtils;
 import org.argeo.jcr.JcrUtils;
+import org.argeo.jcr.gis.GisJcrConstants;
 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.FeatureSource;
+import org.geotools.referencing.CRS;
 import org.opengis.feature.simple.SimpleFeature;
 import org.opengis.feature.simple.SimpleFeatureType;
 import org.opengis.feature.type.Name;
+import org.opengis.referencing.FactoryException;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
 
+import com.vividsolutions.jts.geom.Coordinate;
 import com.vividsolutions.jts.geom.Geometry;
+import com.vividsolutions.jts.geom.Point;
+import com.vividsolutions.jts.geom.Polygon;
 
-public class SimpleGeoJcrMapper implements GeoJcrMapper {
+/** Maps geographical information meta data in a JCR repository. */
+public class SimpleGeoJcrMapper implements GeoJcrMapper, GisNames {
        private final static Log log = LogFactory.getLog(SimpleGeoJcrMapper.class);
 
-       private String dataStoresBasePath = "/gis/dataStores";
-
        private Map<String, DataStore> registeredDataStores = Collections
                        .synchronizedSortedMap(new TreeMap<String, DataStore>());
 
-       // private Session session;
+       private Session systemSession;
+
+       public void init() throws RepositoryException {
+       }
+
+       public void dispose() {
+               if (systemSession != null)
+                       systemSession.logout();
+       }
 
        public Map<String, List<FeatureSource<SimpleFeatureType, SimpleFeature>>> getPossibleFeatureSources() {
                Map<String, List<FeatureSource<SimpleFeatureType, SimpleFeature>>> res = new TreeMap<String, List<FeatureSource<SimpleFeatureType, SimpleFeature>>>();
@@ -102,16 +116,46 @@ public class SimpleGeoJcrMapper implements GeoJcrMapper {
                                Node featureNode = featureSourceNode.addNode(featureId);
                                featureNode.addMixin(GisTypes.GIS_FEATURE);
                                Geometry geometry = (Geometry) feature.getDefaultGeometry();
-                               featureNode.setProperty(GisNames.GIS_SRS, featureSource
-                                               .getSchema().getCoordinateReferenceSystem().getName()
-                                               .toString());
 
+                               // SRS
+                               String srs;
+                               CoordinateReferenceSystem crs = featureSource.getSchema()
+                                               .getCoordinateReferenceSystem();
+                               try {
+                                       Integer epsgCode = CRS.lookupEpsgCode(crs, false);
+                                       if (epsgCode != null)
+                                               srs = "EPSG:" + epsgCode;
+                                       else
+                                               srs = crs.toWKT();
+                               } catch (FactoryException e) {
+                                       log.warn("Cannot lookup EPSG code", e);
+                                       srs = crs.toWKT();
+                               }
+                               featureNode.setProperty(GIS_SRS, srs);
+
+                               Polygon bboxPolygon;
+                               Geometry envelope = geometry.getEnvelope();
+                               if (envelope instanceof Point) {
+                                       Point pt = (Point) envelope;
+                                       Coordinate[] coords = new Coordinate[4];
+                                       for (int i = 0; i < coords.length; i++)
+                                               coords[i] = pt.getCoordinate();
+                                       bboxPolygon = JtsJcrUtils.getGeometryFactory()
+                                                       .createPolygon(
+                                                                       JtsJcrUtils.getGeometryFactory()
+                                                                                       .createLinearRing(coords), null);
+                               } else if (envelope instanceof Polygon) {
+                                       bboxPolygon = (Polygon) envelope;
+                               } else {
+                                       throw new ArgeoException("Unsupported envelope format "
+                                                       + envelope.getClass());
+                               }
                                bbox = JtsJcrUtils.writeWkb(featureNode.getSession(),
-                                               geometry.getEnvelope());
-                               featureNode.setProperty(GisNames.GIS_BBOX, bbox);
+                                               bboxPolygon);
+                               featureNode.setProperty(GIS_BBOX, bbox);
                                centroid = JtsJcrUtils.writeWkb(featureNode.getSession(),
                                                geometry.getCentroid());
-                               featureNode.setProperty(GisNames.GIS_CENTROID, centroid);
+                               featureNode.setProperty(GIS_CENTROID, centroid);
                                featureSourceNode.getSession().save();
                                return featureNode;
                        } else {
@@ -126,25 +170,21 @@ public class SimpleGeoJcrMapper implements GeoJcrMapper {
                }
        }
 
-       protected Node getNode(Session session, String dataStoreAlias) {
+       protected Node getDataStoreNode(Session session, String dataStoreAlias) {
                try {
-                       Node dataStores;
-                       if (!session.itemExists(dataStoresBasePath)) {
-                               dataStores = JcrUtils.mkdirs(session, dataStoresBasePath);
-                               dataStores.getSession().save();
-                       } else
-                               dataStores = session.getNode(dataStoresBasePath);
-
-                       Node dataStoreNode;
-                       if (dataStores.hasNode(dataStoreAlias))
-                               dataStoreNode = dataStores.getNode(dataStoreAlias);
-                       else {
-                               dataStoreNode = dataStores.addNode(dataStoreAlias,
-                                               GisTypes.GIS_DATA_STORE);
-                               dataStoreNode.getSession().save();
-                       }
+                       // normalize by starting with a '/'
+                       String path = dataStoreAlias.startsWith("/") ? GisJcrConstants.DATA_STORES_BASE_PATH
+                                       + dataStoreAlias
+                                       : GisJcrConstants.DATA_STORES_BASE_PATH + '/'
+                                                       + dataStoreAlias;
+                       Node dataStoreNode = JcrUtils.mkdirs(session, path,
+                                       GisTypes.GIS_DATA_STORE);
+                       dataStoreNode.setProperty(GIS_ALIAS, dataStoreAlias);
+                       if (session.hasPendingChanges())
+                               session.save();
                        return dataStoreNode;
                } catch (RepositoryException e) {
+                       JcrUtils.discardQuietly(session);
                        throw new ArgeoException("Cannot get node for data store "
                                        + dataStoreAlias, e);
                }
@@ -153,12 +193,14 @@ public class SimpleGeoJcrMapper implements GeoJcrMapper {
        public Node getFeatureSourceNode(Session session, String dataStoreAlias,
                        FeatureSource<SimpleFeatureType, SimpleFeature> featureSource) {
                try {
-                       String name = featureSource.getName().toString();
-                       Node dataStoreNode = getNode(session, dataStoreAlias);
-                       if (dataStoreNode.hasNode(name))
-                               return dataStoreNode.getNode(name);
+                       // String name = featureSource.getName().toString();
+                       Name name = featureSource.getName();
+                       String nodeName = name.getLocalPart();
+                       Node dataStoreNode = getDataStoreNode(session, dataStoreAlias);
+                       if (dataStoreNode.hasNode(nodeName))
+                               return dataStoreNode.getNode(nodeName);
                        else {
-                               Node featureSourceNode = dataStoreNode.addNode(name);
+                               Node featureSourceNode = dataStoreNode.addNode(nodeName);
                                featureSourceNode.addMixin(GisTypes.GIS_FEATURE_SOURCE);
                                featureSourceNode.getSession().save();
                                return featureSourceNode;
@@ -176,11 +218,14 @@ public class SimpleGeoJcrMapper implements GeoJcrMapper {
                try {
                        Node dataStoreNode = node.getParent();
                        // TODO: check a dataStore type
-                       if (!registeredDataStores.containsKey(dataStoreNode.getName()))
+                       if (!dataStoreNode.hasProperty(GIS_ALIAS))
+                               throw new ArgeoException("Data store " + dataStoreNode
+                                               + " is not active.");
+                       String alias = dataStoreNode.getProperty(GIS_ALIAS).getString();
+                       if (!registeredDataStores.containsKey(alias))
                                throw new ArgeoException("No data store registered under "
                                                + dataStoreNode);
-                       DataStore dataStore = registeredDataStores.get(dataStoreNode
-                                       .getName());
+                       DataStore dataStore = registeredDataStores.get(alias);
                        return dataStore.getFeatureSource(node.getName());
                } catch (Exception e) {
                        throw new ArgeoException("Cannot find feature source " + node, e);
@@ -192,30 +237,67 @@ public class SimpleGeoJcrMapper implements GeoJcrMapper {
                return null;
        }
 
-       public void register(DataStore dataStore, Map<String, String> properties) {
+       public synchronized void register(DataStore dataStore,
+                       Map<String, String> properties) {
                if (!properties.containsKey(GeoToolsConstants.ALIAS_KEY)) {
                        log.warn("Cannot register data store " + dataStore
                                        + " since it has no '" + GeoToolsConstants.ALIAS_KEY
                                        + "' property");
                        return;
                }
-               registeredDataStores.put(properties.get(GeoToolsConstants.ALIAS_KEY),
-                               dataStore);
+               String alias = properties.get(GeoToolsConstants.ALIAS_KEY);
+               Node dataStoreNode = getDataStoreNode(systemSession, alias);
+               try {
+                       dataStoreNode.setProperty(GIS_ALIAS, alias);
+
+                       // TODO synchronize namespace if registered
+                       for (Name name : dataStore.getNames()) {
+                               String sourceName = name.getLocalPart();
+                               if (!dataStoreNode.hasNode(sourceName)) {
+                                       Node featureSourceNode = dataStoreNode.addNode(sourceName);
+                                       featureSourceNode.addMixin(GisTypes.GIS_FEATURE_SOURCE);
+                               }
+                       }
+
+                       // TODO check feature sources which are registered but not available
+                       // anymore
+                       systemSession.save();
+                       registeredDataStores.put(alias, dataStore);
+                       JcrUtils.discardQuietly(systemSession);
+               } catch (Exception e) {
+                       throw new ArgeoException("Cannot register data store " + alias
+                                       + ", " + dataStore, e);
+               }
        }
 
-       public void unregister(DataStore dataStore, Map<String, String> properties) {
+       public synchronized void unregister(DataStore dataStore,
+                       Map<String, String> properties) {
                if (!properties.containsKey(GeoToolsConstants.ALIAS_KEY)) {
                        log.warn("Cannot unregister data store " + dataStore
                                        + " since it has no '" + GeoToolsConstants.ALIAS_KEY
                                        + "' property");
                        return;
                }
-               registeredDataStores
-                               .remove(properties.get(GeoToolsConstants.ALIAS_KEY));
+
+               if (!systemSession.isLive())
+                       return;
+
+               String alias = properties.get(GeoToolsConstants.ALIAS_KEY);
+               registeredDataStores.remove(alias);
+               Node dataStoreNode = getDataStoreNode(systemSession, alias);
+               try {
+                       dataStoreNode.getProperty(GIS_ALIAS).remove();
+                       systemSession.save();
+               } catch (RepositoryException e) {
+                       JcrUtils.discardQuietly(systemSession);
+                       throw new ArgeoException("Cannot unregister data store " + alias
+                                       + ", " + dataStore, e);
+               }
        }
 
-       // public void setSession(Session session) {
-       // this.session = session;
-       // }
+       /** Expects to own this session (will be logged out on dispose) */
+       public void setSystemSession(Session systemSession) {
+               this.systemSession = systemSession;
+       }
 
 }