Statistics
| Revision:

root / branches / v2_0_0_prep / libraries / libRemoteServices / src / org / gvsig / remoteclient / wfs / WFSProtocolHandler.java @ 33983

History | View | Annotate | Download (14.6 KB)

1
package org.gvsig.remoteclient.wfs;
2

    
3
import java.io.File;
4
import java.net.URL;
5
import java.util.ArrayList;
6
import java.util.Hashtable;
7
import java.util.Set;
8
import java.util.StringTokenizer;
9
import java.util.Vector;
10

    
11
import org.kxml2.io.KXmlParser;
12

    
13
import org.gvsig.compat.net.ICancellable;
14
import org.gvsig.remoteclient.ogc.OGCProtocolHandler;
15
import org.gvsig.remoteclient.ogc.OGCServiceInformation;
16
import org.gvsig.remoteclient.utils.CapabilitiesTags;
17
import org.gvsig.remoteclient.wfs.edition.WFSTTransaction;
18
import org.gvsig.remoteclient.wfs.exceptions.WFSException;
19
import org.gvsig.remoteclient.wfs.request.WFSDescribeFeatureTypeRequest;
20
import org.gvsig.remoteclient.wfs.request.WFSGetFeatureRequest;
21
import org.gvsig.remoteclient.wfs.request.WFSTLockFeatureRequest;
22
import org.gvsig.remoteclient.wfs.schema.GMLTags;
23

    
24
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
25
 *
26
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
27
 *
28
 * This program is free software; you can redistribute it and/or
29
 * modify it under the terms of the GNU General Public License
30
 * as published by the Free Software Foundation; either version 2
31
 * of the License, or (at your option) any later version.
32
 *
33
 * This program is distributed in the hope that it will be useful,
34
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
35
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
36
 * GNU General Public License for more details.
37
 *
38
 * You should have received a copy of the GNU General Public License
39
 * along with this program; if not, write to the Free Software
40
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
41
 *
42
 * For more information, contact:
43
 *
44
 *  Generalitat Valenciana
45
 *   Conselleria d'Infraestructures i Transport
46
 *   Av. Blasco Ib??ez, 50
47
 *   46010 VALENCIA
48
 *   SPAIN
49
 *
50
 *      +34 963862235
51
 *   gvsig@gva.es
52
 *      www.gvsig.gva.es
53
 *
54
 *    or
55
 *
56
 *   IVER T.I. S.A
57
 *   Salamanca 50
58
 *   46005 Valencia
59
 *   Spain
60
 *
61
 *   +34 963163400
62
 *   dac@iver.es
63
 */
64
/* CVS MESSAGES:
65
 *
66
 * $Id: WFSProtocolHandler.java 33983 2010-10-27 12:37:48Z nbrodin $
67
 * $Log$
68
 * Revision 1.11  2007-09-20 09:30:12  jaume
69
 * removed unnecessary imports
70
 *
71
 * Revision 1.10  2007/02/09 14:11:01  jorpiell
72
 * Primer piloto del soporte para WFS 1.1 y para WFS-T
73
 *
74
 * Revision 1.9  2007/01/12 13:09:42  jorpiell
75
 * added searches by area
76
 *
77
 * Revision 1.8  2006/10/10 12:52:28  jorpiell
78
 * Soporte para features complejas.
79
 *
80
 * Revision 1.7  2006/06/21 12:53:03  jorpiell
81
 * Se tienen en cuanta el n?mero de features
82
 *
83
 * Revision 1.6  2006/06/14 08:46:07  jorpiell
84
 * Se tiene en cuanta la opcion para refrescar las capabilities
85
 *
86
 * Revision 1.5  2006/06/14 07:54:18  jorpiell
87
 * Se parsea el online resource que antes se ignoraba
88
 *
89
 * Revision 1.4  2006/05/30 13:58:03  jaume
90
 * cancelable downloads
91
 *
92
 * Revision 1.3  2006/05/23 13:23:13  jorpiell
93
 * Se ha cambiado el final del bucle de parseado y se tiene en cuenta el online resource
94
 *
95
 * Revision 1.2  2006/04/20 16:39:16  jorpiell
96
 * A?adida la operacion de describeFeatureType y el parser correspondiente.
97
 *
98
 * Revision 1.1  2006/04/19 12:51:35  jorpiell
99
 * A?adidas algunas de las clases del servicio WFS
100
 *
101
 *
102
 */
103
/**
104
 * @author Jorge Piera Llodr? (piera_jor@gva.es)
105
 */
