Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.db / org.gvsig.fmap.dal.db.jdbc / src / main / java / org / gvsig / fmap / dal / store / jdbc2 / spi / JDBCStoreProviderBase.java @ 43408

History | View | Annotate | Download (17.8 KB)

1 43020 jjdelcerro
package org.gvsig.fmap.dal.store.jdbc2.spi;
2
3
import org.gvsig.fmap.dal.store.jdbc2.JDBCStoreProvider;
4
import java.util.Arrays;
5
import java.util.Collections;
6
import java.util.Iterator;
7
import java.util.List;
8 43361 jjdelcerro
import org.apache.commons.lang3.BooleanUtils;
9
import org.apache.commons.lang3.StringUtils;
10 43020 jjdelcerro
import org.cresques.cts.IProjection;
11
import org.gvsig.fmap.dal.DALLocator;
12
import org.gvsig.fmap.dal.DataManager;
13
import org.gvsig.fmap.dal.DataServerExplorer;
14
import org.gvsig.fmap.dal.DataStore;
15
import org.gvsig.fmap.dal.DataStoreNotification;
16
import org.gvsig.fmap.dal.DataTypes;
17
import org.gvsig.fmap.dal.exception.CloseException;
18
import org.gvsig.fmap.dal.exception.DataException;
19
import org.gvsig.fmap.dal.exception.InitializeException;
20
import org.gvsig.fmap.dal.exception.OpenException;
21
import org.gvsig.fmap.dal.exception.ReadException;
22
import org.gvsig.fmap.dal.feature.EditableFeatureType;
23
import org.gvsig.fmap.dal.feature.FeatureQuery;
24
import org.gvsig.fmap.dal.feature.FeatureRule;
25
import org.gvsig.fmap.dal.feature.FeatureRules;
26
import org.gvsig.fmap.dal.feature.FeatureType;
27
import org.gvsig.fmap.dal.feature.spi.AbstractFeatureStoreProvider;
28
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
29
import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices;
30
import org.gvsig.fmap.dal.feature.spi.FeatureSetProvider;
31
import org.gvsig.fmap.dal.resource.spi.ResourceConsumer;
32
import org.gvsig.fmap.dal.resource.spi.ResourceProvider;
33
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
34
//import org.gvsig.fmap.dal.store.jdbc2.JDBCServerExplorerBase;
35
import org.gvsig.fmap.dal.store.jdbc.JDBCServerExplorerParameters;
36
import org.gvsig.fmap.dal.store.jdbc.JDBCStoreParameters;
37
import org.gvsig.fmap.dal.store.jdbc2.JDBCHelper;
38
import org.gvsig.fmap.dal.store.jdbc2.JDBCUtils;
39
import org.gvsig.fmap.dal.store.jdbc2.OperationsFactory;
40
import org.gvsig.fmap.dal.store.jdbc2.ResulSetControler;
41
import org.gvsig.fmap.dal.store.jdbc2.impl.JDBCSetProvider;
42
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.AppendOperation;
43
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.CalculateEnvelopeOfColumnOperation;
44
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.CanModifyTableOperation;
45
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.CountOperation;
46
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.FetchFeatureProviderByReferenceOperation;
47
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.FetchFeatureTypeOperation;
48
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.PerformChangesOperation;
49
import org.gvsig.fmap.geom.primitive.Envelope;
50
import org.gvsig.tools.dynobject.DynObject;
51
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
52
import org.gvsig.tools.exception.BaseException;
53
import org.slf4j.Logger;
54
import org.slf4j.LoggerFactory;
55
56
public class JDBCStoreProviderBase
57
        extends AbstractFeatureStoreProvider
