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 7897 jorpiell
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 31835 jpiera
package org.gvsig.remoteclient.wfs.filters.filterencoding;
43 18271 jpiera
import java.util.ArrayList;
44 7897 jorpiell
import java.util.Hashtable;
45 18271 jpiera
import java.util.Iterator;
46
import java.util.Set;
47 7897 jorpiell
48 33738 jpiera
import org.gvsig.compat.CompatLocator;
49
import org.gvsig.compat.lang.StringUtils;
50 29680 jpiera
import org.gvsig.remoteclient.wfs.WFSStatus;
51 31835 jpiera
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 29680 jpiera
import org.gvsig.remoteclient.wfs.filters.BinaryTree.Node;
56 31835 jpiera
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 7897 jorpiell
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 31835 jpiera
public class FilterEncoding extends AbstractFilter {
72 7897 jorpiell
        public static final int RELATIONSHIP_PROPERTY = 0;
73
        public static final int RELATIONSHIP_VAUES = 1;
74 18271 jpiera
75 7897 jorpiell
        private StringBuffer currentQuery = null;
76 18271 jpiera
        //Operation types
77 7897 jorpiell
        private static final int OPERATION_PROPERTYNAME = 0;
78
        private static final int OPERATION_LITERAL = 1;
79 18271 jpiera
        //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 7897 jorpiell
        private String wildCardChar = null;
86 18271 jpiera
        //This character must be replaced by one character (typically "?")
87 7897 jorpiell
        private String singleChar = null;
88 18271 jpiera
        //Escape character (typically "\")
89 7897 jorpiell
        private String escapeChar = null;
90 18271 jpiera
        //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 7897 jorpiell
        private Hashtable filterAttributes = new Hashtable();
98 18271 jpiera
99 7897 jorpiell
        /**
100 18271 jpiera
         * If the namespace XML is qualified
101
         */
102
        private boolean isQualified = false;
103
104 33738 jpiera
        private static final StringUtils stringUtils = CompatLocator.getStringUtils();
105
106 18271 jpiera
        /**
107 7897 jorpiell
         * Create a new Filter Encoding Parser
108
         *
109
         *
110 18271 jpiera
         * @param namepacePrefix
111 7897 jorpiell
         * 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 18271 jpiera
        public FilterEncoding(ISQLExpressionFormat formatter,String namesPacePrefix, String wildCard, String singleChar, String escape, Hashtable filterAttributes) {
121 7897 jorpiell
                super(formatter);
122 18271 jpiera
                if (namesPacePrefix == null){
123
                        setQualified(false);
124 8221 jorpiell
                }else{
125 18271 jpiera
                        setQualified(true);
126 8221 jorpiell
                }
127 7897 jorpiell
                this.wildCardChar = wildCard;
128
                this.singleChar = singleChar;
129
                this.escapeChar = escape;
130
                this.filterAttributes = filterAttributes;
131
        }
132 18271 jpiera
133
134 7897 jorpiell
        /**
135
         * Create a new Filter Encoding Parser
136
         * @param formatter
137
         */
138
        public FilterEncoding(ISQLExpressionFormat formatter) {
139 18271 jpiera
                this(formatter,null,DEFAULT_WILDCARD,DEFAULT_SINGLECHAR,
140
                                DEFAULT_ESCAPE,new Hashtable());
141 7897 jorpiell
        }
142 18271 jpiera
143
        /**
144
         * Create a new Filter Encoding Parser
145
         */
146
        public FilterEncoding() {
147
                this(new DefaultSQLExpressionFormat());
148 29680 jpiera
        }
149
150
        /**
151
         * Create a new Filter Encoding Parser
152
         */
153
        public FilterEncoding(WFSStatus status) {
154
                this();
155 31835 jpiera
                setQueryByAttribute(status.getFilterByAttribute());
156
                clearSpatialFilters();
157
                addSpatialFilter(status.getFilterByArea());
158 18271 jpiera
        }
159
160 7897 jorpiell
        /*
161
         *  (non-Javadoc)
162
         * @see org.gvsig.remoteClient.filterEncoding.QueryLanguage#toString(org.gvsig.remoteClient.filterEncoding.BinaryTree)
163
         */
164 31835 jpiera
        public String toString(BinaryTree tree) {
165 18271 jpiera
                //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 31835 jpiera
                if ((tree.getRoot() == null) && (getSpatialFiltersCount() == 0)){
182 8221 jorpiell
                        return null;
183
                }
184 10392 jorpiell
                if (tree.getRoot() != null){
185
                        currentQuery = new StringBuffer();
186
                        filterQuery = getFilterNode(tree.getRoot());
187 31835 jpiera
                        if (getSpatialFiltersCount() == 0){
188 10392 jorpiell
                                return enclosesWithFilterTag(filterQuery);
189
                        }
190
                }
191 18271 jpiera
                //If is a filter by area
192
                String bboxQuery = null;
193 31835 jpiera
                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 10392 jorpiell
                        }
210 10619 jorpiell
                }
211
                return enclosesWithFilterTag(filterQuery + bboxQuery);
212 7897 jorpiell
        }
213 18271 jpiera
214 7897 jorpiell
        /**
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 18271 jpiera
236 7897 jorpiell
        /**
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 33738 jpiera
                String[] words = stringUtils.split(expression, " ");
244 8699 jorpiell
                //Param
245 7897 jorpiell
                String param = words[0];
246 8699 jorpiell
                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 7897 jorpiell
                String operator = words[1];
254 8699 jorpiell
                //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 8528 jorpiell
                int operatorCode = getRelationalOperator(operator);
266 7897 jorpiell
                operator = getRelationalOperator(operatorCode);
267
                return createExpression(operator,param,value);
268
        }
269 18271 jpiera
270 7897 jorpiell
        /**
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 18271 jpiera
                cadena = "<" + namepacePrefix + property;
285 7897 jorpiell
                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 18271 jpiera
                return cadena + "</" + namepacePrefix + property + ">";
299 7897 jorpiell
        }
300 18271 jpiera
301 7897 jorpiell
        /**
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 10392 jorpiell
        }
316 18271 jpiera
317 10392 jorpiell
        /**
318 18271 jpiera
         * 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 10392 jorpiell
         * 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 18271 jpiera
                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 10392 jorpiell
                filter.append(query);
381 18271 jpiera
                filter.append("</" + namepacePrefix + "Filter>");
382 10392 jorpiell
                return filter.toString();
383
        }
384 18271 jpiera
385 7897 jorpiell
        /*
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 18271 jpiera
402 7897 jorpiell
        /*
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 8221 jorpiell
                        return "PropertyIsEqualTo";
410 7897 jorpiell
                case RELATIONAL_OPERATOR_IS_NOT_EQUALS_TO:
411 8221 jorpiell
                        return "PropertyIsNotEqualTo";
412 7897 jorpiell
                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 18271 jpiera
431 7897 jorpiell
        /*
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 18271 jpiera
463 7897 jorpiell
        }
464 18271 jpiera
465 7897 jorpiell
        public String getSeparator(int separator) {
466
                return null;
467
        }
468 18271 jpiera
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 7897 jorpiell
}