]> dev.renevier.net Git - syp.git/blob - openlayers/lib/OpenLayers/Format/WFST/v1.js
initial commit
[syp.git] / openlayers / lib / OpenLayers / Format / WFST / v1.js
1 /* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
2  * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
3  * full text of the license. */
4
5 /**
6  * @requires OpenLayers/Format/XML.js
7  * @requires OpenLayers/Format/WFST.js
8  */
9
10 /**
11  * Class: OpenLayers.Format.WFST.v1
12  * Superclass for WFST parsers.
13  *
14  * Inherits from:
15  *  - <OpenLayers.Format.XML>
16  */
17 OpenLayers.Format.WFST.v1 = OpenLayers.Class(OpenLayers.Format.XML, {
18     
19     /**
20      * Property: namespaces
21      * {Object} Mapping of namespace aliases to namespace URIs.
22      */
23     namespaces: {
24         xlink: "http://www.w3.org/1999/xlink",
25         xsi: "http://www.w3.org/2001/XMLSchema-instance",
26         wfs: "http://www.opengis.net/wfs",
27         gml: "http://www.opengis.net/gml",
28         ogc: "http://www.opengis.net/ogc"
29     },
30     
31     /**
32      * Property: defaultPrefix
33      */
34     defaultPrefix: "wfs",
35
36     /**
37      * Property: version
38      * {String} WFS version number.
39      */
40     version: null,
41
42     /**
43      * Property: schemaLocation
44      * {String} Schema location for a particular minor version.
45      */
46     schemaLocations: null,
47     
48     /**
49      * APIProperty: srsName
50      * {String} URI for spatial reference system.
51      */
52     srsName: null,
53
54     /**
55      * APIProperty: extractAttributes
56      * {Boolean} Extract attributes from GML.  Default is true.
57      */
58     extractAttributes: true,
59     
60     /**
61      * APIProperty: xy
62      * {Boolean} Order of the GML coordinate true:(x,y) or false:(y,x)
63      * Changing is not recommended, a new Format should be instantiated.
64      */ 
65     xy: true,
66
67     /**
68      * Property: stateName
69      * {Object} Maps feature states to node names.
70      */
71     stateName: null,
72
73     /**
74      * Constructor: OpenLayers.Format.WFST.v1
75      * Instances of this class are not created directly.  Use the
76      *     <OpenLayers.Format.WFST.v1_0_0> or <OpenLayers.Format.WFST.v1_1_0>
77      *     constructor instead.
78      *
79      * Parameters:
80      * options - {Object} An optional object whose properties will be set on
81      *     this instance.
82      */
83     initialize: function(options) {
84         // set state name mapping
85         this.stateName = {};
86         this.stateName[OpenLayers.State.INSERT] = "wfs:Insert";
87         this.stateName[OpenLayers.State.UPDATE] = "wfs:Update";
88         this.stateName[OpenLayers.State.DELETE] = "wfs:Delete";
89         OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
90     },
91     
92     /**
93      * Method: getSrsName
94      */
95     getSrsName: function(feature, options) {
96         var srsName = options && options.srsName;
97         if(!srsName) {
98             if(feature && feature.layer) {
99                 srsName = feature.layer.projection.getCode();
100             } else {
101                 srsName = this.srsName;
102             }
103         }
104         return srsName;
105     },
106
107     /**
108      * Method: read
109      * Parse the response from a transaction.  Because WFS is split into
110      *     Transaction requests (create, update, and delete) and GetFeature
111      *     requests (read), this method handles parsing of both types of
112      *     responses.
113      */
114     read: function(data) {
115         if(typeof data == "string") { 
116             data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
117         }
118         if(data && data.nodeType == 9) {
119             data = data.documentElement;
120         }
121         var obj = {};
122         this.readNode(data, obj);
123         if(obj.features) {
124             obj = obj.features;
125         }
126         return obj;
127     },
128     
129     /**
130      * Property: readers
131      * Contains public functions, grouped by namespace prefix, that will
132      *     be applied when a namespaced node is found matching the function
133      *     name.  The function will be applied in the scope of this parser
134      *     with two arguments: the node being read and a context object passed
135      *     from the parent.
136      */
137     readers: {
138         "wfs": {
139             "FeatureCollection": function(node, obj) {
140                 obj.features = [];
141                 this.readChildNodes(node, obj);
142             }
143         }
144     },
145     
146     /**
147      * Method: write
148      * Given an array of features, write a WFS transaction.  This assumes
149      *     the features have a state property that determines the operation
150      *     type - insert, update, or delete.
151      *
152      * Parameters:
153      * features - {Array(<OpenLayers.Feature.Vector>)} A list of features.
154      *
155      * Returns:
156      * {String} A serialized WFS transaction.
157      */
158     write: function(features) {
159         var node = this.writeNode("wfs:Transaction", features);
160         var value = this.schemaLocationAttr();
161         if(value) {
162             this.setAttributeNS(
163                 node, this.namespaces["xsi"], "xsi:schemaLocation",  value
164             )
165         }
166         return OpenLayers.Format.XML.prototype.write.apply(this, [node]);
167     },
168     
169     /**
170      * Property: writers
171      * As a compliment to the readers property, this structure contains public
172      *     writing functions grouped by namespace alias and named like the
173      *     node names they produce.
174      */
175     writers: {
176         "wfs": {
177             "GetFeature": function(options) {
178                 var node = this.createElementNSPlus("wfs:GetFeature", {
179                     attributes: {
180                         service: "WFS",
181                         version: this.version,
182                         maxFeatures: options && options.maxFeatures,
183                         "xsi:schemaLocation": this.schemaLocationAttr(options)
184                     }
185                 });
186                 this.writeNode("Query", options, node);
187                 return node;
188             },
189             "Query": function(options) {
190                 options = OpenLayers.Util.extend({
191                     featureNS: this.featureNS,
192                     featurePrefix: this.featurePrefix,
193                     featureType: this.featureType,
194                     srsName: this.srsName
195                 }, options);
196                 // TODO: this is still version specific and should be separated out
197                 // v1.0.0 does not allow srsName on wfs:Query
198                 var node = this.createElementNSPlus("wfs:Query", {
199                     attributes: {
200                         typeName: (options.featureNS ? options.featurePrefix + ":" : "") +
201                             options.featureType,
202                         srsName: options.srsName
203                     }
204                 });
205                 if(options.featureNS) {
206                     node.setAttribute("xmlns:" + options.featurePrefix, options.featureNS);
207                 }
208                 if(options.filter) {
209                     this.setFilterProperty(options.filter);
210                     this.writeNode("ogc:Filter", options.filter, node);
211                 }
212                 return node;
213             },
214             "Transaction": function(features) {
215                 var node = this.createElementNSPlus("wfs:Transaction", {
216                     attributes: {
217                         service: "WFS",
218                         version: this.version
219                     }
220                 });
221                 if(features) {
222                     var name, feature;
223                     for(var i=0, len=features.length; i<len; ++i) {
224                         feature = features[i];
225                         name = this.stateName[feature.state];
226                         if(name) {
227                             this.writeNode(name, feature, node);
228                         }
229                     }
230                 }
231                 return node;
232             },
233             "Insert": function(feature) {
234                 var node = this.createElementNSPlus("wfs:Insert");
235                 this.srsName = this.getSrsName(feature);
236                 this.writeNode("feature:_typeName", feature, node);
237                 return node;
238             },
239             "Update": function(feature) {
240                 var node = this.createElementNSPlus("wfs:Update", {
241                     attributes: {
242                         typeName: (this.featureNS ? this.featurePrefix + ":" : "") +
243                             this.featureType
244                     }
245                 });
246                 if(this.featureNS) {
247                     node.setAttribute("xmlns:" + this.featurePrefix, this.featureNS);
248                 }
249                 
250                 // add in geometry
251                 this.writeNode(
252                     "Property", {name: this.geometryName, value: feature}, node
253                 );
254         
255                 // add in attributes
256                 for(var key in feature.attributes) {
257                     this.writeNode(
258                         "Property", {name: key, value: feature.attributes[key]}, node
259                     );
260                 }
261                 
262                 // add feature id filter
263                 this.writeNode("ogc:Filter", new OpenLayers.Filter.FeatureId({
264                     fids: [feature.fid]
265                 }), node);
266         
267                 return node;
268             },
269             "Property": function(obj) {
270                 var node = this.createElementNSPlus("wfs:Property");
271                 this.writeNode("Name", obj.name, node);
272                 this.writeNode("Value", obj.value, node);
273                 return node;
274             },
275             "Name": function(name) {
276                 return this.createElementNSPlus("wfs:Name", {value: name});
277             },
278             "Value": function(obj) {
279                 var node;
280                 if(obj instanceof OpenLayers.Feature.Vector) {
281                     node = this.createElementNSPlus("wfs:Value");
282                     this.srsName = this.getSrsName(obj);
283                     var geom = this.writeNode("feature:_geometry", obj.geometry).firstChild;
284                     node.appendChild(geom);
285                 } else {
286                     node = this.createElementNSPlus("wfs:Value", {value: obj});                
287                 }
288                 return node;
289             },
290             "Delete": function(feature) {
291                 var node = this.createElementNSPlus("wfs:Delete", {
292                     attributes: {
293                         typeName: (this.featureNS ? this.featurePrefix + ":" : "") +
294                             this.featureType
295                     }
296                 });
297                 if(this.featureNS) {
298                     node.setAttribute("xmlns:" + this.featurePrefix, this.featureNS);
299                 }
300                 this.writeNode("ogc:Filter", new OpenLayers.Filter.FeatureId({
301                     fids: [feature.fid]
302                 }), node);
303                 return node;
304             }
305         }
306     },
307
308     /**
309      * Method: schemaLocationAttr
310      * Generate the xsi:schemaLocation attribute value.
311      *
312      * Returns:
313      * {String} The xsi:schemaLocation attribute or undefined if none.
314      */
315     schemaLocationAttr: function(options) {
316         options = OpenLayers.Util.extend({
317             featurePrefix: this.featurePrefix,
318             schema: this.schema
319         }, options);
320         var schemaLocations = OpenLayers.Util.extend({}, this.schemaLocations);
321         if(options.schema) {
322             schemaLocations[options.featurePrefix] = options.schema;
323         }
324         var parts = [];
325         var uri;
326         for(var key in schemaLocations) {
327             uri = this.namespaces[key];
328             if(uri) {
329                 parts.push(uri + " " + schemaLocations[key]);
330             }
331         }
332         var value = parts.join(" ") || undefined;
333         return value;
334     },
335     
336     /**
337      * Method: setFilterProperty
338      * Set the property of each spatial filter.
339      *
340      * Parameters:
341      * filter - {<OpenLayers.Filter>}
342      */
343     setFilterProperty: function(filter) {
344         if(filter.filters) {
345             for(var i=0, len=filter.filters.length; i<len; ++i) {
346                 this.setFilterProperty(filter.filters[i]);
347             }
348         } else {
349             if(filter instanceof OpenLayers.Filter.Spatial) {
350                 // got a spatial filter, set its property
351                 filter.property = this.geometryName;
352             }
353         }
354     },
355
356     CLASS_NAME: "OpenLayers.Format.WFST.v1" 
357
358 });