Statistics
| Revision:

svn-gvsig-desktop / tags / v2_0_0_Build_2020 / libraries / libRemoteServices / src / org / gvsig / remoteclient / wfs / filters / filterencoding / FilterEncoding.java @ 33910

History | View | Annotate | Download (14.5 KB)

1

    
2
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
3
 *
4
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
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 2
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., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
19
 *
20
 * For more information, contact:
21
 *
22
 *  Generalitat Valenciana
23
 *   Conselleria d'Infraestructures i Transport
24
 *   Av. Blasco Ib??ez, 50
25
 *   46010 VALENCIA
26
 *   SPAIN
27
 *
28
 *      +34 963862235
29
 *   gvsig@gva.es
30
 *      www.gvsig.gva.es
31
 *
32
 *    or
33
 *
34
 *   IVER T.I. S.A
35
 *   Salamanca 50
36
 *   46005 Valencia
37
 *   Spain
38
 *
39
 *   +34 963163400
40
 *   dac@iver.es
41
 */
42
package org.gvsig.remoteclient.wfs.filters.filterencoding;
43
import java.util.ArrayList;
44
import java.util.Hashtable;
45
import java.util.Iterator;
46
import java.util.Set;
47

    
48
import org.gvsig.compat.CompatLocator;
49
import org.gvsig.compat.lang.StringUtils;
50
import org.gvsig.remoteclient.wfs.WFSStatus;
51
import org.gvsig.remoteclient.wfs.filters.AbstractFilter;
52
import org.gvsig.remoteclient.wfs.filters.BinaryTree;
53
import org.gvsig.remoteclient.wfs.filters.DefaultSQLExpressionFormat;
54
import org.gvsig.remoteclient.wfs.filters.ISQLExpressionFormat;
55
import org.gvsig.remoteclient.wfs.filters.BinaryTree.Node;
56
import org.gvsig.remoteclient.wfs.filters.operations.WFSEnvelopeFilterOperation;
57
import org.gvsig.remoteclient.wfs.filters.operations.WFSGeometryFilterOperation;
58
import org.gvsig.remoteclient.wfs.filters.operations.WFSSpatialFilterOperation;
59

    
60
/**
61
 * This class implements the Filter Encoding Language. It is used to
62
 * create querys in this language
63
 * 
64
 * Name: OpenGIS? Filter Encoding Implementation Specification
65
 * Version: 1.1.0
66
 * Project Document: OGC 04-095 
67
 * @see http://portal.opengeospatial.org/files/?artifact_id=8340
68
 * 
69
 * @author Jorge Piera Llodra (piera_jor@gva.es)
70
 */
