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

History | View | Annotate | Download (29.6 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.apache.commons.lang3.builder.ToStringBuilder;
34
import org.cresques.cts.IProjection;
35
import org.gvsig.expressionevaluator.Expression;
36
import org.gvsig.fmap.dal.DALLocator;
37
import org.gvsig.fmap.dal.DataManager;
38
import org.gvsig.fmap.dal.DataServerExplorer;
39
import org.gvsig.fmap.dal.DataStore;
40
import org.gvsig.fmap.dal.DataStoreNotification;
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.expressionevaluator.FeatureAttributeEmulatorExpression;
48
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
49
import org.gvsig.fmap.dal.feature.EditableFeatureType;
50
import org.gvsig.fmap.dal.feature.Feature;
51
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
52
import org.gvsig.fmap.dal.feature.FeatureAttributeEmulator;
53
import org.gvsig.fmap.dal.feature.FeatureQuery;
54
import org.gvsig.fmap.dal.feature.FeatureRule;
55
import org.gvsig.fmap.dal.feature.FeatureRules;
56
import org.gvsig.fmap.dal.feature.FeatureSet;
57
import org.gvsig.fmap.dal.feature.FeatureStore;
58
import org.gvsig.fmap.dal.feature.FeatureType;
59
import org.gvsig.fmap.dal.feature.spi.AbstractFeatureStoreProvider;
60
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
61
import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices;
62
import org.gvsig.fmap.dal.feature.spi.FeatureSetProvider;
63
import org.gvsig.fmap.dal.resource.ResourceParameters;
64
import org.gvsig.fmap.dal.resource.exception.AccessResourceException;
65
import org.gvsig.fmap.dal.resource.exception.ResourceException;
66
import org.gvsig.fmap.dal.resource.spi.AbstractResource;
67
import org.gvsig.fmap.dal.resource.spi.ResourceConsumer;
68
import org.gvsig.fmap.dal.resource.spi.ResourceProvider;
69
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
70
import org.gvsig.fmap.dal.spi.DataTransactionServices;
71
import org.gvsig.fmap.dal.store.jdbc.JDBCServerExplorerParameters;
72
import org.gvsig.fmap.dal.store.jdbc.JDBCStoreParameters;
73
import org.gvsig.fmap.dal.store.jdbc2.JDBCHelper;
74
import org.gvsig.fmap.dal.store.jdbc2.JDBCStoreProvider;
75
import org.gvsig.fmap.dal.store.jdbc2.JDBCUtils;
76
import org.gvsig.fmap.dal.store.jdbc2.OperationsFactory;
77
import org.gvsig.fmap.dal.store.jdbc2.ResulSetControler;
78
import org.gvsig.fmap.dal.store.jdbc2.impl.JDBCSetProvider;
79
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.AppendOperation;
80
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.CalculateEnvelopeOfColumnOperation;
81
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.CanModifyTableOperation;
82
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.CountOperation;
83
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.DeletePassThroughOperation;
84
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.FetchFeatureProviderByReferenceOperation;
85
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.FetchFeatureTypeOperation;
86
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.PerformChangesOperation;
87
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.UpdatePassThroughOperation;
88
import org.gvsig.fmap.geom.Geometry;
89
import org.gvsig.fmap.geom.GeometryUtils;
90
import org.gvsig.fmap.geom.primitive.Envelope;
91
import org.gvsig.tools.dynobject.DynField;
92
import org.gvsig.tools.dynobject.DynObject;
93
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
94
import org.gvsig.tools.exception.BaseException;
95
import org.gvsig.tools.observer.BaseNotification;
96
import org.gvsig.tools.observer.Observable;
97
import org.gvsig.tools.observer.Observer;
98
import org.slf4j.Logger;
99
import org.slf4j.LoggerFactory;
100

    
101
@SuppressWarnings("UseSpecificCatch")
102
public class JDBCStoreProviderBase
103
        extends AbstractFeatureStoreProvider
104
        implements ResourceConsumer, JDBCStoreProvider {
105

    
106
    final static protected Logger LOGGER = LoggerFactory.getLogger(JDBCStoreProviderBase.class);
107

    
108
    public class CountValue implements CalculatedValue<Long> {
109
        
110
        private Long value = null;
111

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

    
147
        @Override
148
        public void calculate() {
149
            FeatureStore featureStore;
150
            FeatureType featureType;
151
            try {
152
                featureStore = getFeatureStore();
153
                if (featureStore == null) {
154
                    return;
155
                }
156
                featureType = featureStore.getDefaultFeatureType();
157
                if (featureType == null) {
158
                    return;
159
                }
160
            } catch (Exception ex) {
161
                throw new RuntimeException("Can't calculate envelope.", ex);
162
            }
163
            try {
164
                value = null;
165
                String columnName = featureType.getDefaultGeometryAttributeName();
166
                if( columnName==null ) {
167
                    return;
168
                }
169
                FeatureAttributeDescriptor attr = featureType.getAttributeDescriptor(columnName);
170
                boolean toDataBase = true;
171
                if(attr.isComputed()){
172
                    FeatureAttributeEmulator attrEmulator = attr.getFeatureAttributeEmulator();
173
                    if( !(attrEmulator instanceof FeatureAttributeEmulatorExpression) ) {
174
                        toDataBase = false;
175
                    } else {
176
                        FeatureAttributeEmulatorExpression x = (FeatureAttributeEmulatorExpression) attrEmulator;
177
                        Expression exp = x.getExpression();
178
                        if (exp == null || exp.isEmpty() ) {
179
                            toDataBase = false;
180
                        } else {
181
                            if (!helper.supportExpression(null, exp.getPhrase())) {
182
                                toDataBase = false;
183
                            }
184
                        }
185
                    }
186
                }
187
                
188
                if(toDataBase){
189
                    IProjection crs = getFeatureStore()
190
                            .getDefaultFeatureType()
191
                            .getDefaultSRS();
192
                    JDBCStoreParameters params = getParameters();
193
                    CalculateEnvelopeOfColumnOperation calculateEnvelopeOfColumn = 
194
                        getOperations().createCalculateEnvelopeOfColumn(
195
                            getFeatureStore().getDefaultFeatureType(),
196
                            getOperations().createTableReference(params),
197
                            columnName, 
198
                            params.getBaseFilter(), 
199
                            params.getWorkingArea(), 
200
                            crs
201
                        );
202
                    value = (Envelope) calculateEnvelopeOfColumn.perform(); 
203
                } else {
204
                    FeatureSet fset = getFeatureStore().getFeatureSet();
205
                    Envelope finalEnvelope = GeometryUtils.createEnvelope(Geometry.SUBTYPES.GEOM2D);
206
                    for (Feature feature : fset) {
207
                        Geometry geometry = feature.getGeometry(columnName);
208
                        finalEnvelope.add(geometry);
209
                    }
210
                    value = finalEnvelope;
211
                }
212
                
213
            } catch(Throwable ex) {
214
                throw new RuntimeException("Can't calculate envelope.", ex);
215
            } finally {
216
               needCalculate = false;
217
            }
218
        }
219
        
220
        @Override
221
        public void reset() {
222
            this.value = null;
223
            this.needCalculate = true;
224
        }
225
        
226
        @Override
227
        public synchronized Envelope get() {
228
            if( needCalculate ) {
229
                this.calculate();
230
            }
231
            return this.value;
232
        }
233
    } 
234
        
235
    public class AllowWriteValue implements CalculatedValue<Boolean> {
236
        
237
        private Boolean value = null;
238

    
239
        @Override
240
        public void calculate() {
241
            try {
242
                JDBCStoreParameters params = getParameters();
243
                CanModifyTableOperation canModifyTable = 
244
                    getOperations().createCanModifyTableOperation(
245
                        getOperations().createTableReference(params)
246
                    );
247
                this.value = (boolean) canModifyTable.perform();
248
            } catch(Exception ex) {
249
                throw new RuntimeException("Can't determine if allow write.", ex);
250
            }
251
        }
252
        
253
        @Override
254
        public void reset() {
255
            this.value = null;
256
        }
257
        
258
        @Override
259
        public Boolean get() {
260
            if( this.value == null ) {
261
                this.calculate();
262
            }
263
            return this.value;
264
        }
265
    } 
266
    
267
    protected final JDBCHelper helper;
268

    
269
    protected CalculatedValue<Long> count = null;
270
    
271
    protected CalculatedValue<Envelope> envelope = null;
272

    
273
    protected CalculatedValue<Boolean> allowWrite = null;
274

    
275
    protected AppendOperation appendOperation = null;
276
    
277
    protected Observer transactionObserver;
278
    
279
    @SuppressWarnings({"OverridableMethodCallInConstructor", "CallToThreadStartDuringObjectConstruction"})
280
    protected JDBCStoreProviderBase(
281
            JDBCStoreParameters params,
282
            DataStoreProviderServices storeServices,
283
            DynObject metadata,
284
            JDBCHelper helper
285
    ) throws InitializeException {
286
        super(params, storeServices, metadata);
287
        this.helper = helper;
288
        this.initializeFeatureType();
289
        try {
290
            if( BooleanUtils.isTrue((Boolean) params.getDynValue("precalculateEnvelope"))  ) {
291
                FeatureType featureType = this.getStoreServices().getDefaultFeatureType();
292
                if( !StringUtils.isEmpty(featureType.getDefaultGeometryAttributeName()) ) {
293
                    Thread thread = new Thread(() -> {
294
                        LOGGER.trace("Precalculating envelope of '"+getSourceId()+"'.");
295
                        getEnvelopeValue().get();
296
                    }, "PrecalculateEnvelopeOfDBTable");
297
                    thread.start();
298
                    Thread.sleep(1);
299
                }
300
           }
301
        } catch(Exception ex) {
302
            LOGGER.warn("Probems precalculating the envelope of table '"+this.getSourceId()+"'.", ex);
303
        }
304
        this.transactionObserver = new Observer() {
305
            @Override
306
            public void update(Observable o, Object o1) {
307
                if( o1 instanceof BaseNotification && (
308
                        ((BaseNotification)o1).isOfType("ROLLBACK") ||
309
                        ((BaseNotification)o1).isOfType("COMMIT")
310
                        ) ) {
311
                    getCountValue().reset();
312
                    getEnvelopeValue().reset();
313
                }
314
            }
315
        };
316
    }
317

    
318
    @Override
319
    public JDBCStoreParameters getParameters() {
320
        return (JDBCStoreParameters) super.getParameters();
321
    }  
322

    
323
    @Override
324
    public JDBCHelper getHelper() {
325
        return helper;
326
    }
327
    
328
    public OperationsFactory getOperations() {
329
        return this.getHelper().getOperations();
330
    }
331
    
332
    @Override
333
    public String getProviderName() {
334
        return this.getHelper().getProviderName();
335
    }
336
    
337
    @Override
338
    public int getOIDType() {
339
        return DataTypes.UNKNOWN;
340
    }
341

    
342
    @Override
343
    public Object createNewOID() {
344
        return null;
345
    }
346
    
347
    @Override
348
    public boolean allowAutomaticValues() {
349
        return this.getHelper().allowAutomaticValues();
350
    }
351

    
352
    @Override
353
    public boolean allowWrite() {
354
        return this.getAllowWriteValue().get();
355
    }
356
    
357
    @Override
358
    public Object getDynValue(String name) throws DynFieldNotFoundException {
359
        try {
360
            if (DataStore.METADATA_ENVELOPE.equalsIgnoreCase(name)) {
361
                Envelope env = this.getEnvelope();
362
                if (env != null) {
363
                    return env;
364
                }
365
            } else if (DataStore.METADATA_CRS.equalsIgnoreCase(name)) {
366
                IProjection proj;
367
                proj = this.getFeatureStore().getDefaultFeatureType().getDefaultSRS();
368
                if (proj != null) {
369
                    return proj;
370
                }
371
            }
372
        } catch (DataException e) {
373
            throw new RuntimeException(e);
374
        }
375
        return super.getDynValue(name);
376
    }
377

    
378
    @Override
379
    public CalculatedValue<Long> getCountValue() {
380
        if( this.count == null ) {
381
            this.count = new CountValue();
382
        }
383
        return this.count;
384
    }
385

    
386
    @Override
387
    public CalculatedValue<Envelope> getEnvelopeValue() {
388
        if( this.envelope == null ) {
389
            this.envelope = new EnvelopeValue();
390
        }
391
        return this.envelope;
392
    }
393
    
394
    @Override
395
    public CalculatedValue<Boolean> getAllowWriteValue() {
396
        if( this.allowWrite == null ) {
397
            this.allowWrite = new AllowWriteValue();
398
        }
399
        return this.allowWrite;
400
    }
401
    
402
    @Override
403
    public long getFeatureCount() throws DataException {
404
        return this.getCountValue().get();
405
    }
406
    
407
    @Override
408
    public boolean closeResourceRequested(ResourceProvider resource) {
409
        ResulSetControler resulSetControler = this.getHelper().getResulSetControler();
410
        resulSetControler.pack();
411
        return resulSetControler.getOpenCount() == 0;
412
    }
413

    
414
    @Override
415
    public void close() throws CloseException {
416
        JDBCUtils.closeQuietly(this.getHelper());
417
    }
418

    
419
    @Override
420
    public void resourceChanged(ResourceProvider resource) {
421
        this.getStoreServices().notifyChange(
422
                DataStoreNotification.RESOURCE_CHANGED,
423
                resource
424
        );
425
    }
426

    
427
    @Override
428
    public DataServerExplorer getExplorer() throws ReadException {
429
        DataManager manager = DALLocator.getDataManager();
430
        JDBCServerExplorerParameters exParams;
431
        JDBCStoreParameters params = getParameters();
432
        try {
433
            exParams = this.getHelper().createServerExplorerParameters();
434
            DynField[] fields = exParams.getDynClass().getDynFields();
435
            for (DynField field : fields) {
436
                try {
437
                    exParams.setDynValue(field.getName(), params.getDynValue(field.getName()));
438
                } catch(Exception ex) {
439
                    // Ignore
440
                }
441
            }
442
            exParams.setHost(params.getHost());
443
            exParams.setPort(params.getPort());
444
            exParams.setDBName(params.getDBName());
445
            exParams.setUser(params.getUser());
446
            exParams.setPassword(params.getPassword());
447
            exParams.setUrl(params.getUrl());
448
            exParams.setCatalog(params.getCatalog());
449
            exParams.setSchema(params.getSchema());
450
            exParams.setJDBCDriverClassName(params.getJDBCDriverClassName());
451

    
452
            return manager.openServerExplorer(exParams.getExplorerName(), exParams);
453
        } catch (Exception e) {
454
            throw new ReadException(this.getProviderName(), e);
455
        }
456
    }
457

    
458
    @Override
459
    protected void doDispose() throws BaseException {
460
        if( this.helper.getTransaction()!=null ) {
461
            this.helper.getTransaction().deleteObserver(transactionObserver);
462
        }
463
        this.close();
464
        this.getHelper().dispose();
465
        super.doDispose();
466
    }
467

    
468
    @Override
469
    public String getSourceId() {
470
        try {
471
            return this.getHelper().getSourceId(this.getParameters());
472
        } catch(Exception ex) {
473
            return "unknow";
474
        }
475
    }
476

    
477
    @Override
478
    public String getName() {
479
        return this.getParameters().getTable();
480
    }
481

    
482
    @Override
483
    public String getFullName() {
484
        return this.getHelper().getSourceId(this.getParameters());
485
    }
486

    
487
    private static class DummyResource extends AbstractResource {
488

    
489
        private final String name;
490

    
491
        DummyResource(String name) throws InitializeException {
492
            super((ResourceParameters)null);
493
            this.name = name;
494
        }
495
        
496
        @Override
497
        public String getName() throws AccessResourceException {
498
            return MessageFormat.format("DummyResource({0})",
499
                                new Object[] { this.name });
500
        }
501

    
502
        @Override
503
        public Object get() throws AccessResourceException {
504
            return null;
505
        }
506

    
507
        @Override
508
        public boolean isThis(ResourceParameters parameters) throws ResourceException {
509
            return true;
510
        }
511
        
512
    }
513
    
514
    @Override
515
    public ResourceProvider getResource() {
516
        ResourceProvider r = getHelper().getResource();
517
        if( r == null ) {
518
            try {
519
                r = new DummyResource(this.getName());
520
            } catch (InitializeException ex) {
521
                LOGGER.warn("Can't create DummyResource",ex);
522
                // Do nothing
523
            }
524
        }
525
        return r;
526
    }
527

    
528
    @Override
529
    public void open() throws OpenException {
530

    
531
    }
532

    
533
    @Override
534
    public FeatureSetProvider createSet(
535
            FeatureQuery query,
536
            FeatureType featureType
537
        ) throws DataException {
538
        
539
        FeatureSetProvider set = new JDBCSetProvider(
540
                this,
541
                this.getHelper(), 
542
                query, 
543
                featureType
544
        );
545
        
546
        return set;
547
    }
548

    
549
    protected void initializeFeatureType() {
550
        EditableFeatureType type = this.getStoreServices().createFeatureType(getName());
551
        JDBCStoreParameters params = this.getParameters();
552
        List<String> primaryKeys = null;
553
        if( params.getPkFields() != null ) {
554
            primaryKeys = Arrays.asList(params.getPkFields());
555
        }
556
        FetchFeatureTypeOperation fetchFeatureType = 
557
             this.getOperations().createFetchFeatureType(
558
                type,
559
                this.getOperations().createTableReference(params),
560
                primaryKeys,
561
                params.getDefaultGeometryField(),
562
                params.getCRS(),
563
                params.getGeometryType(),
564
                params.getGeometrySubtype()
565
            );
566
        fetchFeatureType.perform();
567

    
568
        if (!StringUtils.isBlank(params.getDefaultGeometryField())) {
569
            if (!params.getDefaultGeometryField().equalsIgnoreCase(type.getDefaultGeometryAttributeName())) {
570
                if (type.getAttributeDescriptor(params.getDefaultGeometryField()) != null) {
571
                    type.setDefaultGeometryAttributeName(params.getDefaultGeometryField());
572
                } else {
573
                    type.setDefaultGeometryAttributeName(null);
574
                }
575
                if (type.getDefaultGeometryAttribute() != null) {
576
                    EditableFeatureAttributeDescriptor attr = (EditableFeatureAttributeDescriptor) type.getDefaultGeometryAttribute();
577
                    attr.setGeometryType(Geometry.TYPES.GEOMETRY, Geometry.SUBTYPES.GEOM2D);
578
                }
579
            } else {
580
                type.setDefaultGeometryAttributeName(null);
581
            }
582
        }
583
        
584
        FeatureType defaultType = type.getNotEditableCopy();
585
        this.getHelper().setProviderFeatureType(defaultType);
586
        List<FeatureType> types = Collections.singletonList(defaultType);
587
        this.getStoreServices().setFeatureTypes(types, defaultType);
588
    }
589

    
590
    @Override
591
    protected FeatureProvider internalGetFeatureProviderByReference(
592
            FeatureReferenceProviderServices reference, 
593
            FeatureType featureType
594
        ) throws DataException {
595
        JDBCStoreParameters params = this.getParameters();
596
        FetchFeatureProviderByReferenceOperation fetchFeatureProviderByReference = 
597
            this.getOperations().createFetchFeatureProviderByReference(
598
                reference, 
599
                featureType, 
600
                this.getOperations().createTableReference(params)
601
            );
602
        FeatureProvider feature = (FeatureProvider) fetchFeatureProviderByReference.perform();
603
        return feature;
604
    }
605
    
606
    @Override
607
    public Envelope getEnvelope() throws DataException {
608
        return this.getEnvelopeValue().get();
609
    }
610

    
611
    @Override
612
    public void performChanges(Iterator deleteds, Iterator inserteds,
613
                    Iterator updateds, Iterator featureTypesChanged)
614
                    throws DataException {
615

    
616
        FeatureType type = this.getFeatureStore().getDefaultFeatureType();
617
        JDBCStoreParameters params = this.getParameters();
618
        PerformChangesOperation performChanges = this.getOperations().createPerformChanges(
619
                this.getOperations().createTableReference(params),
620
                type, 
621
                deleteds, 
622
                inserteds, 
623
                updateds, 
624
                featureTypesChanged,
625
                this.getStoreServices()
626
        );
627
        performChanges.perform();
628
        if( performChanges.isTypeChanged() ) {
629
            // Get rules before initializing feature type
630
            FeatureRules saved_rules = getFeatureStore().getDefaultFeatureType().getRules();
631

    
632
             // This initialization loses the feature type rules
633
            this.initializeFeatureType();
634

    
635
            // Get new feature type, clear rules and add the ones saved previously
636
            FeatureType featureType = getFeatureStore().getDefaultFeatureType();
637
            FeatureRules rules = featureType.getRules();
638
            rules.clear();
639
            for (FeatureRule rule : saved_rules) {
640
                rules.add(rule);
641
            }
642
        }
643
        this.getCountValue().reset();
644
        this.getEnvelopeValue().reset();
645
    }    
646
    
647
    @Override
648
    public boolean supportsAppendMode() {
649
        return true;
650
    }
651

    
652
    protected AppendOperation createAppendOperation() throws DataException {
653
        FeatureType type = this.getFeatureStore().getDefaultFeatureType();
654
        JDBCStoreParameters params = this.getParameters();
655
        AppendOperation theAppendOperation = this.getOperations().createAppend(
656
                this.getOperations().createTableReference(params),
657
                type 
658
        );
659
        return theAppendOperation;
660
    }
661
    
662
    @Override
663
    public void endAppend() throws DataException {
664
        this.appendOperation.end();
665
        this.getCountValue().reset();
666
        this.getEnvelopeValue().reset();
667
    }
668

    
669
    @Override
670
    public void abortAppend() throws DataException {
671
        this.appendOperation.abort();
672
    }
673
    
674
    @Override
675
    public void beginAppend() throws DataException {
676
        if( this.appendOperation == null ) {
677
            this.appendOperation = createAppendOperation();
678
        }
679
        this.appendOperation.begin();
680
    }
681

    
682
    @Override
683
    public void append(final FeatureProvider featureProvider) throws DataException {
684
        this.appendOperation.append(featureProvider);
685
    }    
686
    
687
    @Override
688
    public boolean canWriteGeometry(int geometryType, int geometrySubtype)
689
            throws DataException {
690
        return this.getHelper().canWriteGeometry(geometryType,geometrySubtype);
691
    }
692

    
693
    @Override
694
    public boolean supportsPassThroughMode() {
695
        return true;
696
    }
697

    
698
    @Override
699
    public void passThroughInsert(FeatureProvider featureProvider) throws DataException {
700
        FeatureType type = this.getFeatureStore().getDefaultFeatureType();
701
        JDBCStoreParameters params = this.getParameters();
702
        PerformChangesOperation performChanges = this.getOperations().createPerformChanges(
703
                this.getOperations().createTableReference(params),
704
                type, 
705
                Collections.emptyIterator(), 
706
                Collections.singletonList(featureProvider).iterator(),
707
                Collections.emptyIterator(), 
708
                Collections.emptyIterator(),
709
                this.getStoreServices()
710
        );
711
        performChanges.perform();
712
        this.getCountValue().reset();
713
        this.getEnvelopeValue().reset();
714
    }
715

    
716
    @Override
717
    public void passThroughUpdate(FeatureProvider featureProvider) throws DataException {
718
        FeatureType type = this.getFeatureStore().getDefaultFeatureType();
719
        JDBCStoreParameters params = this.getParameters();
720
        PerformChangesOperation performChanges = this.getOperations().createPerformChanges(
721
                this.getOperations().createTableReference(params),
722
                type, 
723
                Collections.emptyIterator(), 
724
                Collections.emptyIterator(), 
725
                Collections.singletonList(featureProvider).iterator(),
726
                Collections.emptyIterator(),
727
                this.getStoreServices()
728
        );
729
        performChanges.perform();
730
//        this.getCountValue().reset();
731
        this.getEnvelopeValue().reset();
732
    }
733
    
734
    @Override
735
    public void passThroughUpdate(Object[] parameters, Expression filter){
736
        JDBCStoreParameters params = this.getParameters();
737
        UpdatePassThroughOperation operation = this.getOperations().createUpdatePassThroughOperation(
738
                this.getOperations().createTableReference(params),
739
                parameters,
740
                filter
741
        );
742
        operation.perform();
743
//        this.getCountValue().reset();
744
        this.getEnvelopeValue().reset();
745
    }
746

    
747
    @Override
748
    public void passThroughDelete(FeatureReferenceProviderServices featureReference) throws DataException {
749
        FeatureType type = this.getFeatureStore().getDefaultFeatureType();
750
        JDBCStoreParameters params = this.getParameters();
751
        PerformChangesOperation performChanges = this.getOperations().createPerformChanges(
752
                this.getOperations().createTableReference(params),
753
                type, 
754
                Collections.singletonList(featureReference).iterator(),
755
                Collections.emptyIterator(), 
756
                Collections.emptyIterator(), 
757
                Collections.emptyIterator(),
758
                this.getStoreServices()
759
        );
760
        performChanges.perform();
761
        this.getCountValue().reset();
762
        this.getEnvelopeValue().reset();
763
    }
764
    
765
    @Override
766
    public void passThroughDelete(Expression expression) throws DataException {
767
        JDBCStoreParameters params = this.getParameters();
768
        DeletePassThroughOperation operation = this.getOperations().createDeletePassThroughOperation(
769
                this.getOperations().createTableReference(params),
770
                expression
771
        );
772
        operation.perform();
773
        this.getCountValue().reset();
774
        this.getEnvelopeValue().reset();
775
    }
776

    
777
    @Override
778
    public void setTransaction(DataTransactionServices transaction) {
779
        if( this.helper.getTransaction()!=null ) {
780
            this.helper.getTransaction().deleteObserver(transactionObserver);
781
        }
782
        this.helper.setTransaction(transaction);
783
        if( transaction!=null ) {
784
            transaction.addObserver(transactionObserver);
785
        }
786
    }
787
    
788
    @Override
789
    public String toString() {
790
        try {
791
            ToStringBuilder builder = new ToStringBuilder(this);
792
            builder.append("hash", String.format("%x", this.hashCode()));
793
            builder.append("helper", this.helper, true);
794
            return builder.toString();
795
        } catch (Exception e) {
796
            return super.toString();
797
        }
798
    }
799

    
800
    @Override
801
    public void refresh() throws OpenException {
802
        // Force to recalculare count, envelope and allowWrite
803
        this.count = null;
804
        this.envelope = null;
805
        this.allowWrite = null;
806
//        
807
//        if( this.helper.getResulSetControler().getOpenCount()>0 ) {
808
//            // Has ResultSetEntry open. Oh!!!!
809
//            this.helper.getResulSetControler().closeAll();
810
//        }
811
//        if( this.appendOperation!=null ) {
812
//            // Has and append operation in progress, Oh!!
813
//            this.appendOperation.abort();
814
//            this.appendOperation = null;
815
//        }
816
        super.refresh(); 
817
    }
818
    
819
}