Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.remoteclient / src / main / java / org / gvsig / remoteclient / wfs / WFSProtocolHandler.java @ 40559

History | View | Annotate | Download (14.2 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 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.remoteclient.wfs;
25

    
26
import java.io.File;
27
import java.net.URL;
28
import java.util.ArrayList;
29
import java.util.Hashtable;
30
import java.util.StringTokenizer;
31

    
32
import org.gvsig.compat.net.ICancellable;
33
import org.gvsig.remoteclient.ogc.OGCProtocolHandler;
34
import org.gvsig.remoteclient.ogc.OGCServiceInformation;
35
import org.gvsig.remoteclient.utils.CapabilitiesTags;
36
import org.gvsig.remoteclient.wfs.exceptions.WFSException;
37
import org.gvsig.remoteclient.wfs.request.WFSDescribeFeatureTypeRequest;
38
import org.gvsig.remoteclient.wfs.request.WFSGetFeatureRequest;
39
import org.gvsig.remoteclient.wfs.request.WFSTLockFeatureRequest;
40
import org.gvsig.remoteclient.wfs.request.WFSTransactionRequest;
41
import org.gvsig.remoteclient.wfs.schema.GMLTags;
42
import org.kxml2.io.KXmlParser;
43

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

    
137
        /**
138
         * This class contains all the data that the library is able
139
         * to retrieve of the server for all the requests. 
140
         */
141
        protected ArrayList wfsRequestInformations = new ArrayList();
142

    
143
        /**
144
         * Clear the connection
145
         */
146
        private void clear() {
147
                features.clear();
148
                serviceInfo.clear();
149
        }
150

    
151
        /**
152
         * <p>Builds a GetCapabilities request that is sent to the WFS
153
         * the response will be parse to extract the data needed by the
154
         * WFS client</p>
155
         */
156
        public void getCapabilities(WFSStatus status,boolean override, ICancellable cancel) throws WFSException {
157
                URL request = null;
158
                try {
159
                        request = new URL(buildCapabilitiesRequest(status));
160
                        if (override){
161
                            downloader.removeURL(request);
162
                        }
163
                        File f = downloader.downloadFile(request,"wfs_capabilities.xml", cancel);
164
                        if (f == null)
165
                                return;
166
                        clear();
167
                        parseCapabilities(f);
168
                } catch (Exception e){
169
                        throw new WFSException(e);
170
                }
171
        }    
172

    
173
        /**
174
         * @return
175
         */
176
        private String buildCapabilitiesRequest(WFSStatus status) {
177
                StringBuffer req = new StringBuffer();
178
                String symbol = null;
179

    
180
                String onlineResource;
181
                if (status == null || status.getOnlineResource() == null)
182
                        onlineResource = getHost();
183
                else 
184
                        onlineResource = status.getOnlineResource();
185
                symbol = getSymbol(onlineResource);
186

    
187
                req.append(onlineResource).append(symbol).append("REQUEST=GetCapabilities&SERVICE=WFS&");
188
                req.append("VERSION=").append(getVersion()).append("&EXCEPTIONS=XML");
189
                return req.toString();
190
        }   
191

    
192
        /**
193
         * Builds the GetCapabilitiesRequest according to the OGC WFS Specifications
194
         * without a VERSION, to get the highest version than a WFS supports.
195
         */
196
        public static String buildCapabilitiesSuitableVersionRequest(String _host, String _version)
197
        {
198
                int index = _host.indexOf('?');
199

    
200
                if (index > -1) {
201
                        String host = _host.substring(0, index + 1);
202
                        String query = _host.substring(index + 1, _host.length());
203

    
204
                        StringTokenizer tokens = new StringTokenizer(query, "&");
205
                        String newQuery = "", token;
206

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

    
211
                                if (token.toUpperCase().compareTo("REQUEST=GETCAPABILITIES") == 0)
212
                                        continue;
213

    
214
                                if (token.toUpperCase().compareTo("SERVICE=WFS") == 0)
215
                                        continue;
216

    
217
                                if ((_version != null) && (_version.length() > 0)) {
218
                                        if (token.toUpperCase().compareTo("VERSION=" + _version) == 0)
219
                                                continue;
220
                                }
221

    
222
                                if (token.toUpperCase().compareTo("EXCEPTIONS=XML") == 0)
223
                                        continue;
224

    
225
                                newQuery += token + "&";
226
                        }
227

    
228
                        _host = host + newQuery;
229
                }
230
                else {
231
                        _host += "?";
232
                }
233

    
234
                if ((_version != null) && (_version.compareTo("") != 0))
235
                        _host += "REQUEST=GetCapabilities&SERVICE=WFS&VERSION=" + _version + "&EXCEPTIONS=XML";
236
                else
237
                        _host += "REQUEST=GetCapabilities&SERVICE=WFS&EXCEPTIONS=XML";
238

    
239
                return _host;    
240
        }
