]> git.argeo.org Git - lgpl/argeo-commons.git/blob - gis/runtime/org.argeo.gis.geotools/src/main/java/org/argeo/geotools/jcr/SimpleGeoJcrMapper.java
Improve GIS
[lgpl/argeo-commons.git] / gis / runtime / org.argeo.gis.geotools / src / main / java / org / argeo / geotools / jcr / SimpleGeoJcrMapper.java
1 package org.argeo.geotools.jcr;
2
3 import java.io.IOException;
4 import java.util.ArrayList;
5 import java.util.Collections;
6 import java.util.List;
7 import java.util.Map;
8 import java.util.TreeMap;
9
10 import javax.jcr.Binary;
11 import javax.jcr.Node;
12 import javax.jcr.RepositoryException;
13 import javax.jcr.Session;
14
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;
33
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;
38
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);
42
43 private Map<String, DataStore> registeredDataStores = Collections
44 .synchronizedSortedMap(new TreeMap<String, DataStore>());
45
46 private Session systemSession;
47
48 public void init() throws RepositoryException {
49 }
50
51 public void dispose() {
52 if (systemSession != null)
53 systemSession.logout();
54 }
55
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);
60 List<Name> names;
61 try {
62 names = dataStore.getNames();
63 } catch (IOException e) {
64 log.warn("Cannot list features sources of data store " + alias,
65 e);
66 continue dataStores;
67 }
68 List<FeatureSource<SimpleFeatureType, SimpleFeature>> lst = new ArrayList<FeatureSource<SimpleFeatureType, SimpleFeature>>();
69 for (Name name : names) {
70 try {
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);
77 }
78 }
79 res.put(alias, lst);
80 }
81 return res;
82 }
83
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());
90 //
91 // // TODO: use centroid or bbox to create some depth
92 // // Geometry geometry = (Geometry)feature.getDefaultGeometry();
93 // // Point centroid = geometry.getCentroid();
94 //
95 // pathBuf.append('/').append(feature.getID());
96 //
97 // String path = pathBuf.toString();
98 // try {
99 // if (session.itemExists(path))
100 // return session.getNode(path);
101 // else
102 // return JcrUtils.mkdirs(session, path);
103 // } catch (RepositoryException e) {
104 // throw new ArgeoException("Cannot get feature node for " + path, e);
105 // }
106 // }
107
108 public Node getFeatureNode(Node featureSourceNode, String featureId) {
109 Binary bbox = null;
110 Binary centroid = null;
111 try {
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();
119
120 // SRS
121 String srs;
122 CoordinateReferenceSystem crs = featureSource.getSchema()
123 .getCoordinateReferenceSystem();
124 try {
125 Integer epsgCode = CRS.lookupEpsgCode(crs, false);
126 if (epsgCode != null)
127 srs = "EPSG:" + epsgCode;
128 else
129 srs = crs.toWKT();
130 } catch (FactoryException e) {
131 log.warn("Cannot lookup EPSG code", e);
132 srs = crs.toWKT();
133 }
134 featureNode.setProperty(GIS_SRS, srs);
135
136 Polygon bboxPolygon;
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()
144 .createPolygon(
145 JtsJcrUtils.getGeometryFactory()
146 .createLinearRing(coords), null);
147 } else if (envelope instanceof Polygon) {
148 bboxPolygon = (Polygon) envelope;
149 } else {
150 throw new ArgeoException("Unsupported envelope format "
151 + envelope.getClass());
152 }
153 bbox = JtsJcrUtils.writeWkb(featureNode.getSession(),
154 bboxPolygon);
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();
160 return featureNode;
161 } else {
162 return featureSourceNode.getNode(featureId);
163 }
164 } catch (RepositoryException e) {
165 throw new ArgeoException("Cannot get feature node for feature "
166 + featureId + " from " + featureSourceNode, e);
167 } finally {
168 JcrUtils.closeQuietly(bbox);
169 JcrUtils.closeQuietly(centroid);
170 }
171 }
172
173 protected Node getDataStoreNode(Session session, String dataStoreAlias) {
174 try {
175 // normalize by starting with a '/'
176 String path = dataStoreAlias.startsWith("/") ? GisJcrConstants.DATA_STORES_BASE_PATH
177 + dataStoreAlias
178 : GisJcrConstants.DATA_STORES_BASE_PATH + '/'
179 + dataStoreAlias;
180 Node dataStoreNode = JcrUtils.mkdirs(session, path,
181 GisTypes.GIS_DATA_STORE);
182 dataStoreNode.setProperty(GIS_ALIAS, dataStoreAlias);
183 if (session.hasPendingChanges())
184 session.save();
185 return dataStoreNode;
186 } catch (RepositoryException e) {
187 JcrUtils.discardQuietly(session);
188 throw new ArgeoException("Cannot get node for data store "
189 + dataStoreAlias, e);
190 }
191 }
192
193 public Node getFeatureSourceNode(Session session, String dataStoreAlias,
194 FeatureSource<SimpleFeatureType, SimpleFeature> featureSource) {
195 try {
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);
202 else {
203 Node featureSourceNode = dataStoreNode.addNode(nodeName);
204 featureSourceNode.addMixin(GisTypes.GIS_FEATURE_SOURCE);
205 featureSourceNode.getSession().save();
206 return featureSourceNode;
207 }
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);
213 }
214 }
215
216 public FeatureSource<SimpleFeatureType, SimpleFeature> getFeatureSource(
217 Node node) {
218 try {
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 "
227 + dataStoreNode);
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);
232 }
233 }
234
235 public SimpleFeature getFeature(Node node) {
236 // TODO Auto-generated method stub
237 return null;
238 }
239
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
245 + "' property");
246 return;
247 }
248 String alias = properties.get(GeoToolsConstants.ALIAS_KEY);
249 Node dataStoreNode = getDataStoreNode(systemSession, alias);
250 try {
251 dataStoreNode.setProperty(GIS_ALIAS, alias);
252
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);
259 }
260 }
261
262 // TODO check feature sources which are registered but not available
263 // anymore
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);
270 }
271 }
272
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
278 + "' property");
279 return;
280 }
281
282 if (!systemSession.isLive())
283 return;
284
285 String alias = properties.get(GeoToolsConstants.ALIAS_KEY);
286 registeredDataStores.remove(alias);
287 Node dataStoreNode = getDataStoreNode(systemSession, alias);
288 try {
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);
295 }
296 }
297
298 /** Expects to own this session (will be logged out on dispose) */
299 public void setSystemSession(Session systemSession) {
300 this.systemSession = systemSession;
301 }
302
303 }