106
public abstract class WFSProtocolHandler extends OGCProtocolHandler {
107
        /**
108
         * WFS metadata
109
         */
110
        protected WFSServiceInformation serviceInfo = new WFSServiceInformation();
111
        protected Hashtable features = new Hashtable();
112
        protected String currentFeature = null;
113
        private int numberOfErrors = 0;
114

    
115
        /**
116
         * This class contains all the data that the library is able
117
         * to retrieve of the server for all the requests. 
118
         */
119
        protected ArrayList wfsRequestInformations = new ArrayList();
120

    
121
        /**
122
         * Clear the connection
123
         */
124
        private void clear() {
125
                features.clear();
126
                serviceInfo.clear();
127
        }
128

    
129
        /**
130
         * <p>Builds a GetCapabilities request that is sent to the WFS
131
         * the response will be parse to extract the data needed by the
132
         * WFS client</p>
133
         */
134
        public void getCapabilities(WFSStatus status,boolean override, ICancellable cancel) throws WFSException {
135
                URL request = null;
136
                try {
137
                        request = new URL(buildCapabilitiesRequest(status));
138
                        if (override){
139
                            downloader.removeURL(request);
140
                        }
141
                        File f = downloader.downloadFile(request,"wfs_capabilities.xml", cancel);
142
                        if (f == null)
143
                                return;
144
                        clear();
145
                        parseCapabilities(f);
146
                } catch (Exception e){
147
                        throw new WFSException(e);
148
                }
149
        }    
150

    
151
        /**
152
         * @return
153
         */
154
        private String buildCapabilitiesRequest(WFSStatus status) {
155
                StringBuffer req = new StringBuffer();
156
                String symbol = null;
157

    
158
                String onlineResource;
159
                if (status == null || status.getOnlineResource() == null)
160
                        onlineResource = getHost();
161
                else 
162
                        onlineResource = status.getOnlineResource();
163
                symbol = getSymbol(onlineResource);
164

    
165
                req.append(onlineResource).append(symbol).append("REQUEST=GetCapabilities&SERVICE=WFS&");
166
                req.append("VERSION=").append(getVersion()).append("&EXCEPTIONS=XML");
167
                return req.toString();
168
        }   
169

    
170
        /**
171
         * Builds the GetCapabilitiesRequest according to the OGC WFS Specifications
172
         * without a VERSION, to get the highest version than a WFS supports.
173
         */
174
        public static String buildCapabilitiesSuitableVersionRequest(String _host, String _version)
175
        {
176
                int index = _host.indexOf('?');
177

    
178
                if (index > -1) {
179
                        String host = _host.substring(0, index + 1);
180
                        String query = _host.substring(index + 1, _host.length());
181

    
182
                        StringTokenizer tokens = new StringTokenizer(query, "&");
183
                        String newQuery = "", token;
184

    
185
                        // If there is a field or a value with spaces, (and then it's on different tokens) -> unify them
186
                        while (tokens.hasMoreTokens()) {
187
                                token = tokens.nextToken().trim();
188

    
189
                                if (token.toUpperCase().compareTo("REQUEST=GETCAPABILITIES") == 0)
190
                                        continue;
191

    
192
                                if (token.toUpperCase().compareTo("SERVICE=WFS") == 0)
193
                                        continue;
194

    
195
                                if ((_version != null) && (_version.length() > 0)) {
196
                                        if (token.toUpperCase().compareTo("VERSION=" + _version) == 0)
197
                                                continue;
198
                                }
199

    
200
                                if (token.toUpperCase().compareTo("EXCEPTIONS=XML") == 0)
201
                                        continue;
202

    
203
                                newQuery += token + "&";
204
                        }
205

    
206
                        _host = host + newQuery;
207
                }
208
                else {
209
                        _host += "?";
210
                }
211

    
212
                if ((_version != null) && (_version.compareTo("") != 0))
213
                        _host += "REQUEST=GetCapabilities&SERVICE=WFS&VERSION=" + _version + "&EXCEPTIONS=XML";
214
                else
215
                        _host += "REQUEST=GetCapabilities&SERVICE=WFS&EXCEPTIONS=XML";
216

    
217
                return _host;    
218
        }
219

    
220
        /**
221
         * <p>Builds a describeFeatureType request that is sent to the WFS
222
         * the response will be parse to extract the data needed by the
223
         * WFS client</p>
224
         * @param status
225
         * WFS client status. Contains all the information to create
226
         * the query. In this case, the only the feature name is needed.
227
         */
228
        public void describeFeatureType(WFSStatus status,boolean override, ICancellable cancel)throws WFSException {
229
                this.currentFeature = status.getFeatureName();
230
                //sets the namespace URI and the namespace prefix
231
                int index = currentFeature.indexOf(":");
232
                if (index > 0){
233
                        String namespacePrefix = currentFeature.substring(0, index);
234
                        String namespaceURI = serviceInfo.getNamespace(namespacePrefix);
235
                        if (namespaceURI != null){
236
                                status.setNamespace(namespaceURI);
237
                                status.setNamespacePrefix(namespacePrefix);
238
                        }
239
                }
240
                try {
241
                        WFSDescribeFeatureTypeRequest request = createDescribeFeatureTypeRequest(status);
242
                        File f = request.sendRequest(cancel);
243
                        parseDescribeFeatureType(f,status.getNamespacePrefix());
244
                } catch (Exception e){
245
                        throw new WFSException(e);
246
                }
247
        }             
248

    
249
        /**
250
         * parses the data retrieved by the DescribeCoverage XML document
251
         */
252
        protected abstract boolean parseDescribeFeatureType(File f,String nameSpace);
253

    
254
        /**
255
         * <p>Builds a getFeature request that is sent to the WFS
256
         * the response will be parse to extract the data needed by the
257
         * WFS client</p>
258
         * @param status
259
         * WFS client status. Contains all the information to create
260
         * the query. 
261
         * @return File
262
         * GML file
263
         */    
264
        public File getFeature(WFSStatus status,boolean override, ICancellable cancel) throws WFSException{
265
                try{                
266
                        WFSGetFeatureRequest request = createGetFeatureRequest(status);
267
                        File f = request.sendRequest(cancel);                        
268
                        parseGetFeature(f, status.getNamespacePrefix());
269
                        return f;
270
                } catch (Exception e){
271
                        throw new WFSException(e);
272
                }                
273
        }
274

    
275
        /**
276
         * parses the data retrieved by the GetFeature XML document. It is
277
         * used just to find errors
278
         */
279
        protected abstract boolean parseGetFeature(File f,String nameSpace) throws WFSException;
280

    
281

    
282
        /**
283
         * <p>Builds a transaction request that is sent to the WFS
284
         * the response will be parse to extract the data needed by the
285
         * WFS client</p>
286
         * @param status
287
         * WFS client status. Contains all the information to create
288
         * the query. 
289
         */   
290
        public void transaction(WFSStatus status,boolean override, ICancellable cancel) throws WFSException {
291
                URL request = null;
292
                try {
293
                        request = new URL(buildTransactionRequest(status));
294
                        for (int i=0 ; i<status.getTransactionsSize() ; i++){
295
                                WFSTTransaction transaction = status.getTransactionAt(i);
296
                                if (transaction.getStatus() == WFSTTransaction.STATUS_NO_EXECUTED){
297
                                        System.out.println(transaction.getWFSTRequest());
298
                                        File f = downloader.downloadFile(request, 
299
                                                        transaction.getWFSTRequest(),
300
                                                        "wfs_transaction.xml", null);
301
                                        parseTransaction(f,status.getNamespacePrefix(),transaction);        
302
                                        //If the transaction has been executed with success,
303
                                        //it is necessary to remove the getFeature file from the
304
                                        //downloader manager. 
305
                                        if (transaction.getStatus() == WFSTTransaction.STATUS_SUCCESS){
306
                                                WFSGetFeatureRequest requestAux = createGetFeatureRequest(status);
307
                                                requestAux.setDeleted(true);
308
                                                requestAux.sendRequest(cancel);
309
                                        }
310
                                }
311
                        }                        
312
                } catch (Exception e){
313
                        throw new WFSException(e);
314
                }
315
        }
316

    
317
        /**
318
         * <p>Builds a transaction request that is sent to the WFS
319
         * the response will be parse to extract the data needed by the
320
         * WFS client</p>
321
         * @param status
322
         * WFS client status. Contains all the information to create
323
         * the query. 
324
         */
325
        private String buildTransactionRequest(WFSStatus status){
326
                StringBuffer req = new StringBuffer();
327
                String symbol = null;
328

    
329
                String onlineResource;
330
                if(serviceInfo.getOnlineResource(CapabilitiesTags.WFS_TRANSACTION) != null){
331
                        onlineResource = serviceInfo.getOnlineResource(CapabilitiesTags.WFS_TRANSACTION);
332
                }else {
333
                        onlineResource = getHost();
334
                }
335
                symbol = getSymbol(onlineResource);
336

    
337
                req.append(onlineResource);
338
                return req.toString();
339
        }
340

    
341
        /**
342
         * parses the data retrieved by the transaction operation
343
         * @param f
344
         * The retrieved file
345
         * @param nameSpace
346
         * The namespace
347
         * @param transaction
348
         * The current WFSTransaction
349
         */
350
        protected abstract boolean parseTransaction(File f,String nameSpace, WFSTTransaction transaction) throws WFSException;
351

    
352
        /**
353
         * <p>Builds a lockFeature request that is sent to the WFS
354
         * the response will be parse to extract the data needed by the
355
         * WFS client</p>
356
         * @param status
357
         * WFS client status. Contains all the information to create
358
         * the query. 
359
         */  
360
        public void lockFeature(WFSStatus status,boolean override, ICancellable cancel) throws WFSException {
361
                try {
362
                        WFSTLockFeatureRequest request = createLockFeatureRequest(status);
363
                        File f = request.sendRequest(cancel);
364
                        parseLockFeature(f,status.getNamespacePrefix(),status);
365
                } catch(WFSException e) {
366
                        throw e;
367
                } catch (Exception e){
368
                        throw new WFSException(e);
369
                }                
370
        }        
371

    
372
        /**
373
         * parses the data retrieved by the LockFeature operation
374
         */
375
        protected abstract boolean parseLockFeature(File f,String nameSpace, WFSStatus status) throws WFSException;
376

    
377
        /**
378
         * @return Returns the features.
379
         */
380
        public Hashtable getFeatures() {
381
                return features;
382
        }
383

    
384
        /**
385
         * @return Returns the currentFeature.
386
         */
387
        public String getCurrentFeature() {
388
                return currentFeature;
389
        }
390

    
391
        /**
392
         * Sets the fields of the current feature
393
         * @param fields
394
         */
395
        public void setFields(Vector fields){
396
                WFSFeature feature = (WFSFeature) features.get(currentFeature);
397
                feature.setFields(fields);
398
                features.put(feature.getName(),feature);                
399
        }
400

    
401
        /**
402
         * Sets the fields of the current feature
403
         * @param fields
404
         */
405
        public void setFields(Hashtable fields){
406
                WFSFeature feature = (WFSFeature) features.get(currentFeature);
407
                Vector vFields = new Vector();
408
                Set keys = fields.keySet();
409
                for (int i=0 ; i<keys.size() ; i++){
410
                        vFields.add(fields.get(keys.toArray()[i]));
411
                }
412
                feature.setFields(vFields);
413
                features.put(feature.getName(),feature);                
414
        }
415

    
416

    
417
        /**
418
         * @param currentFeature The currentFeature to set.
419
         */
420
        public void setCurrentFeature(String currentFeature) {
421
                this.currentFeature = currentFeature;
422
        }    
423

    
424
        /**
425
         * It parses the attributes of the current KXMLParser 
426
         * and add the new namespaces to the service information
427
         * @param parser
428
         * The KXML parser
429
         */
430
        protected void parseNamespaces(KXmlParser parser){
431
                for (int i=0 ; i<parser.getAttributeCount() ; i++){
432
                        String attName = parser.getAttributeName(i);
433
                        if (attName.startsWith(GMLTags.XML_NAMESPACE)){
434
                                int index = attName.indexOf(":");
435
                                if (index > 0){
436
                                        serviceInfo.addNamespace(attName.substring(index+1, attName.length()), 
437
                                                        parser.getAttributeValue(i));
438
                                }
439
                        }
440
                }                        
441
        }
442

    
443
        /* (non-Javadoc)
444
         * @see org.gvsig.remoteClient.ogc.OGCProtocolHandler#getServiceInformation()
445
         */
446
        public OGCServiceInformation getServiceInformation() {
447
                return serviceInfo;
448
        }        
449

    
450
        /**
451
         * @param status
452
         * The WFS status
453
         * @param protocolHandler
454
         * The handler to parse the requests
455
         * @return an object to send the DescribeFeatureType requests
456
         */
457
        protected abstract WFSDescribeFeatureTypeRequest createDescribeFeatureTypeRequest(WFSStatus status);
458

    
459
        /**
460
         * @param status
461
         * The WFS status
462
         * @param protocolHandler
463
         * The handler to parse the requests
464
         * @return an object to send the GetFeature requests
465
         */
466
        protected abstract WFSGetFeatureRequest createGetFeatureRequest(WFSStatus status);
467

    
468
        /**
469
         * @param status
470
         * The WFS status
471
         * @param protocolHandler
472
         * The handler to parse the requests
473
         * @return an object to send the LockFeature requests
474
         */
475
        protected abstract WFSTLockFeatureRequest createLockFeatureRequest(WFSStatus status);
476

    
477
        /**
478
         * @return the wfsRequestInformations
479
         */
480
        ArrayList getWfsRequestInformations() {
481
                return wfsRequestInformations;
482
        }
483

    
484
        /**
485
         * Adds a new WFSRequestInformation
486
         * @param wfsRequestInformation
487
         */
488
        public void addLastWfsRequestInformation(
489
                        WFSRequestInformation wfsRequestInformation) {
490
                wfsRequestInformations.add(wfsRequestInformation);                
491
        }
492
        
493
        /**
494
         * @return the lastWfsRequestInformation
495
         */
496
        public WFSRequestInformation getLastWfsRequestInformation() {
497
                if (wfsRequestInformations.size() > 0){
498
                        return (WFSRequestInformation)wfsRequestInformations.get(wfsRequestInformations.size() - 1);
499
                }
500
                return null;
501
        }
502
}