Statistics
| Revision:

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

History | View | Annotate | Download (13.2 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.gvsig.compat.net.ICancellable;
10
import org.gvsig.remoteclient.ogc.OGCProtocolHandler;
11
import org.gvsig.remoteclient.ogc.OGCServiceInformation;
12
import org.gvsig.remoteclient.utils.CapabilitiesTags;
13
import org.gvsig.remoteclient.wfs.exceptions.WFSException;
14
import org.gvsig.remoteclient.wfs.request.WFSDescribeFeatureTypeRequest;
15
import org.gvsig.remoteclient.wfs.request.WFSGetFeatureRequest;
16
import org.gvsig.remoteclient.wfs.request.WFSTLockFeatureRequest;
17
import org.gvsig.remoteclient.wfs.request.WFSTransactionRequest;
18
import org.gvsig.remoteclient.wfs.schema.GMLTags;
19
import org.kxml2.io.KXmlParser;
20

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
216
                return _host;    
217
        }
218

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

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

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

    
272

    
273
        /**
274
         * <p>Builds a transaction request that is sent to the WFS
275
         * the response will be parse to extract the data needed by the
276
         * WFS client</p>
277
         * @param status
278
         * WFS client status. Contains all the information to create
279
         * the query. 
280
         */   
281
        public void transaction(WFSStatus status,boolean override, ICancellable cancel) throws WFSException {
282
                try {
283
                    WFSTransactionRequest request = createTransactionRequest(status);
284
            File f = request.sendRequest(cancel);           
285
            parseTransaction(f, status); 
286
                } catch (Exception e){
287
                        throw new WFSException(e);
288
                }
289
        }
290

    
291
        /**
292
         * <p>Builds a transaction request that is sent to the WFS
293
         * the response will be parse to extract the data needed by the
294
         * WFS client</p>
295
         * @param status
296
         * WFS client status. Contains all the information to create
297
         * the query. 
298
         */
299
        private String buildTransactionRequest(WFSStatus status){
300
                StringBuffer req = new StringBuffer();
301
                String symbol = null;
302

    
303
                String onlineResource;
304
                if(serviceInfo.getOnlineResource(CapabilitiesTags.WFS_TRANSACTION) != null){
305
                        onlineResource = serviceInfo.getOnlineResource(CapabilitiesTags.WFS_TRANSACTION);
306
                }else {
307
                        onlineResource = getHost();
308
                }
309
                symbol = getSymbol(onlineResource);
310

    
311
                req.append(onlineResource);
312
                return req.toString();
313
        }
314

    
315
        /**
316
         * parses the data retrieved by the transaction operation
317
         * @param f
318
         * The retrieved file
319
         * @param nameSpace
320
         * The namespace
321
         */
322
        protected abstract boolean parseTransaction(File f,  WFSStatus status) throws WFSException;
323

    
324
        /**
325
         * <p>Builds a lockFeature request that is sent to the WFS
326
         * the response will be parse to extract the data needed by the
327
         * WFS client</p>
328
         * @param status
329
         * WFS client status. Contains all the information to create
330
         * the query. 
331
         */  
332
        public void lockFeature(WFSStatus status,boolean override, ICancellable cancel) throws WFSException {
333
                try {
334
                        WFSTLockFeatureRequest request = createLockFeatureRequest(status);
335
                        File f = request.sendRequest(cancel);
336
                        parseLockFeature(f,status.getNamespacePrefix(),status);
337
                } catch(WFSException e) {
338
                        throw e;
339
                } catch (Exception e){
340
                        throw new WFSException(e);
341
                }                
342
        }        
343

    
344
        /**
345
         * parses the data retrieved by the LockFeature operation
346
         */
347
        protected abstract boolean parseLockFeature(File f,String nameSpace, WFSStatus status) throws WFSException;
348

    
349
        /**
350
         * @return Returns the features.
351
         */
352
        public Hashtable getFeatures() {
353
                return features;
354
        }
355

    
356
        /**
357
         * @return Returns the currentFeature.
358
         */
359
        public String getCurrentFeature() {
360
                return currentFeature;
361
        }
362

    
363
        /**
364
         * @param currentFeature The currentFeature to set.
365
         */
366
        public void setCurrentFeature(String currentFeature) {
367
                this.currentFeature = currentFeature;
368
        }    
369

    
370
        /**
371
         * It parses the attributes of the current KXMLParser 
372
         * and add the new namespaces to the service information
373
         * @param parser
374
         * The KXML parser
375
         */
376
        protected void parseNamespaces(KXmlParser parser){
377
                for (int i=0 ; i<parser.getAttributeCount() ; i++){
378
                        String attName = parser.getAttributeName(i);
379
                        if (attName.startsWith(GMLTags.XML_NAMESPACE)){
380
                                int index = attName.indexOf(":");
381
                                if (index > 0){
382
                                        serviceInfo.addNamespace(attName.substring(index+1, attName.length()), 
383
                                                        parser.getAttributeValue(i));
384
                                }
385
                        }
386
                }                        
387
        }
388

    
389
        /* (non-Javadoc)
390
         * @see org.gvsig.remoteClient.ogc.OGCProtocolHandler#getServiceInformation()
391
         */
392
        public OGCServiceInformation getServiceInformation() {
393
                return serviceInfo;
394
        }        
395

    
396
        /**
397
         * @param status
398
         * The WFS status
399
         * @param protocolHandler
400
         * The handler to parse the requests
401
         * @return an object to send the DescribeFeatureType requests
402
         */
403
        protected abstract WFSDescribeFeatureTypeRequest createDescribeFeatureTypeRequest(WFSStatus status);
404

    
405
        /**
406
         * @param status
407
         * The WFS status
408
         * @param protocolHandler
409
         * The handler to parse the requests
410
         * @return an object to send the GetFeature requests
411
         */
412
        protected abstract WFSGetFeatureRequest createGetFeatureRequest(WFSStatus status);
413

    
414
        /**
415
         * @param status
416
         * The WFS status
417
         * @param protocolHandler
418
         * The handler to parse the requests
419
         * @return an object to send the LockFeature requests
420
         */
421
        protected abstract WFSTLockFeatureRequest createLockFeatureRequest(WFSStatus status);
422
        
423
        /**
424
     * @param status
425
     * The WFS status
426
     * @param protocolHandler
427
     * The handler to parse the requests
428
     * @return an object to send the Transaction request
429
     */        
430
        protected abstract WFSTransactionRequest createTransactionRequest(WFSStatus status);
431

    
432
        /**
433
         * @return the wfsRequestInformations
434
         */
435
        ArrayList getWfsRequestInformations() {
436
                return wfsRequestInformations;
437
        }
438

    
439
        /**
440
         * Adds a new WFSRequestInformation
441
         * @param wfsRequestInformation
442
         */
443
        public void addLastWfsRequestInformation(
444
                        WFSRequestInformation wfsRequestInformation) {
445
                wfsRequestInformations.add(wfsRequestInformation);                
446
        }
447
        
448
        /**
449
         * @return the lastWfsRequestInformation
450
         */
451
        public WFSRequestInformation getLastWfsRequestInformation() {
452
                if (wfsRequestInformations.size() > 0){
453
                        return (WFSRequestInformation)wfsRequestInformations.get(wfsRequestInformations.size() - 1);
454
                }
455
                return null;
456
        }
457
}