Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / libraries / libRemoteServices / src / org / gvsig / remoteclient / wfs / WFSProtocolHandler.java @ 34026

History | View | Annotate | Download (13.7 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.StringTokenizer;
8

    
9
import org.kxml2.io.KXmlParser;
10
import org.slf4j.Logger;
11
import org.slf4j.LoggerFactory;
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 34026 2010-11-08 13:06:02Z jpiera $
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
        protected static Logger LOG = LoggerFactory.getLogger(WFSProtocolHandler.class);
108
        
109
    /**
110
         * WFS metadata
111
         */
112
        protected WFSServiceInformation serviceInfo = new WFSServiceInformation();
113
        protected Hashtable features = new Hashtable();
114
        protected String currentFeature = null;
115
        private int numberOfErrors = 0;
116

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

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

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

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

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

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

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

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

    
184
                        StringTokenizer tokens = new StringTokenizer(query, "&");
185
                        String newQuery = "", token;
186

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

    
191
                                if (token.toUpperCase().compareTo("REQUEST=GETCAPABILITIES") == 0)
192
                                        continue;
193

    
194
                                if (token.toUpperCase().compareTo("SERVICE=WFS") == 0)
195
                                        continue;
196

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

    
202
                                if (token.toUpperCase().compareTo("EXCEPTIONS=XML") == 0)
203
                                        continue;
204

    
205
                                newQuery += token + "&";
206
                        }
207

    
208
                        _host = host + newQuery;
209
                }
210
                else {
211
                        _host += "?";
212
                }
213

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

    
219
                return _host;    
220
        }
221

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

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

    
269
        /**
270
         * parses the data retrieved by the GetFeature XML document. It is
271
         * used just to find errors
272
         */
273
        protected abstract boolean parseGetFeature(File f,String nameSpace) throws WFSException;
274

    
275

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

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

    
323
                String onlineResource;
324
                if(serviceInfo.getOnlineResource(CapabilitiesTags.WFS_TRANSACTION) != null){
325
                        onlineResource = serviceInfo.getOnlineResource(CapabilitiesTags.WFS_TRANSACTION);
326
                }else {
327
                        onlineResource = getHost();
328
                }
329
                symbol = getSymbol(onlineResource);
330

    
331
                req.append(onlineResource);
332
                return req.toString();
333
        }
334

    
335
        /**
336
         * parses the data retrieved by the transaction operation
337
         * @param f
338
         * The retrieved file
339
         * @param nameSpace
340
         * The namespace
341
         * @param transaction
342
         * The current WFSTransaction
343
         */
344
        protected abstract boolean parseTransaction(File f,String nameSpace, WFSTTransaction transaction) throws WFSException;
345

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

    
366
        /**
367
         * parses the data retrieved by the LockFeature operation
368
         */
369
        protected abstract boolean parseLockFeature(File f,String nameSpace, WFSStatus status) throws WFSException;
370

    
371
        /**
372
         * @return Returns the features.
373
         */
374
        public Hashtable getFeatures() {
375
                return features;
376
        }
377

    
378
        /**
379
         * @return Returns the currentFeature.
380
         */
381
        public String getCurrentFeature() {
382
                return currentFeature;
383
        }
384

    
385
        /**
386
         * @param currentFeature The currentFeature to set.
387
         */
388
        public void setCurrentFeature(String currentFeature) {
389
                this.currentFeature = currentFeature;
390
        }    
391

    
392
        /**
393
         * It parses the attributes of the current KXMLParser 
394
         * and add the new namespaces to the service information
395
         * @param parser
396
         * The KXML parser
397
         */
398
        protected void parseNamespaces(KXmlParser parser){
399
                for (int i=0 ; i<parser.getAttributeCount() ; i++){
400
                        String attName = parser.getAttributeName(i);
401
                        if (attName.startsWith(GMLTags.XML_NAMESPACE)){
402
                                int index = attName.indexOf(":");
403
                                if (index > 0){
404
                                        serviceInfo.addNamespace(attName.substring(index+1, attName.length()), 
405
                                                        parser.getAttributeValue(i));
406
                                }
407
                        }
408
                }                        
409
        }
410

    
411
        /* (non-Javadoc)
412
         * @see org.gvsig.remoteClient.ogc.OGCProtocolHandler#getServiceInformation()
413
         */
414
        public OGCServiceInformation getServiceInformation() {
415
                return serviceInfo;
416
        }        
417

    
418
        /**
419
         * @param status
420
         * The WFS status
421
         * @param protocolHandler
422
         * The handler to parse the requests
423
         * @return an object to send the DescribeFeatureType requests
424
         */
425
        protected abstract WFSDescribeFeatureTypeRequest createDescribeFeatureTypeRequest(WFSStatus status);
426

    
427
        /**
428
         * @param status
429
         * The WFS status
430
         * @param protocolHandler
431
         * The handler to parse the requests
432
         * @return an object to send the GetFeature requests
433
         */
434
        protected abstract WFSGetFeatureRequest createGetFeatureRequest(WFSStatus status);
435

    
436
        /**
437
         * @param status
438
         * The WFS status
439
         * @param protocolHandler
440
         * The handler to parse the requests
441
         * @return an object to send the LockFeature requests
442
         */
443
        protected abstract WFSTLockFeatureRequest createLockFeatureRequest(WFSStatus status);
444

    
445
        /**
446
         * @return the wfsRequestInformations
447
         */
448
        ArrayList getWfsRequestInformations() {
449
                return wfsRequestInformations;
450
        }
451

    
452
        /**
453
         * Adds a new WFSRequestInformation
454
         * @param wfsRequestInformation
455
         */
456
        public void addLastWfsRequestInformation(
457
                        WFSRequestInformation wfsRequestInformation) {
458
                wfsRequestInformations.add(wfsRequestInformation);                
459
        }
460
        
461
        /**
462
         * @return the lastWfsRequestInformation
463
         */
464
        public WFSRequestInformation getLastWfsRequestInformation() {
465
                if (wfsRequestInformations.size() > 0){
466
                        return (WFSRequestInformation)wfsRequestInformations.get(wfsRequestInformations.size() - 1);
467
                }
468
                return null;
469
        }
470
}