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 @ 40596

History | View | Annotate | Download (11.8 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
/**
45
 * @author Jorge Piera Llodr? (piera_jor@gva.es)
46
 */
47
public abstract class WFSProtocolHandler extends OGCProtocolHandler {
48
        //protected static Logger LOG = LoggerFactory.getLogger(WFSProtocolHandler.class);
49
        
50
    /**
51
         * WFS metadata
52
         */
53
        protected WFSServiceInformation serviceInfo = new WFSServiceInformation();
54
        protected Hashtable features = new Hashtable();
55
        protected String currentFeature = null;
56
        private int numberOfErrors = 0;
57

    
58
        /**
59
         * This class contains all the data that the library is able
60
         * to retrieve of the server for all the requests. 
61
         */
62
        protected ArrayList wfsRequestInformations = new ArrayList();
63

    
64
        /**
65
         * Clear the connection
66
         */
67
        private void clear() {
68
                features.clear();
69
                serviceInfo.clear();
70
        }
71

    
72
        /**
73
         * <p>Builds a GetCapabilities request that is sent to the WFS
74
         * the response will be parse to extract the data needed by the
75
         * WFS client</p>
76
         */
77
        public void getCapabilities(WFSStatus status,boolean override, ICancellable cancel) throws WFSException {
78
                URL request = null;
79
                try {
80
                        request = new URL(buildCapabilitiesRequest(status));
81
                        if (override){
82
                            downloader.removeURL(request);
83
                        }
84
                        File f = downloader.downloadFile(request,"wfs_capabilities.xml", cancel);
85
                        if (f == null)
86
                                return;
87
                        clear();
88
                        parseCapabilities(f);
89
                } catch (Exception e){
90
                        throw new WFSException(e);
91
                }
92
        }    
93

    
94
        /**
95
         * @return
96
         */
97
        private String buildCapabilitiesRequest(WFSStatus status) {
98
                StringBuffer req = new StringBuffer();
99
                String symbol = null;
100

    
101
                String onlineResource;
102
                if (status == null || status.getOnlineResource() == null)
103
                        onlineResource = getHost();
104
                else 
105
                        onlineResource = status.getOnlineResource();
106
                symbol = getSymbol(onlineResource);
107

    
108
                req.append(onlineResource).append(symbol).append("REQUEST=GetCapabilities&SERVICE=WFS&");
109
                req.append("VERSION=").append(getVersion()).append("&EXCEPTIONS=XML");
110
                return req.toString();
111
        }   
112

    
113
        /**
114
         * Builds the GetCapabilitiesRequest according to the OGC WFS Specifications
115
         * without a VERSION, to get the highest version than a WFS supports.
116
         */
117
        public static String buildCapabilitiesSuitableVersionRequest(String _host, String _version)
118
        {
119
                int index = _host.indexOf('?');
120

    
121
                if (index > -1) {
122
                        String host = _host.substring(0, index + 1);
123
                        String query = _host.substring(index + 1, _host.length());
124

    
125
                        StringTokenizer tokens = new StringTokenizer(query, "&");
126
                        String newQuery = "", token;
127

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

    
132
                                if (token.toUpperCase().compareTo("REQUEST=GETCAPABILITIES") == 0)
133
                                        continue;
134

    
135
                                if (token.toUpperCase().compareTo("SERVICE=WFS") == 0)
136
                                        continue;
137

    
138
                                if ((_version != null) && (_version.length() > 0)) {
139
                                        if (token.toUpperCase().compareTo("VERSION=" + _version) == 0)
140
                                                continue;
141
                                }
142

    
143
                                if (token.toUpperCase().compareTo("EXCEPTIONS=XML") == 0)
144
                                        continue;
145

    
146
                                newQuery += token + "&";
147
                        }
148

    
149
                        _host = host + newQuery;
150
                }
151
                else {
152
                        _host += "?";
153
                }
154

    
155
                if ((_version != null) && (_version.compareTo("") != 0))
156
                        _host += "REQUEST=GetCapabilities&SERVICE=WFS&VERSION=" + _version + "&EXCEPTIONS=XML";
157
                else
158
                        _host += "REQUEST=GetCapabilities&SERVICE=WFS&EXCEPTIONS=XML";
159

    
160
                return _host;    
161
        }
162

    
163
        /**
164
         * <p>Builds a describeFeatureType request that is sent to the WFS
165
         * the response will be parse to extract the data needed by the
166
         * WFS client</p>
167
         * @param status
168
         * WFS client status. Contains all the information to create
169
         * the query. In this case, the only the feature name is needed.
170
         */
171
        public File describeFeatureType(WFSStatus status,boolean override, ICancellable cancel)throws WFSException {
172
                this.currentFeature = status.getFeatureFullName();
173
                //sets the namespace URI         
174
                if ((status.getNamespacePrefix() != null) && (status.getNamespaceLocation() == null)){                        
175
                        String namespaceURI = serviceInfo.getNamespace(status.getNamespacePrefix());
176
                        if (namespaceURI != null){
177
                                status.setNamespaceLocation(namespaceURI);                                
178
                        }
179
                }
180
                try {
181
                        WFSDescribeFeatureTypeRequest request = createDescribeFeatureTypeRequest(status);
182
                        File f = request.sendRequest(cancel);
183
                        return f;
184
                } catch (Exception e){
185
                        throw new WFSException(e);
186
                }
187
        }             
188

    
189
        /**
190
         * <p>Builds a getFeature request that is sent to the WFS
191
         * the response will be parse to extract the data needed by the
192
         * WFS client</p>
193
         * @param status
194
         * WFS client status. Contains all the information to create
195
         * the query. 
196
         * @return File
197
         * GML file
198
         */    
199
        public File getFeature(WFSStatus status,boolean override, ICancellable cancel) throws WFSException{
200
                try{                
201
                        WFSGetFeatureRequest request = createGetFeatureRequest(status);
202
                        File f = request.sendRequest(cancel);                        
203
                        parseGetFeature(f, status.getNamespacePrefix());
204
                        return f;
205
                } catch (Exception e){
206
                        throw new WFSException(e);
207
                }                
208
        }
209

    
210
        /**
211
         * parses the data retrieved by the GetFeature XML document. It is
212
         * used just to find errors
213
         */
214
        protected abstract boolean parseGetFeature(File f,String nameSpace) throws WFSException;
215

    
216

    
217
        /**
218
         * <p>Builds a transaction request that is sent to the WFS
219
         * the response will be parse to extract the data needed by the
220
         * WFS client</p>
221
         * @param status
222
         * WFS client status. Contains all the information to create
223
         * the query. 
224
         */   
225
        public void transaction(WFSStatus status,boolean override, ICancellable cancel) throws WFSException {
226
                try {
227
                    WFSTransactionRequest request = createTransactionRequest(status);
228
            File f = request.sendRequest(cancel);           
229
            parseTransaction(f, status); 
230
                } catch (Exception e){
231
                        throw new WFSException(e);
232
                }
233
        }
234

    
235
        /**
236
         * <p>Builds a transaction request that is sent to the WFS
237
         * the response will be parse to extract the data needed by the
238
         * WFS client</p>
239
         * @param status
240
         * WFS client status. Contains all the information to create
241
         * the query. 
242
         */
243
        private String buildTransactionRequest(WFSStatus status){
244
                StringBuffer req = new StringBuffer();
245
                String symbol = null;
246

    
247
                String onlineResource;
248
                if(serviceInfo.getOnlineResource(CapabilitiesTags.WFS_TRANSACTION) != null){
249
                        onlineResource = serviceInfo.getOnlineResource(CapabilitiesTags.WFS_TRANSACTION);
250
                }else {
251
                        onlineResource = getHost();
252
                }
253
                symbol = getSymbol(onlineResource);
254

    
255
                req.append(onlineResource);
256
                return req.toString();
257
        }
258

    
259
        /**
260
         * parses the data retrieved by the transaction operation
261
         * @param f
262
         * The retrieved file
263
         * @param nameSpace
264
         * The namespace
265
         */
266
        protected abstract boolean parseTransaction(File f,  WFSStatus status) throws WFSException;
267

    
268
        /**
269
         * <p>Builds a lockFeature 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
         */  
276
        public void lockFeature(WFSStatus status,boolean override, ICancellable cancel) throws WFSException {
277
                try {
278
                        WFSTLockFeatureRequest request = createLockFeatureRequest(status);
279
                        File f = request.sendRequest(cancel);
280
                        parseLockFeature(f,status.getNamespacePrefix(),status);
281
                } catch(WFSException e) {
282
                        throw e;
283
                } catch (Exception e){
284
                        throw new WFSException(e);
285
                }                
286
        }        
287

    
288
        /**
289
         * parses the data retrieved by the LockFeature operation
290
         */
291
        protected abstract boolean parseLockFeature(File f,String nameSpace, WFSStatus status) throws WFSException;
292

    
293
        /**
294
         * @return Returns the features.
295
         */
296
        public Hashtable getFeatures() {
297
                return features;
298
        }
299

    
300
        /**
301
         * @return Returns the currentFeature.
302
         */
303
        public String getCurrentFeature() {
304
                return currentFeature;
305
        }
306

    
307
        /**
308
         * @param currentFeature The currentFeature to set.
309
         */
310
        public void setCurrentFeature(String currentFeature) {
311
                this.currentFeature = currentFeature;
312
        }    
313

    
314
        /**
315
         * It parses the attributes of the current KXMLParser 
316
         * and add the new namespaces to the service information
317
         * @param parser
318
         * The KXML parser
319
         */
320
        protected void parseNamespaces(KXmlParser parser){
321
                for (int i=0 ; i<parser.getAttributeCount() ; i++){
322
                        String attName = parser.getAttributeName(i);
323
                        if (attName.startsWith(GMLTags.XML_NAMESPACE)){
324
                                int index = attName.indexOf(":");
325
                                if (index > 0){
326
                                        serviceInfo.addNamespace(attName.substring(index+1, attName.length()), 
327
                                                        parser.getAttributeValue(i));
328
                                }
329
                        }
330
                }                        
331
        }
332

    
333
        /* (non-Javadoc)
334
         * @see org.gvsig.remoteClient.ogc.OGCProtocolHandler#getServiceInformation()
335
         */
336
        public OGCServiceInformation getServiceInformation() {
337
                return serviceInfo;
338
        }        
339

    
340
        /**
341
         * @param status
342
         * The WFS status
343
         * @param protocolHandler
344
         * The handler to parse the requests
345
         * @return an object to send the DescribeFeatureType requests
346
         */
347
        protected abstract WFSDescribeFeatureTypeRequest createDescribeFeatureTypeRequest(WFSStatus status);
348

    
349
        /**
350
         * @param status
351
         * The WFS status
352
         * @param protocolHandler
353
         * The handler to parse the requests
354
         * @return an object to send the GetFeature requests
355
         */
356
        protected abstract WFSGetFeatureRequest createGetFeatureRequest(WFSStatus status);
357

    
358
        /**
359
         * @param status
360
         * The WFS status
361
         * @param protocolHandler
362
         * The handler to parse the requests
363
         * @return an object to send the LockFeature requests
364
         */
365
        protected abstract WFSTLockFeatureRequest createLockFeatureRequest(WFSStatus status);
366
        
367
        /**
368
     * @param status
369
     * The WFS status
370
     * @param protocolHandler
371
     * The handler to parse the requests
372
     * @return an object to send the Transaction request
373
     */        
374
        protected abstract WFSTransactionRequest createTransactionRequest(WFSStatus status);
375

    
376
        /**
377
         * @return the wfsRequestInformations
378
         */
379
        ArrayList getWfsRequestInformations() {
380
                return wfsRequestInformations;
381
        }
382

    
383
        /**
384
         * Adds a new WFSRequestInformation
385
         * @param wfsRequestInformation
386
         */
387
        public void addLastWfsRequestInformation(
388
                        WFSRequestInformation wfsRequestInformation) {
389
                wfsRequestInformations.add(wfsRequestInformation);                
390
        }
391
        
392
        /**
393
         * @return the lastWfsRequestInformation
394
         */
395
        public WFSRequestInformation getLastWfsRequestInformation() {
396
                if (wfsRequestInformations.size() > 0){
397
                        return (WFSRequestInformation)wfsRequestInformations.get(wfsRequestInformations.size() - 1);
398
                }
399
                return null;
400
        }
401
}