source: ether_iasi/trunk/web/resources/js/OpenLayers-2.12/lib/OpenLayers/Format/GML/Base.js @ 738

Last change on this file since 738 was 738, checked in by vmipsl, 11 years ago

OpenLayers?

File size: 24.2 KB
Line 
1/* Copyright (c) 2006-2012 by OpenLayers Contributors (see authors.txt for
2 * full list of contributors). Published under the 2-clause BSD license.
3 * See license.txt in the OpenLayers distribution or repository for the
4 * full text of the license. */
5
6/**
7 * @requires OpenLayers/Format/XML.js
8 * @requires OpenLayers/Format/GML.js
9 */
10
11/**
12 * Though required in the full build, if the GML format is excluded, we set
13 * the namespace here.
14 */
15if(!OpenLayers.Format.GML) {
16    OpenLayers.Format.GML = {};
17}
18
19/**
20 * Class: OpenLayers.Format.GML.Base
21 * Superclass for GML parsers.
22 *
23 * Inherits from:
24 *  - <OpenLayers.Format.XML>
25 */
26OpenLayers.Format.GML.Base = OpenLayers.Class(OpenLayers.Format.XML, {
27   
28    /**
29     * Property: namespaces
30     * {Object} Mapping of namespace aliases to namespace URIs.
31     */
32    namespaces: {
33        gml: "http://www.opengis.net/gml",
34        xlink: "http://www.w3.org/1999/xlink",
35        xsi: "http://www.w3.org/2001/XMLSchema-instance",
36        wfs: "http://www.opengis.net/wfs" // this is a convenience for reading wfs:FeatureCollection
37    },
38   
39    /**
40     * Property: defaultPrefix
41     */
42    defaultPrefix: "gml",
43
44    /**
45     * Property: schemaLocation
46     * {String} Schema location for a particular minor version.
47     */
48    schemaLocation: null,
49   
50    /**
51     * APIProperty: featureType
52     * {Array(String) or String} The local (without prefix) feature typeName(s).
53     */
54    featureType: null,
55   
56    /**
57     * APIProperty: featureNS
58     * {String} The feature namespace.  Must be set in the options at
59     *     construction.
60     */
61    featureNS: null,
62
63    /**
64     * APIProperty: geometry
65     * {String} Name of geometry element.  Defaults to "geometry". If null, it
66     * will be set on <read> when the first geometry is parsed.
67     */
68    geometryName: "geometry",
69
70    /**
71     * APIProperty: extractAttributes
72     * {Boolean} Extract attributes from GML.  Default is true.
73     */
74    extractAttributes: true,
75   
76    /**
77     * APIProperty: srsName
78     * {String} URI for spatial reference system.  This is optional for
79     *     single part geometries and mandatory for collections and multis.
80     *     If set, the srsName attribute will be written for all geometries.
81     *     Default is null.
82     */
83    srsName: null,
84
85    /**
86     * APIProperty: xy
87     * {Boolean} Order of the GML coordinate true:(x,y) or false:(y,x)
88     * Changing is not recommended, a new Format should be instantiated.
89     */ 
90    xy: true,
91
92    /**
93     * Property: geometryTypes
94     * {Object} Maps OpenLayers geometry class names to GML element names.
95     *     Use <setGeometryTypes> before accessing this property.
96     */
97    geometryTypes: null,
98
99    /**
100     * Property: singleFeatureType
101     * {Boolean} True if there is only 1 featureType, and not an array
102     *     of featuretypes.
103     */
104    singleFeatureType: null,
105   
106    /**
107     * Property: autoConfig
108     * {Boolean} Indicates if the format was configured without a <featureNS>,
109     * but auto-configured <featureNS> and <featureType> during read.
110     * Subclasses making use of <featureType> auto-configuration should make
111     * the first call to the <readNode> method (usually in the read method)
112     * with true as 3rd argument, so the auto-configured featureType can be
113     * reset and the format can be reused for subsequent reads with data from
114     * different featureTypes. Set to false after read if you want to keep the
115     * auto-configured values.
116     */
117
118    /**
119     * Property: regExes
120     * Compiled regular expressions for manipulating strings.
121     */
122    regExes: {
123        trimSpace: (/^\s*|\s*$/g),
124        removeSpace: (/\s*/g),
125        splitSpace: (/\s+/),
126        trimComma: (/\s*,\s*/g),
127        featureMember: (/^(.*:)?featureMembers?$/)
128    },
129
130    /**
131     * Constructor: OpenLayers.Format.GML.Base
132     * Instances of this class are not created directly.  Use the
133     *     <OpenLayers.Format.GML.v2> or <OpenLayers.Format.GML.v3> constructor
134     *     instead.
135     *
136     * Parameters:
137     * options - {Object} An optional object whose properties will be set on
138     *     this instance.
139     *
140     * Valid options properties:
141     * featureType - {Array(String) or String} Local (without prefix) feature
142     *     typeName(s) (required for write).
143     * featureNS - {String} Feature namespace (required for write).
144     * geometryName - {String} Geometry element name (required for write).
145     */
146    initialize: function(options) {
147        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
148        this.setGeometryTypes();
149        if(options && options.featureNS) {
150            this.setNamespace("feature", options.featureNS);
151        }
152        this.singleFeatureType = !options || (typeof options.featureType === "string");
153    },
154   
155    /**
156     * Method: read
157     *
158     * Parameters:
159     * data - {DOMElement} A gml:featureMember element, a gml:featureMembers
160     *     element, or an element containing either of the above at any level.
161     *
162     * Returns:
163     * {Array(<OpenLayers.Feature.Vector>)} An array of features.
164     */
165    read: function(data) {
166        if(typeof data == "string") { 
167            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
168        }
169        if(data && data.nodeType == 9) {
170            data = data.documentElement;
171        }
172        var features = [];
173        this.readNode(data, {features: features}, true);
174        if(features.length == 0) {
175            // look for gml:featureMember elements
176            var elements = this.getElementsByTagNameNS(
177                data, this.namespaces.gml, "featureMember"
178            );
179            if(elements.length) {
180                for(var i=0, len=elements.length; i<len; ++i) {
181                    this.readNode(elements[i], {features: features}, true);
182                }
183            } else {
184                // look for gml:featureMembers elements (this is v3, but does no harm here)
185                var elements = this.getElementsByTagNameNS(
186                    data, this.namespaces.gml, "featureMembers"
187                );
188                if(elements.length) {
189                    // there can be only one
190                    this.readNode(elements[0], {features: features}, true);
191                }
192            }
193        }
194        return features;
195    },
196   
197    /**
198     * Method: readNode
199     * Shorthand for applying one of the named readers given the node
200     *     namespace and local name.  Readers take two args (node, obj) and
201     *     generally extend or modify the second.
202     *
203     * Parameters:
204     * node - {DOMElement} The node to be read (required).
205     * obj - {Object} The object to be modified (optional).
206     * first - {Boolean} Should be set to true for the first node read. This
207     *     is usually the readNode call in the read method. Without this being
208     *     set, auto-configured properties will stick on subsequent reads.
209     *
210     * Returns:
211     * {Object} The input object, modified (or a new one if none was provided).
212     */
213    readNode: function(node, obj, first) {
214        // on subsequent calls of format.read(), we want to reset auto-
215        // configured properties and auto-configure again.
216        if (first === true && this.autoConfig === true) {
217            this.featureType = null;
218            delete this.namespaceAlias[this.featureNS];
219            delete this.namespaces["feature"];
220            this.featureNS = null;
221        }
222        // featureType auto-configuration
223        if (!this.featureNS && (!(node.prefix in this.namespaces) &&
224                node.parentNode.namespaceURI == this.namespaces["gml"] &&
225                this.regExes.featureMember.test(node.parentNode.nodeName))) {
226            this.featureType = node.nodeName.split(":").pop();
227            this.setNamespace("feature", node.namespaceURI);
228            this.featureNS = node.namespaceURI;
229            this.autoConfig = true;
230        }
231        return OpenLayers.Format.XML.prototype.readNode.apply(this, [node, obj]);
232    },
233
234    /**
235     * Property: readers
236     * Contains public functions, grouped by namespace prefix, that will
237     *     be applied when a namespaced node is found matching the function
238     *     name.  The function will be applied in the scope of this parser
239     *     with two arguments: the node being read and a context object passed
240     *     from the parent.
241     */
242    readers: {
243        "gml": {
244            "featureMember": function(node, obj) {
245                this.readChildNodes(node, obj);
246            },
247            "featureMembers": function(node, obj) {
248                this.readChildNodes(node, obj);               
249            },
250            "name": function(node, obj) {
251                obj.name = this.getChildValue(node);
252            },
253            "boundedBy": function(node, obj) {
254                var container = {};
255                this.readChildNodes(node, container);
256                if(container.components && container.components.length > 0) {
257                    obj.bounds = container.components[0];
258                }
259            },
260            "Point": function(node, container) {
261                var obj = {points: []};
262                this.readChildNodes(node, obj);
263                if(!container.components) {
264                    container.components = [];
265                }
266                container.components.push(obj.points[0]);
267            },
268            "coordinates": function(node, obj) {
269                var str = this.getChildValue(node).replace(
270                    this.regExes.trimSpace, ""
271                );
272                str = str.replace(this.regExes.trimComma, ",");
273                var pointList = str.split(this.regExes.splitSpace);
274                var coords;
275                var numPoints = pointList.length;
276                var points = new Array(numPoints);
277                for(var i=0; i<numPoints; ++i) {
278                    coords = pointList[i].split(",");
279                    if (this.xy) {
280                        points[i] = new OpenLayers.Geometry.Point(
281                            coords[0], coords[1], coords[2]
282                        );
283                    } else {
284                        points[i] = new OpenLayers.Geometry.Point(
285                            coords[1], coords[0], coords[2]
286                        );
287                    }
288                }
289                obj.points = points;
290            },
291            "coord": function(node, obj) {
292                var coord = {};
293                this.readChildNodes(node, coord);
294                if(!obj.points) {
295                    obj.points = [];
296                }
297                obj.points.push(new OpenLayers.Geometry.Point(
298                    coord.x, coord.y, coord.z
299                ));
300            },
301            "X": function(node, coord) {
302                coord.x = this.getChildValue(node);
303            },
304            "Y": function(node, coord) {
305                coord.y = this.getChildValue(node);
306            },
307            "Z": function(node, coord) {
308                coord.z = this.getChildValue(node);
309            },
310            "MultiPoint": function(node, container) {
311                var obj = {components: []};
312                this.readChildNodes(node, obj);
313                container.components = [
314                    new OpenLayers.Geometry.MultiPoint(obj.components)
315                ];
316            },
317            "pointMember": function(node, obj) {
318                this.readChildNodes(node, obj);
319            },
320            "LineString": function(node, container) {
321                var obj = {};
322                this.readChildNodes(node, obj);
323                if(!container.components) {
324                    container.components = [];
325                }
326                container.components.push(
327                    new OpenLayers.Geometry.LineString(obj.points)
328                );
329            },
330            "MultiLineString": function(node, container) {
331                var obj = {components: []};
332                this.readChildNodes(node, obj);
333                container.components = [
334                    new OpenLayers.Geometry.MultiLineString(obj.components)
335                ];
336            },
337            "lineStringMember": function(node, obj) {
338                this.readChildNodes(node, obj);
339            },
340            "Polygon": function(node, container) {
341                var obj = {outer: null, inner: []};
342                this.readChildNodes(node, obj);
343                obj.inner.unshift(obj.outer);
344                if(!container.components) {
345                    container.components = [];
346                }
347                container.components.push(
348                    new OpenLayers.Geometry.Polygon(obj.inner)
349                );
350            },
351            "LinearRing": function(node, obj) {
352                var container = {};
353                this.readChildNodes(node, container);
354                obj.components = [new OpenLayers.Geometry.LinearRing(
355                    container.points
356                )];
357            },
358            "MultiPolygon": function(node, container) {
359                var obj = {components: []};
360                this.readChildNodes(node, obj);
361                container.components = [
362                    new OpenLayers.Geometry.MultiPolygon(obj.components)
363                ];
364            },
365            "polygonMember": function(node, obj) {
366                this.readChildNodes(node, obj);
367            },
368            "GeometryCollection": function(node, container) {
369                var obj = {components: []};
370                this.readChildNodes(node, obj);
371                container.components = [
372                    new OpenLayers.Geometry.Collection(obj.components)
373                ];
374            },
375            "geometryMember": function(node, obj) {
376                this.readChildNodes(node, obj);
377            }
378        },
379        "feature": {
380            "*": function(node, obj) {
381                // The node can either be named like the featureType, or it
382                // can be a child of the feature:featureType.  Children can be
383                // geometry or attributes.
384                var name;
385                var local = node.localName || node.nodeName.split(":").pop();
386                // Since an attribute can have the same name as the feature type
387                // we only want to read the node as a feature if the parent
388                // node can have feature nodes as children.  In this case, the
389                // obj.features property is set.
390                if (obj.features) {
391                    if (!this.singleFeatureType &&
392                        (OpenLayers.Util.indexOf(this.featureType, local) !== -1)) {
393                        name = "_typeName";
394                    } else if(local === this.featureType) {
395                        name = "_typeName";
396                    }
397                } else {
398                    // Assume attribute elements have one child node and that the child
399                    // is a text node.  Otherwise assume it is a geometry node.
400                    if(node.childNodes.length == 0 ||
401                       (node.childNodes.length == 1 && node.firstChild.nodeType == 3)) {
402                        if(this.extractAttributes) {
403                            name = "_attribute";
404                        }
405                    } else {
406                        name = "_geometry";
407                    }
408                }
409                if(name) {
410                    this.readers.feature[name].apply(this, [node, obj]);
411                }
412            },
413            "_typeName": function(node, obj) {
414                var container = {components: [], attributes: {}};
415                this.readChildNodes(node, container);
416                // look for common gml namespaced elements
417                if(container.name) {
418                    container.attributes.name = container.name;
419                }
420                var feature = new OpenLayers.Feature.Vector(
421                    container.components[0], container.attributes
422                );
423                if (!this.singleFeatureType) {
424                    feature.type = node.nodeName.split(":").pop();
425                    feature.namespace = node.namespaceURI;
426                }
427                var fid = node.getAttribute("fid") ||
428                    this.getAttributeNS(node, this.namespaces["gml"], "id");
429                if(fid) {
430                    feature.fid = fid;
431                }
432                if(this.internalProjection && this.externalProjection &&
433                   feature.geometry) {
434                    feature.geometry.transform(
435                        this.externalProjection, this.internalProjection
436                    );
437                }
438                if(container.bounds) {
439                    feature.bounds = container.bounds;
440                }
441                obj.features.push(feature);
442            },
443            "_geometry": function(node, obj) {
444                if (!this.geometryName) {
445                    this.geometryName = node.nodeName.split(":").pop();
446                }
447                this.readChildNodes(node, obj);
448            },
449            "_attribute": function(node, obj) {
450                var local = node.localName || node.nodeName.split(":").pop();
451                var value = this.getChildValue(node);
452                obj.attributes[local] = value;
453            }
454        },
455        "wfs": {
456            "FeatureCollection": function(node, obj) {
457                this.readChildNodes(node, obj);
458            }
459        }
460    },
461   
462    /**
463     * Method: write
464     *
465     * Parameters:
466     * features - {Array(<OpenLayers.Feature.Vector>) | OpenLayers.Feature.Vector}
467     *     An array of features or a single feature.
468     *
469     * Returns:
470     * {String} Given an array of features, a doc with a gml:featureMembers
471     *     element will be returned.  Given a single feature, a doc with a
472     *     gml:featureMember element will be returned.
473     */
474    write: function(features) {
475        var name;
476        if(OpenLayers.Util.isArray(features)) {
477            name = "featureMembers";
478        } else {
479            name = "featureMember";
480        }
481        var root = this.writeNode("gml:" + name, features);
482        this.setAttributeNS(
483            root, this.namespaces["xsi"],
484            "xsi:schemaLocation", this.schemaLocation
485        );
486
487        return OpenLayers.Format.XML.prototype.write.apply(this, [root]);
488    },
489   
490    /**
491     * Property: writers
492     * As a compliment to the readers property, this structure contains public
493     *     writing functions grouped by namespace alias and named like the
494     *     node names they produce.
495     */
496    writers: {
497        "gml": {
498            "featureMember": function(feature) {
499                var node = this.createElementNSPlus("gml:featureMember");
500                this.writeNode("feature:_typeName", feature, node);
501                return node;
502            },
503            "MultiPoint": function(geometry) {
504                var node = this.createElementNSPlus("gml:MultiPoint");
505                var components = geometry.components || [geometry];
506                for(var i=0, ii=components.length; i<ii; ++i) {
507                    this.writeNode("pointMember", components[i], node);
508                }
509                return node;
510            },
511            "pointMember": function(geometry) {
512                var node = this.createElementNSPlus("gml:pointMember");
513                this.writeNode("Point", geometry, node);
514                return node;
515            },
516            "MultiLineString": function(geometry) {
517                var node = this.createElementNSPlus("gml:MultiLineString");
518                var components = geometry.components || [geometry];
519                for(var i=0, ii=components.length; i<ii; ++i) {
520                    this.writeNode("lineStringMember", components[i], node);
521                }
522                return node;
523            },
524            "lineStringMember": function(geometry) {
525                var node = this.createElementNSPlus("gml:lineStringMember");
526                this.writeNode("LineString", geometry, node);
527                return node;
528            },
529            "MultiPolygon": function(geometry) {
530                var node = this.createElementNSPlus("gml:MultiPolygon");
531                var components = geometry.components || [geometry];
532                for(var i=0, ii=components.length; i<ii; ++i) {
533                    this.writeNode(
534                        "polygonMember", components[i], node
535                    );
536                }
537                return node;
538            },
539            "polygonMember": function(geometry) {
540                var node = this.createElementNSPlus("gml:polygonMember");
541                this.writeNode("Polygon", geometry, node);
542                return node;
543            },
544            "GeometryCollection": function(geometry) {
545                var node = this.createElementNSPlus("gml:GeometryCollection");
546                for(var i=0, len=geometry.components.length; i<len; ++i) {
547                    this.writeNode("geometryMember", geometry.components[i], node);
548                }
549                return node;
550            },
551            "geometryMember": function(geometry) {
552                var node = this.createElementNSPlus("gml:geometryMember");
553                var child = this.writeNode("feature:_geometry", geometry);
554                node.appendChild(child.firstChild);
555                return node;
556            }
557        },
558        "feature": {
559            "_typeName": function(feature) {
560                var node = this.createElementNSPlus("feature:" + this.featureType, {
561                    attributes: {fid: feature.fid}
562                });
563                if(feature.geometry) {
564                    this.writeNode("feature:_geometry", feature.geometry, node);
565                }
566                for(var name in feature.attributes) {
567                    var value = feature.attributes[name];
568                    if(value != null) {
569                        this.writeNode(
570                            "feature:_attribute",
571                            {name: name, value: value}, node
572                        );
573                    }
574                }
575                return node;
576            },
577            "_geometry": function(geometry) {
578                if(this.externalProjection && this.internalProjection) {
579                    geometry = geometry.clone().transform(
580                        this.internalProjection, this.externalProjection
581                    );
582                }   
583                var node = this.createElementNSPlus(
584                    "feature:" + this.geometryName
585                );
586                var type = this.geometryTypes[geometry.CLASS_NAME];
587                var child = this.writeNode("gml:" + type, geometry, node);
588                if(this.srsName) {
589                    child.setAttribute("srsName", this.srsName);
590                }
591                return node;
592            },
593            "_attribute": function(obj) {
594                return this.createElementNSPlus("feature:" + obj.name, {
595                    value: obj.value
596                });
597            }
598        },
599        "wfs": {
600            "FeatureCollection": function(features) {
601                /**
602                 * This is only here because GML2 only describes abstract
603                 * feature collections.  Typically, you would not be using
604                 * the GML format to write wfs elements.  This just provides
605                 * some way to write out lists of features.  GML3 defines the
606                 * featureMembers element, so that is used by default instead.
607                 */
608                var node = this.createElementNSPlus("wfs:FeatureCollection");
609                for(var i=0, len=features.length; i<len; ++i) {
610                    this.writeNode("gml:featureMember", features[i], node);
611                }
612                return node;
613            }
614        }
615    },
616   
617    /**
618     * Method: setGeometryTypes
619     * Sets the <geometryTypes> mapping.
620     */
621    setGeometryTypes: function() {
622        this.geometryTypes = {
623            "OpenLayers.Geometry.Point": "Point",
624            "OpenLayers.Geometry.MultiPoint": "MultiPoint",
625            "OpenLayers.Geometry.LineString": "LineString",
626            "OpenLayers.Geometry.MultiLineString": "MultiLineString",
627            "OpenLayers.Geometry.Polygon": "Polygon",
628            "OpenLayers.Geometry.MultiPolygon": "MultiPolygon",
629            "OpenLayers.Geometry.Collection": "GeometryCollection"
630        };
631    },
632
633    CLASS_NAME: "OpenLayers.Format.GML.Base" 
634
635});
Note: See TracBrowser for help on using the repository browser.