241

    
242
        /**
243
         * <p>Builds a describeFeatureType request that is sent to the WFS
244
         * the response will be parse to extract the data needed by the
245
         * WFS client</p>
246
         * @param status
247
         * WFS client status. Contains all the information to create
248
         * the query. In this case, the only the feature name is needed.
249
         */
250
        public File describeFeatureType(WFSStatus status,boolean override, ICancellable cancel)throws WFSException {
251
                this.currentFeature = status.getFeatureFullName();
252
                //sets the namespace URI         
253
                if ((status.getNamespacePrefix() != null) && (status.getNamespaceLocation() == null)){                        
254
                        String namespaceURI = serviceInfo.getNamespace(status.getNamespacePrefix());
255
                        if (namespaceURI != null){
256
                                status.setNamespaceLocation(namespaceURI);                                
257
                        }
258
                }
259
                try {
260
                        WFSDescribeFeatureTypeRequest request = createDescribeFeatureTypeRequest(status);
261
                        File f = request.sendRequest(cancel);
262
                        return f;
263
                } catch (Exception e){
264
                        throw new WFSException(e);
265
                }
266
        }             
267

    
268
        /**
269
         * <p>Builds a getFeature request that is sent to the WFS
270
         * the response will be parse to extract the data needed by the
271
         * WFS client</p>
272
         * @param status
273
         * WFS client status. Contains all the information to create
274
         * the query. 
275
         * @return File
276
         * GML file
277
         */    
278
        public File getFeature(WFSStatus status,boolean override, ICancellable cancel) throws WFSException{
279
                try{                
280
                        WFSGetFeatureRequest request = createGetFeatureRequest(status);
281
                        File f = request.sendRequest(cancel);                        
282
                        parseGetFeature(f, status.getNamespacePrefix());
283
                        return f;
284
                } catch (Exception e){
285
                        throw new WFSException(e);
286
                }                
287
        }
288

    
289
        /**
290
         * parses the data retrieved by the GetFeature XML document. It is
291
         * used just to find errors
292
         */
293
        protected abstract boolean parseGetFeature(File f,String nameSpace) throws WFSException;
294

    
295

    
296
        /**
297
         * <p>Builds a transaction request that is sent to the WFS
298
         * the response will be parse to extract the data needed by the
299
         * WFS client</p>
300
         * @param status
301
         * WFS client status. Contains all the information to create
302
         * the query. 
303
         */   
304
        public void transaction(WFSStatus status,boolean override, ICancellable cancel) throws WFSException {
305
                try {
306
                    WFSTransactionRequest request = createTransactionRequest(status);
307
            File f = request.sendRequest(cancel);           
308
            parseTransaction(f, status); 
309
                } catch (Exception e){
310
                        throw new WFSException(e);
311
                }
312
        }
313

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

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

    
334
                req.append(onlineResource);
335
                return req.toString();
336
        }
337

    
338
        /**
339
         * parses the data retrieved by the transaction operation
340
         * @param f
341
         * The retrieved file
342
         * @param nameSpace
343
         * The namespace
344
         */
345
        protected abstract boolean parseTransaction(File f,  WFSStatus status) throws WFSException;
346

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

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

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

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

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

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

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

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

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

    
437
        /**
438
         * @param status
439
         * The WFS status
440
         * @param protocolHandler
441
         * The handler to parse the requests
442
         * @return an object to send the LockFeature requests
443
         */
444
        protected abstract WFSTLockFeatureRequest createLockFeatureRequest(WFSStatus status);
445
        
446
        /**
447
     * @param status
448
     * The WFS status
449
     * @param protocolHandler
450
     * The handler to parse the requests
451
     * @return an object to send the Transaction request
452
     */        
453
        protected abstract WFSTransactionRequest createTransactionRequest(WFSStatus status);
454

    
455
        /**
456
         * @return the wfsRequestInformations
457
         */
458
        ArrayList getWfsRequestInformations() {
459
                return wfsRequestInformations;
460
        }
461

    
462
        /**
463
         * Adds a new WFSRequestInformation
464
         * @param wfsRequestInformation
465
         */
466
        public void addLastWfsRequestInformation(
467
                        WFSRequestInformation wfsRequestInformation) {
468
                wfsRequestInformations.add(wfsRequestInformation);                
469
        }
470
        
471
        /**
472
         * @return the lastWfsRequestInformation
473
         */
474
        public WFSRequestInformation getLastWfsRequestInformation() {
475
                if (wfsRequestInformations.size() > 0){
476
                        return (WFSRequestInformation)wfsRequestInformations.get(wfsRequestInformations.size() - 1);
477
                }
478
                return null;
479
        }
480
}