gvsig-gdal / trunk / org.gvsig.gdal2 / org.gvsig.gdal2.prov / org.gvsig.gdal2.prov.ogr / src / main / java / org / gvsig / gdal / prov / ogr / OGRDataExplorer.java @ 368
History | View | Annotate | Download (17 KB)
1 | 368 | jjdelcerro | /**
|
---|---|---|---|
2 | * gvSIG. Desktop Geographic Information System.
|
||
3 | *
|
||
4 | * Copyright ? 2007-2016 gvSIG Association
|
||
5 | *
|
||
6 | * This program is free software; you can redistribute it and/or
|
||
7 | * modify it under the terms of the GNU General Public License
|
||
8 | * as published by the Free Software Foundation; either version 2
|
||
9 | * of the License, or (at your option) any later version.
|
||
10 | *
|
||
11 | * This program is distributed in the hope that it will be useful,
|
||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
14 | * GNU General Public License for more details.
|
||
15 | *
|
||
16 | * You should have received a copy of the GNU General Public License
|
||
17 | * along with this program; if not, write to the Free Software
|
||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||
19 | * MA 02110-1301, USA.
|
||
20 | *
|
||
21 | * For any additional information, do not hesitate to contact us
|
||
22 | * at info AT gvsig.com, or visit our website www.gvsig.com.
|
||
23 | */
|
||
24 | package org.gvsig.gdal.prov.ogr; |
||
25 | |||
26 | import java.io.File; |
||
27 | import java.util.ArrayList; |
||
28 | import java.util.List; |
||
29 | |||
30 | import org.apache.commons.lang3.StringUtils; |
||
31 | import org.cresques.cts.ICRSFactory; |
||
32 | import org.cresques.cts.IProjection; |
||
33 | import org.gdal.ogr.DataSource; |
||
34 | import org.gdal.ogr.FieldDefn; |
||
35 | import org.gdal.ogr.GeomFieldDefn; |
||
36 | import org.gdal.ogr.Layer; |
||
37 | import org.gdal.ogr.ogr; |
||
38 | import org.gdal.ogr.ogrConstants; |
||
39 | import org.gdal.osr.SpatialReference; |
||
40 | import org.gvsig.fmap.dal.DALLocator; |
||
41 | import org.gvsig.fmap.dal.DataManager; |
||
42 | import org.gvsig.fmap.dal.DataServerExplorerParameters; |
||
43 | import org.gvsig.fmap.dal.DataStoreParameters; |
||
44 | import org.gvsig.fmap.dal.NewDataStoreParameters; |
||
45 | import org.gvsig.fmap.dal.exception.DataException; |
||
46 | import org.gvsig.fmap.dal.exception.InitializeException; |
||
47 | import org.gvsig.fmap.dal.exception.ReadRuntimeException; |
||
48 | import org.gvsig.fmap.dal.feature.EditableFeatureType; |
||
49 | import org.gvsig.fmap.dal.resource.ResourceAction; |
||
50 | import org.gvsig.fmap.dal.resource.file.FileResource; |
||
51 | import org.gvsig.fmap.dal.resource.spi.ResourceConsumer; |
||
52 | import org.gvsig.fmap.dal.resource.spi.ResourceManagerProviderServices; |
||
53 | import org.gvsig.fmap.dal.resource.spi.ResourceProvider; |
||
54 | import org.gvsig.fmap.dal.spi.AbstractDataServerExplorer; |
||
55 | import org.gvsig.fmap.dal.spi.DataServerExplorerProvider; |
||
56 | import org.gvsig.fmap.dal.spi.DataServerExplorerProviderServices; |
||
57 | import org.gvsig.tools.dynobject.DynField; |
||
58 | import org.slf4j.Logger; |
||
59 | import org.slf4j.LoggerFactory; |
||
60 | |||
61 | /**
|
||
62 | *
|
||
63 | * @author <a href="mailto:lmarques@disid.com">Lluis Marques</a>
|
||
64 | *
|
||
65 | */
|
||
66 | public class OGRDataExplorer extends AbstractDataServerExplorer implements DataServerExplorerProvider, ResourceConsumer { |
||
67 | |||
68 | private static final Logger LOG = LoggerFactory.getLogger(OGRDataExplorer.class); |
||
69 | |||
70 | /**
|
||
71 | *
|
||
72 | */
|
||
73 | public static final String NAME = "OGRDataExplorer"; |
||
74 | |||
75 | private DataServerExplorerProviderServices providerServives;
|
||
76 | protected OGRDataExplorerParameters parameters;
|
||
77 | |||
78 | private ResourceProvider resourceProvider;
|
||
79 | |||
80 | protected DataSource dataSource; |
||
81 | |||
82 | protected Boolean updateSupport; |
||
83 | |||
84 | private List<Layer> layerList; |
||
85 | |||
86 | /**
|
||
87 | * @param parameters
|
||
88 | * Parameters to open data explorer.
|
||
89 | * @param providerServices
|
||
90 | * Available services
|
||
91 | * @throws InitializeException
|
||
92 | * If there is some error initializing this store provider
|
||
93 | */
|
||
94 | public OGRDataExplorer(OGRDataExplorerParameters parameters,
|
||
95 | DataServerExplorerProviderServices providerServices) throws InitializeException {
|
||
96 | super(parameters, providerServices);
|
||
97 | this.providerServives = providerServices;
|
||
98 | this.parameters = parameters;
|
||
99 | |||
100 | getResourceProvider().addConsumer(this);
|
||
101 | } |
||
102 | |||
103 | private ResourceProvider getResourceProvider() {
|
||
104 | if (this.resourceProvider == null) { |
||
105 | ResourceManagerProviderServices manager = |
||
106 | (ResourceManagerProviderServices) DALLocator.getResourceManager(); |
||
107 | |||
108 | if (StringUtils.isBlank(parameters.getConnectionString())) {
|
||
109 | try {
|
||
110 | this.resourceProvider =
|
||
111 | (FileResource) manager.createAddResource(FileResource.NAME, |
||
112 | new Object[] { this.parameters.getFile().getAbsolutePath() }); |
||
113 | } catch (InitializeException e) {
|
||
114 | throw new ReadRuntimeException(getProviderName(), e); |
||
115 | } |
||
116 | } else {
|
||
117 | try {
|
||
118 | this.resourceProvider =
|
||
119 | (OGRResource) manager.createAddResource(OGRResource.NAME, |
||
120 | new Object[] { this.parameters.getConnectionString() }); |
||
121 | } catch (InitializeException e) {
|
||
122 | throw new ReadRuntimeException(getProviderName(), e); |
||
123 | } |
||
124 | } |
||
125 | } |
||
126 | return this.resourceProvider; |
||
127 | } |
||
128 | |||
129 | protected synchronized DataSource getDataSource() throws OGRUnsupportedFormatException { |
||
130 | if (this.dataSource == null) { |
||
131 | // Prioritize connection string over file
|
||
132 | if (StringUtils.isNotBlank(this.parameters.getConnectionString())) { |
||
133 | // Trying to open in update mode
|
||
134 | this.dataSource = ogr.Open(this.parameters.getConnectionString(), 1); |
||
135 | |||
136 | if (this.dataSource == null) { |
||
137 | this.dataSource = ogr.Open(this.parameters.getConnectionString()); |
||
138 | updateSupport = false;
|
||
139 | } else {
|
||
140 | updateSupport = true;
|
||
141 | } |
||
142 | |||
143 | } else if (this.parameters.getFile() != null && this.parameters.getFile().exists()) { |
||
144 | |||
145 | // Trying to open in update mode
|
||
146 | this.dataSource = ogr.Open(this.parameters.getFile().getAbsolutePath(), 1); |
||
147 | |||
148 | if (this.dataSource == null) { |
||
149 | this.dataSource = ogr.Open(this.parameters.getFile().getAbsolutePath()); |
||
150 | updateSupport = false;
|
||
151 | } else {
|
||
152 | updateSupport = true;
|
||
153 | } |
||
154 | |||
155 | } else {
|
||
156 | throw new IllegalStateException( |
||
157 | "Invalid parameters. Connection string must not be blank or file must exists");
|
||
158 | } |
||
159 | } |
||
160 | |||
161 | if (this.dataSource == null) { |
||
162 | |||
163 | if (StringUtils.isNotBlank(this.parameters.getConnectionString())) { |
||
164 | throw new OGRUnsupportedFormatException(this.parameters.getConnectionString()); |
||
165 | } |
||
166 | } |
||
167 | |||
168 | return this.dataSource; |
||
169 | } |
||
170 | |||
171 | @SuppressWarnings("unchecked") |
||
172 | protected List<Layer> getLayerList() { |
||
173 | if (this.layerList == null) { |
||
174 | this.layerList = (List<Layer>) getResourceProvider().execute(new ResourceAction() { |
||
175 | |||
176 | @Override
|
||
177 | public Object run() throws Exception { |
||
178 | List<Layer> layers = new ArrayList<Layer>(); |
||
179 | |||
180 | for (int i = 0; i < getDataSource().GetLayerCount(); i++) { |
||
181 | layers.add(getDataSource().GetLayer(i)); |
||
182 | } |
||
183 | |||
184 | return layers;
|
||
185 | } |
||
186 | }); |
||
187 | } |
||
188 | return this.layerList; |
||
189 | } |
||
190 | |||
191 | private Boolean hasUpdateSupport() throws OGRUnsupportedFormatException { |
||
192 | if (this.updateSupport == null) { |
||
193 | // Open data source to check update support of driver
|
||
194 | getDataSource(); |
||
195 | } |
||
196 | return this.updateSupport; |
||
197 | } |
||
198 | |||
199 | @Override
|
||
200 | public String getProviderName() { |
||
201 | return NAME;
|
||
202 | } |
||
203 | |||
204 | @Override
|
||
205 | public boolean canAdd() { |
||
206 | |||
207 | return (boolean) getResourceProvider().execute(new ResourceAction() { |
||
208 | |||
209 | @Override
|
||
210 | public Object run() throws Exception { |
||
211 | return getDataSource().TestCapability(ogrConstants.ODsCCreateLayer)
|
||
212 | && getDataSource().TestCapability(ogrConstants.ODsCDeleteLayer) |
||
213 | && hasUpdateSupport(); |
||
214 | } |
||
215 | }); |
||
216 | } |
||
217 | |||
218 | @Override
|
||
219 | public boolean canAdd(String storeName) throws DataException { |
||
220 | return getDataStoreProviderNames().contains(storeName) && canAdd();
|
||
221 | } |
||
222 | |||
223 | @SuppressWarnings("rawtypes") |
||
224 | @Override
|
||
225 | public List list() throws DataException { |
||
226 | return list(MODE_ALL);
|
||
227 | } |
||
228 | |||
229 | @SuppressWarnings("rawtypes") |
||
230 | @Override
|
||
231 | public List list(int mode) throws DataException { |
||
232 | List<Layer> layerList = getLayerList();
|
||
233 | DataManager dataManager = DALLocator.getDataManager(); |
||
234 | |||
235 | List<OGRDataStoreParameters> parametersList = new ArrayList<OGRDataStoreParameters>(); |
||
236 | for (Layer layer : layerList) {
|
||
237 | |||
238 | OGRDataStoreParameters storeParameters = |
||
239 | (OGRDataStoreParameters) dataManager.createStoreParameters(OGRDataStoreProvider.NAME); |
||
240 | String connectionString = this.parameters.getConnectionString(); |
||
241 | File file = this.parameters.getFile(); |
||
242 | storeParameters.setConnectionString(connectionString); |
||
243 | storeParameters.setFile(file); |
||
244 | storeParameters.setLayerName(layer.GetName()); |
||
245 | parametersList.add(storeParameters); |
||
246 | } |
||
247 | return parametersList;
|
||
248 | } |
||
249 | |||
250 | @Override
|
||
251 | public boolean add(String provider, final NewDataStoreParameters parameters, |
||
252 | final boolean overwrite) throws DataException { |
||
253 | |||
254 | if (canAdd()) {
|
||
255 | |||
256 | return (boolean) getResourceProvider().execute(new ResourceAction() { |
||
257 | |||
258 | @Override
|
||
259 | public Object run() throws Exception { |
||
260 | |||
261 | if (parameters instanceof OGRNewDataStoreParameters) { |
||
262 | OGRNewDataStoreParameters ogrParameters = |
||
263 | (OGRNewDataStoreParameters) parameters; |
||
264 | |||
265 | String layerName = ogrParameters.getLayerName();
|
||
266 | if (overwrite) {
|
||
267 | for (int i = 0; i < getLayerList().size(); i++) { |
||
268 | if (getLayerList().get(i).GetName().equals(layerName)) {
|
||
269 | getDataSource().DeleteLayer(i); |
||
270 | } |
||
271 | } |
||
272 | } else {
|
||
273 | for (Layer layer : getLayerList()) {
|
||
274 | if (layer.GetName().equals(layerName)) {
|
||
275 | return false; |
||
276 | } |
||
277 | } |
||
278 | } |
||
279 | |||
280 | EditableFeatureType editableFeatureType = |
||
281 | ogrParameters.getDefaultFeatureType(); |
||
282 | |||
283 | OGRConverter converter = new OGRConverter();
|
||
284 | |||
285 | // If SRS is defined convert it to spatial reference
|
||
286 | IProjection projection = editableFeatureType.getDefaultSRS(); |
||
287 | SpatialReference srs = null;
|
||
288 | if (projection != null) { |
||
289 | srs = new SpatialReference(projection.export(ICRSFactory.FORMAT_PROJ4));
|
||
290 | } |
||
291 | |||
292 | // Convert to geometry type to OGR Geometry type
|
||
293 | Integer ogrGeometryType = null; |
||
294 | if (editableFeatureType.getDefaultGeometryAttribute() != null) { |
||
295 | int geomType =
|
||
296 | editableFeatureType.getDefaultGeometryAttribute().getGeomType() |
||
297 | .getType(); |
||
298 | ogrGeometryType = converter.convertToOGRGeomType(geomType); |
||
299 | } |
||
300 | |||
301 | // Create layer
|
||
302 | Layer newlayer = null;
|
||
303 | if (srs == null) { |
||
304 | newlayer = getDataSource().CreateLayer(layerName); |
||
305 | } else if (ogrGeometryType == null && srs != null) { |
||
306 | newlayer = getDataSource().CreateLayer(layerName, srs); |
||
307 | } else if (ogrGeometryType != null && srs != null) { |
||
308 | newlayer = getDataSource().CreateLayer(layerName, srs, ogrGeometryType); |
||
309 | } |
||
310 | |||
311 | List<FieldDefn> fields =
|
||
312 | converter.convertFields(editableFeatureType.getNotEditableCopy()); |
||
313 | for (FieldDefn fieldDefn : fields) {
|
||
314 | newlayer.CreateField(fieldDefn); |
||
315 | } |
||
316 | |||
317 | List<GeomFieldDefn> geometryFields =
|
||
318 | converter.convertGeometryFields( |
||
319 | editableFeatureType.getNotEditableCopy(), false);
|
||
320 | for (GeomFieldDefn geomFieldDefn : geometryFields) {
|
||
321 | newlayer.CreateGeomField(geomFieldDefn); |
||
322 | } |
||
323 | return true; |
||
324 | } |
||
325 | return false; |
||
326 | } |
||
327 | }); |
||
328 | } |
||
329 | return false; |
||
330 | } |
||
331 | |||
332 | @Override
|
||
333 | public void remove(final DataStoreParameters parameters) throws DataException { |
||
334 | |||
335 | if (canAdd()) {
|
||
336 | |||
337 | getResourceProvider().execute(new ResourceAction() {
|
||
338 | |||
339 | @Override
|
||
340 | public Object run() throws Exception { |
||
341 | if (parameters instanceof OGRNewDataStoreParameters) { |
||
342 | OGRNewDataStoreParameters ogrParameters = |
||
343 | (OGRNewDataStoreParameters) parameters; |
||
344 | |||
345 | String layerName = ogrParameters.getLayerName();
|
||
346 | for (int i = 0; i < getLayerList().size(); i++) { |
||
347 | if (getLayerList().get(i).GetName().equals(layerName)) {
|
||
348 | getDataSource().DeleteLayer(i); |
||
349 | return true; |
||
350 | } |
||
351 | } |
||
352 | } |
||
353 | return false; |
||
354 | } |
||
355 | }); |
||
356 | } |
||
357 | } |
||
358 | |||
359 | @Override
|
||
360 | public NewDataStoreParameters getAddParameters(String storeName) throws DataException { |
||
361 | |||
362 | if (getDataStoreProviderNames().contains(storeName)) {
|
||
363 | OGRNewDataStoreParameters newParameters = new OGRNewDataStoreParameters();
|
||
364 | newParameters.setFile(this.parameters.getFile());
|
||
365 | newParameters.setConnectionString(this.parameters.getConnectionString());
|
||
366 | return newParameters;
|
||
367 | } |
||
368 | |||
369 | return null; |
||
370 | } |
||
371 | |||
372 | @Override
|
||
373 | public DataServerExplorerParameters getParameters() {
|
||
374 | return parameters;
|
||
375 | } |
||
376 | |||
377 | @SuppressWarnings("rawtypes") |
||
378 | @Override
|
||
379 | public List getDataStoreProviderNames() { |
||
380 | List<String> providerNames = new ArrayList<String>(); |
||
381 | providerNames.add(OGRDataStoreProvider.NAME); |
||
382 | return providerNames;
|
||
383 | } |
||
384 | |||
385 | @Override
|
||
386 | public void doDispose() { |
||
387 | |||
388 | try {
|
||
389 | getDataSource().SyncToDisk(); |
||
390 | getDataSource().delete(); |
||
391 | } catch (OGRUnsupportedFormatException e) {
|
||
392 | LOG.warn("Can not dispose OGRDataExplorer", e);
|
||
393 | } |
||
394 | |||
395 | this.dataSource = null; |
||
396 | this.layerList = null; |
||
397 | |||
398 | getResourceProvider().removeConsumer(this);
|
||
399 | this.resourceProvider = null; |
||
400 | } |
||
401 | |||
402 | @Override
|
||
403 | public DataServerExplorerProviderServices getServerExplorerProviderServices() {
|
||
404 | return providerServives;
|
||
405 | } |
||
406 | |||
407 | @Override
|
||
408 | public boolean closeResourceRequested(ResourceProvider resource) { |
||
409 | |||
410 | try {
|
||
411 | getDataSource().SyncToDisk(); |
||
412 | getDataSource().delete(); |
||
413 | } catch (OGRUnsupportedFormatException e) {
|
||
414 | LOG.warn(String.format("Can not close requested resource %1s", resource), e); |
||
415 | } |
||
416 | |||
417 | this.dataSource = null; |
||
418 | this.layerList = null; |
||
419 | return true; |
||
420 | } |
||
421 | |||
422 | @Override
|
||
423 | public void resourceChanged(ResourceProvider resource) { |
||
424 | |||
425 | try {
|
||
426 | getDataSource().SyncToDisk(); |
||
427 | getDataSource().delete(); |
||
428 | } catch (OGRUnsupportedFormatException e) {
|
||
429 | LOG.warn("Can not sync to disk or release native resources to reopen data source", e);
|
||
430 | } |
||
431 | |||
432 | this.dataSource = null; |
||
433 | this.layerList = null; |
||
434 | } |
||
435 | |||
436 | @Override
|
||
437 | public DataStoreParameters get(String name) throws DataException { |
||
438 | // "name" es un nombre de fichero sin path.
|
||
439 | |||
440 | // No tengo nada clara esta implementacion
|
||
441 | OGRDataStoreParameters params = new OGRDataStoreParameters();
|
||
442 | //
|
||
443 | // Copiamos los paramametros que se llamen igual entre el explorer y
|
||
444 | // el DataStoreParametes
|
||
445 | for( DynField field : params.getDynClass().getDynFields() ) {
|
||
446 | String fieldName = field.getName();
|
||
447 | if( parameters.hasDynValue(fieldName) ) {
|
||
448 | params.setDynValue(fieldName, parameters.getDynValue(fieldName)); |
||
449 | } |
||
450 | } |
||
451 | // Si el file es una carpeta asignamos como file el fichero name que haya
|
||
452 | // en ella
|
||
453 | // Si el file es un fichero cogemos el fichero name que se encuentre en
|
||
454 | // su misma carpeta.
|
||
455 | if( parameters.getFile().isDirectory() ) {
|
||
456 | params.setFile(new File(parameters.getFile(),name)); |
||
457 | } else {
|
||
458 | params.setFile(new File(parameters.getFile().getParentFile(),name)); |
||
459 | } |
||
460 | // Usamos como layer el nombre del fichero pasado como parametro.
|
||
461 | params.setLayerName(name); |
||
462 | return params;
|
||
463 | } |
||
464 | } |