58
        implements ResourceConsumer, JDBCStoreProvider {
59
60
    final static private Logger logger = LoggerFactory.getLogger(JDBCStoreProviderBase.class);
61
62
    public class CountValue implements CalculatedValue<Long> {
63
64
        private Long value = null;
65
66
        @Override
67
        public void calculate() {
68
            JDBCStoreParameters params = getParameters();
69
            CountOperation count = getOperations().createCount(
70
                    params.getDBName(),
71
                    params.getSchema(),
72
                    params.getTable(),
73
                    params.getSQL(),
74
                    params.getBaseFilter(),
75
                    null
76
            );
77
            this.value = (Long) count.perform();
78
        }
79
80
        @Override
81
        public void reset() {
82
            this.value = null;
83
        }
84
85
        @Override
86
        public Long get() {
87
            if( this.value == null ) {
88
                this.calculate();
89
            }
90
            return this.value;
91
        }
92
    }
93
94
    public class EnvelopeValue implements CalculatedValue<Envelope> {
95
96
        private Envelope value = null;
97 43163 jjdelcerro
        private boolean needCalculate = true;
98 43020 jjdelcerro
99
        @Override
100
        public void calculate() {
101
            try {
102 43163 jjdelcerro
                value = null;
103 43020 jjdelcerro
                String columnName = getFeatureStore()
104
                        .getDefaultFeatureType()
105
                        .getDefaultGeometryAttributeName();
106 43163 jjdelcerro
                if( columnName==null ) {
107
                    return;
108
                }
109 43020 jjdelcerro
                IProjection crs = getFeatureStore()
110
                        .getDefaultFeatureType()
111
                        .getDefaultSRS();
112
                JDBCStoreParameters params = getParameters();
113
                CalculateEnvelopeOfColumnOperation calculateEnvelopeOfColumn =
114
                    getOperations().createCalculateEnvelopeOfColumn(
115
                        params.getSQL(),
116
                        params.getDBName(),
117
                        params.getSchema(),
118
                        params.getTable(),
119
                        columnName,
120
                        params.getBaseFilter(),
121
                        params.getWorkingArea(),
122
                        crs
123
                    );
124
                value = (Envelope) calculateEnvelopeOfColumn.perform();
125 43163 jjdelcerro
126 43020 jjdelcerro
            } catch(Exception ex) {
127
                throw new RuntimeException("Can't calculate envelope.", ex);
128 43163 jjdelcerro
            } finally {
129
               needCalculate = false;
130 43020 jjdelcerro
            }
131
        }
132
133
        @Override
134
        public void reset() {
135
            this.value = null;
136 43163 jjdelcerro
            this.needCalculate = true;
137 43020 jjdelcerro
        }
138
139
        @Override
140 43361 jjdelcerro
        public synchronized Envelope get() {
141 43163 jjdelcerro
            if( needCalculate ) {
142 43020 jjdelcerro
                this.calculate();
143
            }
144
            return this.value;
145
        }
146
    }
147 43163 jjdelcerro
148 43020 jjdelcerro
    public class AllowWriteValue implements CalculatedValue<Boolean> {
149
150
        private Boolean value = null;
151
152
        @Override
153
        public void calculate() {
154
            try {
155
                JDBCStoreParameters params = getParameters();
156
                CanModifyTableOperation canModifyTable =
157
                    getOperations().createCanModifyTableOperation(
158
                        params.getDBName(),
159
                        params.getSchema(),
160
                        params.getTable()
161
                    );
162
                this.value = (boolean) canModifyTable.perform();
163
            } catch(Exception ex) {
164
                throw new RuntimeException("Can't determine if allow write.", ex);
165
            }
166
        }
167
168
        @Override
169
        public void reset() {
170
            this.value = null;
171
        }
172
173
        @Override
174
        public Boolean get() {
175
            if( this.value == null ) {
176
                this.calculate();
177
            }
178
            return this.value;
179
        }
180
    }
181
182
    protected final JDBCHelper helper;
183
184
    protected CalculatedValue<Long> count = null;
185
186
    protected CalculatedValue<Envelope> envelope = null;
187
188
    protected CalculatedValue<Boolean> allowWrite = null;
189
190
    protected AppendOperation appendOperation = null;
191
192
    protected JDBCStoreProviderBase(
193
            JDBCStoreParameters params,
194
            DataStoreProviderServices storeServices,
195
            DynObject metadata,
196
            JDBCHelper helper
197
    ) throws InitializeException {
198
        super(params, storeServices, metadata);
199
        this.helper = helper;
200
        this.initializeFeatureType();
201 43361 jjdelcerro
        try {
202
            if( BooleanUtils.isTrue((Boolean) params.getDynValue("precalculateEnvelope"))  ) {
203
                FeatureType featureType = this.getStoreServices().getDefaultFeatureType();
204
                if( !StringUtils.isEmpty(featureType.getDefaultGeometryAttributeName()) ) {
205
                    Thread thread = new Thread(new Runnable() {
206
                        @Override
207
                        public void run() {
208
                            logger.debug("Precalculating envelope of '"+getSourceId()+"'.");
209
                            getEnvelopeValue().get();
210
                        }
211
                    }, "PrecalculateEnvelopeOfDBTable");
212
                    thread.start();
213
                    Thread.sleep(1);
214
                }
215
           }
216
        } catch(Exception ex) {
217
            logger.warn("Probems precalculating the envelope of table '"+this.getSourceId()+"'.", ex);
218
        }
219 43020 jjdelcerro
    }
220
221
222
    @Override
223 43088 jjdelcerro
    public JDBCSQLBuilderBase createExpression() {
224 43020 jjdelcerro
        return this.getHelper().createSQLBuilder();
225
    }
226
227
    @Override
228
    public JDBCStoreParameters getParameters() {
229
        return (JDBCStoreParameters) super.getParameters();
230
    }
231
232
    @Override
233
    public JDBCHelper getHelper() {
234
        return helper;
235
    }
236
237
    public OperationsFactory getOperations() {
238
        return this.getHelper().getOperations();
239
    }
240
241
    @Override
242
    public String getProviderName() {
243
        return this.getHelper().getProviderName();
244
    }
245
246
    @Override
247
    public int getOIDType() {
248
        return DataTypes.UNKNOWN;
249
    }
250
251
    @Override
252
    public Object createNewOID() {
253
        return null;
254
    }
255
256
    @Override
257
    public boolean allowAutomaticValues() {
258
        return this.getHelper().allowAutomaticValues();
259
    }
260
261
    @Override
262
    public boolean allowWrite() {
263
        return this.getAllowWriteValue().get();
264
    }
265
266
    @Override
267
    public Object getDynValue(String name) throws DynFieldNotFoundException {
268
        try {
269
            if (DataStore.METADATA_ENVELOPE.equalsIgnoreCase(name)) {
270
                Envelope env = this.getEnvelope();
271
                if (env != null) {
272
                    return env;
273
                }
274
            } else if (DataStore.METADATA_CRS.equalsIgnoreCase(name)) {
275
                IProjection proj;
276
                proj = this.getFeatureStore().getDefaultFeatureType().getDefaultSRS();
277
                if (proj != null) {
278
                    return proj;
279
                }
280
            }
281
        } catch (DataException e) {
282
            throw new RuntimeException(e);
283
        }
284
        return super.getDynValue(name);
285
    }
286
287
    @Override
288
    public CalculatedValue<Long> getCountValue() {
289
        if( this.count == null ) {
290
            this.count = new CountValue();
291
        }
292
        return this.count;
293
    }
294
295
    @Override
296
    public CalculatedValue<Envelope> getEnvelopeValue() {
297
        if( this.envelope == null ) {
298
            this.envelope = new EnvelopeValue();
299
        }
300
        return this.envelope;
301
    }
302
303
    @Override
304
    public CalculatedValue<Boolean> getAllowWriteValue() {
305
        if( this.allowWrite == null ) {
306
            this.allowWrite = new AllowWriteValue();
307
        }
308
        return this.allowWrite;
309
    }
310
311
    @Override
312
    public long getFeatureCount() throws DataException {
313
        return this.getCountValue().get();
314
    }
315
316
    @Override
317
    public boolean closeResourceRequested(ResourceProvider resource) {
318
        ResulSetControler resulSetControler = this.getHelper().getResulSetControler();
319
        resulSetControler.pack();
320
        return resulSetControler.getOpenCount() == 0;
321
    }
322
323
    @Override
324
    public void close() throws CloseException {
325
        JDBCUtils.closeQuietly(this.getHelper());
326
    }
327
328
    @Override
329
    public void resourceChanged(ResourceProvider resource) {
330
        this.getStoreServices().notifyChange(
331
                DataStoreNotification.RESOURCE_CHANGED,
332
                resource
333
        );
334
    }
335
336
    @Override
337
    public DataServerExplorer getExplorer() throws ReadException {
338
        DataManager manager = DALLocator.getDataManager();
339
        JDBCServerExplorerParameters exParams;
340
        JDBCStoreParameters params = getParameters();
341
        try {
342
            exParams = this.getHelper().createServerExplorerParameters();
343
            exParams.setHost(params.getHost());
344
            exParams.setPort(params.getPort());
345
            exParams.setDBName(params.getDBName());
346
            exParams.setUser(params.getUser());
347
            exParams.setPassword(params.getPassword());
348
            exParams.setUrl(params.getUrl());
349
            exParams.setCatalog(params.getCatalog());
350
            exParams.setSchema(params.getSchema());
351
            exParams.setJDBCDriverClassName(params.getJDBCDriverClassName());
352
353
            return manager.openServerExplorer(exParams.getExplorerName(), exParams);
354
        } catch (Exception e) {
355
            throw new ReadException(this.getProviderName(), e);
356
        }
357
    }
358
359
    @Override
360
    protected void doDispose() throws BaseException {
361
        this.close();
362
        this.getHelper().dispose();
363
        super.doDispose();
364
    }
365
366
    @Override
367
    public String getSourceId() {
368 43361 jjdelcerro
        try {
369
            return this.getHelper().getSourceId(this.getParameters());
370
        } catch(Exception ex) {
371
            return "unknow";
372
        }
373 43020 jjdelcerro
    }
374
375
    @Override
376
    public String getName() {
377 43397 jjdelcerro
        return this.getParameters().getTable();
378 43020 jjdelcerro
    }
379
380
    @Override
381
    public String getFullName() {
382
        return this.getHelper().getSourceId(this.getParameters());
383
    }
384
385
    @Override
386
    public ResourceProvider getResource() {
387
        return getHelper().getResource();
388
    }
389
390
    @Override
391
    public void open() throws OpenException {
392
393
    }
394
395
    @Override
396
    public FeatureSetProvider createSet(
397
            FeatureQuery query,
398
            FeatureType featureType
399
        ) throws DataException {
400
401
        FeatureSetProvider set = new JDBCSetProvider(
402
                this,
403
                this.getHelper(),
404
                query,
405
                featureType
406
        );
407
408
        return set;
409
    }
410
411
    protected void initializeFeatureType() {
412
        EditableFeatureType type = this.getStoreServices().createFeatureType(getName());
413
        JDBCStoreParameters params = this.getParameters();
414
        List<String> primaryKeys = null;
415
        if( params.getPkFields() != null ) {
416
            primaryKeys = Arrays.asList(params.getPkFields());
417
        }
418
        FetchFeatureTypeOperation fetchFeatureType =
419
             this.getOperations().createFetchFeatureType(
420
                type,
421
                params.getDBName(),
422
                params.getSchema(),
423
                params.getTable(),
424
                primaryKeys,
425
                params.getDefaultGeometryField(),
426
                params.getCRS()
427
            );
428
        fetchFeatureType.perform();
429
430
        FeatureType defaultType = type.getNotEditableCopy();
431
        List<FeatureType> types = Collections.singletonList(defaultType);
432
        this.getStoreServices().setFeatureTypes(types, defaultType);
433
    }
434
435
    @Override
436
    protected FeatureProvider internalGetFeatureProviderByReference(
437
            FeatureReferenceProviderServices reference,
438
            FeatureType featureType
439
        ) throws DataException {
440
        JDBCStoreParameters params = this.getParameters();
441
        FetchFeatureProviderByReferenceOperation fetchFeatureProviderByReference =
442
            this.getOperations().createFetchFeatureProviderByReference(
443
                reference,
444
                featureType,
445
                params.getDBName(),
446
                params.getSchema(),
447
                params.getTable()
448
            );
449
        FeatureProvider feature = (FeatureProvider) fetchFeatureProviderByReference.perform();
450
        return feature;
451
    }
452
453
    @Override
454
    public Envelope getEnvelope() throws DataException {
455
        return this.getEnvelopeValue().get();
456
    }
457
458
    @Override
459
    public void performChanges(Iterator deleteds, Iterator inserteds,
460
                    Iterator updateds, Iterator featureTypesChanged)
461
                    throws DataException {
462
463
        FeatureType type = this.getFeatureStore().getDefaultFeatureType();
464
        JDBCStoreParameters params = this.getParameters();
465
        PerformChangesOperation performChanges = this.getOperations().createPerformChanges(
466
                params.getDBName(),
467
                params.getSchema(),
468
                params.getTable(),
469
                type,
470
                deleteds,
471
                inserteds,
472
                updateds,
473
                featureTypesChanged
474
        );
475
        performChanges.perform();
476
        if( performChanges.isTypeChanged() ) {
477
            // Get rules before initializing feature type
478
            FeatureRules saved_rules = getFeatureStore().getDefaultFeatureType().getRules();
479
480
             // This initialization loses the feature type rules
481
            this.initializeFeatureType();
482
483
            // Get new feature type, clear rules and add the ones saved previously
484
            FeatureType featureType = getFeatureStore().getDefaultFeatureType();
485
            FeatureRules rules = featureType.getRules();
486
            rules.clear();
487
            for (FeatureRule rule : saved_rules) {
488
                rules.add(rule);
489
            }
490
        }
491
        this.getCountValue().reset();
492
        this.getEnvelopeValue().reset();
493
    }
494
495
    @Override
496
    public boolean supportsAppendMode() {
497
        return true;
498
    }
499
500
    protected AppendOperation getAppendOperation() throws DataException {
501
        if( this.appendOperation == null ) {
502
            FeatureType type = this.getFeatureStore().getDefaultFeatureType();
503
            JDBCStoreParameters params = this.getParameters();
504
            this.appendOperation = this.getOperations().createAppend(
505
                params.getDBName(),
506
                params.getSchema(),
507
                params.getTable(),
508
                type
509
            );
510
        }
511
        return this.appendOperation;
512
    }
513
514
    @Override
515
    public void endAppend() throws DataException {
516
        this.getAppendOperation().end();
517
    }
518
519
    @Override
520 43408 jjdelcerro
    public void abortAppend() throws DataException {
521
        this.getAppendOperation().abort();
522
    }
523
524
    @Override
525 43020 jjdelcerro
    public void beginAppend() throws DataException {
526
        this.getAppendOperation().begin();
527
    }
528
529
    @Override
530
    public void append(final FeatureProvider featureProvider) throws DataException {
531
        this.getAppendOperation().append(featureProvider);
532
    }
533
534
    @Override
535
    public boolean canWriteGeometry(int geometryType, int geometrySubtype)
536
            throws DataException {
537
        return this.getHelper().canWriteGeometry(geometryType,geometrySubtype);
538
    }
539
}