[76] | 1 | /* Copyright (c) 2006-2010 by OpenLayers Contributors (see authors.txt for |
---|
| 2 | * full list of contributors). Published under the Clear BSD license. |
---|
| 3 | * See http://svn.openlayers.org/trunk/openlayers/license.txt for the |
---|
| 4 | * full text of the license. */ |
---|
| 5 | /** |
---|
| 6 | * @requires OpenLayers/Format/Filter.js |
---|
| 7 | * @requires OpenLayers/Format/XML.js |
---|
| 8 | */ |
---|
| 9 | |
---|
| 10 | /** |
---|
| 11 | * Class: OpenLayers.Format.Filter.v1 |
---|
| 12 | * Superclass for Filter version 1 parsers. |
---|
| 13 | * |
---|
| 14 | * Inherits from: |
---|
| 15 | * - <OpenLayers.Format.XML> |
---|
| 16 | */ |
---|
| 17 | OpenLayers.Format.Filter.v1 = OpenLayers.Class(OpenLayers.Format.XML, { |
---|
| 18 | |
---|
| 19 | /** |
---|
| 20 | * Property: namespaces |
---|
| 21 | * {Object} Mapping of namespace aliases to namespace URIs. |
---|
| 22 | */ |
---|
| 23 | namespaces: { |
---|
| 24 | ogc: "http://www.opengis.net/ogc", |
---|
| 25 | gml: "http://www.opengis.net/gml", |
---|
| 26 | xlink: "http://www.w3.org/1999/xlink", |
---|
| 27 | xsi: "http://www.w3.org/2001/XMLSchema-instance" |
---|
| 28 | }, |
---|
| 29 | |
---|
| 30 | /** |
---|
| 31 | * Property: defaultPrefix |
---|
| 32 | */ |
---|
| 33 | defaultPrefix: "ogc", |
---|
| 34 | |
---|
| 35 | /** |
---|
| 36 | * Property: schemaLocation |
---|
| 37 | * {String} Schema location for a particular minor version. |
---|
| 38 | */ |
---|
| 39 | schemaLocation: null, |
---|
| 40 | |
---|
| 41 | /** |
---|
| 42 | * Constructor: OpenLayers.Format.Filter.v1 |
---|
| 43 | * Instances of this class are not created directly. Use the |
---|
| 44 | * <OpenLayers.Format.Filter> constructor instead. |
---|
| 45 | * |
---|
| 46 | * Parameters: |
---|
| 47 | * options - {Object} An optional object whose properties will be set on |
---|
| 48 | * this instance. |
---|
| 49 | */ |
---|
| 50 | initialize: function(options) { |
---|
| 51 | OpenLayers.Format.XML.prototype.initialize.apply(this, [options]); |
---|
| 52 | }, |
---|
| 53 | |
---|
| 54 | /** |
---|
| 55 | * Method: read |
---|
| 56 | * |
---|
| 57 | * Parameters: |
---|
| 58 | * data - {DOMElement} A Filter document element. |
---|
| 59 | * |
---|
| 60 | * Returns: |
---|
| 61 | * {<OpenLayers.Filter>} A filter object. |
---|
| 62 | */ |
---|
| 63 | read: function(data) { |
---|
| 64 | var obj = {}; |
---|
| 65 | this.readers.ogc["Filter"].apply(this, [data, obj]); |
---|
| 66 | return obj.filter; |
---|
| 67 | }, |
---|
| 68 | |
---|
| 69 | /** |
---|
| 70 | * Property: readers |
---|
| 71 | * Contains public functions, grouped by namespace prefix, that will |
---|
| 72 | * be applied when a namespaced node is found matching the function |
---|
| 73 | * name. The function will be applied in the scope of this parser |
---|
| 74 | * with two arguments: the node being read and a context object passed |
---|
| 75 | * from the parent. |
---|
| 76 | */ |
---|
| 77 | readers: { |
---|
| 78 | "ogc": { |
---|
| 79 | "Filter": function(node, parent) { |
---|
| 80 | // Filters correspond to subclasses of OpenLayers.Filter. |
---|
| 81 | // Since they contain information we don't persist, we |
---|
| 82 | // create a temporary object and then pass on the filter |
---|
| 83 | // (ogc:Filter) to the parent obj. |
---|
| 84 | var obj = { |
---|
| 85 | fids: [], |
---|
| 86 | filters: [] |
---|
| 87 | }; |
---|
| 88 | this.readChildNodes(node, obj); |
---|
| 89 | if(obj.fids.length > 0) { |
---|
| 90 | parent.filter = new OpenLayers.Filter.FeatureId({ |
---|
| 91 | fids: obj.fids |
---|
| 92 | }); |
---|
| 93 | } else if(obj.filters.length > 0) { |
---|
| 94 | parent.filter = obj.filters[0]; |
---|
| 95 | } |
---|
| 96 | }, |
---|
| 97 | "FeatureId": function(node, obj) { |
---|
| 98 | var fid = node.getAttribute("fid"); |
---|
| 99 | if(fid) { |
---|
| 100 | obj.fids.push(fid); |
---|
| 101 | } |
---|
| 102 | }, |
---|
| 103 | "And": function(node, obj) { |
---|
| 104 | var filter = new OpenLayers.Filter.Logical({ |
---|
| 105 | type: OpenLayers.Filter.Logical.AND |
---|
| 106 | }); |
---|
| 107 | this.readChildNodes(node, filter); |
---|
| 108 | obj.filters.push(filter); |
---|
| 109 | }, |
---|
| 110 | "Or": function(node, obj) { |
---|
| 111 | var filter = new OpenLayers.Filter.Logical({ |
---|
| 112 | type: OpenLayers.Filter.Logical.OR |
---|
| 113 | }); |
---|
| 114 | this.readChildNodes(node, filter); |
---|
| 115 | obj.filters.push(filter); |
---|
| 116 | }, |
---|
| 117 | "Not": function(node, obj) { |
---|
| 118 | var filter = new OpenLayers.Filter.Logical({ |
---|
| 119 | type: OpenLayers.Filter.Logical.NOT |
---|
| 120 | }); |
---|
| 121 | this.readChildNodes(node, filter); |
---|
| 122 | obj.filters.push(filter); |
---|
| 123 | }, |
---|
| 124 | "PropertyIsLessThan": function(node, obj) { |
---|
| 125 | var filter = new OpenLayers.Filter.Comparison({ |
---|
| 126 | type: OpenLayers.Filter.Comparison.LESS_THAN |
---|
| 127 | }); |
---|
| 128 | this.readChildNodes(node, filter); |
---|
| 129 | obj.filters.push(filter); |
---|
| 130 | }, |
---|
| 131 | "PropertyIsGreaterThan": function(node, obj) { |
---|
| 132 | var filter = new OpenLayers.Filter.Comparison({ |
---|
| 133 | type: OpenLayers.Filter.Comparison.GREATER_THAN |
---|
| 134 | }); |
---|
| 135 | this.readChildNodes(node, filter); |
---|
| 136 | obj.filters.push(filter); |
---|
| 137 | }, |
---|
| 138 | "PropertyIsLessThanOrEqualTo": function(node, obj) { |
---|
| 139 | var filter = new OpenLayers.Filter.Comparison({ |
---|
| 140 | type: OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO |
---|
| 141 | }); |
---|
| 142 | this.readChildNodes(node, filter); |
---|
| 143 | obj.filters.push(filter); |
---|
| 144 | }, |
---|
| 145 | "PropertyIsGreaterThanOrEqualTo": function(node, obj) { |
---|
| 146 | var filter = new OpenLayers.Filter.Comparison({ |
---|
| 147 | type: OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO |
---|
| 148 | }); |
---|
| 149 | this.readChildNodes(node, filter); |
---|
| 150 | obj.filters.push(filter); |
---|
| 151 | }, |
---|
| 152 | "PropertyIsBetween": function(node, obj) { |
---|
| 153 | var filter = new OpenLayers.Filter.Comparison({ |
---|
| 154 | type: OpenLayers.Filter.Comparison.BETWEEN |
---|
| 155 | }); |
---|
| 156 | this.readChildNodes(node, filter); |
---|
| 157 | obj.filters.push(filter); |
---|
| 158 | }, |
---|
| 159 | "Literal": function(node, obj) { |
---|
| 160 | obj.value = OpenLayers.String.numericIf( |
---|
| 161 | this.getChildValue(node)); |
---|
| 162 | }, |
---|
| 163 | "PropertyName": function(node, filter) { |
---|
| 164 | filter.property = this.getChildValue(node); |
---|
| 165 | }, |
---|
| 166 | "LowerBoundary": function(node, filter) { |
---|
| 167 | filter.lowerBoundary = OpenLayers.String.numericIf( |
---|
| 168 | this.readOgcExpression(node)); |
---|
| 169 | }, |
---|
| 170 | "UpperBoundary": function(node, filter) { |
---|
| 171 | filter.upperBoundary = OpenLayers.String.numericIf( |
---|
| 172 | this.readOgcExpression(node)); |
---|
| 173 | }, |
---|
| 174 | "Intersects": function(node, obj) { |
---|
| 175 | this.readSpatial(node, obj, OpenLayers.Filter.Spatial.INTERSECTS); |
---|
| 176 | }, |
---|
| 177 | "Within": function(node, obj) { |
---|
| 178 | this.readSpatial(node, obj, OpenLayers.Filter.Spatial.WITHIN); |
---|
| 179 | }, |
---|
| 180 | "Contains": function(node, obj) { |
---|
| 181 | this.readSpatial(node, obj, OpenLayers.Filter.Spatial.CONTAINS); |
---|
| 182 | }, |
---|
| 183 | "DWithin": function(node, obj) { |
---|
| 184 | this.readSpatial(node, obj, OpenLayers.Filter.Spatial.DWITHIN); |
---|
| 185 | }, |
---|
| 186 | "Distance": function(node, obj) { |
---|
| 187 | obj.distance = parseInt(this.getChildValue(node)); |
---|
| 188 | obj.distanceUnits = node.getAttribute("units"); |
---|
| 189 | } |
---|
| 190 | } |
---|
| 191 | }, |
---|
| 192 | |
---|
| 193 | /** |
---|
| 194 | * Method: readSpatial |
---|
| 195 | * |
---|
| 196 | * Read a {<OpenLayers.Filter.Spatial>} filter. |
---|
| 197 | * |
---|
| 198 | * Parameters: |
---|
| 199 | * node - {DOMElement} A DOM element that contains an ogc:expression. |
---|
| 200 | * obj - {Object} The target object. |
---|
| 201 | * type - {String} One of the OpenLayers.Filter.Spatial.* constants. |
---|
| 202 | * |
---|
| 203 | * Returns: |
---|
| 204 | * {<OpenLayers.Filter.Spatial>} The created filter. |
---|
| 205 | */ |
---|
| 206 | readSpatial: function(node, obj, type) { |
---|
| 207 | var filter = new OpenLayers.Filter.Spatial({ |
---|
| 208 | type: type |
---|
| 209 | }); |
---|
| 210 | this.readChildNodes(node, filter); |
---|
| 211 | filter.value = filter.components[0]; |
---|
| 212 | delete filter.components; |
---|
| 213 | obj.filters.push(filter); |
---|
| 214 | }, |
---|
| 215 | |
---|
| 216 | /** |
---|
| 217 | * Method: readOgcExpression |
---|
| 218 | * Limited support for OGC expressions. |
---|
| 219 | * |
---|
| 220 | * Parameters: |
---|
| 221 | * node - {DOMElement} A DOM element that contains an ogc:expression. |
---|
| 222 | * |
---|
| 223 | * Returns: |
---|
| 224 | * {String} A value to be used in a symbolizer. |
---|
| 225 | */ |
---|
| 226 | readOgcExpression: function(node) { |
---|
| 227 | var obj = {}; |
---|
| 228 | this.readChildNodes(node, obj); |
---|
| 229 | var value = obj.value; |
---|
| 230 | if(value === undefined) { |
---|
| 231 | value = this.getChildValue(node); |
---|
| 232 | } |
---|
| 233 | return value; |
---|
| 234 | }, |
---|
| 235 | |
---|
| 236 | /** |
---|
| 237 | * Method: write |
---|
| 238 | * |
---|
| 239 | * Parameters: |
---|
| 240 | * filter - {<OpenLayers.Filter>} A filter object. |
---|
| 241 | * |
---|
| 242 | * Returns: |
---|
| 243 | * {DOMElement} An ogc:Filter element. |
---|
| 244 | */ |
---|
| 245 | write: function(filter) { |
---|
| 246 | return this.writers.ogc["Filter"].apply(this, [filter]); |
---|
| 247 | }, |
---|
| 248 | |
---|
| 249 | /** |
---|
| 250 | * Property: writers |
---|
| 251 | * As a compliment to the readers property, this structure contains public |
---|
| 252 | * writing functions grouped by namespace alias and named like the |
---|
| 253 | * node names they produce. |
---|
| 254 | */ |
---|
| 255 | writers: { |
---|
| 256 | "ogc": { |
---|
| 257 | "Filter": function(filter) { |
---|
| 258 | var node = this.createElementNSPlus("ogc:Filter"); |
---|
| 259 | var sub = filter.CLASS_NAME.split(".").pop(); |
---|
| 260 | if(sub == "FeatureId") { |
---|
| 261 | for(var i=0; i<filter.fids.length; ++i) { |
---|
| 262 | this.writeNode("FeatureId", filter.fids[i], node); |
---|
| 263 | } |
---|
| 264 | } else { |
---|
| 265 | this.writeNode(this.getFilterType(filter), filter, node); |
---|
| 266 | } |
---|
| 267 | return node; |
---|
| 268 | }, |
---|
| 269 | "FeatureId": function(fid) { |
---|
| 270 | return this.createElementNSPlus("ogc:FeatureId", { |
---|
| 271 | attributes: {fid: fid} |
---|
| 272 | }); |
---|
| 273 | }, |
---|
| 274 | "And": function(filter) { |
---|
| 275 | var node = this.createElementNSPlus("ogc:And"); |
---|
| 276 | var childFilter; |
---|
| 277 | for(var i=0; i<filter.filters.length; ++i) { |
---|
| 278 | childFilter = filter.filters[i]; |
---|
| 279 | this.writeNode( |
---|
| 280 | this.getFilterType(childFilter), childFilter, node |
---|
| 281 | ); |
---|
| 282 | } |
---|
| 283 | return node; |
---|
| 284 | }, |
---|
| 285 | "Or": function(filter) { |
---|
| 286 | var node = this.createElementNSPlus("ogc:Or"); |
---|
| 287 | var childFilter; |
---|
| 288 | for(var i=0; i<filter.filters.length; ++i) { |
---|
| 289 | childFilter = filter.filters[i]; |
---|
| 290 | this.writeNode( |
---|
| 291 | this.getFilterType(childFilter), childFilter, node |
---|
| 292 | ); |
---|
| 293 | } |
---|
| 294 | return node; |
---|
| 295 | }, |
---|
| 296 | "Not": function(filter) { |
---|
| 297 | var node = this.createElementNSPlus("ogc:Not"); |
---|
| 298 | var childFilter = filter.filters[0]; |
---|
| 299 | this.writeNode( |
---|
| 300 | this.getFilterType(childFilter), childFilter, node |
---|
| 301 | ); |
---|
| 302 | return node; |
---|
| 303 | }, |
---|
| 304 | "PropertyIsLessThan": function(filter) { |
---|
| 305 | var node = this.createElementNSPlus("ogc:PropertyIsLessThan"); |
---|
| 306 | // no ogc:expression handling for now |
---|
| 307 | this.writeNode("PropertyName", filter, node); |
---|
| 308 | this.writeNode("Literal", filter.value, node); |
---|
| 309 | return node; |
---|
| 310 | }, |
---|
| 311 | "PropertyIsGreaterThan": function(filter) { |
---|
| 312 | var node = this.createElementNSPlus("ogc:PropertyIsGreaterThan"); |
---|
| 313 | // no ogc:expression handling for now |
---|
| 314 | this.writeNode("PropertyName", filter, node); |
---|
| 315 | this.writeNode("Literal", filter.value, node); |
---|
| 316 | return node; |
---|
| 317 | }, |
---|
| 318 | "PropertyIsLessThanOrEqualTo": function(filter) { |
---|
| 319 | var node = this.createElementNSPlus("ogc:PropertyIsLessThanOrEqualTo"); |
---|
| 320 | // no ogc:expression handling for now |
---|
| 321 | this.writeNode("PropertyName", filter, node); |
---|
| 322 | this.writeNode("Literal", filter.value, node); |
---|
| 323 | return node; |
---|
| 324 | }, |
---|
| 325 | "PropertyIsGreaterThanOrEqualTo": function(filter) { |
---|
| 326 | var node = this.createElementNSPlus("ogc:PropertyIsGreaterThanOrEqualTo"); |
---|
| 327 | // no ogc:expression handling for now |
---|
| 328 | this.writeNode("PropertyName", filter, node); |
---|
| 329 | this.writeNode("Literal", filter.value, node); |
---|
| 330 | return node; |
---|
| 331 | }, |
---|
| 332 | "PropertyIsBetween": function(filter) { |
---|
| 333 | var node = this.createElementNSPlus("ogc:PropertyIsBetween"); |
---|
| 334 | // no ogc:expression handling for now |
---|
| 335 | this.writeNode("PropertyName", filter, node); |
---|
| 336 | this.writeNode("LowerBoundary", filter, node); |
---|
| 337 | this.writeNode("UpperBoundary", filter, node); |
---|
| 338 | return node; |
---|
| 339 | }, |
---|
| 340 | "PropertyName": function(filter) { |
---|
| 341 | // no ogc:expression handling for now |
---|
| 342 | return this.createElementNSPlus("ogc:PropertyName", { |
---|
| 343 | value: filter.property |
---|
| 344 | }); |
---|
| 345 | }, |
---|
| 346 | "Literal": function(value) { |
---|
| 347 | // no ogc:expression handling for now |
---|
| 348 | return this.createElementNSPlus("ogc:Literal", { |
---|
| 349 | value: value |
---|
| 350 | }); |
---|
| 351 | }, |
---|
| 352 | "LowerBoundary": function(filter) { |
---|
| 353 | // no ogc:expression handling for now |
---|
| 354 | var node = this.createElementNSPlus("ogc:LowerBoundary"); |
---|
| 355 | this.writeNode("Literal", filter.lowerBoundary, node); |
---|
| 356 | return node; |
---|
| 357 | }, |
---|
| 358 | "UpperBoundary": function(filter) { |
---|
| 359 | // no ogc:expression handling for now |
---|
| 360 | var node = this.createElementNSPlus("ogc:UpperBoundary"); |
---|
| 361 | this.writeNode("Literal", filter.upperBoundary, node); |
---|
| 362 | return node; |
---|
| 363 | }, |
---|
| 364 | "INTERSECTS": function(filter) { |
---|
| 365 | return this.writeSpatial(filter, "Intersects"); |
---|
| 366 | }, |
---|
| 367 | "WITHIN": function(filter) { |
---|
| 368 | return this.writeSpatial(filter, "Within"); |
---|
| 369 | }, |
---|
| 370 | "CONTAINS": function(filter) { |
---|
| 371 | return this.writeSpatial(filter, "Contains"); |
---|
| 372 | }, |
---|
| 373 | "DWITHIN": function(filter) { |
---|
| 374 | var node = this.writeSpatial(filter, "DWithin"); |
---|
| 375 | this.writeNode("Distance", filter, node); |
---|
| 376 | return node; |
---|
| 377 | }, |
---|
| 378 | "Distance": function(filter) { |
---|
| 379 | return this.createElementNSPlus("ogc:Distance", { |
---|
| 380 | attributes: { |
---|
| 381 | units: filter.distanceUnits |
---|
| 382 | }, |
---|
| 383 | value: filter.distance |
---|
| 384 | }); |
---|
| 385 | } |
---|
| 386 | } |
---|
| 387 | }, |
---|
| 388 | |
---|
| 389 | /** |
---|
| 390 | * Method: getFilterType |
---|
| 391 | */ |
---|
| 392 | getFilterType: function(filter) { |
---|
| 393 | var filterType = this.filterMap[filter.type]; |
---|
| 394 | if(!filterType) { |
---|
| 395 | throw "Filter writing not supported for rule type: " + filter.type; |
---|
| 396 | } |
---|
| 397 | return filterType; |
---|
| 398 | }, |
---|
| 399 | |
---|
| 400 | /** |
---|
| 401 | * Property: filterMap |
---|
| 402 | * {Object} Contains a member for each filter type. Values are node names |
---|
| 403 | * for corresponding OGC Filter child elements. |
---|
| 404 | */ |
---|
| 405 | filterMap: { |
---|
| 406 | "&&": "And", |
---|
| 407 | "||": "Or", |
---|
| 408 | "!": "Not", |
---|
| 409 | "==": "PropertyIsEqualTo", |
---|
| 410 | "!=": "PropertyIsNotEqualTo", |
---|
| 411 | "<": "PropertyIsLessThan", |
---|
| 412 | ">": "PropertyIsGreaterThan", |
---|
| 413 | "<=": "PropertyIsLessThanOrEqualTo", |
---|
| 414 | ">=": "PropertyIsGreaterThanOrEqualTo", |
---|
| 415 | "..": "PropertyIsBetween", |
---|
| 416 | "~": "PropertyIsLike", |
---|
| 417 | "BBOX": "BBOX", |
---|
| 418 | "DWITHIN": "DWITHIN", |
---|
| 419 | "WITHIN": "WITHIN", |
---|
| 420 | "CONTAINS": "CONTAINS", |
---|
| 421 | "INTERSECTS": "INTERSECTS" |
---|
| 422 | }, |
---|
| 423 | |
---|
| 424 | CLASS_NAME: "OpenLayers.Format.Filter.v1" |
---|
| 425 | |
---|
| 426 | }); |
---|