71
public class FilterEncoding extends AbstractFilter {
72
        public static final int RELATIONSHIP_PROPERTY = 0;
73
        public static final int RELATIONSHIP_VAUES = 1;
74

    
75
        private StringBuffer currentQuery = null;
76
        //Operation types
77
        private static final int OPERATION_PROPERTYNAME = 0;
78
        private static final int OPERATION_LITERAL = 1;
79
        //Filter namespace. (typically "ogc")
80
        private String namepacePrefix = null;
81
        //If the Filter can have blanckSpaces
82
        private boolean hasBlankSpaces = true;
83
        private String defaultBlankSpace = "%20";
84
        //This character must be replaced by any set of characters (typically "*")
85
        private String wildCardChar = null;
86
        //This character must be replaced by one character (typically "?")
87
        private String singleChar = null;
88
        //Escape character (typically "\")
89
        private String escapeChar = null;
90
        //Default values
91
        public static final String DEFAULT_NAMESPACE_PREFIX = "ogc";
92
        public static final String DEFAULT_WILDCARD = "*";
93
        public static final String DEFAULT_SINGLECHAR = "?";
94
        public static final String DEFAULT_ESCAPE = "\\";
95
        public static final String DEFAULT_NAMESPACE = "xmlns:ogc=\"http://www.opengis.net/ogc\"";
96

    
97
        private Hashtable filterAttributes = new Hashtable();
98

    
99
        /**
100
         * If the namespace XML is qualified
101
         */
102
        private boolean isQualified = false;
103

    
104
        private static final StringUtils stringUtils = CompatLocator.getStringUtils();
105
        
106
        /**
107
         * Create a new Filter Encoding Parser
108
         * 
109
         * 
110
         * @param namepacePrefix
111
         * Filter namespace. (typically "ogc")
112
         * @param wildCardChar 
113
         * This character must be replaced by any set of characters (typically "*")
114
         * @param singleChar 
115
         * This character must be replaced by one character (typically "?")
116
         * @param escape 
117
         * Escape character
118
         * @param filterAttribute Sometimes, "Field" label needs an attribute.
119
         */
120
        public FilterEncoding(ISQLExpressionFormat formatter,String namesPacePrefix, String wildCard, String singleChar, String escape, Hashtable filterAttributes) {        
121
                super(formatter);
122
                if (namesPacePrefix == null){
123
                        setQualified(false);
124
                }else{
125
                        setQualified(true);
126
                }
127
                this.wildCardChar = wildCard;
128
                this.singleChar = singleChar;
129
                this.escapeChar = escape;
130
                this.filterAttributes = filterAttributes;
131
        } 
132

    
133

    
134
        /**
135
         * Create a new Filter Encoding Parser
136
         * @param formatter
137
         */
138
        public FilterEncoding(ISQLExpressionFormat formatter) {        
139
                this(formatter,null,DEFAULT_WILDCARD,DEFAULT_SINGLECHAR,
140
                                DEFAULT_ESCAPE,new Hashtable());
141
        } 
142

    
143
        /**
144
         * Create a new Filter Encoding Parser
145
         */
146
        public FilterEncoding() {        
147
                this(new DefaultSQLExpressionFormat());                
148
        }         
149

    
150
        /**
151
         * Create a new Filter Encoding Parser
152
         */
153
        public FilterEncoding(WFSStatus status) {        
154
                this();        
155
                setQueryByAttribute(status.getFilterByAttribute());
156
                clearSpatialFilters();
157
                addSpatialFilter(status.getFilterByArea());                
158
        } 
159

    
160
        /*
161
         *  (non-Javadoc)
162
         * @see org.gvsig.remoteClient.filterEncoding.QueryLanguage#toString(org.gvsig.remoteClient.filterEncoding.BinaryTree)
163
         */
164
        public String toString(BinaryTree tree) {
165
                //If is a filter by ids...
166
                StringBuffer idQuery = null;
167
                if (getIds() != null){
168
                        idQuery = new StringBuffer();
169
                        ArrayList ids = getIds();
170
                        for (int i=0 ; i<ids.size() ; i++){
171
                                if (ids.get(i) != null){
172
                                        Hashtable attributes = new Hashtable();
173
                                        attributes.put("fid","\"" + ids.get(i).toString() + "\"");
174
                                        idQuery.append(setTag("FeatureId", attributes, null));
175
                                }
176
                        }
177
                        return enclosesWithFilterTag(idQuery.toString());
178
                }
179
                //If is a filter by attributes...
180
                String filterQuery = null;
181
                if ((tree.getRoot() == null) && (getSpatialFiltersCount() == 0)){
182
                        return null;
183
                }
184
                if (tree.getRoot() != null){
185
                        currentQuery = new StringBuffer();
186
                        filterQuery = getFilterNode(tree.getRoot());
187
                        if (getSpatialFiltersCount() == 0){
188
                                return enclosesWithFilterTag(filterQuery);
189
                        }
190
                }
191
                //If is a filter by area
192
                String bboxQuery = null;
193
                if (getSpatialFiltersCount() > 0){
194
                        for (int i=0 ; i<getSpatialFiltersCount() ; i++){
195
                                WFSSpatialFilterOperation spatialFilter = getSpatialFilterAt(i);
196
                                SpatialFEQuery feQuery = null;
197
                                if (spatialFilter instanceof WFSGeometryFilterOperation){
198
                                        feQuery = new GeometryFEQuery((WFSGeometryFilterOperation)spatialFilter);
199
                                }else if (spatialFilter instanceof WFSEnvelopeFilterOperation){
200
                                        feQuery = new EnvelopeFEQuery((WFSEnvelopeFilterOperation)spatialFilter);
201
                                }
202
                                //If there is a spatial query
203
                                if (feQuery != null){
204
                                        bboxQuery = feQuery.getFilterEncoding();
205
                                        if (tree.getRoot() == null){
206
                                                return bboxQuery;
207
                                        }        
208
                                }
209
                        }
210
                }                
211
                return enclosesWithFilterTag(filterQuery + bboxQuery);
212
        }
213

    
214
        /**
215
         * Gets the filter code from a node
216
         * @param node
217
         */
218
        private String getFilterNode(Node node){
219
                if (node.isField()){
220
                        return getExpression(node.getValue());
221
                }else{
222
                        String left = "";
223
                        String rigth = "";
224
                        if (node.getLeftNode() != null){
225
                                left = getFilterNode(node.getLeftNode());
226
                        }
227
                        if (node.getRigthNode() != null){
228
                                rigth = getFilterNode(node.getRigthNode());
229
                        }
230
                        int operationCode = getLogicalOperator(node.getValue());
231
                        String operation = getLogicalOperator(operationCode);
232
                        return enterLabel(left+rigth, operation);
233
                }                
234
        }   
235

    
236
        /**
237
         * Parses a expresion like 'A op B' and returns the
238
         * expresion using the filter encoding language
239
         * @param expression
240
         * @return
241
         */
242
        private String getExpression(String expression){
243
                String[] words = stringUtils.split(expression, " ");
244
                //Param
245
                String param = words[0];
246
                if (param.charAt(0) == '"'){
247
                        param = param.substring(1,param.length());
248
                }
249
                if (param.charAt(param.length()-1) == '"'){
250
                        param = param.substring(0,param.length()-1);
251
                }
252
                //Operator
253
                String operator = words[1];
254
                //Value
255
                String value = words[2];                
256
                for (int i=3 ; i<words.length ; i++){
257
                        value = value + " " + words[i];
258
                }
259
                if (value.charAt(0) == '\''){
260
                        value = value.substring(1,value.length());
261
                }
262
                if (value.charAt(value.length()-1) == '\''){
263
                        value = value.substring(0,value.length()-1);
264
                }
265
                int operatorCode = getRelationalOperator(operator);
266
                operator = getRelationalOperator(operatorCode);
267
                return createExpression(operator,param,value);
268
        }
269

    
270
        /**
271
         * It writes a "PropertyIsXXX" part of a filtyer encoding query
272
         * 
273
         * 
274
         * @return The part of the query
275
         * @param property Possible Values: PropertIsLike, PropertyIsLess, PropertyIsGreater,... See
276
         * the Filter Encoding documentation
277
         * @param parameter Parameter name
278
         * @param value Parameter value
279
         * @param type Values: "P" (to comparate two propertyes) or "L" (to comparate one property
280
         * and one literal value)
281
         */
282
        private String createExpression(String property, String parameter, String value) {        
283
                String cadena = "";
284
                cadena = "<" + namepacePrefix + property;
285
                if (property.equals("PropertyIsLike")) {
286
                        if (wildCardChar != null) {
287
                                cadena = cadena + " wildCard=\"" + this.wildCardChar + "\"";
288
                        }
289
                        if (singleChar != null) {
290
                                cadena = cadena + " singleChar=\"" + this.singleChar + "\"";
291
                        }
292
                        if (escapeChar != null) {
293
                                cadena = cadena + " escape=\"" + this.escapeChar + "\"";
294
                        }
295
                }
296
                cadena = cadena + ">" + enterLabel(parameter, "PropertyName");
297
                cadena = cadena + enterLabel(value, "Literal");
298
                return cadena + "</" + namepacePrefix + property + ">";
299
        }         
300

    
301
        /**
302
         * Envuelve a una pregunta con una etiqueta
303
         * 
304
         * 
305
         * @return String : parte de la query en el lenguaje soportado
306
         * @param pregunta Pregunta a envolver
307
         * @param etiqueta Nombre de la etiqueta
308
         */
309
        private String enterLabel(String value, String tagName) {        
310
                if (tagName.equals("Filter") && (!(filterAttributes.isEmpty()))) {
311
                        return setTag(tagName,filterAttributes,value);
312
                } else {
313
                        return setTag(tagName,null,value);
314
                }
315
        } 
316

    
317
        /**
318
         * Envolves a value with an XML tag
319
         * 
320
         * @return String
321
         * XML tag with its value
322
         * @param tagName 
323
         * XML tag name
324
         * @param attributes
325
         * XML tag attributes
326
         * @param value 
327
         * Tag value
328
         */
329
        public String setTag(String tagName, Hashtable attributes, String value) {        
330
                StringBuffer tag = new StringBuffer();
331

    
332
                tag.append("<");
333
                tag.append(namepacePrefix);
334
                tag.append(tagName);            
335
                if (attributes != null){
336
                        Set keys = attributes.keySet();
337
                        if (attributes.size() > 0){
338
                                Iterator it = keys.iterator();
339
                                while (it.hasNext()){
340
                                        String key = (String)it.next();
341
                                        if (hasBlankSpaces){
342
                                                tag.append(" ");
343
                                        }else{
344
                                                tag.append(defaultBlankSpace);
345
                                        }
346
                                        tag.append(key + "=" + (String)attributes.get(key));
347

    
348
                                }
349
                        }
350
                }
351
                if (value == null){
352
                        tag.append("/>");
353
                }else{
354
                        tag.append(">" + value);
355
                        tag.append("</");
356
                        tag.append(namepacePrefix);
357
                        tag.append(tagName);
358
                        tag.append(">");
359
                }
360
                return tag.toString();
361
        }
362

    
363

    
364
        /**
365
         * Encloses a query with the filter tag
366
         * @param query
367
         * @return
368
         */
369
        private String enclosesWithFilterTag(String query){
370
                StringBuffer filter = new StringBuffer();
371
                filter.append("<" + namepacePrefix + "Filter");
372
                if (!isQualified){
373
                        filter.append("%20");
374
                        filter.append("xmlns:ogc=\"http://www.opengis.net/ogc\"%20");
375
                        filter.append("xmlns:gml=\"http://www.opengis.net/gml\"%20"); 
376
                        filter.append("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"%20");
377
                        filter.append("xsi:schemaLocation=\"http://www.opengis.net/ogc%20../filter/1.0.0/filter.xsd%20http://www.opengis.net/gml%20../gml/2.1.2/geometry.xsd\"");
378
                }
379
                filter.append(">");
380
                filter.append(query);
381
                filter.append("</" + namepacePrefix + "Filter>");
382
                return filter.toString();
383
        }
384

    
385
        /*
386
         *  (non-Javadoc)
387
         * @see org.gvsig.remoteClient.filterEncoding.AQueryLanguage#getLogicOperator(int)
388
         */
389
        public String getLogicalOperator(int operator) {
390
                switch (operator){
391
                case LOGICAL_OPERATOR_AND:
392
                        return "And";
393
                case LOGICAL_OPERATOR_OR:
394
                        return "Or";
395
                case LOGICAL_OPERATOR_NOT:
396
                        return "Not";
397
                default:
398
                        return "And";
399
                }    
400
        } 
401

    
402
        /*
403
         *  (non-Javadoc)
404
         * @see org.gvsig.remoteClient.filterEncoding.AQueryLanguage#getRelationalOperator(int)
405
         */
406
        public String getRelationalOperator(int operator) {
407
                switch (operator){
408
                case RELATIONAL_OPERATOR_IS_EQUALS_TO:
409
                        return "PropertyIsEqualTo";
410
                case RELATIONAL_OPERATOR_IS_NOT_EQUALS_TO:
411
                        return "PropertyIsNotEqualTo";
412
                case RELATIONAL_OPERATOR_IS_LESS_THAN:
413
                        return "PropertyIsLessThan";
414
                case RELATIONAL_OPERATOR_IS_GREATER_THAN:
415
                        return "PropertyIsGreaterThan";
416
                case RELATIONAL_OPERATOR_IS_LESS_THAN_OR_EQUAL_TO:
417
                        return "PropertyIsLessThanOrEqualTo";
418
                case RELATIONAL_OPERATOR_IS_GREATER_THAN_OR_EQUAL_TO:
419
                        return "PropertyIsGreaterThanOrEqualTo";
420
                case RELATIONAL_OPERATOR_IS_LIKE:
421
                        return "PropertyIsLike";
422
                case RELATIONAL_OPERATOR_IS_NULL:
423
                        return "PropertyIsNull";
424
                case RELATIONAL_OPERATOR_IS_BETWEEN:
425
                        return "PropertyIsBetween";
426
                default:
427
                        return "PropertyIsLike";
428
                }
429
        }
430

    
431
        /*
432
         *  (non-Javadoc)
433
         * @see org.gvsig.remoteClient.filterEncoding.AQueryLanguage#getGeometricOperator(int)
434
         */
435
        public String getGeometricOperator(int operator) {
436
                switch (operator){
437
                case GEOMETRIC_OPERATOR_EQUALS:
438
                        return "Equals";
439
                case GEOMETRIC_OPERATOR_DISJOINT:
440
                        return "Disjoint";
441
                case GEOMETRIC_OPERATOR_TOUCHES:
442
                        return "Touches";
443
                case GEOMETRIC_OPERATOR_WITHIN:
444
                        return "Within";
445
                case GEOMETRIC_OPERATOR_OVERLAPS:
446
                        return "Overlaps";
447
                case GEOMETRIC_OPERATOR_CROSSES:
448
                        return "Crosses";
449
                case GEOMETRIC_OPERATOR_INTERSECT:
450
                        return "Intersect";
451
                case GEOMETRIC_OPERATOR_CONTAINS:
452
                        return "Contains";
453
                case GEOMETRIC_OPERATOR_DWITHIN:
454
                        return "Dwithin";
455
                case GEOMETRIC_OPERATOR_BEYOND:
456
                        return "Beyond";
457
                case GEOMETRIC_OPERATOR_BBOX:
458
                        return "BBOX";
459
                default:
460
                        return "Equals";
461
                } 
462

    
463
        }
464

    
465
        public String getSeparator(int separator) {
466
                return null;
467
        }
468

    
469
        /**
470
         * @param isQualified the isQualified to set
471
         */
472
        public void setQualified(boolean isQualified) {
473
                this.isQualified = isQualified;
474
                if (isQualified){
475
                        namepacePrefix = DEFAULT_NAMESPACE_PREFIX + ":";
476
                }else{
477
                        namepacePrefix = "";
478
                }
479
        }
480

    
481

    
482
        /**
483
         * @param namepacePrefix the namepacePrefix to set
484
         */
485
        public void setNamepacePrefix(String namepacePrefix) {
486
                if ((namepacePrefix == null) || (namepacePrefix.equals(""))){
487
                        this.namepacePrefix = "";
488
                }else{
489
                        this.namepacePrefix = namepacePrefix + ":";
490
                }
491
        }
492

    
493

    
494
        /**
495
         * @param hasBlankSpaces the hasBlankSpaces to set
496
         */
497
        public void setHasBlankSpaces(boolean hasBlankSpaces) {
498
                this.hasBlankSpaces = hasBlankSpaces;
499
        }
500
}