1 package org
.argeo
.geotools
.jcr
;
3 import java
.io
.IOException
;
4 import java
.util
.ArrayList
;
5 import java
.util
.Collections
;
8 import java
.util
.TreeMap
;
10 import javax
.jcr
.Binary
;
11 import javax
.jcr
.Node
;
12 import javax
.jcr
.RepositoryException
;
13 import javax
.jcr
.Session
;
15 import org
.apache
.commons
.logging
.Log
;
16 import org
.apache
.commons
.logging
.LogFactory
;
17 import org
.argeo
.ArgeoException
;
18 import org
.argeo
.geotools
.GeoToolsConstants
;
19 import org
.argeo
.geotools
.GeoToolsUtils
;
20 import org
.argeo
.jcr
.JcrUtils
;
21 import org
.argeo
.jcr
.gis
.GisJcrConstants
;
22 import org
.argeo
.jcr
.gis
.GisNames
;
23 import org
.argeo
.jcr
.gis
.GisTypes
;
24 import org
.argeo
.jts
.jcr
.JtsJcrUtils
;
25 import org
.geotools
.data
.DataStore
;
26 import org
.geotools
.data
.FeatureSource
;
27 import org
.geotools
.referencing
.CRS
;
28 import org
.opengis
.feature
.simple
.SimpleFeature
;
29 import org
.opengis
.feature
.simple
.SimpleFeatureType
;
30 import org
.opengis
.feature
.type
.Name
;
31 import org
.opengis
.referencing
.FactoryException
;
32 import org
.opengis
.referencing
.crs
.CoordinateReferenceSystem
;
34 import com
.vividsolutions
.jts
.geom
.Coordinate
;
35 import com
.vividsolutions
.jts
.geom
.Geometry
;
36 import com
.vividsolutions
.jts
.geom
.Point
;
37 import com
.vividsolutions
.jts
.geom
.Polygon
;
39 /** Maps geographical information meta data in a JCR repository. */
40 public class SimpleGeoJcrMapper
implements GeoJcrMapper
, GisNames
{
41 private final static Log log
= LogFactory
.getLog(SimpleGeoJcrMapper
.class);
43 private Map
<String
, DataStore
> registeredDataStores
= Collections
44 .synchronizedSortedMap(new TreeMap
<String
, DataStore
>());
46 private Session systemSession
;
48 public void init() throws RepositoryException
{
51 public void dispose() {
52 if (systemSession
!= null)
53 systemSession
.logout();
56 public Map
<String
, List
<FeatureSource
<SimpleFeatureType
, SimpleFeature
>>> getPossibleFeatureSources() {
57 Map
<String
, List
<FeatureSource
<SimpleFeatureType
, SimpleFeature
>>> res
= new TreeMap
<String
, List
<FeatureSource
<SimpleFeatureType
, SimpleFeature
>>>();
58 dataStores
: for (String alias
: registeredDataStores
.keySet()) {
59 DataStore dataStore
= registeredDataStores
.get(alias
);
62 names
= dataStore
.getNames();
63 } catch (IOException e
) {
64 log
.warn("Cannot list features sources of data store " + alias
,
68 List
<FeatureSource
<SimpleFeatureType
, SimpleFeature
>> lst
= new ArrayList
<FeatureSource
<SimpleFeatureType
, SimpleFeature
>>();
69 for (Name name
: names
) {
71 lst
.add(dataStore
.getFeatureSource(name
));
72 } catch (IOException e
) {
73 if (log
.isTraceEnabled())
74 log
.trace("Skipping " + name
+ " of data store "
75 + alias
+ " because it is probably"
76 + " not a feature source", e
);
84 // public Node getNode(String dataStoreAlias,
85 // FeatureSource<SimpleFeatureType, SimpleFeature> featureSource,
86 // SimpleFeature feature) {
87 // StringBuffer pathBuf = new StringBuffer(dataStoresBasePath);
88 // pathBuf.append('/').append(dataStoreAlias);
89 // pathBuf.append('/').append(featureSource.getName());
91 // // TODO: use centroid or bbox to create some depth
92 // // Geometry geometry = (Geometry)feature.getDefaultGeometry();
93 // // Point centroid = geometry.getCentroid();
95 // pathBuf.append('/').append(feature.getID());
97 // String path = pathBuf.toString();
99 // if (session.itemExists(path))
100 // return session.getNode(path);
102 // return JcrUtils.mkdirs(session, path);
103 // } catch (RepositoryException e) {
104 // throw new ArgeoException("Cannot get feature node for " + path, e);
108 public Node
getFeatureNode(Node featureSourceNode
, String featureId
) {
110 Binary centroid
= null;
112 if (!featureSourceNode
.hasNode(featureId
)) {
113 FeatureSource
<SimpleFeatureType
, SimpleFeature
> featureSource
= getFeatureSource(featureSourceNode
);
114 SimpleFeature feature
= GeoToolsUtils
.querySingleFeature(
115 featureSource
, featureId
);
116 Node featureNode
= featureSourceNode
.addNode(featureId
);
117 featureNode
.addMixin(GisTypes
.GIS_FEATURE
);
118 Geometry geometry
= (Geometry
) feature
.getDefaultGeometry();
122 CoordinateReferenceSystem crs
= featureSource
.getSchema()
123 .getCoordinateReferenceSystem();
125 Integer epsgCode
= CRS
.lookupEpsgCode(crs
, false);
126 if (epsgCode
!= null)
127 srs
= "EPSG:" + epsgCode
;
130 } catch (FactoryException e
) {
131 log
.warn("Cannot lookup EPSG code", e
);
134 featureNode
.setProperty(GIS_SRS
, srs
);
137 Geometry envelope
= geometry
.getEnvelope();
138 if (envelope
instanceof Point
) {
139 Point pt
= (Point
) envelope
;
140 Coordinate
[] coords
= new Coordinate
[4];
141 for (int i
= 0; i
< coords
.length
; i
++)
142 coords
[i
] = pt
.getCoordinate();
143 bboxPolygon
= JtsJcrUtils
.getGeometryFactory()
145 JtsJcrUtils
.getGeometryFactory()
146 .createLinearRing(coords
), null);
147 } else if (envelope
instanceof Polygon
) {
148 bboxPolygon
= (Polygon
) envelope
;
150 throw new ArgeoException("Unsupported envelope format "
151 + envelope
.getClass());
153 bbox
= JtsJcrUtils
.writeWkb(featureNode
.getSession(),
155 featureNode
.setProperty(GIS_BBOX
, bbox
);
156 centroid
= JtsJcrUtils
.writeWkb(featureNode
.getSession(),
157 geometry
.getCentroid());
158 featureNode
.setProperty(GIS_CENTROID
, centroid
);
159 featureSourceNode
.getSession().save();
162 return featureSourceNode
.getNode(featureId
);
164 } catch (RepositoryException e
) {
165 throw new ArgeoException("Cannot get feature node for feature "
166 + featureId
+ " from " + featureSourceNode
, e
);
168 JcrUtils
.closeQuietly(bbox
);
169 JcrUtils
.closeQuietly(centroid
);
173 protected Node
getDataStoreNode(Session session
, String dataStoreAlias
) {
175 // normalize by starting with a '/'
176 String path
= dataStoreAlias
.startsWith("/") ? GisJcrConstants
.DATA_STORES_BASE_PATH
178 : GisJcrConstants
.DATA_STORES_BASE_PATH
+ '/'
180 Node dataStoreNode
= JcrUtils
.mkdirs(session
, path
,
181 GisTypes
.GIS_DATA_STORE
);
182 dataStoreNode
.setProperty(GIS_ALIAS
, dataStoreAlias
);
183 if (session
.hasPendingChanges())
185 return dataStoreNode
;
186 } catch (RepositoryException e
) {
187 JcrUtils
.discardQuietly(session
);
188 throw new ArgeoException("Cannot get node for data store "
189 + dataStoreAlias
, e
);
193 public Node
getFeatureSourceNode(Session session
, String dataStoreAlias
,
194 FeatureSource
<SimpleFeatureType
, SimpleFeature
> featureSource
) {
196 // String name = featureSource.getName().toString();
197 Name name
= featureSource
.getName();
198 String nodeName
= name
.getLocalPart();
199 Node dataStoreNode
= getDataStoreNode(session
, dataStoreAlias
);
200 if (dataStoreNode
.hasNode(nodeName
))
201 return dataStoreNode
.getNode(nodeName
);
203 Node featureSourceNode
= dataStoreNode
.addNode(nodeName
);
204 featureSourceNode
.addMixin(GisTypes
.GIS_FEATURE_SOURCE
);
205 featureSourceNode
.getSession().save();
206 return featureSourceNode
;
208 } catch (RepositoryException e
) {
209 throw new ArgeoException(
210 "Cannot get feature source node for data store "
211 + dataStoreAlias
+ " and feature source "
212 + featureSource
.getName(), e
);
216 public FeatureSource
<SimpleFeatureType
, SimpleFeature
> getFeatureSource(
219 Node dataStoreNode
= node
.getParent();
220 // TODO: check a dataStore type
221 if (!dataStoreNode
.hasProperty(GIS_ALIAS
))
222 throw new ArgeoException("Data store " + dataStoreNode
223 + " is not active.");
224 String alias
= dataStoreNode
.getProperty(GIS_ALIAS
).getString();
225 if (!registeredDataStores
.containsKey(alias
))
226 throw new ArgeoException("No data store registered under "
228 DataStore dataStore
= registeredDataStores
.get(alias
);
229 return dataStore
.getFeatureSource(node
.getName());
230 } catch (Exception e
) {
231 throw new ArgeoException("Cannot find feature source " + node
, e
);
235 public SimpleFeature
getFeature(Node node
) {
236 // TODO Auto-generated method stub
240 public synchronized void register(DataStore dataStore
,
241 Map
<String
, String
> properties
) {
242 if (!properties
.containsKey(GeoToolsConstants
.ALIAS_KEY
)) {
243 log
.warn("Cannot register data store " + dataStore
244 + " since it has no '" + GeoToolsConstants
.ALIAS_KEY
248 String alias
= properties
.get(GeoToolsConstants
.ALIAS_KEY
);
249 Node dataStoreNode
= getDataStoreNode(systemSession
, alias
);
251 dataStoreNode
.setProperty(GIS_ALIAS
, alias
);
253 // TODO synchronize namespace if registered
254 for (Name name
: dataStore
.getNames()) {
255 String sourceName
= name
.getLocalPart();
256 if (!dataStoreNode
.hasNode(sourceName
)) {
257 Node featureSourceNode
= dataStoreNode
.addNode(sourceName
);
258 featureSourceNode
.addMixin(GisTypes
.GIS_FEATURE_SOURCE
);
262 // TODO check feature sources which are registered but not available
264 systemSession
.save();
265 registeredDataStores
.put(alias
, dataStore
);
266 JcrUtils
.discardQuietly(systemSession
);
267 } catch (Exception e
) {
268 throw new ArgeoException("Cannot register data store " + alias
269 + ", " + dataStore
, e
);
273 public synchronized void unregister(DataStore dataStore
,
274 Map
<String
, String
> properties
) {
275 if (!properties
.containsKey(GeoToolsConstants
.ALIAS_KEY
)) {
276 log
.warn("Cannot unregister data store " + dataStore
277 + " since it has no '" + GeoToolsConstants
.ALIAS_KEY
282 if (!systemSession
.isLive())
285 String alias
= properties
.get(GeoToolsConstants
.ALIAS_KEY
);
286 registeredDataStores
.remove(alias
);
287 Node dataStoreNode
= getDataStoreNode(systemSession
, alias
);
289 dataStoreNode
.getProperty(GIS_ALIAS
).remove();
290 systemSession
.save();
291 } catch (RepositoryException e
) {
292 JcrUtils
.discardQuietly(systemSession
);
293 throw new ArgeoException("Cannot unregister data store " + alias
294 + ", " + dataStore
, e
);
298 /** Expects to own this session (will be logged out on dispose) */
299 public void setSystemSession(Session systemSession
) {
300 this.systemSession
= systemSession
;