Statistics
| Revision:

root / tags / v2_0_0_Build_2051 / extensions / extWFS2 / src / org / gvsig / fmap / dal / store / wfs / WFSStoreProvider.java @ 38727

History | View | Annotate | Download (25.1 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Government (CIT)
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 2
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
 */
22

    
23
/*
24
 * AUTHORS (In addition to CIT):
25
 * 2009 {Iver T.I.}   {Task}
26
 */
27

    
28
package org.gvsig.fmap.dal.store.wfs;
29

    
30
import java.io.File;
31
import java.io.IOException;
32
import java.util.ArrayList;
33
import java.util.Iterator;
34
import java.util.List;
35

    
36
import org.cresques.cts.ICoordTrans;
37
import org.cresques.cts.IProjection;
38
import org.gvsig.fmap.crs.CRSFactory;
39
import org.gvsig.fmap.dal.DALLocator;
40
import org.gvsig.fmap.dal.DataManager;
41
import org.gvsig.fmap.dal.DataServerExplorer;
42
import org.gvsig.fmap.dal.DataStoreParameters;
43
import org.gvsig.fmap.dal.DataTypes;
44
import org.gvsig.fmap.dal.exception.ConnectionServerException;
45
import org.gvsig.fmap.dal.exception.DataException;
46
import org.gvsig.fmap.dal.exception.InitializeException;
47
import org.gvsig.fmap.dal.exception.OpenException;
48
import org.gvsig.fmap.dal.exception.ProviderNotRegisteredException;
49
import org.gvsig.fmap.dal.exception.ReadException;
50
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
51
import org.gvsig.fmap.dal.feature.EditableFeatureType;
52
import org.gvsig.fmap.dal.feature.FeatureQuery;
53
import org.gvsig.fmap.dal.feature.FeatureStore;
54
import org.gvsig.fmap.dal.feature.FeatureType;
55
import org.gvsig.fmap.dal.feature.spi.AbstractFeatureStoreProvider;
56
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
57
import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices;
58
import org.gvsig.fmap.dal.feature.spi.FeatureSetProvider;
59
import org.gvsig.fmap.dal.resource.spi.ResourceProvider;
60
import org.gvsig.fmap.dal.serverexplorer.wfs.WFSServerExplorer;
61
import org.gvsig.fmap.dal.serverexplorer.wfs.WFSServerExplorerParameters;
62
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
63
import org.gvsig.fmap.dal.store.gpe.GPEStoreProvider;
64
import org.gvsig.fmap.geom.Geometry;
65
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
66
import org.gvsig.fmap.geom.GeometryLocator;
67
import org.gvsig.fmap.geom.GeometryManager;
68
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
69
import org.gvsig.fmap.geom.operation.GeometryOperationException;
70
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
71
import org.gvsig.fmap.geom.primitive.Envelope;
72
import org.gvsig.gpe.lib.api.exceptions.WriterHandlerCreationException;
73
import org.gvsig.metadata.MetadataLocator;
74
import org.gvsig.metadata.MetadataManager;
75
import org.gvsig.metadata.exceptions.MetadataException;
76
import org.gvsig.remoteclient.ogc.OGCClientOperation;
77
import org.gvsig.remoteclient.utils.BoundaryBox;
78
import org.gvsig.remoteclient.wfs.WFSClient;
79
import org.gvsig.remoteclient.wfs.WFSFeature;
80
import org.gvsig.remoteclient.wfs.WFSFeatureField;
81
import org.gvsig.remoteclient.wfs.WFSStatus;
82
import org.gvsig.remoteclient.wfs.exceptions.WFSException;
83
import org.gvsig.remoteclient.wfs.filters.filterencoding.FilterEncoding;
84
import org.gvsig.remoteclient.wfs.request.WFSGetFeatureRequestInformation;
85
import org.gvsig.remoteclient.wfs.request.WFSTransactionRequestInformation;
86
import org.gvsig.tools.ToolsLocator;
87
import org.gvsig.tools.dynobject.DynStruct;
88
import org.gvsig.tools.evaluator.EvaluatorFieldValue;
89
import org.gvsig.tools.evaluator.EvaluatorFieldValueMatch;
90
import org.gvsig.tools.evaluator.EvaluatorFieldsInfo;
91
import org.gvsig.xmlschema.lib.api.XMLSchemaLocator;
92
import org.gvsig.xmlschema.lib.api.XMLSchemaManager;
93
import org.gvsig.xmlschema.lib.api.som.IXSGeometryTypeDefinition;
94
import org.gvsig.xmlschema.lib.api.som.IXSTypeDefinition;
95
import org.slf4j.Logger;
96
import org.slf4j.LoggerFactory;
97

    
98

    
99
/**
100
 * @author <a href="mailto:jpiera@gvsig.org">Jorge Piera</a>
101
 */
102
public class WFSStoreProvider extends AbstractFeatureStoreProvider {
103
    private static final Logger logger = LoggerFactory.getLogger(WFSStoreProvider.class);
104
    public static String NAME = "WFSStore";
105
    public static String DESCRIPTION = "WFS store to load WFS resources";
106

    
107
    private static final MetadataManager metadataManager = MetadataLocator.getMetadataManager();
108
    private static final String METADATA_DEFINITION_NAME = "WFSStore";    
109
    private static final String METADATA_DEFINITION_DESCRIPTION = "WFSStore metadata definition";
110

    
111
    private IProjection projection;        
112
    private long featureCount = -1;
113
    private boolean isKnownEnvelope = false;
114

    
115
    /**
116
     * If the user has selected the filter by area option
117
     */
118
    private boolean hasFilterByArea = false;
119

    
120
    /**
121
     * GML provider used by delegation to read the GML files
122
     */
123
    private GPEStoreProvider storeProviderDelegate = null;
124

    
125
    private static final DataManager dataManager = DALLocator.getDataManager();   
126
    private static final XMLSchemaManager xmlSchemaManager = XMLSchemaLocator.getXMLSchemaManager();          
127

    
128
    boolean isFilterByAreaSupported = true;
129

    
130
    //WFS Parameters
131
    private WFSClient wfsClient;
132
    private WFSStatus wfsStatus;
133

    
134
    public WFSStoreProvider(DataStoreParameters params,
135
        DataStoreProviderServices storeServices)
136
    throws InitializeException {
137
        super(params, storeServices, 
138
            ToolsLocator.getDynObjectManager().createDynObject(metadataManager.getDefinition(METADATA_DEFINITION_NAME)));                
139
        initParams();
140
        try {
141
            initFeatureType();
142
        } catch (WFSException e) {
143
            throw new InitializeException(e);
144
        } catch (ReadException e) {
145
            throw new InitializeException(e);
146
        }
147
    }
148

    
149
    private void initParams() throws InitializeException{
150
        try {
151
            WFSStoreParameters wfsParameters = getWFSParameters();
152
            try {
153
                if (wfsParameters.getVersion() == null){
154
                    wfsClient = new WFSClient(wfsParameters.getUrl());
155
                    wfsParameters.setVersion(wfsClient.getVersion());
156
                }else{
157
                    wfsClient = new WFSClient(wfsParameters.getUrl(), wfsParameters.getVersion());
158
                }
159
            } catch (IOException e) {
160
                throw new InitializeException(e);
161
            }
162
            wfsStatus = new WFSStatus( wfsParameters.getFeatureType(),
163
                wfsParameters.getFeatureNamespace());
164
            wfsStatus.setNamespacePrefix(wfsParameters.getFeaturePrefix());
165
            wfsStatus.setFields(wfsParameters.getFields());
166

    
167
            //Select the filter by area
168
            wfsStatus.setFilterByArea(wfsParameters.getFilterByAreaGeometry(), wfsParameters.getFilterByAreaAttribute(), 
169
                wfsParameters.getFilterByAreaCrs(), wfsParameters.getFilterByAreaOperation());
170
            this.hasFilterByArea = (wfsStatus.getFilterByArea() != null);
171

    
172
            //Select the filter by attribute
173
            wfsStatus.setFilterByAttribute(wfsParameters.getFilterEncodingByAttribute());
174

    
175
            wfsStatus.setTimeout(wfsParameters.getTimeOut());
176
            wfsStatus.setMaxFeatures(wfsParameters.getMaxFeatures());
177
            wfsStatus.setUserName(wfsParameters.getUser());
178
            wfsStatus.setPassword(wfsParameters.getPassword());
179

    
180
            //Setting the envelope for the layer
181
            wfsClient.getCapabilities(wfsStatus, false, null);
182

    
183
            Envelope envelope = calculateFullEnvelope();
184
            if (envelope != null){
185
                this.setDynValue("Envelope", envelope);
186
                isKnownEnvelope = true;
187
            }                        
188
        } catch (WFSException e) {
189
            throw new InitializeException("Impossible to retrieve the file", e);
190
        }
191
    }
192

    
193
    private WFSFeature getSelectedWFSFeature() throws ReadException, WFSException{
194
        WFSStoreParameters wfsParameters = getWFSParameters();
195

    
196
        return  ((WFSServerExplorer)getExplorer()).getFeatureInfo(wfsParameters.getFeatureNamespace(),
197
            wfsParameters.getFeatureType());
198
    }
199

    
200
    private void initFeatureType() throws WFSException, ReadException{           
201
        WFSFeature feature  = getSelectedWFSFeature();
202

    
203
        if (feature == null){
204
            //TODO read from GML
205
            throw new WFSException("It is not possible to parse the schema");
206
        }
207

    
208
        projection = CRSFactory.getCRS(feature.getDefaultSRS());
209
        this.setDynValue("CRS", projection);
210

    
211
        EditableFeatureType featureType = getStoreServices().createFeatureType();
212

    
213
        for (int i=0 ; i<feature.getFieldSize() ; i++){       
214
            WFSFeatureField featureField = feature.getFieldAt(i);           
215
            int dataType = DataTypes.STRING;               
216
            String typeName = featureField.getType();
217
            EditableFeatureAttributeDescriptor attributeDescriptor = null;
218

    
219
            IXSTypeDefinition typeDefinition = null;
220
            
221
            if (typeName != null){
222
                typeDefinition = xmlSchemaManager.getTypeDefinition(typeName);
223
            }
224
            
225
            if (typeDefinition != null){             
226
                if (typeDefinition.getDataType() != null){
227
                    if (typeDefinition.getDataType().getType() == DataTypes.GEOMETRY){
228
                        dataType = typeDefinition.getDataType().getType();
229
                    }
230
                }
231
                attributeDescriptor = featureType.add(featureField.getName(), dataType);   
232
                if (typeDefinition instanceof IXSGeometryTypeDefinition){
233
                    if (feature.getSrs().size() > 0){
234
                        attributeDescriptor.setSRS(CRSFactory.getCRS((String)feature.getSrs().get(0)));
235
                    }                    
236
                    attributeDescriptor.setGeometryType(((IXSGeometryTypeDefinition)typeDefinition).getGeometryType());
237
                    attributeDescriptor.setGeometrySubType(SUBTYPES.GEOM3D);
238
                    featureType.setDefaultGeometryAttributeName(featureField.getName());
239
                }                               
240
            }else{
241
                attributeDescriptor = featureType.add(typeName, dataType);    
242
            }                 
243
        }       
244
        featureType.setHasOID(true);
245

    
246
        FeatureType defaultType = featureType.getNotEditableCopy();
247
        List types = new ArrayList(1);
248
        types.add(defaultType);
249
        this.getStoreServices().setFeatureTypes(types, defaultType);
250
    }
251

    
252
    private Envelope calculateFullEnvelope() {
253
        GeometryManager geometryManager = GeometryLocator.getGeometryManager();
254

    
255
        try{
256
            WFSFeature feature  = getSelectedWFSFeature();
257
            if (feature != null){               
258
                if (feature.getSrs().size() > 0){
259
                    String srs = feature.getDefaultSRS();                  
260
                    BoundaryBox boundaryBox = feature.getBbox(srs);
261
                    if (boundaryBox == null)
262
                    {
263
                        boundaryBox = feature.getBbox(srs);
264
                    }        
265
                    //The projection is found
266
                    if (boundaryBox != null){
267
                        return geometryManager.createEnvelope(boundaryBox.getXmin(),
268
                            boundaryBox.getYmin(), boundaryBox.getXmax(), boundaryBox.getYmax(), SUBTYPES.GEOM2D);
269
                    }
270
                    //Check if there is a latlon envelope
271
                    boundaryBox = feature.getLatLonBbox();
272
                    if (boundaryBox != null){
273
                        Envelope envelope = geometryManager.createEnvelope(boundaryBox.getXmin(),
274
                            boundaryBox.getYmin(), boundaryBox.getXmax(), boundaryBox.getYmax(), SUBTYPES.GEOM2D);
275
                        if (!"EPSG:4326".equals(srs)){
276
                            IProjection sourceProjection = CRSFactory.getCRS("EPSG:4326");
277
                            IProjection destinationProjection = CRSFactory.getCRS(srs);
278
                            if (destinationProjection != null){
279
                                ICoordTrans coordTrans = sourceProjection.getCT(destinationProjection);
280
                                return envelope.convert(coordTrans);
281
                            }        
282
                        }
283
                    }
284
                }else{
285
                    //If there is not a SRS is thrown a request for the first 500 features
286
                    int odlMaxFeatures = wfsStatus.getMaxFeatures();
287
                    wfsStatus.setMaxFeatures(500);
288
                    createSet(null, null);
289
                    return storeProviderDelegate.getEnvelope();
290
                }
291
            }
292
        }catch(CreateEnvelopeException e){
293
            logger.error("Impossible to create an envelope", e);
294
        } catch (ReadException e) {
295
            logger.error("Impossible to create an envelope", e);
296
        } catch (WFSException e) {
297
            logger.error("Impossible to create an envelope", e);
298
        } catch (DataException e) {
299
            logger.error("Impossible to create an envelope", e);
300
        }
301
        return null;
302
    }
303

    
304
    private WFSStoreParameters getWFSParameters() {
305
        return (WFSStoreParameters) getParameters();
306
    }
307

    
308
    /* (non-Javadoc)
309
     * @see org.gvsig.fmap.dal.store.gpe.GPEStoreProvider#open()
310
     */
311
    public void open() throws OpenException {
312
        try {
313
            List featureTypes = this.getFeatureStore().getFeatureTypes();
314
            for (int i=0 ; i<featureTypes.size() ; i++){
315
                FeatureType featureType = (FeatureType)featureTypes.get(i);
316
            }
317
        } catch (DataException e) {
318
            throw new OpenException("Reading the geometry type", e);
319
        }
320
    }
321

    
322
    protected static void registerMetadataDefinition() throws MetadataException {       
323
        if (metadataManager.getDefinition(METADATA_DEFINITION_NAME) == null) {
324
            DynStruct metadataDefinition = metadataManager.addDefinition(
325
                METADATA_DEFINITION_NAME, METADATA_DEFINITION_DESCRIPTION);
326

    
327
            metadataDefinition.addDynFieldObject("Envelope").setClassOfValue(Envelope.class).setMandatory(false);
328
            metadataDefinition.addDynFieldObject("CRS").setClassOfValue(IProjection.class).setMandatory(true);
329

    
330
            metadataDefinition.extend(metadataManager
331
                .getDefinition(FeatureStore.METADATA_DEFINITION_NAME));
332
        }
333
    }
334

    
335
    /* (non-Javadoc)
336
     * @see org.gvsig.fmap.dal.feature.spi.AbstractFeatureStoreProvider#getExplorer()
337
     */
338
    public DataServerExplorer getExplorer() throws ReadException {
339
        DataManager manager = DALLocator.getDataManager();
340
        WFSServerExplorerParameters params;
341
        try {
342
            params = (WFSServerExplorerParameters) manager
343
            .createServerExplorerParameters(WFSServerExplorer.NAME);
344
            params.setUrl(wfsClient.getHost());
345
            return manager.openServerExplorer(WFSServerExplorer.NAME,params);
346
        } catch (Exception e) {
347
            throw new ReadException(this.getName(), e);
348
        }
349
    }
350

    
351
    public String getProviderName() {
352
        return NAME;
353
    }
354

    
355
    public FeatureSetProvider createSet(FeatureQuery query)
356
    throws DataException {
357
        return createSet(query, null);
358
    }
359

    
360
    public FeatureSetProvider createSet(FeatureQuery query,
361
        FeatureType featureType) throws DataException {
362
        if ((featureCount == -1) ||
363
            (storeProviderDelegate == null) ||
364
            (featureCount >= wfsStatus.getMaxFeatures())){ 
365

    
366
            File file = null;
367

    
368
            if (query == null){
369
                file = executeQuery();   
370
            }else{
371
                //If it is possible to execute a spatial query...
372
                if ((query.getFilter() != null) && (!hasFilterByArea)){
373
                    file = executeSpatialQuery(query);
374
                }else{
375
                    file = executeQuery();   
376
                }        
377

    
378
            }
379
            storeProviderDelegate = createProvider(file);
380
        }
381
        
382
        return storeProviderDelegate.createSet(query, featureType);
383
    }
384

    
385
    /**
386
     * It creates the provider that is used to retrieve features from a file.
387
     * @param file
388
     * the file that contains the downloaded file
389
     * @return
390
     * @throws InitializeException
391
     * @throws ProviderNotRegisteredException
392
     */
393
    private GPEStoreProvider createProvider(File file) throws InitializeException, ProviderNotRegisteredException{
394
        return new GPEStoreProvider(createStoreParameters(file), getStoreServices());
395
    }        
396

    
397
    private DataStoreParameters createStoreParameters(File file) throws InitializeException, ProviderNotRegisteredException{
398
        DataStoreParameters parameters = dataManager.createStoreParameters(GPEStoreProvider.NAME);
399

    
400
        parameters.setDynValue("File", file.getAbsolutePath());
401
        parameters.setDynValue("Envelope", this.getDynValue("Envelope"));
402
        return parameters;
403
    }
404

    
405
    /**
406
     * It executes a wfs Query without spatial filter
407
     * @throws DataException
408
     */
409
    private File executeQuery() throws DataException{
410
        try{
411
            wfsStatus.setResultType(WFSStatus.RESULTYPE_RESULTS);
412
            if (!hasFilterByArea){
413
                wfsStatus.removeFilterByArea();
414
            }
415
            return wfsClient.getFeature(wfsStatus, true, null);
416
        } catch (WFSException e) {
417
            throw new InitializeException("Impossible to retrieve the file", e);
418
        }
419
    }
420

    
421
    /**
422
     * Executes a new query sending the FilterEncoding request to the server
423
     * @param query
424
     * The Query to send
425
     * @throws InitializeException
426
     * If there is a problem with the request or the parsing process
427
     */
428
    private File executeSpatialQuery(FeatureQuery query) throws DataException{
429
        EvaluatorFieldsInfo fieldsInfo = query.getFilter().getFieldsInfo();
430
        String[] fields = fieldsInfo.getFieldNames();
431
        for (int i=0 ; i<fields.length ; i++){
432
            EvaluatorFieldValue[] evaluatorFieldValues = fieldsInfo.getFieldValues(fields[i]);
433
            for (int j=0 ; j<evaluatorFieldValues.length ; j++){                                
434
                if (EvaluatorFieldValue.MATCH == evaluatorFieldValues[j].getType()){
435
                    EvaluatorFieldValueMatch evaluatorFieldValueMatch = (EvaluatorFieldValueMatch)evaluatorFieldValues[j];
436
                    Object area = evaluatorFieldValueMatch.getValue();
437
                    if (area instanceof Envelope){
438
                        return executeSpatialQueryFromEnvelope(evaluatorFieldValueMatch.getFieldName(),
439
                            (Envelope)area);                                        
440
                    }else if (area instanceof Geometry){
441
                        return executeSpatialQueryFromGeometry(evaluatorFieldValueMatch.getFieldName(),
442
                            (Geometry)area);                                                
443
                    }
444
                }
445
            }                        
446
        }
447
        return null;
448
    }
449

    
450
    private File executeSpatialQueryFromGeometry(String the_geom, Geometry geometry) throws DataException{
451
        wfsStatus.setFilterByArea(geometry, the_geom, projection.getAbrev(), 
452
            FilterEncoding.GEOMETRIC_OPERATOR_CONTAINS);
453
        return executeSpatialQuery();
454
    }
455

    
456
    private File executeSpatialQueryFromEnvelope(String the_geom, Envelope envelope) throws DataException{
457
        wfsStatus.setFilterByArea(envelope, the_geom, projection.getAbrev(), 
458
            FilterEncoding.GEOMETRIC_OPERATOR_CONTAINS);                
459
        return executeSpatialQuery();
460
    }
461

    
462
    private File executeSpatialQuery() throws DataException{
463
        try {
464
            wfsStatus.setProtocol(OGCClientOperation.PROTOCOL_POST);
465
            //If it is not possible to calculate the 
466
            wfsStatus.setResultType(WFSStatus.RESULTYPE_RESULTS);
467
            return wfsClient.getFeature(wfsStatus, true, null);
468
        } catch (WFSException e) {
469
            throw new InitializeException("Impossible to retrieve the file", e);
470
        }
471
    }                
472

    
473
    public Object getSourceId() {
474
        StringBuffer sourceID = new StringBuffer(getWFSParameters().getUrl());
475
        sourceID.append("_" + getWFSParameters().getFeatureType());
476
        int hash = sourceID.hashCode();
477
        if (sourceID.length() > 60){
478
            return sourceID.substring(0, 60) + "_" + hash;
479
        }else{
480
            return sourceID.toString() + "_" + hash;
481
        }
482
    }
483
   
484
    public Object createNewOID() {        
485
        try {
486
            return String.valueOf(getFeatureCount()+1);
487
        } catch (DataException e) {
488
            return String.valueOf(Math.random());
489
        }
490
    }
491

    
492
    public long getFeatureCount() throws DataException {
493
        if (featureCount == -1){
494
            wfsStatus.setResultType(WFSStatus.RESULTYPE_HITS);
495
            try {
496
                //The filter encoding is better supported using POST
497
                if (hasFilterByArea){
498
                    wfsStatus.setProtocol(OGCClientOperation.PROTOCOL_POST);
499
                }else{
500
                    wfsStatus.setProtocol(OGCClientOperation.PROTOCOL_GET);
501
                }
502
                File file = wfsClient.getFeature(wfsStatus, true, null);
503
                featureCount = ((WFSGetFeatureRequestInformation)wfsClient.getLastWfsRequestInformation()).getNumberOfFeatures();
504
                //If the service doesn't support RESULTTYPE_HITS, parse the file and get the FeatureCount
505
                if (featureCount == -1){
506
                    storeProviderDelegate = createProvider(file);
507
                    featureCount = storeProviderDelegate.getFeatureCount();
508
                }
509
            } catch (WFSException e) {
510
                throw new ConnectionServerException("Error calculating the feature count", e);
511
            }
512
        }
513
        return featureCount;
514
    }
515

    
516
    public int getOIDType() {
517
        return DataTypes.STRING;
518
    }
519

    
520
    public ResourceProvider getResource() {
521
        return storeProviderDelegate.getResource();
522
    }
523

    
524
    protected FeatureProvider internalGetFeatureProviderByReference(
525
        FeatureReferenceProviderServices reference, FeatureType featureType)
526
    throws DataException {
527
        return storeProviderDelegate.internalGetFeatureProviderByReference(reference, featureType);
528
    }
529

    
530
    public String getFullName() {       
531
        return getWFSParameters().getUrl() + "_" + getWFSParameters().getFeatureType();
532
    }
533

    
534
    public String getName() {        
535
        return getFullName();
536
    }
537

    
538
    public boolean isKnownEnvelope(){  
539
        return isKnownEnvelope;
540
    }
541

    
542
    public boolean hasRetrievedFeaturesLimit(){
543
        return true;
544
    }
545

    
546
    public int getRetrievedFeaturesLimit(){
547
        //WFS 1.0.0 can not know where is the limit
548
        if (getWFSParameters().getVersion().equals("1.0.0")){
549
            return 0;
550
        }else{
551
            return wfsClient.getServiceInformation().getMaxFeatures();
552
        }
553
    }
554

    
555
    public void performChanges(Iterator deleteds, Iterator inserteds,
556
        Iterator updateds, Iterator featureTypesChanged)
557
    throws DataException {
558
        WFSTTransactionBuilder transactionBuilder = new WFSTTransactionBuilder(wfsStatus, wfsClient);
559

    
560
        //Create the Query
561
        try {
562
            //Add new features
563
            while (inserteds.hasNext()){
564
                transactionBuilder.addInsertFeature((FeatureProvider)inserteds.next());
565
            }
566
            //Add deleted features
567
            while (deleteds.hasNext()){
568
                transactionBuilder.addDeleteFeature(
569
                    internalGetFeatureProviderByReference((FeatureReferenceProviderServices)deleteds.next(), null).getOID().toString());;
570
            }
571
            //Add updated features
572
            while (updateds.hasNext()){
573
                transactionBuilder.addUpdateFeature((FeatureProvider)updateds.next());
574
            }
575
        } catch (WriterHandlerCreationException e) {
576
            throw new WFSTTRansactionException(e);
577
        } catch (GeometryOperationNotSupportedException e) {
578
            throw new WFSTTRansactionException(e);
579
        } catch (GeometryOperationException e) {
580
            throw new WFSTTRansactionException(e);
581
        }
582
        
583
        //Send the query to the server
584
        try {
585
            wfsClient.transaction(wfsStatus, true, null);
586
            WFSTransactionRequestInformation transactionRequestInformation =  (WFSTransactionRequestInformation)wfsClient.getLastWfsRequestInformation();
587
            if (transactionRequestInformation.getStatus() == WFSTransactionRequestInformation.STATUS_FAILED){
588
                throw new WFSTTRansactionException(transactionRequestInformation.getMessage());
589
            }
590
        } catch (WFSException e) {
591
            throw new WFSTTRansactionException(e);
592
        }
593
    }
594

    
595
    public boolean allowWrite() {
596
        return wfsClient.getServiceInformation().isOperationSupported("Transaction");
597
    }
598

    
599
    public Envelope getEnvelope() throws DataException {        
600
        return (Envelope) this.getDynValue("Envelope");
601
    }
602

    
603
    public FeatureProvider createFeatureProvider(FeatureType type)
604
    throws DataException {       
605
        return super.createFeatureProvider(type);
606
    }
607

    
608

    
609
}
610