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 @ 46517

History | View | Annotate | Download (27.4 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2020 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 3
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.fmap.dal.store.jdbc2.spi;
25

    
26
import java.text.MessageFormat;
27
import java.util.Arrays;
28
import java.util.Collections;
29
import java.util.Iterator;
30
import java.util.List;
31
import org.apache.commons.lang3.BooleanUtils;
32
import org.apache.commons.lang3.StringUtils;
33
import org.cresques.cts.IProjection;
34
import org.gvsig.expressionevaluator.Expression;
35
import org.gvsig.fmap.dal.DALLocator;
36
import org.gvsig.fmap.dal.DataManager;
37
import org.gvsig.fmap.dal.DataServerExplorer;
38
import org.gvsig.fmap.dal.DataStore;
39
import org.gvsig.fmap.dal.DataStoreNotification;
40
import org.gvsig.fmap.dal.DataTypes;
41
import org.gvsig.fmap.dal.exception.CloseException;
42
import org.gvsig.fmap.dal.exception.DataException;
43
import org.gvsig.fmap.dal.exception.InitializeException;
44
import org.gvsig.fmap.dal.exception.OpenException;
45
import org.gvsig.fmap.dal.exception.ReadException;
46
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
47
import org.gvsig.fmap.dal.feature.EditableFeatureType;
48
import org.gvsig.fmap.dal.feature.FeatureQuery;
49
import org.gvsig.fmap.dal.feature.FeatureRule;
50
import org.gvsig.fmap.dal.feature.FeatureRules;
51
import org.gvsig.fmap.dal.feature.FeatureStore;
52
import org.gvsig.fmap.dal.feature.FeatureType;
53
import org.gvsig.fmap.dal.feature.spi.AbstractFeatureStoreProvider;
54
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
55
import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices;
56
import org.gvsig.fmap.dal.feature.spi.FeatureSetProvider;
57
import org.gvsig.fmap.dal.resource.ResourceParameters;
58
import org.gvsig.fmap.dal.resource.exception.AccessResourceException;
59
import org.gvsig.fmap.dal.resource.exception.ResourceException;
60
import org.gvsig.fmap.dal.resource.spi.AbstractResource;
61
import org.gvsig.fmap.dal.resource.spi.ResourceConsumer;
62
import org.gvsig.fmap.dal.resource.spi.ResourceProvider;
63
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
64
import org.gvsig.fmap.dal.spi.DataTransactionServices;
65
import org.gvsig.fmap.dal.store.jdbc.JDBCServerExplorerParameters;
66
import org.gvsig.fmap.dal.store.jdbc.JDBCStoreParameters;
67
import org.gvsig.fmap.dal.store.jdbc2.JDBCHelper;
68
import org.gvsig.fmap.dal.store.jdbc2.JDBCStoreProvider;
69
import org.gvsig.fmap.dal.store.jdbc2.JDBCUtils;
70
import org.gvsig.fmap.dal.store.jdbc2.OperationsFactory;
71
import org.gvsig.fmap.dal.store.jdbc2.ResulSetControler;
72
import org.gvsig.fmap.dal.store.jdbc2.impl.JDBCSetProvider;
73
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.AppendOperation;
74
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.CalculateEnvelopeOfColumnOperation;
75
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.CanModifyTableOperation;
76
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.CountOperation;
77
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.DeletePassThroughOperation;
78
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.FetchFeatureProviderByReferenceOperation;
79
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.FetchFeatureTypeOperation;
80
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.PerformChangesOperation;
81
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.UpdatePassThroughOperation;
82
import org.gvsig.fmap.geom.Geometry;
83
import org.gvsig.fmap.geom.primitive.Envelope;
84
import org.gvsig.tools.dynobject.DynField;
85
import org.gvsig.tools.dynobject.DynObject;
86
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
87
import org.gvsig.tools.exception.BaseException;
88
import org.gvsig.tools.observer.BaseNotification;
89
import org.gvsig.tools.observer.Observable;
90
import org.gvsig.tools.observer.Observer;
91
import org.slf4j.Logger;
92
import org.slf4j.LoggerFactory;
93

    
94
@SuppressWarnings("UseSpecificCatch")
95
public class JDBCStoreProviderBase
96
        extends AbstractFeatureStoreProvider
97
        implements ResourceConsumer, JDBCStoreProvider {
98

    
99
    final static protected Logger LOGGER = LoggerFactory.getLogger(JDBCStoreProviderBase.class);
100

    
101
    public class CountValue implements CalculatedValue<Long> {
102
        
103
        private Long value = null;
104

    
105
        @Override
106
        public void calculate() {
107
            try {
108
                JDBCStoreParameters params = getParameters();
109
                CountOperation count = getOperations().createCount(
110
                        getFeatureStore().getDefaultFeatureType(),
111
                        getOperations().createTableReference(params),
112
                        params.getBaseFilter(),
113
                        null
114
                );            
115
                this.value = (Long) count.perform();
116
            } catch (DataException ex) {
117
                throw new RuntimeException("Can't calculate count",ex);
118
            }
119
        }
120
        
121
        @Override
122
        public void reset() {
123
            this.value = null;
124
        }
125
        
126
        @Override
127
        public Long get() {
128
            if( this.value == null ) {
129
                this.calculate();
130
            }
131
            return this.value;
132
        }
133
    } 
134
    
135
    public class EnvelopeValue implements CalculatedValue<Envelope> {
136
        
137
        private Envelope value = null;
138
        private boolean needCalculate = true;
139

    
140
        @Override
141
        public void calculate() {
142
            FeatureStore featureStore;
143
            FeatureType featureType;
144
            try {
145
                featureStore = getFeatureStore();
146
                if (featureStore == null) {
147
                    return;
148
                }
149
                featureType = featureStore.getDefaultFeatureType();
150
                if (featureType == null) {
151
                    return;
152
                }
153
            } catch (Exception ex) {
154
                throw new RuntimeException("Can't calculate envelope.", ex);
155
            }
156
            try {
157
                value = null;
158
                String columnName = featureType.getDefaultGeometryAttributeName();
159
                if( columnName==null ) {
160
                    return;
161
                }
162
                IProjection crs = getFeatureStore()
163
                        .getDefaultFeatureType()
164
                        .getDefaultSRS();
165
                JDBCStoreParameters params = getParameters();
166
                CalculateEnvelopeOfColumnOperation calculateEnvelopeOfColumn = 
167
                    getOperations().createCalculateEnvelopeOfColumn(
168
                        getFeatureStore().getDefaultFeatureType(),
169
                        getOperations().createTableReference(params),
170
                        columnName, 
171
                        params.getBaseFilter(), 
172
                        params.getWorkingArea(), 
173
                        crs
174
                    );
175
                value = (Envelope) calculateEnvelopeOfColumn.perform();
176
                
177
            } catch(Throwable ex) {
178
                throw new RuntimeException("Can't calculate envelope.", ex);
179
            } finally {
180
               needCalculate = false;
181
            }
182
        }
183
        
184
        @Override
185
        public void reset() {
186
            this.value = null;
187
            this.needCalculate = true;
188
        }
189
        
190
        @Override
191
        public synchronized Envelope get() {
192
            if( needCalculate ) {
193
                this.calculate();
194
            }
195
            return this.value;
196
        }
197
    } 
198
        
199
    public class AllowWriteValue implements CalculatedValue<Boolean> {
200
        
201
        private Boolean value = null;
202

    
203
        @Override
204
        public void calculate() {
205
            try {
206
                JDBCStoreParameters params = getParameters();
207
                CanModifyTableOperation canModifyTable = 
208
                    getOperations().createCanModifyTableOperation(
209
                        getOperations().createTableReference(params)
210
                    );
211
                this.value = (boolean) canModifyTable.perform();
212
            } catch(Exception ex) {
213
                throw new RuntimeException("Can't determine if allow write.", ex);
214
            }
215
        }
216
        
217
        @Override
218
        public void reset() {
219
            this.value = null;
220
        }
221
        
222
        @Override
223
        public Boolean get() {
224
            if( this.value == null ) {
225
                this.calculate();
226
            }
227
            return this.value;
228
        }
229
    } 
230
    
231
    protected final JDBCHelper helper;
232

    
233
    protected CalculatedValue<Long> count = null;
234
    
235
    protected CalculatedValue<Envelope> envelope = null;
236

    
237
    protected CalculatedValue<Boolean> allowWrite = null;
238

    
239
    protected AppendOperation appendOperation = null;
240
    
241
    protected Observer transactionObserver;
242
    
243
    @SuppressWarnings({"OverridableMethodCallInConstructor", "CallToThreadStartDuringObjectConstruction"})
244
    protected JDBCStoreProviderBase(
245
            JDBCStoreParameters params,
246
            DataStoreProviderServices storeServices,
247
            DynObject metadata,
248
            JDBCHelper helper
249
    ) throws InitializeException {
250
        super(params, storeServices, metadata);
251
        this.helper = helper;
252
        this.initializeFeatureType();
253
        try {
254
            if( BooleanUtils.isTrue((Boolean) params.getDynValue("precalculateEnvelope"))  ) {
255
                FeatureType featureType = this.getStoreServices().getDefaultFeatureType();
256
                if( !StringUtils.isEmpty(featureType.getDefaultGeometryAttributeName()) ) {
257
                    Thread thread = new Thread(() -> {
258
                        LOGGER.trace("Precalculating envelope of '"+getSourceId()+"'.");
259
                        getEnvelopeValue().get();
260
                    }, "PrecalculateEnvelopeOfDBTable");
261
                    thread.start();
262
                    Thread.sleep(1);
263
                }
264
           }
265
        } catch(Exception ex) {
266
            LOGGER.warn("Probems precalculating the envelope of table '"+this.getSourceId()+"'.", ex);
267
        }
268
        this.transactionObserver = new Observer() {
269
            @Override
270
            public void update(Observable o, Object o1) {
271
                if( o1 instanceof BaseNotification && (
272
                        ((BaseNotification)o1).isOfType("ROLLBACK") ||
273
                        ((BaseNotification)o1).isOfType("COMMIT")
274
                        ) ) {
275
                    getCountValue().reset();
276
                    getEnvelopeValue().reset();
277
                }
278
            }
279
        };
280
    }
281

    
282
    @Override
283
    public JDBCStoreParameters getParameters() {
284
        return (JDBCStoreParameters) super.getParameters();
285
    }  
286

    
287
    @Override
288
    public JDBCHelper getHelper() {
289
        return helper;
290
    }
291
    
292
    public OperationsFactory getOperations() {
293
        return this.getHelper().getOperations();
294
    }
295
    
296
    @Override
297
    public String getProviderName() {
298
        return this.getHelper().getProviderName();
299
    }
300
    
301
    @Override
302
    public int getOIDType() {
303
        return DataTypes.UNKNOWN;
304
    }
305

    
306
    @Override
307
    public Object createNewOID() {
308
        return null;
309
    }
310
    
311
    @Override
312
    public boolean allowAutomaticValues() {
313
        return this.getHelper().allowAutomaticValues();
314
    }
315

    
316
    @Override
317
    public boolean allowWrite() {
318
        return this.getAllowWriteValue().get();
319
    }
320
    
321
    @Override
322
    public Object getDynValue(String name) throws DynFieldNotFoundException {
323
        try {
324
            if (DataStore.METADATA_ENVELOPE.equalsIgnoreCase(name)) {
325
                Envelope env = this.getEnvelope();
326
                if (env != null) {
327
                    return env;
328
                }
329
            } else if (DataStore.METADATA_CRS.equalsIgnoreCase(name)) {
330
                IProjection proj;
331
                proj = this.getFeatureStore().getDefaultFeatureType().getDefaultSRS();
332
                if (proj != null) {
333
                    return proj;
334
                }
335
            }
336
        } catch (DataException e) {
337
            throw new RuntimeException(e);
338
        }
339
        return super.getDynValue(name);
340
    }
341

    
342
    @Override
343
    public CalculatedValue<Long> getCountValue() {
344
        if( this.count == null ) {
345
            this.count = new CountValue();
346
        }
347
        return this.count;
348
    }
349

    
350
    @Override
351
    public CalculatedValue<Envelope> getEnvelopeValue() {
352
        if( this.envelope == null ) {
353
            this.envelope = new EnvelopeValue();
354
        }
355
        return this.envelope;
356
    }
357
    
358
    @Override
359
    public CalculatedValue<Boolean> getAllowWriteValue() {
360
        if( this.allowWrite == null ) {
361
            this.allowWrite = new AllowWriteValue();
362
        }
363
        return this.allowWrite;
364
    }
365
    
366
    @Override
367
    public long getFeatureCount() throws DataException {
368
        return this.getCountValue().get();
369
    }
370
    
371
    @Override
372
    public boolean closeResourceRequested(ResourceProvider resource) {
373
        ResulSetControler resulSetControler = this.getHelper().getResulSetControler();
374
        resulSetControler.pack();
375
        return resulSetControler.getOpenCount() == 0;
376
    }
377

    
378
    @Override
379
    public void close() throws CloseException {
380
        JDBCUtils.closeQuietly(this.getHelper());
381
    }
382

    
383
    @Override
384
    public void resourceChanged(ResourceProvider resource) {
385
        this.getStoreServices().notifyChange(
386
                DataStoreNotification.RESOURCE_CHANGED,
387
                resource
388
        );
389
    }
390

    
391
    @Override
392
    public DataServerExplorer getExplorer() throws ReadException {
393
        DataManager manager = DALLocator.getDataManager();
394
        JDBCServerExplorerParameters exParams;
395
        JDBCStoreParameters params = getParameters();
396
        try {
397
            exParams = this.getHelper().createServerExplorerParameters();
398
            DynField[] fields = exParams.getDynClass().getDynFields();
399
            for (DynField field : fields) {
400
                try {
401
                    exParams.setDynValue(field.getName(), params.getDynValue(field.getName()));
402
                } catch(Exception ex) {
403
                    // Ignore
404
                }
405
            }
406
            exParams.setHost(params.getHost());
407
            exParams.setPort(params.getPort());
408
            exParams.setDBName(params.getDBName());
409
            exParams.setUser(params.getUser());
410
            exParams.setPassword(params.getPassword());
411
            exParams.setUrl(params.getUrl());
412
            exParams.setCatalog(params.getCatalog());
413
            exParams.setSchema(params.getSchema());
414
            exParams.setJDBCDriverClassName(params.getJDBCDriverClassName());
415

    
416
            return manager.openServerExplorer(exParams.getExplorerName(), exParams);
417
        } catch (Exception e) {
418
            throw new ReadException(this.getProviderName(), e);
419
        }
420
    }
421

    
422
    @Override
423
    protected void doDispose() throws BaseException {
424
        if( this.helper.getTransaction()!=null ) {
425
            this.helper.getTransaction().deleteObserver(transactionObserver);
426
        }
427
        this.close();
428
        this.getHelper().dispose();
429
        super.doDispose();
430
    }
431

    
432
    @Override
433
    public String getSourceId() {
434
        try {
435
            return this.getHelper().getSourceId(this.getParameters());
436
        } catch(Exception ex) {
437
            return "unknow";
438
        }
439
    }
440

    
441
    @Override
442
    public String getName() {
443
        return this.getParameters().getTable();
444
    }
445

    
446
    @Override
447
    public String getFullName() {
448
        return this.getHelper().getSourceId(this.getParameters());
449
    }
450

    
451
    private static class DummyResource extends AbstractResource {
452

    
453
        private final String name;
454

    
455
        DummyResource(String name) throws InitializeException {
456
            super((ResourceParameters)null);
457
            this.name = name;
458
        }
459
        
460
        @Override
461
        public String getName() throws AccessResourceException {
462
            return MessageFormat.format("DummyResource({0})",
463
                                new Object[] { this.name });
464
        }
465

    
466
        @Override
467
        public Object get() throws AccessResourceException {
468
            return null;
469
        }
470

    
471
        @Override
472
        public boolean isThis(ResourceParameters parameters) throws ResourceException {
473
            return true;
474
        }
475
        
476
    }
477
    
478
    @Override
479
    public ResourceProvider getResource() {
480
        ResourceProvider r = getHelper().getResource();
481
        if( r == null ) {
482
            try {
483
                r = new DummyResource(this.getName());
484
            } catch (InitializeException ex) {
485
                LOGGER.warn("Can't create DummyResource",ex);
486
                // Do nothing
487
            }
488
        }
489
        return r;
490
    }
491

    
492
    @Override
493
    public void open() throws OpenException {
494

    
495
    }
496

    
497
    @Override
498
    public FeatureSetProvider createSet(
499
            FeatureQuery query,
500
            FeatureType featureType
501
        ) throws DataException {
502
        
503
        FeatureSetProvider set = new JDBCSetProvider(
504
                this,
505
                this.getHelper(), 
506
                query, 
507
                featureType
508
        );
509
        
510
        return set;
511
    }
512

    
513
    protected void initializeFeatureType() {
514
        EditableFeatureType type = this.getStoreServices().createFeatureType(getName());
515
        JDBCStoreParameters params = this.getParameters();
516
        List<String> primaryKeys = null;
517
        if( params.getPkFields() != null ) {
518
            primaryKeys = Arrays.asList(params.getPkFields());
519
        }
520
        FetchFeatureTypeOperation fetchFeatureType = 
521
             this.getOperations().createFetchFeatureType(
522
                type,
523
                this.getOperations().createTableReference(params),
524
                primaryKeys,
525
                params.getDefaultGeometryField(),
526
                params.getCRS(),
527
                params.getGeometryType(),
528
                params.getGeometrySubtype()
529
            );
530
        fetchFeatureType.perform();
531

    
532
        if (!StringUtils.isBlank(params.getDefaultGeometryField())) {
533
            if (!params.getDefaultGeometryField().equalsIgnoreCase(type.getDefaultGeometryAttributeName())) {
534
                if (type.getAttributeDescriptor(params.getDefaultGeometryField()) != null) {
535
                    type.setDefaultGeometryAttributeName(params.getDefaultGeometryField());
536
                } else {
537
                    type.setDefaultGeometryAttributeName(null);
538
                }
539
                if (type.getDefaultGeometryAttribute() != null) {
540
                    EditableFeatureAttributeDescriptor attr = (EditableFeatureAttributeDescriptor) type.getDefaultGeometryAttribute();
541
                    attr.setGeometryType(Geometry.TYPES.GEOMETRY, Geometry.SUBTYPES.GEOM2D);
542
                }
543
            } else {
544
                type.setDefaultGeometryAttributeName(null);
545
            }
546
        }
547
        
548
        FeatureType defaultType = type.getNotEditableCopy();
549
        this.getHelper().setProviderFeatureType(defaultType);
550
        List<FeatureType> types = Collections.singletonList(defaultType);
551
        this.getStoreServices().setFeatureTypes(types, defaultType);
552
    }
553

    
554
    @Override
555
    protected FeatureProvider internalGetFeatureProviderByReference(
556
            FeatureReferenceProviderServices reference, 
557
            FeatureType featureType
558
        ) throws DataException {
559
        JDBCStoreParameters params = this.getParameters();
560
        FetchFeatureProviderByReferenceOperation fetchFeatureProviderByReference = 
561
            this.getOperations().createFetchFeatureProviderByReference(
562
                reference, 
563
                featureType, 
564
                this.getOperations().createTableReference(params)
565
            );
566
        FeatureProvider feature = (FeatureProvider) fetchFeatureProviderByReference.perform();
567
        return feature;
568
    }
569
    
570
    @Override
571
    public Envelope getEnvelope() throws DataException {
572
        return this.getEnvelopeValue().get();
573
    }
574

    
575
    @Override
576
    public void performChanges(Iterator deleteds, Iterator inserteds,
577
                    Iterator updateds, Iterator featureTypesChanged)
578
                    throws DataException {
579

    
580
        FeatureType type = this.getFeatureStore().getDefaultFeatureType();
581
        JDBCStoreParameters params = this.getParameters();
582
        PerformChangesOperation performChanges = this.getOperations().createPerformChanges(
583
                this.getOperations().createTableReference(params),
584
                type, 
585
                deleteds, 
586
                inserteds, 
587
                updateds, 
588
                featureTypesChanged
589
        );
590
        performChanges.perform();
591
        if( performChanges.isTypeChanged() ) {
592
            // Get rules before initializing feature type
593
            FeatureRules saved_rules = getFeatureStore().getDefaultFeatureType().getRules();
594

    
595
             // This initialization loses the feature type rules
596
            this.initializeFeatureType();
597

    
598
            // Get new feature type, clear rules and add the ones saved previously
599
            FeatureType featureType = getFeatureStore().getDefaultFeatureType();
600
            FeatureRules rules = featureType.getRules();
601
            rules.clear();
602
            for (FeatureRule rule : saved_rules) {
603
                rules.add(rule);
604
            }
605
        }
606
        this.getCountValue().reset();
607
        this.getEnvelopeValue().reset();
608
    }    
609
    
610
    @Override
611
    public boolean supportsAppendMode() {
612
        return true;
613
    }
614

    
615
    protected AppendOperation createAppendOperation() throws DataException {
616
        FeatureType type = this.getFeatureStore().getDefaultFeatureType();
617
        JDBCStoreParameters params = this.getParameters();
618
        AppendOperation theAppendOperation = this.getOperations().createAppend(
619
                this.getOperations().createTableReference(params),
620
                type 
621
        );
622
        return theAppendOperation;
623
    }
624
    
625
    @Override
626
    public void endAppend() throws DataException {
627
        this.appendOperation.end();
628
        this.getCountValue().reset();
629
        this.getEnvelopeValue().reset();
630
    }
631

    
632
    @Override
633
    public void abortAppend() throws DataException {
634
        this.appendOperation.abort();
635
    }
636
    
637
    @Override
638
    public void beginAppend() throws DataException {
639
        if( this.appendOperation == null ) {
640
            this.appendOperation = createAppendOperation();
641
        }
642
        this.appendOperation.begin();
643
    }
644

    
645
    @Override
646
    public void append(final FeatureProvider featureProvider) throws DataException {
647
        this.appendOperation.append(featureProvider);
648
    }    
649
    
650
    @Override
651
    public boolean canWriteGeometry(int geometryType, int geometrySubtype)
652
            throws DataException {
653
        return this.getHelper().canWriteGeometry(geometryType,geometrySubtype);
654
    }
655

    
656
    @Override
657
    public boolean supportsPassThroughMode() {
658
        return true;
659
    }
660

    
661
    @Override
662
    public void passThroughInsert(FeatureProvider featureProvider) throws DataException {
663
        FeatureType type = this.getFeatureStore().getDefaultFeatureType();
664
        JDBCStoreParameters params = this.getParameters();
665
        PerformChangesOperation performChanges = this.getOperations().createPerformChanges(
666
                this.getOperations().createTableReference(params),
667
                type, 
668
                Collections.emptyIterator(), 
669
                Collections.singletonList(featureProvider).iterator(),
670
                Collections.emptyIterator(), 
671
                Collections.emptyIterator()
672
        );
673
        performChanges.perform();
674
        this.getCountValue().reset();
675
        this.getEnvelopeValue().reset();
676
    }
677

    
678
    @Override
679
    public void passThroughUpdate(FeatureProvider featureProvider) throws DataException {
680
        FeatureType type = this.getFeatureStore().getDefaultFeatureType();
681
        JDBCStoreParameters params = this.getParameters();
682
        PerformChangesOperation performChanges = this.getOperations().createPerformChanges(
683
                this.getOperations().createTableReference(params),
684
                type, 
685
                Collections.emptyIterator(), 
686
                Collections.emptyIterator(), 
687
                Collections.singletonList(featureProvider).iterator(),
688
                Collections.emptyIterator()
689
        );
690
        performChanges.perform();
691
//        this.getCountValue().reset();
692
        this.getEnvelopeValue().reset();
693
    }
694
    
695
    @Override
696
    public void passThroughUpdate(Object[] parameters, Expression filter){
697
        JDBCStoreParameters params = this.getParameters();
698
        UpdatePassThroughOperation operation = this.getOperations().createUpdatePassThroughOperation(
699
                this.getOperations().createTableReference(params),
700
                parameters,
701
                filter
702
        );
703
        operation.perform();
704
//        this.getCountValue().reset();
705
        this.getEnvelopeValue().reset();
706
    }
707

    
708
    @Override
709
    public void passThroughDelete(FeatureReferenceProviderServices featureReference) throws DataException {
710
        FeatureType type = this.getFeatureStore().getDefaultFeatureType();
711
        JDBCStoreParameters params = this.getParameters();
712
        PerformChangesOperation performChanges = this.getOperations().createPerformChanges(
713
                this.getOperations().createTableReference(params),
714
                type, 
715
                Collections.singletonList(featureReference).iterator(),
716
                Collections.emptyIterator(), 
717
                Collections.emptyIterator(), 
718
                Collections.emptyIterator()
719
        );
720
        performChanges.perform();
721
        this.getCountValue().reset();
722
        this.getEnvelopeValue().reset();
723
    }
724
    
725
    public void passThroughDelete(Expression expression) throws DataException {
726
        JDBCStoreParameters params = this.getParameters();
727
        DeletePassThroughOperation operation = this.getOperations().createDeletePassThroughOperation(
728
                this.getOperations().createTableReference(params),
729
                expression
730
        );
731
        operation.perform();
732
        this.getCountValue().reset();
733
        this.getEnvelopeValue().reset();
734
    }
735

    
736
    @Override
737
    public void setTransaction(DataTransactionServices transaction) {
738
        if( this.helper.getTransaction()!=null ) {
739
            this.helper.getTransaction().deleteObserver(transactionObserver);
740
        }
741
        this.helper.setTransaction(transaction);
742
        if( transaction!=null ) {
743
            transaction.addObserver(transactionObserver);
744
        }
745
    }
746
    
747
    @Override
748
    public String toString() {
749
        try {
750
            return String.format("%s %x %s", this.getClass().getSimpleName(), this.hashCode(), this.helper.toString());
751
        } catch (Exception e) {
752
            return super.toString();
753
        }
754
    }
755

    
756
    @Override
757
    public void refresh() throws OpenException {
758
        // Force to recalculare count, envelope and allowWrite
759
        this.count = null;
760
        this.envelope = null;
761
        this.allowWrite = null;
762
//        
763
//        if( this.helper.getResulSetControler().getOpenCount()>0 ) {
764
//            // Has ResultSetEntry open. Oh!!!!
765
//            this.helper.getResulSetControler().closeAll();
766
//        }
767
//        if( this.appendOperation!=null ) {
768
//            // Has and append operation in progress, Oh!!
769
//            this.appendOperation.abort();
770
//            this.appendOperation = null;
771
//        }
772
        super.refresh(); 
773
    }
774
    
775
}