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

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

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

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

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

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

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

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

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

    
274
    protected CalculatedValue<Boolean> allowWrite = null;
275

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

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

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

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

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

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

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

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

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

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

    
456
            return explorer;
457
        } catch (Exception e) {
458
            throw new ReadException(this.getProviderName(), e);
459
        }
460
    }
461

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

    
472
    @Override
473
    public String getSourceId() {
474
        try {
475
            return this.getHelper().getSourceId(this.getParameters());
476
        } catch(Exception ex) {
477
            return "unknow";
478
        }
479
    }
480

    
481
    @Override
482
    public String getName() {
483
        return this.getParameters().getTable();
484
    }
485

    
486
    @Override
487
    public String getFullName() {
488
        return this.getHelper().getSourceId(this.getParameters());
489
    }
490

    
491
    private static class DummyResource extends AbstractResource {
492

    
493
        private final String name;
494

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

    
506
        @Override
507
        public Object get() throws AccessResourceException {
508
            return null;
509
        }
510

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

    
532
    @Override
533
    public void open() throws OpenException {
534

    
535
    }
536

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

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

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

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

    
615
    @Override
616
    public void performChanges(Iterator deleteds, Iterator inserteds,
617
                    Iterator updateds, Iterator featureTypesChanged)
618
                    throws DataException {
619

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

    
636
             // This initialization loses the feature type rules
637
            this.initializeFeatureType();
638

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

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

    
673
    @Override
674
    public void abortAppend() throws DataException {
675
        this.appendOperation.abort();
676
    }
677
    
678
    @Override
679
    public void beginAppend() throws DataException {
680
        if( this.appendOperation == null ) {
681
            this.appendOperation = createAppendOperation();
682
        }
683
        this.appendOperation.begin();
684
    }
685

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

    
697
    @Override
698
    public boolean supportsPassThroughMode() {
699
        return true;
700
    }
701

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

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

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

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

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