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

History | View | Annotate | Download (26 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.DataTransaction;
41
import org.gvsig.fmap.dal.DataTypes;
42
import org.gvsig.fmap.dal.exception.CloseException;
43
import org.gvsig.fmap.dal.exception.DataException;
44
import org.gvsig.fmap.dal.exception.InitializeException;
45
import org.gvsig.fmap.dal.exception.OpenException;
46
import org.gvsig.fmap.dal.exception.ReadException;
47
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
48
import org.gvsig.fmap.dal.feature.EditableFeatureType;
49
import org.gvsig.fmap.dal.feature.FeatureQuery;
50
import org.gvsig.fmap.dal.feature.FeatureRule;
51
import org.gvsig.fmap.dal.feature.FeatureRules;
52
import org.gvsig.fmap.dal.feature.FeatureStore;
53
import org.gvsig.fmap.dal.feature.FeatureType;
54
import org.gvsig.fmap.dal.feature.spi.AbstractFeatureStoreProvider;
55
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
56
import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices;
57
import org.gvsig.fmap.dal.feature.spi.FeatureSetProvider;
58
import org.gvsig.fmap.dal.resource.ResourceParameters;
59
import org.gvsig.fmap.dal.resource.exception.AccessResourceException;
60
import org.gvsig.fmap.dal.resource.exception.ResourceException;
61
import org.gvsig.fmap.dal.resource.spi.AbstractResource;
62
import org.gvsig.fmap.dal.resource.spi.ResourceConsumer;
63
import org.gvsig.fmap.dal.resource.spi.ResourceProvider;
64
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
65
import org.gvsig.fmap.dal.spi.DataTransactionServices;
66
import org.gvsig.fmap.dal.store.jdbc.JDBCServerExplorerParameters;
67
import org.gvsig.fmap.dal.store.jdbc.JDBCStoreParameters;
68
import org.gvsig.fmap.dal.store.jdbc2.JDBCHelper;
69
import org.gvsig.fmap.dal.store.jdbc2.JDBCStoreProvider;
70
import org.gvsig.fmap.dal.store.jdbc2.JDBCUtils;
71
import org.gvsig.fmap.dal.store.jdbc2.OperationsFactory;
72
import org.gvsig.fmap.dal.store.jdbc2.ResulSetControler;
73
import org.gvsig.fmap.dal.store.jdbc2.impl.JDBCSetProvider;
74
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.AppendOperation;
75
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.CalculateEnvelopeOfColumnOperation;
76
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.CanModifyTableOperation;
77
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.CountOperation;
78
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.DeletePassThroughOperation;
79
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.FetchFeatureProviderByReferenceOperation;
80
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.FetchFeatureTypeOperation;
81
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.PerformChangesOperation;
82
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.UpdatePassThroughOperation;
83
import org.gvsig.fmap.geom.Geometry;
84
import org.gvsig.fmap.geom.primitive.Envelope;
85
import org.gvsig.tools.dynobject.DynField;
86
import org.gvsig.tools.dynobject.DynObject;
87
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
88
import org.gvsig.tools.exception.BaseException;
89
import org.slf4j.Logger;
90
import org.slf4j.LoggerFactory;
91

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

    
97
    final static protected Logger LOGGER = LoggerFactory.getLogger(JDBCStoreProviderBase.class);
98

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

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

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

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

    
231
    protected CalculatedValue<Long> count = null;
232
    
233
    protected CalculatedValue<Envelope> envelope = null;
234

    
235
    protected CalculatedValue<Boolean> allowWrite = null;
236

    
237
    protected AppendOperation appendOperation = null;
238
    
239
    @SuppressWarnings({"OverridableMethodCallInConstructor", "CallToThreadStartDuringObjectConstruction"})
240
    protected JDBCStoreProviderBase(
241
            JDBCStoreParameters params,
242
            DataStoreProviderServices storeServices,
243
            DynObject metadata,
244
            JDBCHelper helper
245
    ) throws InitializeException {
246
        super(params, storeServices, metadata);
247
        this.helper = helper;
248
        this.initializeFeatureType();
249
        try {
250
            if( BooleanUtils.isTrue((Boolean) params.getDynValue("precalculateEnvelope"))  ) {
251
                FeatureType featureType = this.getStoreServices().getDefaultFeatureType();
252
                if( !StringUtils.isEmpty(featureType.getDefaultGeometryAttributeName()) ) {
253
                    Thread thread = new Thread(() -> {
254
                        LOGGER.trace("Precalculating envelope of '"+getSourceId()+"'.");
255
                        getEnvelopeValue().get();
256
                    }, "PrecalculateEnvelopeOfDBTable");
257
                    thread.start();
258
                    Thread.sleep(1);
259
                }
260
           }
261
        } catch(Exception ex) {
262
            LOGGER.warn("Probems precalculating the envelope of table '"+this.getSourceId()+"'.", ex);
263
        }
264
    }
265

    
266
    @Override
267
    public JDBCStoreParameters getParameters() {
268
        return (JDBCStoreParameters) super.getParameters();
269
    }  
270

    
271
    @Override
272
    public JDBCHelper getHelper() {
273
        return helper;
274
    }
275
    
276
    public OperationsFactory getOperations() {
277
        return this.getHelper().getOperations();
278
    }
279
    
280
    @Override
281
    public String getProviderName() {
282
        return this.getHelper().getProviderName();
283
    }
284
    
285
    @Override
286
    public int getOIDType() {
287
        return DataTypes.UNKNOWN;
288
    }
289

    
290
    @Override
291
    public Object createNewOID() {
292
        return null;
293
    }
294
    
295
    @Override
296
    public boolean allowAutomaticValues() {
297
        return this.getHelper().allowAutomaticValues();
298
    }
299

    
300
    @Override
301
    public boolean allowWrite() {
302
        return this.getAllowWriteValue().get();
303
    }
304
    
305
    @Override
306
    public Object getDynValue(String name) throws DynFieldNotFoundException {
307
        try {
308
            if (DataStore.METADATA_ENVELOPE.equalsIgnoreCase(name)) {
309
                Envelope env = this.getEnvelope();
310
                if (env != null) {
311
                    return env;
312
                }
313
            } else if (DataStore.METADATA_CRS.equalsIgnoreCase(name)) {
314
                IProjection proj;
315
                proj = this.getFeatureStore().getDefaultFeatureType().getDefaultSRS();
316
                if (proj != null) {
317
                    return proj;
318
                }
319
            }
320
        } catch (DataException e) {
321
            throw new RuntimeException(e);
322
        }
323
        return super.getDynValue(name);
324
    }
325

    
326
    @Override
327
    public CalculatedValue<Long> getCountValue() {
328
        if( this.count == null ) {
329
            this.count = new CountValue();
330
        }
331
        return this.count;
332
    }
333

    
334
    @Override
335
    public CalculatedValue<Envelope> getEnvelopeValue() {
336
        if( this.envelope == null ) {
337
            this.envelope = new EnvelopeValue();
338
        }
339
        return this.envelope;
340
    }
341
    
342
    @Override
343
    public CalculatedValue<Boolean> getAllowWriteValue() {
344
        if( this.allowWrite == null ) {
345
            this.allowWrite = new AllowWriteValue();
346
        }
347
        return this.allowWrite;
348
    }
349
    
350
    @Override
351
    public long getFeatureCount() throws DataException {
352
        return this.getCountValue().get();
353
    }
354
    
355
    @Override
356
    public boolean closeResourceRequested(ResourceProvider resource) {
357
        ResulSetControler resulSetControler = this.getHelper().getResulSetControler();
358
        resulSetControler.pack();
359
        return resulSetControler.getOpenCount() == 0;
360
    }
361

    
362
    @Override
363
    public void close() throws CloseException {
364
        JDBCUtils.closeQuietly(this.getHelper());
365
    }
366

    
367
    @Override
368
    public void resourceChanged(ResourceProvider resource) {
369
        this.getStoreServices().notifyChange(
370
                DataStoreNotification.RESOURCE_CHANGED,
371
                resource
372
        );
373
    }
374

    
375
    @Override
376
    public DataServerExplorer getExplorer() throws ReadException {
377
        DataManager manager = DALLocator.getDataManager();
378
        JDBCServerExplorerParameters exParams;
379
        JDBCStoreParameters params = getParameters();
380
        try {
381
            exParams = this.getHelper().createServerExplorerParameters();
382
            DynField[] fields = exParams.getDynClass().getDynFields();
383
            for (DynField field : fields) {
384
                try {
385
                    exParams.setDynValue(field.getName(), params.getDynValue(field.getName()));
386
                } catch(Exception ex) {
387
                    // Ignore
388
                }
389
            }
390
            exParams.setHost(params.getHost());
391
            exParams.setPort(params.getPort());
392
            exParams.setDBName(params.getDBName());
393
            exParams.setUser(params.getUser());
394
            exParams.setPassword(params.getPassword());
395
            exParams.setUrl(params.getUrl());
396
            exParams.setCatalog(params.getCatalog());
397
            exParams.setSchema(params.getSchema());
398
            exParams.setJDBCDriverClassName(params.getJDBCDriverClassName());
399

    
400
            return manager.openServerExplorer(exParams.getExplorerName(), exParams);
401
        } catch (Exception e) {
402
            throw new ReadException(this.getProviderName(), e);
403
        }
404
    }
405

    
406
    @Override
407
    protected void doDispose() throws BaseException {
408
        this.close();
409
        this.getHelper().dispose();
410
        super.doDispose();
411
    }
412

    
413
    @Override
414
    public String getSourceId() {
415
        try {
416
            return this.getHelper().getSourceId(this.getParameters());
417
        } catch(Exception ex) {
418
            return "unknow";
419
        }
420
    }
421

    
422
    @Override
423
    public String getName() {
424
        return this.getParameters().getTable();
425
    }
426

    
427
    @Override
428
    public String getFullName() {
429
        return this.getHelper().getSourceId(this.getParameters());
430
    }
431

    
432
    private static class DummyResource extends AbstractResource {
433

    
434
        private final String name;
435

    
436
        DummyResource(String name) throws InitializeException {
437
            super((ResourceParameters)null);
438
            this.name = name;
439
        }
440
        
441
        @Override
442
        public String getName() throws AccessResourceException {
443
            return MessageFormat.format("DummyResource({0})",
444
                                new Object[] { this.name });
445
        }
446

    
447
        @Override
448
        public Object get() throws AccessResourceException {
449
            return null;
450
        }
451

    
452
        @Override
453
        public boolean isThis(ResourceParameters parameters) throws ResourceException {
454
            return true;
455
        }
456
        
457
    }
458
    
459
    @Override
460
    public ResourceProvider getResource() {
461
        ResourceProvider r = getHelper().getResource();
462
        if( r == null ) {
463
            try {
464
                r = new DummyResource(this.getName());
465
            } catch (InitializeException ex) {
466
                LOGGER.warn("Can't create DummyResource",ex);
467
                // Do nothing
468
            }
469
        }
470
        return r;
471
    }
472

    
473
    @Override
474
    public void open() throws OpenException {
475

    
476
    }
477

    
478
    @Override
479
    public FeatureSetProvider createSet(
480
            FeatureQuery query,
481
            FeatureType featureType
482
        ) throws DataException {
483
        
484
        FeatureSetProvider set = new JDBCSetProvider(
485
                this,
486
                this.getHelper(), 
487
                query, 
488
                featureType
489
        );
490
        
491
        return set;
492
    }
493

    
494
    protected void initializeFeatureType() {
495
        EditableFeatureType type = this.getStoreServices().createFeatureType(getName());
496
        JDBCStoreParameters params = this.getParameters();
497
        List<String> primaryKeys = null;
498
        if( params.getPkFields() != null ) {
499
            primaryKeys = Arrays.asList(params.getPkFields());
500
        }
501
        FetchFeatureTypeOperation fetchFeatureType = 
502
             this.getOperations().createFetchFeatureType(
503
                type,
504
                this.getOperations().createTableReference(params),
505
                primaryKeys,
506
                params.getDefaultGeometryField(),
507
                params.getCRS(),
508
                params.getGeometryType(),
509
                params.getGeometrySubtype()
510
            );
511
        fetchFeatureType.perform();
512

    
513
        if (!StringUtils.isBlank(params.getDefaultGeometryField())) {
514
            if (!params.getDefaultGeometryField().equalsIgnoreCase(type.getDefaultGeometryAttributeName())) {
515
                if (type.getAttributeDescriptor(params.getDefaultGeometryField()) != null) {
516
                    type.setDefaultGeometryAttributeName(params.getDefaultGeometryField());
517
                } else {
518
                    type.setDefaultGeometryAttributeName(null);
519
                }
520
                if (type.getDefaultGeometryAttribute() != null) {
521
                    EditableFeatureAttributeDescriptor attr = (EditableFeatureAttributeDescriptor) type.getDefaultGeometryAttribute();
522
                    attr.setGeometryType(Geometry.TYPES.GEOMETRY, Geometry.SUBTYPES.GEOM2D);
523
                }
524
            } else {
525
                type.setDefaultGeometryAttributeName(null);
526
            }
527
        }
528
        
529
        FeatureType defaultType = type.getNotEditableCopy();
530
        this.getHelper().setProviderFeatureType(defaultType);
531
        List<FeatureType> types = Collections.singletonList(defaultType);
532
        this.getStoreServices().setFeatureTypes(types, defaultType);
533
    }
534

    
535
    @Override
536
    protected FeatureProvider internalGetFeatureProviderByReference(
537
            FeatureReferenceProviderServices reference, 
538
            FeatureType featureType
539
        ) throws DataException {
540
        JDBCStoreParameters params = this.getParameters();
541
        FetchFeatureProviderByReferenceOperation fetchFeatureProviderByReference = 
542
            this.getOperations().createFetchFeatureProviderByReference(
543
                reference, 
544
                featureType, 
545
                this.getOperations().createTableReference(params)
546
            );
547
        FeatureProvider feature = (FeatureProvider) fetchFeatureProviderByReference.perform();
548
        return feature;
549
    }
550
    
551
    @Override
552
    public Envelope getEnvelope() throws DataException {
553
        return this.getEnvelopeValue().get();
554
    }
555

    
556
    @Override
557
    public void performChanges(Iterator deleteds, Iterator inserteds,
558
                    Iterator updateds, Iterator featureTypesChanged)
559
                    throws DataException {
560

    
561
        FeatureType type = this.getFeatureStore().getDefaultFeatureType();
562
        JDBCStoreParameters params = this.getParameters();
563
        PerformChangesOperation performChanges = this.getOperations().createPerformChanges(
564
                this.getOperations().createTableReference(params),
565
                type, 
566
                deleteds, 
567
                inserteds, 
568
                updateds, 
569
                featureTypesChanged
570
        );
571
        performChanges.perform();
572
        if( performChanges.isTypeChanged() ) {
573
            // Get rules before initializing feature type
574
            FeatureRules saved_rules = getFeatureStore().getDefaultFeatureType().getRules();
575

    
576
             // This initialization loses the feature type rules
577
            this.initializeFeatureType();
578

    
579
            // Get new feature type, clear rules and add the ones saved previously
580
            FeatureType featureType = getFeatureStore().getDefaultFeatureType();
581
            FeatureRules rules = featureType.getRules();
582
            rules.clear();
583
            for (FeatureRule rule : saved_rules) {
584
                rules.add(rule);
585
            }
586
        }
587
        this.getCountValue().reset();
588
        this.getEnvelopeValue().reset();
589
    }    
590
    
591
    @Override
592
    public boolean supportsAppendMode() {
593
        return true;
594
    }
595

    
596
    protected AppendOperation createAppendOperation() throws DataException {
597
        FeatureType type = this.getFeatureStore().getDefaultFeatureType();
598
        JDBCStoreParameters params = this.getParameters();
599
        AppendOperation theAppendOperation = this.getOperations().createAppend(
600
                this.getOperations().createTableReference(params),
601
                type 
602
        );
603
        return theAppendOperation;
604
    }
605
    
606
    @Override
607
    public void endAppend() throws DataException {
608
        this.appendOperation.end();
609
    }
610

    
611
    @Override
612
    public void abortAppend() throws DataException {
613
        this.appendOperation.abort();
614
    }
615
    
616
    @Override
617
    public void beginAppend() throws DataException {
618
        if( this.appendOperation == null ) {
619
            this.appendOperation = createAppendOperation();
620
        }
621
        this.appendOperation.begin();
622
    }
623

    
624
    @Override
625
    public void append(final FeatureProvider featureProvider) throws DataException {
626
        this.appendOperation.append(featureProvider);
627
    }    
628
    
629
    @Override
630
    public boolean canWriteGeometry(int geometryType, int geometrySubtype)
631
            throws DataException {
632
        return this.getHelper().canWriteGeometry(geometryType,geometrySubtype);
633
    }
634

    
635
    @Override
636
    public boolean supportsPassThroughMode() {
637
        return true;
638
    }
639

    
640
    @Override
641
    public void passThroughInsert(FeatureProvider featureProvider) throws DataException {
642
        FeatureType type = this.getFeatureStore().getDefaultFeatureType();
643
        JDBCStoreParameters params = this.getParameters();
644
        PerformChangesOperation performChanges = this.getOperations().createPerformChanges(
645
                this.getOperations().createTableReference(params),
646
                type, 
647
                Collections.emptyIterator(), 
648
                Collections.singletonList(featureProvider).iterator(),
649
                Collections.emptyIterator(), 
650
                Collections.emptyIterator()
651
        );
652
        performChanges.perform();
653
    }
654

    
655
    @Override
656
    public void passThroughUpdate(FeatureProvider featureProvider) throws DataException {
657
        FeatureType type = this.getFeatureStore().getDefaultFeatureType();
658
        JDBCStoreParameters params = this.getParameters();
659
        PerformChangesOperation performChanges = this.getOperations().createPerformChanges(
660
                this.getOperations().createTableReference(params),
661
                type, 
662
                Collections.emptyIterator(), 
663
                Collections.emptyIterator(), 
664
                Collections.singletonList(featureProvider).iterator(),
665
                Collections.emptyIterator()
666
        );
667
        performChanges.perform();
668
    }
669
    
670
    @Override
671
    public void passThroughUpdate(Object[] parameters, Expression filter){
672
        JDBCStoreParameters params = this.getParameters();
673
        UpdatePassThroughOperation operation = this.getOperations().createUpdatePassThroughOperation(
674
                this.getOperations().createTableReference(params),
675
                parameters,
676
                filter
677
        );
678
        operation.perform();
679
    }
680

    
681
    @Override
682
    public void passThroughDelete(FeatureReferenceProviderServices featureReference) throws DataException {
683
        FeatureType type = this.getFeatureStore().getDefaultFeatureType();
684
        JDBCStoreParameters params = this.getParameters();
685
        PerformChangesOperation performChanges = this.getOperations().createPerformChanges(
686
                this.getOperations().createTableReference(params),
687
                type, 
688
                Collections.singletonList(featureReference).iterator(),
689
                Collections.emptyIterator(), 
690
                Collections.emptyIterator(), 
691
                Collections.emptyIterator()
692
        );
693
        performChanges.perform();
694
    }
695
    
696
    public void passThroughDelete(Expression expression) throws DataException {
697
        JDBCStoreParameters params = this.getParameters();
698
        DeletePassThroughOperation operation = this.getOperations().createDeletePassThroughOperation(
699
                this.getOperations().createTableReference(params),
700
                expression
701
        );
702
        operation.perform();
703
    }
704

    
705
    @Override
706
    public void setTransaction(DataTransactionServices transaction) {
707
        this.helper.setTransaction(transaction);
708
    }
709
    
710
    @Override
711
    public String toString() {
712
        try {
713
            return String.format("%s %x %s", this.getClass().getSimpleName(), this.hashCode(), this.helper.toString());
714
        } catch (Exception e) {
715
            return super.toString();
716
        }
717
    }
718

    
719
    @Override
720
    public void refresh() throws OpenException {
721
//        // Force to recalculare count, envelope and allowWrite
722
//        this.count = null;
723
//        this.envelope = null;
724
//        this.allowWrite = null;
725
//        
726
//        if( this.helper.getResulSetControler().getOpenCount()>0 ) {
727
//            // Has ResultSetEntry open. Oh!!!!
728
//            this.helper.getResulSetControler().closeAll();
729
//        }
730
//        if( this.appendOperation!=null ) {
731
//            // Has and append operation in progress, Oh!!
732
//            this.appendOperation.abort();
733
//            this.appendOperation = null;
734
//        }
735
        super.refresh(); 
736
    }
737
    
738
}