summaryrefslogtreecommitdiff
path: root/misc/openlayers/lib/OpenLayers/Format
diff options
context:
space:
mode:
authorChris Schlaeger <chris@linux.com>2014-08-12 21:56:44 +0200
committerChris Schlaeger <chris@linux.com>2014-08-12 21:56:44 +0200
commitea346a785dc1b3f7c156f6fc33da634e1f1a627b (patch)
treeaf67530553d20b6e82ad60fd79593e9c4abf5565 /misc/openlayers/lib/OpenLayers/Format
parent59741cd535c47f25971bf8c32b25da25ceadc6d5 (diff)
downloadpostrunner-ea346a785dc1b3f7c156f6fc33da634e1f1a627b.zip
Adding jquery, flot and openlayers to be included with the GEM.v0.0.4
Diffstat (limited to 'misc/openlayers/lib/OpenLayers/Format')
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/ArcXML.js1028
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/ArcXML/Features.js46
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/Atom.js712
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/CQL.js452
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/CSWGetDomain.js34
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/CSWGetDomain/v2_0_2.js240
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/CSWGetRecords.js34
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/CSWGetRecords/v2_0_2.js457
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/Context.js334
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/EncodedPolyline.js557
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/Filter.js53
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/Filter/v1.js504
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/Filter/v1_0_0.js184
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/Filter/v1_1_0.js222
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/GML.js923
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/GML/Base.js645
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/GML/v2.js193
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/GML/v3.js477
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/GPX.js385
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/GeoJSON.js716
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/GeoRSS.js409
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/JSON.js398
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/KML.js1517
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/OGCExceptionReport.js108
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/OSM.js465
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/OWSCommon.js78
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/OWSCommon/v1.js318
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/OWSCommon/v1_0_0.js62
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/OWSCommon/v1_1_0.js116
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/OWSContext.js86
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/OWSContext/v0_3_1.js595
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/QueryStringFilter.js183
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/SLD.js81
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/SLD/v1.js1309
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/SLD/v1_0_0.js46
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/SLD/v1_0_0_GeoServer.js149
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/SOSCapabilities.js48
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/SOSCapabilities/v1_0_0.js158
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/SOSGetFeatureOfInterest.js190
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/SOSGetObservation.js302
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/Text.js151
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/WCSCapabilities.js47
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/WCSCapabilities/v1.js55
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/WCSCapabilities/v1_0_0.js170
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/WCSCapabilities/v1_1_0.js109
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/WCSGetCoverage.js199
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/WFS.js223
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/WFSCapabilities.js47
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/WFSCapabilities/v1.js129
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/WFSCapabilities/v1_0_0.js115
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/WFSCapabilities/v1_1_0.js63
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/WFSDescribeFeatureType.js234
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/WFST.js34
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/WFST/v1.js446
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/WFST/v1_0_0.js174
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/WFST/v1_1_0.js189
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/WKT.js392
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/WMC.js182
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/WMC/v1.js1267
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/WMC/v1_0_0.js104
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/WMC/v1_1_0.js149
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/WMSCapabilities.js56
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1.js368
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1_1.js122
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1_1_0.js57
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1_1_1.js60
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1_1_1_WMSC.js85
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1_3.js128
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1_3_0.js30
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/WMSDescribeLayer.js53
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/WMSDescribeLayer/v1_1.js122
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/WMSGetFeatureInfo.js296
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/WMTSCapabilities.js230
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/WMTSCapabilities/v1_0_0.js251
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/WPSCapabilities.js48
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/WPSCapabilities/v1_0_0.js119
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/WPSDescribeProcess.js185
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/WPSExecute.js395
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/XLS.js68
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/XLS/v1.js304
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/XLS/v1_1_0.js48
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/XML.js897
-rw-r--r--misc/openlayers/lib/OpenLayers/Format/XML/VersionedOGC.js212
83 files changed, 23427 insertions, 0 deletions
diff --git a/misc/openlayers/lib/OpenLayers/Format/ArcXML.js b/misc/openlayers/lib/OpenLayers/Format/ArcXML.js
new file mode 100644
index 0000000..9d523d1
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/ArcXML.js
@@ -0,0 +1,1028 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Geometry/Polygon.js
+ * @requires OpenLayers/Geometry/Point.js
+ * @requires OpenLayers/Geometry/MultiPolygon.js
+ * @requires OpenLayers/Geometry/LinearRing.js
+ */
+
+/**
+ * Class: OpenLayers.Format.ArcXML
+ * Read/Write ArcXML. Create a new instance with the <OpenLayers.Format.ArcXML>
+ * constructor.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.ArcXML = OpenLayers.Class(OpenLayers.Format.XML, {
+
+ /**
+ * Property: fontStyleKeys
+ * {Array} List of keys used in font styling.
+ */
+ fontStyleKeys: [
+ 'antialiasing', 'blockout', 'font', 'fontcolor','fontsize', 'fontstyle',
+ 'glowing', 'interval', 'outline', 'printmode', 'shadow', 'transparency'
+ ],
+
+ /**
+ * Property: request
+ * A get_image request destined for an ArcIMS server.
+ */
+ request: null,
+
+ /**
+ * Property: response
+ * A parsed response from an ArcIMS server.
+ */
+ response: null,
+
+ /**
+ * Constructor: OpenLayers.Format.ArcXML
+ * Create a new parser/writer for ArcXML. Create an instance of this class
+ * to begin authoring a request to an ArcIMS service. This is used
+ * primarily by the ArcIMS layer, but could be used to do other wild
+ * stuff, like geocoding.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+ initialize: function(options) {
+ this.request = new OpenLayers.Format.ArcXML.Request();
+ this.response = new OpenLayers.Format.ArcXML.Response();
+
+ if (options) {
+ if (options.requesttype == "feature") {
+ this.request.get_image = null;
+
+ var qry = this.request.get_feature.query;
+ this.addCoordSys(qry.featurecoordsys, options.featureCoordSys);
+ this.addCoordSys(qry.filtercoordsys, options.filterCoordSys);
+
+ if (options.polygon) {
+ qry.isspatial = true;
+ qry.spatialfilter.polygon = options.polygon;
+ } else if (options.envelope) {
+ qry.isspatial = true;
+ qry.spatialfilter.envelope = {minx:0, miny:0, maxx:0, maxy:0};
+ this.parseEnvelope(qry.spatialfilter.envelope, options.envelope);
+ }
+ } else if (options.requesttype == "image") {
+ this.request.get_feature = null;
+
+ var props = this.request.get_image.properties;
+ this.parseEnvelope(props.envelope, options.envelope);
+
+ this.addLayers(props.layerlist, options.layers);
+ this.addImageSize(props.imagesize, options.tileSize);
+ this.addCoordSys(props.featurecoordsys, options.featureCoordSys);
+ this.addCoordSys(props.filtercoordsys, options.filterCoordSys);
+ } else {
+ // if an arcxml object is being created with no request type, it is
+ // probably going to consume a response, so do not throw an error if
+ // the requesttype is not defined
+ this.request = null;
+ }
+ }
+
+ OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+ },
+
+ /**
+ * Method: parseEnvelope
+ * Parse an array of coordinates into an ArcXML envelope structure.
+ *
+ * Parameters:
+ * env - {Object} An envelope object that will contain the parsed coordinates.
+ * arr - {Array(double)} An array of coordinates in the order: [ minx, miny, maxx, maxy ]
+ */
+ parseEnvelope: function(env, arr) {
+ if (arr && arr.length == 4) {
+ env.minx = arr[0];
+ env.miny = arr[1];
+ env.maxx = arr[2];
+ env.maxy = arr[3];
+ }
+ },
+
+ /**
+ * Method: addLayers
+ * Add a collection of layers to another collection of layers. Each layer in the list is tuple of
+ * { id, visible }. These layer collections represent the
+ * /ARCXML/REQUEST/get_image/PROPERTIES/LAYERLIST/LAYERDEF items in ArcXML
+ *
+ * TODO: Add support for dynamic layer rendering.
+ *
+ * Parameters:
+ * ll - {Array({id,visible})} A list of layer definitions.
+ * lyrs - {Array({id,visible})} A list of layer definitions.
+ */
+ addLayers: function(ll, lyrs) {
+ for(var lind = 0, len=lyrs.length; lind < len; lind++) {
+ ll.push(lyrs[lind]);
+ }
+ },
+
+ /**
+ * Method: addImageSize
+ * Set the size of the requested image.
+ *
+ * Parameters:
+ * imsize - {Object} An ArcXML imagesize object.
+ * olsize - {<OpenLayers.Size>} The image size to set.
+ */
+ addImageSize: function(imsize, olsize) {
+ if (olsize !== null) {
+ imsize.width = olsize.w;
+ imsize.height = olsize.h;
+ imsize.printwidth = olsize.w;
+ imsize.printheight = olsize.h;
+ }
+ },
+
+ /**
+ * Method: addCoordSys
+ * Add the coordinate system information to an object. The object may be
+ *
+ * Parameters:
+ * featOrFilt - {Object} A featurecoordsys or filtercoordsys ArcXML structure.
+ * fsys - {String} or {<OpenLayers.Projection>} or {filtercoordsys} or
+ * {featurecoordsys} A projection representation. If it's a {String},
+ * the value is assumed to be the SRID. If it's a {OpenLayers.Projection}
+ * AND Proj4js is available, the projection number and name are extracted
+ * from there. If it's a filter or feature ArcXML structure, it is copied.
+ */
+ addCoordSys: function(featOrFilt, fsys) {
+ if (typeof fsys == "string") {
+ featOrFilt.id = parseInt(fsys);
+ featOrFilt.string = fsys;
+ }
+ // is this a proj4js instance?
+ else if (typeof fsys == "object" && fsys.proj !== null){
+ featOrFilt.id = fsys.proj.srsProjNumber;
+ featOrFilt.string = fsys.proj.srsCode;
+ } else {
+ featOrFilt = fsys;
+ }
+ },
+
+ /**
+ * APIMethod: iserror
+ * Check to see if the response from the server was an error.
+ *
+ * Parameters:
+ * data - {String} or {DOMElement} data to read/parse. If nothing is supplied,
+ * the current response is examined.
+ *
+ * Returns:
+ * {Boolean} true if the response was an error.
+ */
+ iserror: function(data) {
+ var ret = null;
+
+ if (!data) {
+ ret = (this.response.error !== '');
+ } else {
+ data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+ var errorNodes = data.documentElement.getElementsByTagName("ERROR");
+ ret = (errorNodes !== null && errorNodes.length > 0);
+ }
+
+ return ret;
+ },
+
+ /**
+ * APIMethod: read
+ * Read data from a string, and return an response.
+ *
+ * Parameters:
+ * data - {String} or {DOMElement} data to read/parse.
+ *
+ * Returns:
+ * {<OpenLayers.Format.ArcXML.Response>} An ArcXML response. Note that this response
+ * data may change in the future.
+ */
+ read: function(data) {
+ if(typeof data == "string") {
+ data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+ }
+
+ var arcNode = null;
+ if (data && data.documentElement) {
+ if(data.documentElement.nodeName == "ARCXML") {
+ arcNode = data.documentElement;
+ } else {
+ arcNode = data.documentElement.getElementsByTagName("ARCXML")[0];
+ }
+ }
+
+ // in Safari, arcNode will be there but will have a child named
+ // parsererror
+ if (!arcNode || arcNode.firstChild.nodeName === 'parsererror') {
+ var error, source;
+ try {
+ error = data.firstChild.nodeValue;
+ source = data.firstChild.childNodes[1].firstChild.nodeValue;
+ } catch (err) {
+ // pass
+ }
+ throw {
+ message: "Error parsing the ArcXML request",
+ error: error,
+ source: source
+ };
+ }
+
+ var response = this.parseResponse(arcNode);
+ return response;
+ },
+
+ /**
+ * APIMethod: write
+ * Generate an ArcXml document string for sending to an ArcIMS server.
+ *
+ * Returns:
+ * {String} A string representing the ArcXML document request.
+ */
+ write: function(request) {
+ if (!request) {
+ request = this.request;
+ }
+ var root = this.createElementNS("", "ARCXML");
+ root.setAttribute("version","1.1");
+
+ var reqElem = this.createElementNS("", "REQUEST");
+
+ if (request.get_image != null) {
+ var getElem = this.createElementNS("", "GET_IMAGE");
+ reqElem.appendChild(getElem);
+
+ var propElem = this.createElementNS("", "PROPERTIES");
+ getElem.appendChild(propElem);
+
+ var props = request.get_image.properties;
+ if (props.featurecoordsys != null) {
+ var feat = this.createElementNS("", "FEATURECOORDSYS");
+ propElem.appendChild(feat);
+
+ if (props.featurecoordsys.id === 0) {
+ feat.setAttribute("string", props.featurecoordsys['string']);
+ }
+ else {
+ feat.setAttribute("id", props.featurecoordsys.id);
+ }
+ }
+
+ if (props.filtercoordsys != null) {
+ var filt = this.createElementNS("", "FILTERCOORDSYS");
+ propElem.appendChild(filt);
+
+ if (props.filtercoordsys.id === 0) {
+ filt.setAttribute("string", props.filtercoordsys.string);
+ }
+ else {
+ filt.setAttribute("id", props.filtercoordsys.id);
+ }
+ }
+
+ if (props.envelope != null) {
+ var env = this.createElementNS("", "ENVELOPE");
+ propElem.appendChild(env);
+
+ env.setAttribute("minx", props.envelope.minx);
+ env.setAttribute("miny", props.envelope.miny);
+ env.setAttribute("maxx", props.envelope.maxx);
+ env.setAttribute("maxy", props.envelope.maxy);
+ }
+
+ var imagesz = this.createElementNS("", "IMAGESIZE");
+ propElem.appendChild(imagesz);
+
+ imagesz.setAttribute("height", props.imagesize.height);
+ imagesz.setAttribute("width", props.imagesize.width);
+
+ if (props.imagesize.height != props.imagesize.printheight ||
+ props.imagesize.width != props.imagesize.printwidth) {
+ imagesz.setAttribute("printheight", props.imagesize.printheight);
+ imagesz.setArrtibute("printwidth", props.imagesize.printwidth);
+ }
+
+ if (props.background != null) {
+ var backgrnd = this.createElementNS("", "BACKGROUND");
+ propElem.appendChild(backgrnd);
+
+ backgrnd.setAttribute("color",
+ props.background.color.r + "," +
+ props.background.color.g + "," +
+ props.background.color.b);
+
+ if (props.background.transcolor !== null) {
+ backgrnd.setAttribute("transcolor",
+ props.background.transcolor.r + "," +
+ props.background.transcolor.g + "," +
+ props.background.transcolor.b);
+ }
+ }
+
+ if (props.layerlist != null && props.layerlist.length > 0) {
+ var layerlst = this.createElementNS("", "LAYERLIST");
+ propElem.appendChild(layerlst);
+
+ for (var ld = 0; ld < props.layerlist.length; ld++) {
+ var ldef = this.createElementNS("", "LAYERDEF");
+ layerlst.appendChild(ldef);
+
+ ldef.setAttribute("id", props.layerlist[ld].id);
+ ldef.setAttribute("visible", props.layerlist[ld].visible);
+
+ if (typeof props.layerlist[ld].query == "object") {
+ var query = props.layerlist[ld].query;
+
+ if (query.where.length < 0) {
+ continue;
+ }
+
+ var queryElem = null;
+ if (typeof query.spatialfilter == "boolean" && query.spatialfilter) {
+ // handle spatial filter madness
+ queryElem = this.createElementNS("", "SPATIALQUERY");
+ }
+ else {
+ queryElem = this.createElementNS("", "QUERY");
+ }
+
+ queryElem.setAttribute("where", query.where);
+
+ if (typeof query.accuracy == "number" && query.accuracy > 0) {
+ queryElem.setAttribute("accuracy", query.accuracy);
+ }
+ if (typeof query.featurelimit == "number" && query.featurelimit < 2000) {
+ queryElem.setAttribute("featurelimit", query.featurelimit);
+ }
+ if (typeof query.subfields == "string" && query.subfields != "#ALL#") {
+ queryElem.setAttribute("subfields", query.subfields);
+ }
+ if (typeof query.joinexpression == "string" && query.joinexpression.length > 0) {
+ queryElem.setAttribute("joinexpression", query.joinexpression);
+ }
+ if (typeof query.jointables == "string" && query.jointables.length > 0) {
+ queryElem.setAttribute("jointables", query.jointables);
+ }
+
+ ldef.appendChild(queryElem);
+ }
+
+ if (typeof props.layerlist[ld].renderer == "object") {
+ this.addRenderer(ldef, props.layerlist[ld].renderer);
+ }
+ }
+ }
+ } else if (request.get_feature != null) {
+ var getElem = this.createElementNS("", "GET_FEATURES");
+ getElem.setAttribute("outputmode", "newxml");
+ getElem.setAttribute("checkesc", "true");
+
+ if (request.get_feature.geometry) {
+ getElem.setAttribute("geometry", request.get_feature.geometry);
+ }
+ else {
+ getElem.setAttribute("geometry", "false");
+ }
+
+ if (request.get_feature.compact) {
+ getElem.setAttribute("compact", request.get_feature.compact);
+ }
+
+ if (request.get_feature.featurelimit == "number") {
+ getElem.setAttribute("featurelimit", request.get_feature.featurelimit);
+ }
+
+ getElem.setAttribute("globalenvelope", "true");
+ reqElem.appendChild(getElem);
+
+ if (request.get_feature.layer != null && request.get_feature.layer.length > 0) {
+ var lyrElem = this.createElementNS("", "LAYER");
+ lyrElem.setAttribute("id", request.get_feature.layer);
+ getElem.appendChild(lyrElem);
+ }
+
+ var fquery = request.get_feature.query;
+ if (fquery != null) {
+ var qElem = null;
+ if (fquery.isspatial) {
+ qElem = this.createElementNS("", "SPATIALQUERY");
+ } else {
+ qElem = this.createElementNS("", "QUERY");
+ }
+ getElem.appendChild(qElem);
+
+ if (typeof fquery.accuracy == "number") {
+ qElem.setAttribute("accuracy", fquery.accuracy);
+ }
+ //qElem.setAttribute("featurelimit", "5");
+
+ if (fquery.featurecoordsys != null) {
+ var fcsElem1 = this.createElementNS("", "FEATURECOORDSYS");
+
+ if (fquery.featurecoordsys.id == 0) {
+ fcsElem1.setAttribute("string", fquery.featurecoordsys.string);
+ } else {
+ fcsElem1.setAttribute("id", fquery.featurecoordsys.id);
+ }
+ qElem.appendChild(fcsElem1);
+ }
+
+ if (fquery.filtercoordsys != null) {
+ var fcsElem2 = this.createElementNS("", "FILTERCOORDSYS");
+
+ if (fquery.filtercoordsys.id === 0) {
+ fcsElem2.setAttribute("string", fquery.filtercoordsys.string);
+ } else {
+ fcsElem2.setAttribute("id", fquery.filtercoordsys.id);
+ }
+ qElem.appendChild(fcsElem2);
+ }
+
+ if (fquery.buffer > 0) {
+ var bufElem = this.createElementNS("", "BUFFER");
+ bufElem.setAttribute("distance", fquery.buffer);
+ qElem.appendChild(bufElem);
+ }
+
+ if (fquery.isspatial) {
+ var spfElem = this.createElementNS("", "SPATIALFILTER");
+ spfElem.setAttribute("relation", fquery.spatialfilter.relation);
+ qElem.appendChild(spfElem);
+
+ if (fquery.spatialfilter.envelope) {
+ var envElem = this.createElementNS("", "ENVELOPE");
+ envElem.setAttribute("minx", fquery.spatialfilter.envelope.minx);
+ envElem.setAttribute("miny", fquery.spatialfilter.envelope.miny);
+ envElem.setAttribute("maxx", fquery.spatialfilter.envelope.maxx);
+ envElem.setAttribute("maxy", fquery.spatialfilter.envelope.maxy);
+ spfElem.appendChild(envElem);
+ } else if(typeof fquery.spatialfilter.polygon == "object") {
+ spfElem.appendChild(this.writePolygonGeometry(fquery.spatialfilter.polygon));
+ }
+ }
+
+ if (fquery.where != null && fquery.where.length > 0) {
+ qElem.setAttribute("where", fquery.where);
+ }
+ }
+ }
+
+ root.appendChild(reqElem);
+
+ return OpenLayers.Format.XML.prototype.write.apply(this, [root]);
+ },
+
+
+ addGroupRenderer: function(ldef, toprenderer) {
+ var topRelem = this.createElementNS("", "GROUPRENDERER");
+ ldef.appendChild(topRelem);
+
+ for (var rind = 0; rind < toprenderer.length; rind++) {
+ var renderer = toprenderer[rind];
+ this.addRenderer(topRelem, renderer);
+ }
+ },
+
+
+ addRenderer: function(topRelem, renderer) {
+ if (OpenLayers.Util.isArray(renderer)) {
+ this.addGroupRenderer(topRelem, renderer);
+ } else {
+ var renderElem = this.createElementNS("", renderer.type.toUpperCase() + "RENDERER");
+ topRelem.appendChild(renderElem);
+
+ if (renderElem.tagName == "VALUEMAPRENDERER") {
+ this.addValueMapRenderer(renderElem, renderer);
+ } else if (renderElem.tagName == "VALUEMAPLABELRENDERER") {
+ this.addValueMapLabelRenderer(renderElem, renderer);
+ } else if (renderElem.tagName == "SIMPLELABELRENDERER") {
+ this.addSimpleLabelRenderer(renderElem, renderer);
+ } else if (renderElem.tagName == "SCALEDEPENDENTRENDERER") {
+ this.addScaleDependentRenderer(renderElem, renderer);
+ }
+ }
+ },
+
+
+ addScaleDependentRenderer: function(renderElem, renderer) {
+ if (typeof renderer.lower == "string" || typeof renderer.lower == "number") {
+ renderElem.setAttribute("lower", renderer.lower);
+ }
+ if (typeof renderer.upper == "string" || typeof renderer.upper == "number") {
+ renderElem.setAttribute("upper", renderer.upper);
+ }
+
+ this.addRenderer(renderElem, renderer.renderer);
+ },
+
+
+ addValueMapLabelRenderer: function(renderElem, renderer) {
+ renderElem.setAttribute("lookupfield", renderer.lookupfield);
+ renderElem.setAttribute("labelfield", renderer.labelfield);
+
+ if (typeof renderer.exacts == "object") {
+ for (var ext=0, extlen=renderer.exacts.length; ext<extlen; ext++) {
+ var exact = renderer.exacts[ext];
+
+ var eelem = this.createElementNS("", "EXACT");
+
+ if (typeof exact.value == "string") {
+ eelem.setAttribute("value", exact.value);
+ }
+ if (typeof exact.label == "string") {
+ eelem.setAttribute("label", exact.label);
+ }
+ if (typeof exact.method == "string") {
+ eelem.setAttribute("method", exact.method);
+ }
+
+ renderElem.appendChild(eelem);
+
+ if (typeof exact.symbol == "object") {
+ var selem = null;
+
+ if (exact.symbol.type == "text") {
+ selem = this.createElementNS("", "TEXTSYMBOL");
+ }
+
+ if (selem != null) {
+ var keys = this.fontStyleKeys;
+ for (var i = 0, len = keys.length; i < len; i++) {
+ var key = keys[i];
+ if (exact.symbol[key]) {
+ selem.setAttribute(key, exact.symbol[key]);
+ }
+ }
+ eelem.appendChild(selem);
+ }
+ }
+ } // for each exact
+ }
+ },
+
+ addValueMapRenderer: function(renderElem, renderer) {
+ renderElem.setAttribute("lookupfield", renderer.lookupfield);
+
+ if (typeof renderer.ranges == "object") {
+ for(var rng=0, rnglen=renderer.ranges.length; rng<rnglen; rng++) {
+ var range = renderer.ranges[rng];
+
+ var relem = this.createElementNS("", "RANGE");
+ relem.setAttribute("lower", range.lower);
+ relem.setAttribute("upper", range.upper);
+
+ renderElem.appendChild(relem);
+
+ if (typeof range.symbol == "object") {
+ var selem = null;
+
+ if (range.symbol.type == "simplepolygon") {
+ selem = this.createElementNS("", "SIMPLEPOLYGONSYMBOL");
+ }
+
+ if (selem != null) {
+ if (typeof range.symbol.boundarycolor == "string") {
+ selem.setAttribute("boundarycolor", range.symbol.boundarycolor);
+ }
+ if (typeof range.symbol.fillcolor == "string") {
+ selem.setAttribute("fillcolor", range.symbol.fillcolor);
+ }
+ if (typeof range.symbol.filltransparency == "number") {
+ selem.setAttribute("filltransparency", range.symbol.filltransparency);
+ }
+ relem.appendChild(selem);
+ }
+ }
+ } // for each range
+ } else if (typeof renderer.exacts == "object") {
+ for (var ext=0, extlen=renderer.exacts.length; ext<extlen; ext++) {
+ var exact = renderer.exacts[ext];
+
+ var eelem = this.createElementNS("", "EXACT");
+ if (typeof exact.value == "string") {
+ eelem.setAttribute("value", exact.value);
+ }
+ if (typeof exact.label == "string") {
+ eelem.setAttribute("label", exact.label);
+ }
+ if (typeof exact.method == "string") {
+ eelem.setAttribute("method", exact.method);
+ }
+
+ renderElem.appendChild(eelem);
+
+ if (typeof exact.symbol == "object") {
+ var selem = null;
+
+ if (exact.symbol.type == "simplemarker") {
+ selem = this.createElementNS("", "SIMPLEMARKERSYMBOL");
+ }
+
+ if (selem != null) {
+ if (typeof exact.symbol.antialiasing == "string") {
+ selem.setAttribute("antialiasing", exact.symbol.antialiasing);
+ }
+ if (typeof exact.symbol.color == "string") {
+ selem.setAttribute("color", exact.symbol.color);
+ }
+ if (typeof exact.symbol.outline == "string") {
+ selem.setAttribute("outline", exact.symbol.outline);
+ }
+ if (typeof exact.symbol.overlap == "string") {
+ selem.setAttribute("overlap", exact.symbol.overlap);
+ }
+ if (typeof exact.symbol.shadow == "string") {
+ selem.setAttribute("shadow", exact.symbol.shadow);
+ }
+ if (typeof exact.symbol.transparency == "number") {
+ selem.setAttribute("transparency", exact.symbol.transparency);
+ }
+ //if (typeof exact.symbol.type == "string")
+ // selem.setAttribute("type", exact.symbol.type);
+ if (typeof exact.symbol.usecentroid == "string") {
+ selem.setAttribute("usecentroid", exact.symbol.usecentroid);
+ }
+ if (typeof exact.symbol.width == "number") {
+ selem.setAttribute("width", exact.symbol.width);
+ }
+
+ eelem.appendChild(selem);
+ }
+ }
+ } // for each exact
+ }
+ },
+
+
+ addSimpleLabelRenderer: function(renderElem, renderer) {
+ renderElem.setAttribute("field", renderer.field);
+ var keys = ['featureweight', 'howmanylabels', 'labelbufferratio',
+ 'labelpriorities', 'labelweight', 'linelabelposition',
+ 'rotationalangles'];
+ for (var i=0, len=keys.length; i<len; i++) {
+ var key = keys[i];
+ if (renderer[key]) {
+ renderElem.setAttribute(key, renderer[key]);
+ }
+ }
+
+ if (renderer.symbol.type == "text") {
+ var symbol = renderer.symbol;
+ var selem = this.createElementNS("", "TEXTSYMBOL");
+ renderElem.appendChild(selem);
+
+ var keys = this.fontStyleKeys;
+ for (var i=0, len=keys.length; i<len; i++) {
+ var key = keys[i];
+ if (symbol[key]) {
+ selem.setAttribute(key, renderer[key]);
+ }
+ }
+ }
+ },
+
+ writePolygonGeometry: function(polygon) {
+ if (!(polygon instanceof OpenLayers.Geometry.Polygon)) {
+ throw {
+ message:'Cannot write polygon geometry to ArcXML with an ' +
+ polygon.CLASS_NAME + ' object.',
+ geometry: polygon
+ };
+ }
+
+ var polyElem = this.createElementNS("", "POLYGON");
+
+ for (var ln=0, lnlen=polygon.components.length; ln<lnlen; ln++) {
+ var ring = polygon.components[ln];
+ var ringElem = this.createElementNS("", "RING");
+
+ for (var rn=0, rnlen=ring.components.length; rn<rnlen; rn++) {
+ var point = ring.components[rn];
+ var pointElem = this.createElementNS("", "POINT");
+
+ pointElem.setAttribute("x", point.x);
+ pointElem.setAttribute("y", point.y);
+
+ ringElem.appendChild(pointElem);
+ }
+
+ polyElem.appendChild(ringElem);
+ }
+
+ return polyElem;
+ },
+
+ /**
+ * Method: parseResponse
+ * Take an ArcXML response, and parse in into this object's internal properties.
+ *
+ * Parameters:
+ * data - {String} or {DOMElement} The ArcXML response, as either a string or the
+ * top level DOMElement of the response.
+ */
+ parseResponse: function(data) {
+ if(typeof data == "string") {
+ var newData = new OpenLayers.Format.XML();
+ data = newData.read(data);
+ }
+ var response = new OpenLayers.Format.ArcXML.Response();
+
+ var errorNode = data.getElementsByTagName("ERROR");
+
+ if (errorNode != null && errorNode.length > 0) {
+ response.error = this.getChildValue(errorNode, "Unknown error.");
+ } else {
+ var responseNode = data.getElementsByTagName("RESPONSE");
+
+ if (responseNode == null || responseNode.length == 0) {
+ response.error = "No RESPONSE tag found in ArcXML response.";
+ return response;
+ }
+
+ var rtype = responseNode[0].firstChild.nodeName;
+ if (rtype == "#text") {
+ rtype = responseNode[0].firstChild.nextSibling.nodeName;
+ }
+
+ if (rtype == "IMAGE") {
+ var envelopeNode = data.getElementsByTagName("ENVELOPE");
+ var outputNode = data.getElementsByTagName("OUTPUT");
+
+ if (envelopeNode == null || envelopeNode.length == 0) {
+ response.error = "No ENVELOPE tag found in ArcXML response.";
+ } else if (outputNode == null || outputNode.length == 0) {
+ response.error = "No OUTPUT tag found in ArcXML response.";
+ } else {
+ var envAttr = this.parseAttributes(envelopeNode[0]);
+ var outputAttr = this.parseAttributes(outputNode[0]);
+
+ if (typeof outputAttr.type == "string") {
+ response.image = {
+ envelope: envAttr,
+ output: {
+ type: outputAttr.type,
+ data: this.getChildValue(outputNode[0])
+ }
+ };
+ } else {
+ response.image = { envelope: envAttr, output: outputAttr };
+ }
+ }
+ } else if (rtype == "FEATURES") {
+ var features = responseNode[0].getElementsByTagName("FEATURES");
+
+ // get the feature count
+ var featureCount = features[0].getElementsByTagName("FEATURECOUNT");
+ response.features.featurecount = featureCount[0].getAttribute("count");
+
+ if (response.features.featurecount > 0) {
+ // get the feature envelope
+ var envelope = features[0].getElementsByTagName("ENVELOPE");
+ response.features.envelope = this.parseAttributes(envelope[0], typeof(0));
+
+ // get the field values per feature
+ var featureList = features[0].getElementsByTagName("FEATURE");
+ for (var fn = 0; fn < featureList.length; fn++) {
+ var feature = new OpenLayers.Feature.Vector();
+ var fields = featureList[fn].getElementsByTagName("FIELD");
+
+ for (var fdn = 0; fdn < fields.length; fdn++) {
+ var fieldName = fields[fdn].getAttribute("name");
+ var fieldValue = fields[fdn].getAttribute("value");
+ feature.attributes[ fieldName ] = fieldValue;
+ }
+
+ var geom = featureList[fn].getElementsByTagName("POLYGON");
+
+ if (geom.length > 0) {
+ // if there is a polygon, create an openlayers polygon, and assign
+ // it to the .geometry property of the feature
+ var ring = geom[0].getElementsByTagName("RING");
+
+ var polys = [];
+ for (var rn = 0; rn < ring.length; rn++) {
+ var linearRings = [];
+ linearRings.push(this.parsePointGeometry(ring[rn]));
+
+ var holes = ring[rn].getElementsByTagName("HOLE");
+ for (var hn = 0; hn < holes.length; hn++) {
+ linearRings.push(this.parsePointGeometry(holes[hn]));
+ }
+ holes = null;
+ polys.push(new OpenLayers.Geometry.Polygon(linearRings));
+ linearRings = null;
+ }
+ ring = null;
+
+ if (polys.length == 1) {
+ feature.geometry = polys[0];
+ } else
+ {
+ feature.geometry = new OpenLayers.Geometry.MultiPolygon(polys);
+ }
+ }
+
+ response.features.feature.push(feature);
+ }
+ }
+ } else {
+ response.error = "Unidentified response type.";
+ }
+ }
+ return response;
+ },
+
+
+ /**
+ * Method: parseAttributes
+ *
+ * Parameters:
+ * node - {<DOMElement>} An element to parse attributes from.
+ *
+ * Returns:
+ * {Object} An attributes object, with properties set to attribute values.
+ */
+ parseAttributes: function(node,type) {
+ var attributes = {};
+ for(var attr = 0; attr < node.attributes.length; attr++) {
+ if (type == "number") {
+ attributes[node.attributes[attr].nodeName] = parseFloat(node.attributes[attr].nodeValue);
+ } else {
+ attributes[node.attributes[attr].nodeName] = node.attributes[attr].nodeValue;
+ }
+ }
+ return attributes;
+ },
+
+
+ /**
+ * Method: parsePointGeometry
+ *
+ * Parameters:
+ * node - {<DOMElement>} An element to parse <COORDS> or <POINT> arcxml data from.
+ *
+ * Returns:
+ * {<OpenLayers.Geometry.LinearRing>} A linear ring represented by the node's points.
+ */
+ parsePointGeometry: function(node) {
+ var ringPoints = [];
+ var coords = node.getElementsByTagName("COORDS");
+
+ if (coords.length > 0) {
+ // if coords is present, it's the only coords item
+ var coordArr = this.getChildValue(coords[0]);
+ coordArr = coordArr.split(/;/);
+ for (var cn = 0; cn < coordArr.length; cn++) {
+ var coordItems = coordArr[cn].split(/ /);
+ ringPoints.push(new OpenLayers.Geometry.Point(coordItems[0], coordItems[1]));
+ }
+ coords = null;
+ } else {
+ var point = node.getElementsByTagName("POINT");
+ if (point.length > 0) {
+ for (var pn = 0; pn < point.length; pn++) {
+ ringPoints.push(
+ new OpenLayers.Geometry.Point(
+ parseFloat(point[pn].getAttribute("x")),
+ parseFloat(point[pn].getAttribute("y"))
+ )
+ );
+ }
+ }
+ point = null;
+ }
+
+ return new OpenLayers.Geometry.LinearRing(ringPoints);
+ },
+
+ CLASS_NAME: "OpenLayers.Format.ArcXML"
+});
+
+OpenLayers.Format.ArcXML.Request = OpenLayers.Class({
+ initialize: function(params) {
+ var defaults = {
+ get_image: {
+ properties: {
+ background: null,
+ /*{
+ color: { r:255, g:255, b:255 },
+ transcolor: null
+ },*/
+ draw: true,
+ envelope: {
+ minx: 0,
+ miny: 0,
+ maxx: 0,
+ maxy: 0
+ },
+ featurecoordsys: {
+ id:0,
+ string:"",
+ datumtransformid:0,
+ datumtransformstring:""
+ },
+ filtercoordsys:{
+ id:0,
+ string:"",
+ datumtransformid:0,
+ datumtransformstring:""
+ },
+ imagesize:{
+ height:0,
+ width:0,
+ dpi:96,
+ printheight:0,
+ printwidth:0,
+ scalesymbols:false
+ },
+ layerlist:[],
+ /* no support for legends */
+ output:{
+ baseurl:"",
+ legendbaseurl:"",
+ legendname:"",
+ legendpath:"",
+ legendurl:"",
+ name:"",
+ path:"",
+ type:"jpg",
+ url:""
+ }
+ }
+ },
+
+ get_feature: {
+ layer: "",
+ query: {
+ isspatial: false,
+ featurecoordsys: {
+ id:0,
+ string:"",
+ datumtransformid:0,
+ datumtransformstring:""
+ },
+ filtercoordsys: {
+ id:0,
+ string:"",
+ datumtransformid:0,
+ datumtransformstring:""
+ },
+ buffer:0,
+ where:"",
+ spatialfilter: {
+ relation: "envelope_intersection",
+ envelope: null
+ }
+ }
+ },
+
+ environment: {
+ separators: {
+ cs:" ",
+ ts:";"
+ }
+ },
+
+ layer: [],
+ workspaces: []
+ };
+
+ return OpenLayers.Util.extend(this, defaults);
+ },
+
+ CLASS_NAME: "OpenLayers.Format.ArcXML.Request"
+});
+
+OpenLayers.Format.ArcXML.Response = OpenLayers.Class({
+ initialize: function(params) {
+ var defaults = {
+ image: {
+ envelope:null,
+ output:''
+ },
+
+ features: {
+ featurecount: 0,
+ envelope: null,
+ feature: []
+ },
+
+ error:''
+ };
+
+ return OpenLayers.Util.extend(this, defaults);
+ },
+
+ CLASS_NAME: "OpenLayers.Format.ArcXML.Response"
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/ArcXML/Features.js b/misc/openlayers/lib/OpenLayers/Format/ArcXML/Features.js
new file mode 100644
index 0000000..5b8730d
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/ArcXML/Features.js
@@ -0,0 +1,46 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/ArcXML.js
+ */
+
+/**
+ * Class: OpenLayers.Format.ArcXML.Features
+ * Read/Write ArcXML features. Create a new instance with the
+ * <OpenLayers.Format.ArcXML.Features> constructor.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.ArcXML.Features = OpenLayers.Class(OpenLayers.Format.XML, {
+
+ /**
+ * Constructor: OpenLayers.Format.ArcXML.Features
+ * Create a new parser/writer for ArcXML Features. Create an instance of this class
+ * to get a set of features from an ArcXML response.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * APIMethod: read
+ * Read data from a string of ArcXML, and return a set of OpenLayers features.
+ *
+ * Parameters:
+ * data - {String} or {DOMElement} data to read/parse.
+ *
+ * Returns:
+ * {Array(<OpenLayers.Feature.Vector>)} A collection of features.
+ */
+ read: function(data) {
+ var axl = new OpenLayers.Format.ArcXML();
+ var parsed = axl.read(data);
+
+ return parsed.features.feature;
+ }
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/Atom.js b/misc/openlayers/lib/OpenLayers/Format/Atom.js
new file mode 100644
index 0000000..8eb5792
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/Atom.js
@@ -0,0 +1,712 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Format/GML/v3.js
+ * @requires OpenLayers/Feature/Vector.js
+ */
+
+/**
+ * Class: OpenLayers.Format.Atom
+ * Read/write Atom feeds. Create a new instance with the
+ * <OpenLayers.Format.AtomFeed> constructor.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.Atom = OpenLayers.Class(OpenLayers.Format.XML, {
+
+ /**
+ * Property: namespaces
+ * {Object} Mapping of namespace aliases to namespace URIs. Properties
+ * of this object should not be set individually. Read-only. All
+ * XML subclasses should have their own namespaces object. Use
+ * <setNamespace> to add or set a namespace alias after construction.
+ */
+ namespaces: {
+ atom: "http://www.w3.org/2005/Atom",
+ georss: "http://www.georss.org/georss"
+ },
+
+ /**
+ * APIProperty: feedTitle
+ * {String} Atom feed elements require a title. Default is "untitled".
+ */
+ feedTitle: "untitled",
+
+ /**
+ * APIProperty: defaultEntryTitle
+ * {String} Atom entry elements require a title. In cases where one is
+ * not provided in the feature attributes, this will be used. Default
+ * is "untitled".
+ */
+ defaultEntryTitle: "untitled",
+
+ /**
+ * Property: gmlParse
+ * {Object} GML Format object for parsing features
+ * Non-API and only created if necessary
+ */
+ gmlParser: null,
+
+ /**
+ * APIProperty: xy
+ * {Boolean} Order of the GML coordinate: true:(x,y) or false:(y,x)
+ * For GeoRSS the default is (y,x), therefore: false
+ */
+ xy: false,
+
+ /**
+ * Constructor: OpenLayers.Format.AtomEntry
+ * Create a new parser for Atom.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * APIMethod: read
+ * Return a list of features from an Atom feed or entry document.
+
+ * Parameters:
+ * doc - {Element} or {String}
+ *
+ * Returns:
+ * Array({<OpenLayers.Feature.Vector>})
+ */
+ read: function(doc) {
+ if (typeof doc == "string") {
+ doc = OpenLayers.Format.XML.prototype.read.apply(this, [doc]);
+ }
+ return this.parseFeatures(doc);
+ },
+
+ /**
+ * APIMethod: write
+ * Serialize or more feature nodes to Atom documents.
+ *
+ * Parameters:
+ * features - {<OpenLayers.Feature.Vector>} or Array({<OpenLayers.Feature.Vector>})
+ *
+ * Returns:
+ * {String} an Atom entry document if passed one feature node, or a feed
+ * document if passed an array of feature nodes.
+ */
+ write: function(features) {
+ var doc;
+ if (OpenLayers.Util.isArray(features)) {
+ doc = this.createElementNSPlus("atom:feed");
+ doc.appendChild(
+ this.createElementNSPlus("atom:title", {
+ value: this.feedTitle
+ })
+ );
+ for (var i=0, ii=features.length; i<ii; i++) {
+ doc.appendChild(this.buildEntryNode(features[i]));
+ }
+ }
+ else {
+ doc = this.buildEntryNode(features);
+ }
+ return OpenLayers.Format.XML.prototype.write.apply(this, [doc]);
+ },
+
+ /**
+ * Method: buildContentNode
+ *
+ * Parameters:
+ * content - {Object}
+ *
+ * Returns:
+ * {DOMElement} an Atom content node.
+ *
+ * TODO: types other than text.
+ */
+ buildContentNode: function(content) {
+ var node = this.createElementNSPlus("atom:content", {
+ attributes: {
+ type: content.type || null
+ }
+ });
+ if (content.src) {
+ node.setAttribute("src", content.src);
+ } else {
+ if (content.type == "text" || content.type == null) {
+ node.appendChild(
+ this.createTextNode(content.value)
+ );
+ } else if (content.type == "html") {
+ if (typeof content.value != "string") {
+ throw "HTML content must be in form of an escaped string";
+ }
+ node.appendChild(
+ this.createTextNode(content.value)
+ );
+ } else if (content.type == "xhtml") {
+ node.appendChild(content.value);
+ } else if (content.type == "xhtml" ||
+ content.type.match(/(\+|\/)xml$/)) {
+ node.appendChild(content.value);
+ }
+ else { // MUST be a valid Base64 encoding
+ node.appendChild(
+ this.createTextNode(content.value)
+ );
+ }
+ }
+ return node;
+ },
+
+ /**
+ * Method: buildEntryNode
+ * Build an Atom entry node from a feature object.
+ *
+ * Parameters:
+ * feature - {<OpenLayers.Feature.Vector>}
+ *
+ * Returns:
+ * {DOMElement} an Atom entry node.
+ *
+ * These entries are geared for publication using AtomPub.
+ *
+ * TODO: support extension elements
+ */
+ buildEntryNode: function(feature) {
+ var attrib = feature.attributes;
+ var atomAttrib = attrib.atom || {};
+ var entryNode = this.createElementNSPlus("atom:entry");
+
+ // atom:author
+ if (atomAttrib.authors) {
+ var authors = OpenLayers.Util.isArray(atomAttrib.authors) ?
+ atomAttrib.authors : [atomAttrib.authors];
+ for (var i=0, ii=authors.length; i<ii; i++) {
+ entryNode.appendChild(
+ this.buildPersonConstructNode(
+ "author", authors[i]
+ )
+ );
+ }
+ }
+
+ // atom:category
+ if (atomAttrib.categories) {
+ var categories = OpenLayers.Util.isArray(atomAttrib.categories) ?
+ atomAttrib.categories : [atomAttrib.categories];
+ var category;
+ for (var i=0, ii=categories.length; i<ii; i++) {
+ category = categories[i];
+ entryNode.appendChild(
+ this.createElementNSPlus("atom:category", {
+ attributes: {
+ term: category.term,
+ scheme: category.scheme || null,
+ label: category.label || null
+ }
+ })
+ );
+ }
+ }
+
+ // atom:content
+ if (atomAttrib.content) {
+ entryNode.appendChild(this.buildContentNode(atomAttrib.content));
+ }
+
+ // atom:contributor
+ if (atomAttrib.contributors) {
+ var contributors = OpenLayers.Util.isArray(atomAttrib.contributors) ?
+ atomAttrib.contributors : [atomAttrib.contributors];
+ for (var i=0, ii=contributors.length; i<ii; i++) {
+ entryNode.appendChild(
+ this.buildPersonConstructNode(
+ "contributor",
+ contributors[i]
+ )
+ );
+ }
+ }
+
+ // atom:id
+ if (feature.fid) {
+ entryNode.appendChild(
+ this.createElementNSPlus("atom:id", {
+ value: feature.fid
+ })
+ );
+ }
+
+ // atom:link
+ if (atomAttrib.links) {
+ var links = OpenLayers.Util.isArray(atomAttrib.links) ?
+ atomAttrib.links : [atomAttrib.links];
+ var link;
+ for (var i=0, ii=links.length; i<ii; i++) {
+ link = links[i];
+ entryNode.appendChild(
+ this.createElementNSPlus("atom:link", {
+ attributes: {
+ href: link.href,
+ rel: link.rel || null,
+ type: link.type || null,
+ hreflang: link.hreflang || null,
+ title: link.title || null,
+ length: link.length || null
+ }
+ })
+ );
+ }
+ }
+
+ // atom:published
+ if (atomAttrib.published) {
+ entryNode.appendChild(
+ this.createElementNSPlus("atom:published", {
+ value: atomAttrib.published
+ })
+ );
+ }
+
+ // atom:rights
+ if (atomAttrib.rights) {
+ entryNode.appendChild(
+ this.createElementNSPlus("atom:rights", {
+ value: atomAttrib.rights
+ })
+ );
+ }
+
+ // atom:source not implemented
+
+ // atom:summary
+ if (atomAttrib.summary || attrib.description) {
+ entryNode.appendChild(
+ this.createElementNSPlus("atom:summary", {
+ value: atomAttrib.summary || attrib.description
+ })
+ );
+ }
+
+ // atom:title
+ entryNode.appendChild(
+ this.createElementNSPlus("atom:title", {
+ value: atomAttrib.title || attrib.title || this.defaultEntryTitle
+ })
+ );
+
+ // atom:updated
+ if (atomAttrib.updated) {
+ entryNode.appendChild(
+ this.createElementNSPlus("atom:updated", {
+ value: atomAttrib.updated
+ })
+ );
+ }
+
+ // georss:where
+ if (feature.geometry) {
+ var whereNode = this.createElementNSPlus("georss:where");
+ whereNode.appendChild(
+ this.buildGeometryNode(feature.geometry)
+ );
+ entryNode.appendChild(whereNode);
+ }
+
+ return entryNode;
+ },
+
+ /**
+ * Method: initGmlParser
+ * Creates a GML parser.
+ */
+ initGmlParser: function() {
+ this.gmlParser = new OpenLayers.Format.GML.v3({
+ xy: this.xy,
+ featureNS: "http://example.com#feature",
+ internalProjection: this.internalProjection,
+ externalProjection: this.externalProjection
+ });
+ },
+
+ /**
+ * Method: buildGeometryNode
+ * builds a GeoRSS node with a given geometry
+ *
+ * Parameters:
+ * geometry - {<OpenLayers.Geometry>}
+ *
+ * Returns:
+ * {DOMElement} A gml node.
+ */
+ buildGeometryNode: function(geometry) {
+ if (!this.gmlParser) {
+ this.initGmlParser();
+ }
+ var node = this.gmlParser.writeNode("feature:_geometry", geometry);
+ return node.firstChild;
+ },
+
+ /**
+ * Method: buildPersonConstructNode
+ *
+ * Parameters:
+ * name - {String}
+ * value - {Object}
+ *
+ * Returns:
+ * {DOMElement} an Atom person construct node.
+ *
+ * Example:
+ * >>> buildPersonConstructNode("author", {name: "John Smith"})
+ * {<author><name>John Smith</name></author>}
+ *
+ * TODO: how to specify extension elements? Add to the oNames array?
+ */
+ buildPersonConstructNode: function(name, value) {
+ var oNames = ["uri", "email"];
+ var personNode = this.createElementNSPlus("atom:" + name);
+ personNode.appendChild(
+ this.createElementNSPlus("atom:name", {
+ value: value.name
+ })
+ );
+ for (var i=0, ii=oNames.length; i<ii; i++) {
+ if (value[oNames[i]]) {
+ personNode.appendChild(
+ this.createElementNSPlus("atom:" + oNames[i], {
+ value: value[oNames[i]]
+ })
+ );
+ }
+ }
+ return personNode;
+ },
+
+ /**
+ * Method: getFirstChildValue
+ *
+ * Parameters:
+ * node - {DOMElement}
+ * nsuri - {String} Child node namespace uri ("*" for any).
+ * name - {String} Child node name.
+ * def - {String} Optional string default to return if no child found.
+ *
+ * Returns:
+ * {String} The value of the first child with the given tag name. Returns
+ * default value or empty string if none found.
+ */
+ getFirstChildValue: function(node, nsuri, name, def) {
+ var value;
+ var nodes = this.getElementsByTagNameNS(node, nsuri, name);
+ if (nodes && nodes.length > 0) {
+ value = this.getChildValue(nodes[0], def);
+ } else {
+ value = def;
+ }
+ return value;
+ },
+
+ /**
+ * Method: parseFeature
+ * Parse feature from an Atom entry node..
+ *
+ * Parameters:
+ * node - {DOMElement} An Atom entry or feed node.
+ *
+ * Returns:
+ * {<OpenLayers.Feature.Vector>}
+ */
+ parseFeature: function(node) {
+ var atomAttrib = {};
+ var value = null;
+ var nodes = null;
+ var attval = null;
+ var atomns = this.namespaces.atom;
+
+ // atomAuthor*
+ this.parsePersonConstructs(node, "author", atomAttrib);
+
+ // atomCategory*
+ nodes = this.getElementsByTagNameNS(node, atomns, "category");
+ if (nodes.length > 0) {
+ atomAttrib.categories = [];
+ }
+ for (var i=0, ii=nodes.length; i<ii; i++) {
+ value = {};
+ value.term = nodes[i].getAttribute("term");
+ attval = nodes[i].getAttribute("scheme");
+ if (attval) { value.scheme = attval; }
+ attval = nodes[i].getAttribute("label");
+ if (attval) { value.label = attval; }
+ atomAttrib.categories.push(value);
+ }
+
+ // atomContent?
+ nodes = this.getElementsByTagNameNS(node, atomns, "content");
+ if (nodes.length > 0) {
+ value = {};
+ attval = nodes[0].getAttribute("type");
+ if (attval) {
+ value.type = attval;
+ }
+ attval = nodes[0].getAttribute("src");
+ if (attval) {
+ value.src = attval;
+ } else {
+ if (value.type == "text" ||
+ value.type == "html" ||
+ value.type == null ) {
+ value.value = this.getFirstChildValue(
+ node,
+ atomns,
+ "content",
+ null
+ );
+ } else if (value.type == "xhtml" ||
+ value.type.match(/(\+|\/)xml$/)) {
+ value.value = this.getChildEl(nodes[0]);
+ } else { // MUST be base64 encoded
+ value.value = this.getFirstChildValue(
+ node,
+ atomns,
+ "content",
+ null
+ );
+ }
+ atomAttrib.content = value;
+ }
+ }
+
+ // atomContributor*
+ this.parsePersonConstructs(node, "contributor", atomAttrib);
+
+ // atomId
+ atomAttrib.id = this.getFirstChildValue(node, atomns, "id", null);
+
+ // atomLink*
+ nodes = this.getElementsByTagNameNS(node, atomns, "link");
+ if (nodes.length > 0) {
+ atomAttrib.links = new Array(nodes.length);
+ }
+ var oAtts = ["rel", "type", "hreflang", "title", "length"];
+ for (var i=0, ii=nodes.length; i<ii; i++) {
+ value = {};
+ value.href = nodes[i].getAttribute("href");
+ for (var j=0, jj=oAtts.length; j<jj; j++) {
+ attval = nodes[i].getAttribute(oAtts[j]);
+ if (attval) {
+ value[oAtts[j]] = attval;
+ }
+ }
+ atomAttrib.links[i] = value;
+ }
+
+ // atomPublished?
+ value = this.getFirstChildValue(node, atomns, "published", null);
+ if (value) {
+ atomAttrib.published = value;
+ }
+
+ // atomRights?
+ value = this.getFirstChildValue(node, atomns, "rights", null);
+ if (value) {
+ atomAttrib.rights = value;
+ }
+
+ // atomSource? -- not implemented
+
+ // atomSummary?
+ value = this.getFirstChildValue(node, atomns, "summary", null);
+ if (value) {
+ atomAttrib.summary = value;
+ }
+
+ // atomTitle
+ atomAttrib.title = this.getFirstChildValue(
+ node, atomns, "title", null
+ );
+
+ // atomUpdated
+ atomAttrib.updated = this.getFirstChildValue(
+ node, atomns, "updated", null
+ );
+
+ var featureAttrib = {
+ title: atomAttrib.title,
+ description: atomAttrib.summary,
+ atom: atomAttrib
+ };
+ var geometry = this.parseLocations(node)[0];
+ var feature = new OpenLayers.Feature.Vector(geometry, featureAttrib);
+ feature.fid = atomAttrib.id;
+ return feature;
+ },
+
+ /**
+ * Method: parseFeatures
+ * Return features from an Atom entry or feed.
+ *
+ * Parameters:
+ * node - {DOMElement} An Atom entry or feed node.
+ *
+ * Returns:
+ * Array({<OpenLayers.Feature.Vector>})
+ */
+ parseFeatures: function(node) {
+ var features = [];
+ var entries = this.getElementsByTagNameNS(
+ node, this.namespaces.atom, "entry"
+ );
+ if (entries.length == 0) {
+ entries = [node];
+ }
+ for (var i=0, ii=entries.length; i<ii; i++) {
+ features.push(this.parseFeature(entries[i]));
+ }
+ return features;
+ },
+
+ /**
+ * Method: parseLocations
+ * Parse the locations from an Atom entry or feed.
+ *
+ * Parameters:
+ * node - {DOMElement} An Atom entry or feed node.
+ *
+ * Returns:
+ * Array({<OpenLayers.Geometry>})
+ */
+ parseLocations: function(node) {
+ var georssns = this.namespaces.georss;
+
+ var locations = {components: []};
+ var where = this.getElementsByTagNameNS(node, georssns, "where");
+ if (where && where.length > 0) {
+ if (!this.gmlParser) {
+ this.initGmlParser();
+ }
+ for (var i=0, ii=where.length; i<ii; i++) {
+ this.gmlParser.readChildNodes(where[i], locations);
+ }
+ }
+
+ var components = locations.components;
+ var point = this.getElementsByTagNameNS(node, georssns, "point");
+ if (point && point.length > 0) {
+ for (var i=0, ii=point.length; i<ii; i++) {
+ var xy = OpenLayers.String.trim(
+ point[i].firstChild.nodeValue
+ ).split(/\s+/);
+ if (xy.length !=2) {
+ xy = OpenLayers.String.trim(
+ point[i].firstChild.nodeValue
+ ).split(/\s*,\s*/);
+ }
+ components.push(new OpenLayers.Geometry.Point(xy[1], xy[0]));
+ }
+ }
+
+ var line = this.getElementsByTagNameNS(node, georssns, "line");
+ if (line && line.length > 0) {
+ var coords;
+ var p;
+ var points;
+ for (var i=0, ii=line.length; i<ii; i++) {
+ coords = OpenLayers.String.trim(
+ line[i].firstChild.nodeValue
+ ).split(/\s+/);
+ points = [];
+ for (var j=0, jj=coords.length; j<jj; j+=2) {
+ p = new OpenLayers.Geometry.Point(coords[j+1], coords[j]);
+ points.push(p);
+ }
+ components.push(
+ new OpenLayers.Geometry.LineString(points)
+ );
+ }
+ }
+
+ var polygon = this.getElementsByTagNameNS(node, georssns, "polygon");
+ if (polygon && polygon.length > 0) {
+ var coords;
+ var p;
+ var points;
+ for (var i=0, ii=polygon.length; i<ii; i++) {
+ coords = OpenLayers.String.trim(
+ polygon[i].firstChild.nodeValue
+ ).split(/\s+/);
+ points = [];
+ for (var j=0, jj=coords.length; j<jj; j+=2) {
+ p = new OpenLayers.Geometry.Point(coords[j+1], coords[j]);
+ points.push(p);
+ }
+ components.push(
+ new OpenLayers.Geometry.Polygon(
+ [new OpenLayers.Geometry.LinearRing(points)]
+ )
+ );
+ }
+ }
+
+ if (this.internalProjection && this.externalProjection) {
+ for (var i=0, ii=components.length; i<ii; i++) {
+ if (components[i]) {
+ components[i].transform(
+ this.externalProjection,
+ this.internalProjection
+ );
+ }
+ }
+ }
+
+ return components;
+ },
+
+ /**
+ * Method: parsePersonConstruct
+ * Parse Atom person constructs from an Atom entry node.
+ *
+ * Parameters:
+ * node - {DOMElement} An Atom entry or feed node.
+ * name - {String} Construcy name ("author" or "contributor")
+ * data = {Object} Object in which to put parsed persons.
+ *
+ * Returns:
+ * An {Object}.
+ */
+ parsePersonConstructs: function(node, name, data) {
+ var persons = [];
+ var atomns = this.namespaces.atom;
+ var nodes = this.getElementsByTagNameNS(node, atomns, name);
+ var oAtts = ["uri", "email"];
+ for (var i=0, ii=nodes.length; i<ii; i++) {
+ var value = {};
+ value.name = this.getFirstChildValue(
+ nodes[i],
+ atomns,
+ "name",
+ null
+ );
+ for (var j=0, jj=oAtts.length; j<jj; j++) {
+ var attval = this.getFirstChildValue(
+ nodes[i],
+ atomns,
+ oAtts[j],
+ null);
+ if (attval) {
+ value[oAtts[j]] = attval;
+ }
+ }
+ persons.push(value);
+ }
+ if (persons.length > 0) {
+ data[name + "s"] = persons;
+ }
+ },
+
+ CLASS_NAME: "OpenLayers.Format.Atom"
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/CQL.js b/misc/openlayers/lib/OpenLayers/Format/CQL.js
new file mode 100644
index 0000000..8430a8b
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/CQL.js
@@ -0,0 +1,452 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WKT.js
+ * @requires OpenLayers/Filter/Comparison.js
+ * @requires OpenLayers/Filter/Logical.js
+ * @requires OpenLayers/Filter/Spatial.js
+ */
+
+/**
+ * Class: OpenLayers.Format.CQL
+ * Read CQL strings to get <OpenLayers.Filter> objects. Write
+ * <OpenLayers.Filter> objects to get CQL strings. Create a new parser with
+ * the <OpenLayers.Format.CQL> constructor.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format>
+ */
+OpenLayers.Format.CQL = (function() {
+
+ var tokens = [
+ "PROPERTY", "COMPARISON", "VALUE", "LOGICAL"
+ ],
+
+ patterns = {
+ PROPERTY: /^[_a-zA-Z]\w*/,
+ COMPARISON: /^(=|<>|<=|<|>=|>|LIKE)/i,
+ IS_NULL: /^IS NULL/i,
+ COMMA: /^,/,
+ LOGICAL: /^(AND|OR)/i,
+ VALUE: /^('([^']|'')*'|\d+(\.\d*)?|\.\d+)/,
+ LPAREN: /^\(/,
+ RPAREN: /^\)/,
+ SPATIAL: /^(BBOX|INTERSECTS|DWITHIN|WITHIN|CONTAINS)/i,
+ NOT: /^NOT/i,
+ BETWEEN: /^BETWEEN/i,
+ GEOMETRY: function(text) {
+ var type = /^(POINT|LINESTRING|POLYGON|MULTIPOINT|MULTILINESTRING|MULTIPOLYGON|GEOMETRYCOLLECTION)/.exec(text);
+ if (type) {
+ var len = text.length;
+ var idx = text.indexOf("(", type[0].length);
+ if (idx > -1) {
+ var depth = 1;
+ while (idx < len && depth > 0) {
+ idx++;
+ switch(text.charAt(idx)) {
+ case '(':
+ depth++;
+ break;
+ case ')':
+ depth--;
+ break;
+ default:
+ // in default case, do nothing
+ }
+ }
+ }
+ return [text.substr(0, idx+1)];
+ }
+ },
+ END: /^$/
+ },
+
+ follows = {
+ LPAREN: ['GEOMETRY', 'SPATIAL', 'PROPERTY', 'VALUE', 'LPAREN'],
+ RPAREN: ['NOT', 'LOGICAL', 'END', 'RPAREN'],
+ PROPERTY: ['COMPARISON', 'BETWEEN', 'COMMA', 'IS_NULL'],
+ BETWEEN: ['VALUE'],
+ IS_NULL: ['END'],
+ COMPARISON: ['VALUE'],
+ COMMA: ['GEOMETRY', 'VALUE', 'PROPERTY'],
+ VALUE: ['LOGICAL', 'COMMA', 'RPAREN', 'END'],
+ SPATIAL: ['LPAREN'],
+ LOGICAL: ['NOT', 'VALUE', 'SPATIAL', 'PROPERTY', 'LPAREN'],
+ NOT: ['PROPERTY', 'LPAREN'],
+ GEOMETRY: ['COMMA', 'RPAREN']
+ },
+
+ operators = {
+ '=': OpenLayers.Filter.Comparison.EQUAL_TO,
+ '<>': OpenLayers.Filter.Comparison.NOT_EQUAL_TO,
+ '<': OpenLayers.Filter.Comparison.LESS_THAN,
+ '<=': OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO,
+ '>': OpenLayers.Filter.Comparison.GREATER_THAN,
+ '>=': OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO,
+ 'LIKE': OpenLayers.Filter.Comparison.LIKE,
+ 'BETWEEN': OpenLayers.Filter.Comparison.BETWEEN,
+ 'IS NULL': OpenLayers.Filter.Comparison.IS_NULL
+ },
+
+ operatorReverse = {},
+
+ logicals = {
+ 'AND': OpenLayers.Filter.Logical.AND,
+ 'OR': OpenLayers.Filter.Logical.OR
+ },
+
+ logicalReverse = {},
+
+ precedence = {
+ 'RPAREN': 3,
+ 'LOGICAL': 2,
+ 'COMPARISON': 1
+ };
+
+ var i;
+ for (i in operators) {
+ if (operators.hasOwnProperty(i)) {
+ operatorReverse[operators[i]] = i;
+ }
+ }
+
+ for (i in logicals) {
+ if (logicals.hasOwnProperty(i)) {
+ logicalReverse[logicals[i]] = i;
+ }
+ }
+
+ function tryToken(text, pattern) {
+ if (pattern instanceof RegExp) {
+ return pattern.exec(text);
+ } else {
+ return pattern(text);
+ }
+ }
+
+ function nextToken(text, tokens) {
+ var i, token, len = tokens.length;
+ for (i=0; i<len; i++) {
+ token = tokens[i];
+ var pat = patterns[token];
+ var matches = tryToken(text, pat);
+ if (matches) {
+ var match = matches[0];
+ var remainder = text.substr(match.length).replace(/^\s*/, "");
+ return {
+ type: token,
+ text: match,
+ remainder: remainder
+ };
+ }
+ }
+
+ var msg = "ERROR: In parsing: [" + text + "], expected one of: ";
+ for (i=0; i<len; i++) {
+ token = tokens[i];
+ msg += "\n " + token + ": " + patterns[token];
+ }
+
+ throw new Error(msg);
+ }
+
+ function tokenize(text) {
+ var results = [];
+ var token, expect = ["NOT", "GEOMETRY", "SPATIAL", "PROPERTY", "LPAREN"];
+
+ do {
+ token = nextToken(text, expect);
+ text = token.remainder;
+ expect = follows[token.type];
+ if (token.type != "END" && !expect) {
+ throw new Error("No follows list for " + token.type);
+ }
+ results.push(token);
+ } while (token.type != "END");
+
+ return results;
+ }
+
+ function buildAst(tokens) {
+ var operatorStack = [],
+ postfix = [];
+
+ while (tokens.length) {
+ var tok = tokens.shift();
+ switch (tok.type) {
+ case "PROPERTY":
+ case "GEOMETRY":
+ case "VALUE":
+ postfix.push(tok);
+ break;
+ case "COMPARISON":
+ case "BETWEEN":
+ case "IS_NULL":
+ case "LOGICAL":
+ var p = precedence[tok.type];
+
+ while (operatorStack.length > 0 &&
+ (precedence[operatorStack[operatorStack.length - 1].type] <= p)
+ ) {
+ postfix.push(operatorStack.pop());
+ }
+
+ operatorStack.push(tok);
+ break;
+ case "SPATIAL":
+ case "NOT":
+ case "LPAREN":
+ operatorStack.push(tok);
+ break;
+ case "RPAREN":
+ while (operatorStack.length > 0 &&
+ (operatorStack[operatorStack.length - 1].type != "LPAREN")
+ ) {
+ postfix.push(operatorStack.pop());
+ }
+ operatorStack.pop(); // toss out the LPAREN
+
+ if (operatorStack.length > 0 &&
+ operatorStack[operatorStack.length-1].type == "SPATIAL") {
+ postfix.push(operatorStack.pop());
+ }
+ case "COMMA":
+ case "END":
+ break;
+ default:
+ throw new Error("Unknown token type " + tok.type);
+ }
+ }
+
+ while (operatorStack.length > 0) {
+ postfix.push(operatorStack.pop());
+ }
+
+ function buildTree() {
+ var tok = postfix.pop();
+ switch (tok.type) {
+ case "LOGICAL":
+ var rhs = buildTree(),
+ lhs = buildTree();
+ return new OpenLayers.Filter.Logical({
+ filters: [lhs, rhs],
+ type: logicals[tok.text.toUpperCase()]
+ });
+ case "NOT":
+ var operand = buildTree();
+ return new OpenLayers.Filter.Logical({
+ filters: [operand],
+ type: OpenLayers.Filter.Logical.NOT
+ });
+ case "BETWEEN":
+ var min, max, property;
+ postfix.pop(); // unneeded AND token here
+ max = buildTree();
+ min = buildTree();
+ property = buildTree();
+ return new OpenLayers.Filter.Comparison({
+ property: property,
+ lowerBoundary: min,
+ upperBoundary: max,
+ type: OpenLayers.Filter.Comparison.BETWEEN
+ });
+ case "COMPARISON":
+ var value = buildTree(),
+ property = buildTree();
+ return new OpenLayers.Filter.Comparison({
+ property: property,
+ value: value,
+ type: operators[tok.text.toUpperCase()]
+ });
+ case "IS_NULL":
+ var property = buildTree();
+ return new OpenLayers.Filter.Comparison({
+ property: property,
+ type: operators[tok.text.toUpperCase()]
+ });
+ case "VALUE":
+ var match = tok.text.match(/^'(.*)'$/);
+ if (match) {
+ return match[1].replace(/''/g, "'");
+ } else {
+ return Number(tok.text);
+ }
+ case "SPATIAL":
+ switch(tok.text.toUpperCase()) {
+ case "BBOX":
+ var maxy = buildTree(),
+ maxx = buildTree(),
+ miny = buildTree(),
+ minx = buildTree(),
+ prop = buildTree();
+
+ return new OpenLayers.Filter.Spatial({
+ type: OpenLayers.Filter.Spatial.BBOX,
+ property: prop,
+ value: OpenLayers.Bounds.fromArray(
+ [minx, miny, maxx, maxy]
+ )
+ });
+ case "INTERSECTS":
+ var value = buildTree(),
+ property = buildTree();
+ return new OpenLayers.Filter.Spatial({
+ type: OpenLayers.Filter.Spatial.INTERSECTS,
+ property: property,
+ value: value
+ });
+ case "WITHIN":
+ var value = buildTree(),
+ property = buildTree();
+ return new OpenLayers.Filter.Spatial({
+ type: OpenLayers.Filter.Spatial.WITHIN,
+ property: property,
+ value: value
+ });
+ case "CONTAINS":
+ var value = buildTree(),
+ property = buildTree();
+ return new OpenLayers.Filter.Spatial({
+ type: OpenLayers.Filter.Spatial.CONTAINS,
+ property: property,
+ value: value
+ });
+ case "DWITHIN":
+ var distance = buildTree(),
+ value = buildTree(),
+ property = buildTree();
+ return new OpenLayers.Filter.Spatial({
+ type: OpenLayers.Filter.Spatial.DWITHIN,
+ value: value,
+ property: property,
+ distance: Number(distance)
+ });
+ }
+ case "GEOMETRY":
+ return OpenLayers.Geometry.fromWKT(tok.text);
+ default:
+ return tok.text;
+ }
+ }
+
+ var result = buildTree();
+ if (postfix.length > 0) {
+ var msg = "Remaining tokens after building AST: \n";
+ for (var i = postfix.length - 1; i >= 0; i--) {
+ msg += postfix[i].type + ": " + postfix[i].text + "\n";
+ }
+ throw new Error(msg);
+ }
+
+ return result;
+ }
+
+ return OpenLayers.Class(OpenLayers.Format, {
+ /**
+ * APIMethod: read
+ * Generate a filter from a CQL string.
+
+ * Parameters:
+ * text - {String} The CQL text.
+ *
+ * Returns:
+ * {<OpenLayers.Filter>} A filter based on the CQL text.
+ */
+ read: function(text) {
+ var result = buildAst(tokenize(text));
+ if (this.keepData) {
+ this.data = result;
+ }
+ return result;
+ },
+
+ /**
+ * APIMethod: write
+ * Convert a filter into a CQL string.
+
+ * Parameters:
+ * filter - {<OpenLayers.Filter>} The filter.
+ *
+ * Returns:
+ * {String} A CQL string based on the filter.
+ */
+ write: function(filter) {
+ if (filter instanceof OpenLayers.Geometry) {
+ return filter.toString();
+ }
+ switch (filter.CLASS_NAME) {
+ case "OpenLayers.Filter.Spatial":
+ switch(filter.type) {
+ case OpenLayers.Filter.Spatial.BBOX:
+ return "BBOX(" +
+ filter.property + "," +
+ filter.value.toBBOX() +
+ ")";
+ case OpenLayers.Filter.Spatial.DWITHIN:
+ return "DWITHIN(" +
+ filter.property + ", " +
+ this.write(filter.value) + ", " +
+ filter.distance + ")";
+ case OpenLayers.Filter.Spatial.WITHIN:
+ return "WITHIN(" +
+ filter.property + ", " +
+ this.write(filter.value) + ")";
+ case OpenLayers.Filter.Spatial.INTERSECTS:
+ return "INTERSECTS(" +
+ filter.property + ", " +
+ this.write(filter.value) + ")";
+ case OpenLayers.Filter.Spatial.CONTAINS:
+ return "CONTAINS(" +
+ filter.property + ", " +
+ this.write(filter.value) + ")";
+ default:
+ throw new Error("Unknown spatial filter type: " + filter.type);
+ }
+ case "OpenLayers.Filter.Logical":
+ if (filter.type == OpenLayers.Filter.Logical.NOT) {
+ // TODO: deal with precedence of logical operators to
+ // avoid extra parentheses (not urgent)
+ return "NOT (" + this.write(filter.filters[0]) + ")";
+ } else {
+ var res = "(";
+ var first = true;
+ for (var i = 0; i < filter.filters.length; i++) {
+ if (first) {
+ first = false;
+ } else {
+ res += ") " + logicalReverse[filter.type] + " (";
+ }
+ res += this.write(filter.filters[i]);
+ }
+ return res + ")";
+ }
+ case "OpenLayers.Filter.Comparison":
+ if (filter.type == OpenLayers.Filter.Comparison.BETWEEN) {
+ return filter.property + " BETWEEN " +
+ this.write(filter.lowerBoundary) + " AND " +
+ this.write(filter.upperBoundary);
+ } else {
+ return (filter.value !== null) ? filter.property +
+ " " + operatorReverse[filter.type] + " " +
+ this.write(filter.value) : filter.property +
+ " " + operatorReverse[filter.type];
+ }
+ case undefined:
+ if (typeof filter === "string") {
+ return "'" + filter.replace(/'/g, "''") + "'";
+ } else if (typeof filter === "number") {
+ return String(filter);
+ }
+ default:
+ throw new Error("Can't encode: " + filter.CLASS_NAME + " " + filter);
+ }
+ },
+
+ CLASS_NAME: "OpenLayers.Format.CQL"
+
+ });
+})();
+
diff --git a/misc/openlayers/lib/OpenLayers/Format/CSWGetDomain.js b/misc/openlayers/lib/OpenLayers/Format/CSWGetDomain.js
new file mode 100644
index 0000000..18d5328
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/CSWGetDomain.js
@@ -0,0 +1,34 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format.js
+ */
+
+/**
+ * Class: OpenLayers.Format.CSWGetDomain
+ * Default version is 2.0.2.
+ *
+ * Returns:
+ * {<OpenLayers.Format>} A CSWGetDomain format of the given version.
+ */
+OpenLayers.Format.CSWGetDomain = function(options) {
+ options = OpenLayers.Util.applyDefaults(
+ options, OpenLayers.Format.CSWGetDomain.DEFAULTS
+ );
+ var cls = OpenLayers.Format.CSWGetDomain["v"+options.version.replace(/\./g, "_")];
+ if(!cls) {
+ throw "Unsupported CSWGetDomain version: " + options.version;
+ }
+ return new cls(options);
+};
+
+/**
+ * Constant: DEFAULTS
+ * {Object} Default properties for the CSWGetDomain format.
+ */
+OpenLayers.Format.CSWGetDomain.DEFAULTS = {
+ "version": "2.0.2"
+};
diff --git a/misc/openlayers/lib/OpenLayers/Format/CSWGetDomain/v2_0_2.js b/misc/openlayers/lib/OpenLayers/Format/CSWGetDomain/v2_0_2.js
new file mode 100644
index 0000000..78200ea
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/CSWGetDomain/v2_0_2.js
@@ -0,0 +1,240 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Format/CSWGetDomain.js
+ */
+
+/**
+ * Class: OpenLayers.Format.CSWGetDomain.v2_0_2
+ * A format for creating CSWGetDomain v2.0.2 transactions.
+ * Create a new instance with the
+ * <OpenLayers.Format.CSWGetDomain.v2_0_2> constructor.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.CSWGetDomain.v2_0_2 = OpenLayers.Class(OpenLayers.Format.XML, {
+
+ /**
+ * Property: namespaces
+ * {Object} Mapping of namespace aliases to namespace URIs.
+ */
+ namespaces: {
+ xlink: "http://www.w3.org/1999/xlink",
+ xsi: "http://www.w3.org/2001/XMLSchema-instance",
+ csw: "http://www.opengis.net/cat/csw/2.0.2"
+ },
+
+ /**
+ * Property: defaultPrefix
+ * {String} The default prefix (used by Format.XML).
+ */
+ defaultPrefix: "csw",
+
+ /**
+ * Property: version
+ * {String} CSW version number.
+ */
+ version: "2.0.2",
+
+ /**
+ * Property: schemaLocation
+ * {String} http://www.opengis.net/cat/csw/2.0.2
+ * http://schemas.opengis.net/csw/2.0.2/CSW-discovery.xsd
+ */
+ schemaLocation: "http://www.opengis.net/cat/csw/2.0.2 http://schemas.opengis.net/csw/2.0.2/CSW-discovery.xsd",
+
+ /**
+ * APIProperty: PropertyName
+ * {String} Value of the csw:PropertyName element, used when
+ * writing a GetDomain document.
+ */
+ PropertyName: null,
+
+ /**
+ * APIProperty: ParameterName
+ * {String} Value of the csw:ParameterName element, used when
+ * writing a GetDomain document.
+ */
+ ParameterName: null,
+
+ /**
+ * Constructor: OpenLayers.Format.CSWGetDomain.v2_0_2
+ * A class for parsing and generating CSWGetDomain v2.0.2 transactions.
+ *
+ * Parameters:
+ * options - {Object} Optional object whose properties will be set on the
+ * instance.
+ *
+ * Valid options properties:
+ * - PropertyName
+ * - ParameterName
+ */
+
+ /**
+ * APIMethod: read
+ * Parse the response from a GetDomain request.
+ */
+ read: function(data) {
+ if(typeof data == "string") {
+ data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+ }
+ if(data && data.nodeType == 9) {
+ data = data.documentElement;
+ }
+ var obj = {};
+ this.readNode(data, obj);
+ return obj;
+ },
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "csw": {
+ "GetDomainResponse": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "DomainValues": function(node, obj) {
+ if (!(OpenLayers.Util.isArray(obj.DomainValues))) {
+ obj.DomainValues = [];
+ }
+ var attrs = node.attributes;
+ var domainValue = {};
+ for(var i=0, len=attrs.length; i<len; ++i) {
+ domainValue[attrs[i].name] = attrs[i].nodeValue;
+ }
+ this.readChildNodes(node, domainValue);
+ obj.DomainValues.push(domainValue);
+ },
+ "PropertyName": function(node, obj) {
+ obj.PropertyName = this.getChildValue(node);
+ },
+ "ParameterName": function(node, obj) {
+ obj.ParameterName = this.getChildValue(node);
+ },
+ "ListOfValues": function(node, obj) {
+ if (!(OpenLayers.Util.isArray(obj.ListOfValues))) {
+ obj.ListOfValues = [];
+ }
+ this.readChildNodes(node, obj.ListOfValues);
+ },
+ "Value": function(node, obj) {
+ var attrs = node.attributes;
+ var value = {};
+ for(var i=0, len=attrs.length; i<len; ++i) {
+ value[attrs[i].name] = attrs[i].nodeValue;
+ }
+ value.value = this.getChildValue(node);
+ obj.push({Value: value});
+ },
+ "ConceptualScheme": function(node, obj) {
+ obj.ConceptualScheme = {};
+ this.readChildNodes(node, obj.ConceptualScheme);
+ },
+ "Name": function(node, obj) {
+ obj.Name = this.getChildValue(node);
+ },
+ "Document": function(node, obj) {
+ obj.Document = this.getChildValue(node);
+ },
+ "Authority": function(node, obj) {
+ obj.Authority = this.getChildValue(node);
+ },
+ "RangeOfValues": function(node, obj) {
+ obj.RangeOfValues = {};
+ this.readChildNodes(node, obj.RangeOfValues);
+ },
+ "MinValue": function(node, obj) {
+ var attrs = node.attributes;
+ var value = {};
+ for(var i=0, len=attrs.length; i<len; ++i) {
+ value[attrs[i].name] = attrs[i].nodeValue;
+ }
+ value.value = this.getChildValue(node);
+ obj.MinValue = value;
+ },
+ "MaxValue": function(node, obj) {
+ var attrs = node.attributes;
+ var value = {};
+ for(var i=0, len=attrs.length; i<len; ++i) {
+ value[attrs[i].name] = attrs[i].nodeValue;
+ }
+ value.value = this.getChildValue(node);
+ obj.MaxValue = value;
+ }
+ }
+ },
+
+ /**
+ * APIMethod: write
+ * Given an configuration js object, write a CSWGetDomain request.
+ *
+ * Parameters:
+ * options - {Object} A object mapping the request.
+ *
+ * Returns:
+ * {String} A serialized CSWGetDomain request.
+ */
+ write: function(options) {
+ var node = this.writeNode("csw:GetDomain", options);
+ return OpenLayers.Format.XML.prototype.write.apply(this, [node]);
+ },
+
+ /**
+ * Property: writers
+ * As a compliment to the readers property, this structure contains public
+ * writing functions grouped by namespace alias and named like the
+ * node names they produce.
+ */
+ writers: {
+ "csw": {
+ "GetDomain": function(options) {
+ var node = this.createElementNSPlus("csw:GetDomain", {
+ attributes: {
+ service: "CSW",
+ version: this.version
+ }
+ });
+ if (options.PropertyName || this.PropertyName) {
+ this.writeNode(
+ "csw:PropertyName",
+ options.PropertyName || this.PropertyName,
+ node
+ );
+ } else if (options.ParameterName || this.ParameterName) {
+ this.writeNode(
+ "csw:ParameterName",
+ options.ParameterName || this.ParameterName,
+ node
+ );
+ }
+ this.readChildNodes(node, options);
+ return node;
+ },
+ "PropertyName": function(value) {
+ var node = this.createElementNSPlus("csw:PropertyName", {
+ value: value
+ });
+ return node;
+ },
+ "ParameterName": function(value) {
+ var node = this.createElementNSPlus("csw:ParameterName", {
+ value: value
+ });
+ return node;
+ }
+ }
+ },
+
+ CLASS_NAME: "OpenLayers.Format.CSWGetDomain.v2_0_2"
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/CSWGetRecords.js b/misc/openlayers/lib/OpenLayers/Format/CSWGetRecords.js
new file mode 100644
index 0000000..923c548
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/CSWGetRecords.js
@@ -0,0 +1,34 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format.js
+ */
+
+/**
+ * Class: OpenLayers.Format.CSWGetRecords
+ * Default version is 2.0.2.
+ *
+ * Returns:
+ * {<OpenLayers.Format>} A CSWGetRecords format of the given version.
+ */
+OpenLayers.Format.CSWGetRecords = function(options) {
+ options = OpenLayers.Util.applyDefaults(
+ options, OpenLayers.Format.CSWGetRecords.DEFAULTS
+ );
+ var cls = OpenLayers.Format.CSWGetRecords["v"+options.version.replace(/\./g, "_")];
+ if(!cls) {
+ throw "Unsupported CSWGetRecords version: " + options.version;
+ }
+ return new cls(options);
+};
+
+/**
+ * Constant: DEFAULTS
+ * {Object} Default properties for the CSWGetRecords format.
+ */
+OpenLayers.Format.CSWGetRecords.DEFAULTS = {
+ "version": "2.0.2"
+};
diff --git a/misc/openlayers/lib/OpenLayers/Format/CSWGetRecords/v2_0_2.js b/misc/openlayers/lib/OpenLayers/Format/CSWGetRecords/v2_0_2.js
new file mode 100644
index 0000000..3c87612
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/CSWGetRecords/v2_0_2.js
@@ -0,0 +1,457 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Format/CSWGetRecords.js
+ * @requires OpenLayers/Format/Filter/v1_0_0.js
+ * @requires OpenLayers/Format/Filter/v1_1_0.js
+ * @requires OpenLayers/Format/OWSCommon/v1_0_0.js
+ */
+
+/**
+ * Class: OpenLayers.Format.CSWGetRecords.v2_0_2
+ * A format for creating CSWGetRecords v2.0.2 transactions.
+ * Create a new instance with the
+ * <OpenLayers.Format.CSWGetRecords.v2_0_2> constructor.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.CSWGetRecords.v2_0_2 = OpenLayers.Class(OpenLayers.Format.XML, {
+
+ /**
+ * Property: namespaces
+ * {Object} Mapping of namespace aliases to namespace URIs.
+ */
+ namespaces: {
+ csw: "http://www.opengis.net/cat/csw/2.0.2",
+ dc: "http://purl.org/dc/elements/1.1/",
+ dct: "http://purl.org/dc/terms/",
+ gmd: "http://www.isotc211.org/2005/gmd",
+ geonet: "http://www.fao.org/geonetwork",
+ ogc: "http://www.opengis.net/ogc",
+ ows: "http://www.opengis.net/ows",
+ xlink: "http://www.w3.org/1999/xlink",
+ xsi: "http://www.w3.org/2001/XMLSchema-instance"
+ },
+
+ /**
+ * Property: defaultPrefix
+ * {String} The default prefix (used by Format.XML).
+ */
+ defaultPrefix: "csw",
+
+ /**
+ * Property: version
+ * {String} CSW version number.
+ */
+ version: "2.0.2",
+
+ /**
+ * Property: schemaLocation
+ * {String} http://www.opengis.net/cat/csw/2.0.2
+ * http://schemas.opengis.net/csw/2.0.2/CSW-discovery.xsd
+ */
+ schemaLocation: "http://www.opengis.net/cat/csw/2.0.2 http://schemas.opengis.net/csw/2.0.2/CSW-discovery.xsd",
+
+ /**
+ * APIProperty: requestId
+ * {String} Value of the requestId attribute of the GetRecords element.
+ */
+ requestId: null,
+
+ /**
+ * APIProperty: resultType
+ * {String} Value of the resultType attribute of the GetRecords element,
+ * specifies the result type in the GetRecords response, "hits" is
+ * the default.
+ */
+ resultType: null,
+
+ /**
+ * APIProperty: outputFormat
+ * {String} Value of the outputFormat attribute of the GetRecords element,
+ * specifies the format of the GetRecords response,
+ * "application/xml" is the default.
+ */
+ outputFormat: null,
+
+ /**
+ * APIProperty: outputSchema
+ * {String} Value of the outputSchema attribute of the GetRecords element,
+ * specifies the schema of the GetRecords response.
+ */
+ outputSchema: null,
+
+ /**
+ * APIProperty: startPosition
+ * {String} Value of the startPosition attribute of the GetRecords element,
+ * specifies the start position (offset+1) for the GetRecords response,
+ * 1 is the default.
+ */
+ startPosition: null,
+
+ /**
+ * APIProperty: maxRecords
+ * {String} Value of the maxRecords attribute of the GetRecords element,
+ * specifies the maximum number of records in the GetRecords response,
+ * 10 is the default.
+ */
+ maxRecords: null,
+
+ /**
+ * APIProperty: DistributedSearch
+ * {String} Value of the csw:DistributedSearch element, used when writing
+ * a csw:GetRecords document.
+ */
+ DistributedSearch: null,
+
+ /**
+ * APIProperty: ResponseHandler
+ * {Array({String})} Values of the csw:ResponseHandler elements, used when
+ * writting a csw:GetRecords document.
+ */
+ ResponseHandler: null,
+
+ /**
+ * APIProperty: Query
+ * {String} Value of the csw:Query element, used when writing a csw:GetRecords
+ * document.
+ */
+ Query: null,
+
+ /**
+ * Property: regExes
+ * Compiled regular expressions for manipulating strings.
+ */
+ regExes: {
+ trimSpace: (/^\s*|\s*$/g),
+ removeSpace: (/\s*/g),
+ splitSpace: (/\s+/),
+ trimComma: (/\s*,\s*/g)
+ },
+
+ /**
+ * Constructor: OpenLayers.Format.CSWGetRecords.v2_0_2
+ * A class for parsing and generating CSWGetRecords v2.0.2 transactions.
+ *
+ * Parameters:
+ * options - {Object} Optional object whose properties will be set on the
+ * instance.
+ *
+ * Valid options properties (documented as class properties):
+ * - requestId
+ * - resultType
+ * - outputFormat
+ * - outputSchema
+ * - startPosition
+ * - maxRecords
+ * - DistributedSearch
+ * - ResponseHandler
+ * - Query
+ */
+ initialize: function(options) {
+ OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+ },
+
+ /**
+ * APIMethod: read
+ * Parse the response from a GetRecords request.
+ */
+ read: function(data) {
+ if(typeof data == "string") {
+ data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+ }
+ if(data && data.nodeType == 9) {
+ data = data.documentElement;
+ }
+ var obj = {};
+ this.readNode(data, obj);
+ return obj;
+ },
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "csw": {
+ "GetRecordsResponse": function(node, obj) {
+ obj.records = [];
+ this.readChildNodes(node, obj);
+ var version = this.getAttributeNS(node, "", 'version');
+ if (version != "") {
+ obj.version = version;
+ }
+ },
+ "RequestId": function(node, obj) {
+ obj.RequestId = this.getChildValue(node);
+ },
+ "SearchStatus": function(node, obj) {
+ obj.SearchStatus = {};
+ var timestamp = this.getAttributeNS(node, "", 'timestamp');
+ if (timestamp != "") {
+ obj.SearchStatus.timestamp = timestamp;
+ }
+ },
+ "SearchResults": function(node, obj) {
+ this.readChildNodes(node, obj);
+ var attrs = node.attributes;
+ var SearchResults = {};
+ for(var i=0, len=attrs.length; i<len; ++i) {
+ if ((attrs[i].name == "numberOfRecordsMatched") ||
+ (attrs[i].name == "numberOfRecordsReturned") ||
+ (attrs[i].name == "nextRecord")) {
+ SearchResults[attrs[i].name] = parseInt(attrs[i].nodeValue);
+ } else {
+ SearchResults[attrs[i].name] = attrs[i].nodeValue;
+ }
+ }
+ obj.SearchResults = SearchResults;
+ },
+ "SummaryRecord": function(node, obj) {
+ var record = {type: "SummaryRecord"};
+ this.readChildNodes(node, record);
+ obj.records.push(record);
+ },
+ "BriefRecord": function(node, obj) {
+ var record = {type: "BriefRecord"};
+ this.readChildNodes(node, record);
+ obj.records.push(record);
+ },
+ "DCMIRecord": function(node, obj) {
+ var record = {type: "DCMIRecord"};
+ this.readChildNodes(node, record);
+ obj.records.push(record);
+ },
+ "Record": function(node, obj) {
+ var record = {type: "Record"};
+ this.readChildNodes(node, record);
+ obj.records.push(record);
+ },
+ "*": function(node, obj) {
+ var name = node.localName || node.nodeName.split(":").pop();
+ obj[name] = this.getChildValue(node);
+ }
+ },
+ "geonet": {
+ "info": function(node, obj) {
+ var gninfo = {};
+ this.readChildNodes(node, gninfo);
+ obj.gninfo = gninfo;
+ }
+ },
+ "dc": {
+ // audience, contributor, coverage, creator, date, description, format,
+ // identifier, language, provenance, publisher, relation, rights,
+ // rightsHolder, source, subject, title, type, URI
+ "*": function(node, obj) {
+ var name = node.localName || node.nodeName.split(":").pop();
+ if (!(OpenLayers.Util.isArray(obj[name]))) {
+ obj[name] = [];
+ }
+ var dc_element = {};
+ var attrs = node.attributes;
+ for(var i=0, len=attrs.length; i<len; ++i) {
+ dc_element[attrs[i].name] = attrs[i].nodeValue;
+ }
+ dc_element.value = this.getChildValue(node);
+ if (dc_element.value != "") {
+ obj[name].push(dc_element);
+ }
+ }
+ },
+ "dct": {
+ // abstract, modified, spatial
+ "*": function(node, obj) {
+ var name = node.localName || node.nodeName.split(":").pop();
+ if (!(OpenLayers.Util.isArray(obj[name]))) {
+ obj[name] = [];
+ }
+ obj[name].push(this.getChildValue(node));
+ }
+ },
+ "ows": OpenLayers.Util.applyDefaults({
+ "BoundingBox": function(node, obj) {
+ if (obj.bounds) {
+ obj.BoundingBox = [{crs: obj.projection, value:
+ [
+ obj.bounds.left,
+ obj.bounds.bottom,
+ obj.bounds.right,
+ obj.bounds.top
+ ]
+ }];
+ delete obj.projection;
+ delete obj.bounds;
+ }
+ OpenLayers.Format.OWSCommon.v1_0_0.prototype.readers["ows"]["BoundingBox"].apply(
+ this, arguments);
+ }
+ }, OpenLayers.Format.OWSCommon.v1_0_0.prototype.readers["ows"])
+ },
+
+ /**
+ * Method: write
+ * Given an configuration js object, write a CSWGetRecords request.
+ *
+ * Parameters:
+ * options - {Object} A object mapping the request.
+ *
+ * Returns:
+ * {String} A serialized CSWGetRecords request.
+ */
+ write: function(options) {
+ var node = this.writeNode("csw:GetRecords", options);
+ node.setAttribute("xmlns:gmd", this.namespaces.gmd);
+ return OpenLayers.Format.XML.prototype.write.apply(this, [node]);
+ },
+
+ /**
+ * Property: writers
+ * As a compliment to the readers property, this structure contains public
+ * writing functions grouped by namespace alias and named like the
+ * node names they produce.
+ */
+ writers: {
+ "csw": {
+ "GetRecords": function(options) {
+ if (!options) {
+ options = {};
+ }
+ var node = this.createElementNSPlus("csw:GetRecords", {
+ attributes: {
+ service: "CSW",
+ version: this.version,
+ requestId: options.requestId || this.requestId,
+ resultType: options.resultType || this.resultType,
+ outputFormat: options.outputFormat || this.outputFormat,
+ outputSchema: options.outputSchema || this.outputSchema,
+ startPosition: options.startPosition || this.startPosition,
+ maxRecords: options.maxRecords || this.maxRecords
+ }
+ });
+ if (options.DistributedSearch || this.DistributedSearch) {
+ this.writeNode(
+ "csw:DistributedSearch",
+ options.DistributedSearch || this.DistributedSearch,
+ node
+ );
+ }
+ var ResponseHandler = options.ResponseHandler || this.ResponseHandler;
+ if (OpenLayers.Util.isArray(ResponseHandler) && ResponseHandler.length > 0) {
+ // ResponseHandler must be a non-empty array
+ for(var i=0, len=ResponseHandler.length; i<len; i++) {
+ this.writeNode(
+ "csw:ResponseHandler",
+ ResponseHandler[i],
+ node
+ );
+ }
+ }
+ this.writeNode("Query", options.Query || this.Query, node);
+ return node;
+ },
+ "DistributedSearch": function(options) {
+ var node = this.createElementNSPlus("csw:DistributedSearch", {
+ attributes: {
+ hopCount: options.hopCount
+ }
+ });
+ return node;
+ },
+ "ResponseHandler": function(options) {
+ var node = this.createElementNSPlus("csw:ResponseHandler", {
+ value: options.value
+ });
+ return node;
+ },
+ "Query": function(options) {
+ if (!options) {
+ options = {};
+ }
+ var node = this.createElementNSPlus("csw:Query", {
+ attributes: {
+ typeNames: options.typeNames || "csw:Record"
+ }
+ });
+ var ElementName = options.ElementName;
+ if (OpenLayers.Util.isArray(ElementName) && ElementName.length > 0) {
+ // ElementName must be a non-empty array
+ for(var i=0, len=ElementName.length; i<len; i++) {
+ this.writeNode(
+ "csw:ElementName",
+ ElementName[i],
+ node
+ );
+ }
+ } else {
+ this.writeNode(
+ "csw:ElementSetName",
+ options.ElementSetName || {value: 'summary'},
+ node
+ );
+ }
+ if (options.Constraint) {
+ this.writeNode(
+ "csw:Constraint",
+ options.Constraint,
+ node
+ );
+ }
+ if (options.SortBy) {
+ this.writeNode(
+ "ogc:SortBy",
+ options.SortBy,
+ node
+ );
+ }
+ return node;
+ },
+ "ElementName": function(options) {
+ var node = this.createElementNSPlus("csw:ElementName", {
+ value: options.value
+ });
+ return node;
+ },
+ "ElementSetName": function(options) {
+ var node = this.createElementNSPlus("csw:ElementSetName", {
+ attributes: {
+ typeNames: options.typeNames
+ },
+ value: options.value
+ });
+ return node;
+ },
+ "Constraint": function(options) {
+ var node = this.createElementNSPlus("csw:Constraint", {
+ attributes: {
+ version: options.version
+ }
+ });
+ if (options.Filter) {
+ var format = new OpenLayers.Format.Filter({
+ version: options.version
+ });
+ node.appendChild(format.write(options.Filter));
+ } else if (options.CqlText) {
+ var child = this.createElementNSPlus("CqlText", {
+ value: options.CqlText.value
+ });
+ node.appendChild(child);
+ }
+ return node;
+ }
+ },
+ "ogc": OpenLayers.Format.Filter.v1_1_0.prototype.writers["ogc"]
+ },
+
+ CLASS_NAME: "OpenLayers.Format.CSWGetRecords.v2_0_2"
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/Context.js b/misc/openlayers/lib/OpenLayers/Format/Context.js
new file mode 100644
index 0000000..73d6203
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/Context.js
@@ -0,0 +1,334 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML/VersionedOGC.js
+ */
+
+/**
+ * Class: OpenLayers.Format.Context
+ * Base class for both Format.WMC and Format.OWSContext
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML.VersionedOGC>
+ */
+OpenLayers.Format.Context = OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC, {
+
+ /**
+ * Property: layerOptions
+ * {Object} Default options for layers created by the parser. These
+ * options are overridden by the options which are read from the
+ * capabilities document.
+ */
+ layerOptions: null,
+
+ /**
+ * Property: layerParams
+ * {Object} Default parameters for layers created by the parser. This
+ * can be used e.g. to override DEFAULT_PARAMS for
+ * OpenLayers.Layer.WMS.
+ */
+ layerParams: null,
+
+ /**
+ * Constructor: OpenLayers.Format.Context
+ * Create a new parser for Context documents.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * APIMethod: read
+ * Read Context data from a string, and return an object with map
+ * properties and a list of layers.
+ *
+ * Parameters:
+ * data - {String} or {DOMElement} data to read/parse.
+ * options - {Object} The options object must contain a map property. If
+ * the map property is a string, it must be the id of a dom element
+ * where the new map will be placed. If the map property is an
+ * <OpenLayers.Map>, the layers from the context document will be added
+ * to the map.
+ *
+ * Returns:
+ * {<OpenLayers.Map>} A map based on the context.
+ */
+ read: function(data, options) {
+ var context = OpenLayers.Format.XML.VersionedOGC.prototype.read.apply(this,
+ arguments);
+ var map;
+ if(options && options.map) {
+ this.context = context;
+ if(options.map instanceof OpenLayers.Map) {
+ map = this.mergeContextToMap(context, options.map);
+ } else {
+ var mapOptions = options.map;
+ if(OpenLayers.Util.isElement(mapOptions) ||
+ typeof mapOptions == "string") {
+ // we assume mapOptions references a div
+ // element
+ mapOptions = {div: mapOptions};
+ }
+ map = this.contextToMap(context, mapOptions);
+ }
+ } else {
+ // not documented as part of the API, provided as a non-API option
+ map = context;
+ }
+ return map;
+ },
+
+ /**
+ * Method: getLayerFromContext
+ * Create a WMS layer from a layerContext object.
+ *
+ * Parameters:
+ * layerContext - {Object} An object representing a WMS layer.
+ *
+ * Returns:
+ * {<OpenLayers.Layer.WMS>} A WMS layer.
+ */
+ getLayerFromContext: function(layerContext) {
+ var i, len;
+ // fill initial options object from layerContext
+ var options = {
+ queryable: layerContext.queryable, //keep queryable for api compatibility
+ visibility: layerContext.visibility,
+ maxExtent: layerContext.maxExtent,
+ metadata: OpenLayers.Util.applyDefaults(layerContext.metadata,
+ {styles: layerContext.styles,
+ formats: layerContext.formats,
+ "abstract": layerContext["abstract"],
+ dataURL: layerContext.dataURL
+ }),
+ numZoomLevels: layerContext.numZoomLevels,
+ units: layerContext.units,
+ isBaseLayer: layerContext.isBaseLayer,
+ opacity: layerContext.opacity,
+ displayInLayerSwitcher: layerContext.displayInLayerSwitcher,
+ singleTile: layerContext.singleTile,
+ tileSize: (layerContext.tileSize) ?
+ new OpenLayers.Size(
+ layerContext.tileSize.width,
+ layerContext.tileSize.height
+ ) : undefined,
+ minScale: layerContext.minScale || layerContext.maxScaleDenominator,
+ maxScale: layerContext.maxScale || layerContext.minScaleDenominator,
+ srs: layerContext.srs,
+ dimensions: layerContext.dimensions,
+ metadataURL: layerContext.metadataURL
+ };
+ if (this.layerOptions) {
+ OpenLayers.Util.applyDefaults(options, this.layerOptions);
+ }
+
+ var params = {
+ layers: layerContext.name,
+ transparent: layerContext.transparent,
+ version: layerContext.version
+ };
+ if (layerContext.formats && layerContext.formats.length>0) {
+ // set default value for params if current attribute is not positionned
+ params.format = layerContext.formats[0].value;
+ for (i=0, len=layerContext.formats.length; i<len; i++) {
+ var format = layerContext.formats[i];
+ if (format.current == true) {
+ params.format = format.value;
+ break;
+ }
+ }
+ }
+ if (layerContext.styles && layerContext.styles.length>0) {
+ for (i=0, len=layerContext.styles.length; i<len; i++) {
+ var style = layerContext.styles[i];
+ if (style.current == true) {
+ // three style types to consider
+ // 1) linked SLD
+ // 2) inline SLD
+ // 3) named style
+ if(style.href) {
+ params.sld = style.href;
+ } else if(style.body) {
+ params.sld_body = style.body;
+ } else {
+ params.styles = style.name;
+ }
+ break;
+ }
+ }
+ }
+ if (this.layerParams) {
+ OpenLayers.Util.applyDefaults(params, this.layerParams);
+ }
+
+ var layer = null;
+ var service = layerContext.service;
+ if (service == OpenLayers.Format.Context.serviceTypes.WFS) {
+ options.strategies = [new OpenLayers.Strategy.BBOX()];
+ options.protocol = new OpenLayers.Protocol.WFS({
+ url: layerContext.url,
+ // since we do not know featureNS, let the protocol
+ // determine it automagically using featurePrefix
+ featurePrefix: layerContext.name.split(":")[0],
+ featureType: layerContext.name.split(":").pop()
+ });
+ layer = new OpenLayers.Layer.Vector(
+ layerContext.title || layerContext.name,
+ options
+ );
+ } else if (service == OpenLayers.Format.Context.serviceTypes.KML) {
+ // use a vector layer with an HTTP Protcol and a Fixed strategy
+ options.strategies = [new OpenLayers.Strategy.Fixed()];
+ options.protocol = new OpenLayers.Protocol.HTTP({
+ url: layerContext.url,
+ format: new OpenLayers.Format.KML()
+ });
+ layer = new OpenLayers.Layer.Vector(
+ layerContext.title || layerContext.name,
+ options
+ );
+ } else if (service == OpenLayers.Format.Context.serviceTypes.GML) {
+ // use a vector layer with a HTTP Protocol and a Fixed strategy
+ options.strategies = [new OpenLayers.Strategy.Fixed()];
+ options.protocol = new OpenLayers.Protocol.HTTP({
+ url: layerContext.url,
+ format: new OpenLayers.Format.GML()
+ });
+ layer = new OpenLayers.Layer.Vector(
+ layerContext.title || layerContext.name,
+ options
+ );
+ } else if (layerContext.features) {
+ // inline GML or KML features
+ layer = new OpenLayers.Layer.Vector(
+ layerContext.title || layerContext.name,
+ options
+ );
+ layer.addFeatures(layerContext.features);
+ } else if (layerContext.categoryLayer !== true) {
+ layer = new OpenLayers.Layer.WMS(
+ layerContext.title || layerContext.name,
+ layerContext.url,
+ params,
+ options
+ );
+ }
+ return layer;
+ },
+
+ /**
+ * Method: getLayersFromContext
+ * Create an array of layers from an array of layerContext objects.
+ *
+ * Parameters:
+ * layersContext - {Array(Object)} An array of objects representing layers.
+ *
+ * Returns:
+ * {Array(<OpenLayers.Layer>)} An array of layers.
+ */
+ getLayersFromContext: function(layersContext) {
+ var layers = [];
+ for (var i=0, len=layersContext.length; i<len; i++) {
+ var layer = this.getLayerFromContext(layersContext[i]);
+ if (layer !== null) {
+ layers.push(layer);
+ }
+ }
+ return layers;
+ },
+
+ /**
+ * Method: contextToMap
+ * Create a map given a context object.
+ *
+ * Parameters:
+ * context - {Object} The context object.
+ * options - {Object} Default map options.
+ *
+ * Returns:
+ * {<OpenLayers.Map>} A map based on the context object.
+ */
+ contextToMap: function(context, options) {
+ options = OpenLayers.Util.applyDefaults({
+ maxExtent: context.maxExtent,
+ projection: context.projection,
+ units: context.units
+ }, options);
+
+ if (options.maxExtent) {
+ options.maxResolution =
+ options.maxExtent.getWidth() / OpenLayers.Map.TILE_WIDTH;
+ }
+
+ var metadata = {
+ contactInformation: context.contactInformation,
+ "abstract": context["abstract"],
+ keywords: context.keywords,
+ logo: context.logo,
+ descriptionURL: context.descriptionURL
+ };
+
+ options.metadata = metadata;
+
+ var map = new OpenLayers.Map(options);
+ map.addLayers(this.getLayersFromContext(context.layersContext));
+ map.setCenter(
+ context.bounds.getCenterLonLat(),
+ map.getZoomForExtent(context.bounds, true)
+ );
+ return map;
+ },
+
+ /**
+ * Method: mergeContextToMap
+ * Add layers from a context object to a map.
+ *
+ * Parameters:
+ * context - {Object} The context object.
+ * map - {<OpenLayers.Map>} The map.
+ *
+ * Returns:
+ * {<OpenLayers.Map>} The same map with layers added.
+ */
+ mergeContextToMap: function(context, map) {
+ map.addLayers(this.getLayersFromContext(context.layersContext));
+ return map;
+ },
+
+ /**
+ * APIMethod: write
+ * Write a context document given a map.
+ *
+ * Parameters:
+ * obj - {<OpenLayers.Map> | Object} A map or context object.
+ * options - {Object} Optional configuration object.
+ *
+ * Returns:
+ * {String} A context document string.
+ */
+ write: function(obj, options) {
+ obj = this.toContext(obj);
+ return OpenLayers.Format.XML.VersionedOGC.prototype.write.apply(this,
+ arguments);
+ },
+
+ CLASS_NAME: "OpenLayers.Format.Context"
+});
+
+/**
+ * Constant: OpenLayers.Format.Context.serviceTypes
+ * Enumeration for service types
+ */
+OpenLayers.Format.Context.serviceTypes = {
+ "WMS": "urn:ogc:serviceType:WMS",
+ "WFS": "urn:ogc:serviceType:WFS",
+ "WCS": "urn:ogc:serviceType:WCS",
+ "GML": "urn:ogc:serviceType:GML",
+ "SLD": "urn:ogc:serviceType:SLD",
+ "FES": "urn:ogc:serviceType:FES",
+ "KML": "urn:ogc:serviceType:KML"
+};
diff --git a/misc/openlayers/lib/OpenLayers/Format/EncodedPolyline.js b/misc/openlayers/lib/OpenLayers/Format/EncodedPolyline.js
new file mode 100644
index 0000000..e10e8b2
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/EncodedPolyline.js
@@ -0,0 +1,557 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format.js
+ * @requires OpenLayers/Feature/Vector.js
+ */
+
+/**
+ * Class: OpenLayers.Format.EncodedPolyline
+ * Class for reading and writing encoded polylines. Create a new instance
+ * with the <OpenLayers.Format.EncodedPolyline> constructor.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format>
+ */
+OpenLayers.Format.EncodedPolyline = OpenLayers.Class(OpenLayers.Format, {
+
+ /**
+ * APIProperty: geometryType
+ * {String} Geometry type to output. One of: linestring (default),
+ * linearring, point, multipoint or polygon. If the geometryType is
+ * point, only the first point of the string is returned.
+ */
+ geometryType: "linestring",
+
+ /**
+ * Constructor: OpenLayers.Format.EncodedPolyline
+ * Create a new parser for encoded polylines
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance
+ *
+ * Returns:
+ * {<OpenLayers.Format.EncodedPolyline>} A new encoded polylines parser.
+ */
+ initialize: function(options) {
+ OpenLayers.Format.prototype.initialize.apply(this, [options]);
+ },
+
+ /**
+ * APIMethod: read
+ * Deserialize an encoded polyline string and return a vector feature.
+ *
+ * Parameters:
+ * encoded - {String} An encoded polyline string
+ *
+ * Returns:
+ * {<OpenLayers.Feature.Vector>} A vector feature with a linestring.
+ */
+ read: function(encoded) {
+ var geomType;
+ if (this.geometryType == "linestring")
+ geomType = OpenLayers.Geometry.LineString;
+ else if (this.geometryType == "linearring")
+ geomType = OpenLayers.Geometry.LinearRing;
+ else if (this.geometryType == "multipoint")
+ geomType = OpenLayers.Geometry.MultiPoint;
+ else if (this.geometryType != "point" && this.geometryType != "polygon")
+ return null;
+
+ var flatPoints = this.decodeDeltas(encoded, 2);
+ var flatPointsLength = flatPoints.length;
+
+ var pointGeometries = [];
+ for (var i = 0; i + 1 < flatPointsLength;) {
+ var y = flatPoints[i++], x = flatPoints[i++];
+ pointGeometries.push(new OpenLayers.Geometry.Point(x, y));
+ }
+
+
+ if (this.geometryType == "point")
+ return new OpenLayers.Feature.Vector(
+ pointGeometries[0]
+ );
+
+ if (this.geometryType == "polygon")
+ return new OpenLayers.Feature.Vector(
+ new OpenLayers.Geometry.Polygon([
+ new OpenLayers.Geometry.LinearRing(pointGeometries)
+ ])
+ );
+
+ return new OpenLayers.Feature.Vector(
+ new geomType(pointGeometries)
+ );
+ },
+
+ /**
+ * APIMethod: decode
+ * Deserialize an encoded string and return an array of n-dimensional
+ * points.
+ *
+ * Parameters:
+ * encoded - {String} An encoded string
+ * dims - {int} The dimension of the points that are returned
+ *
+ * Returns:
+ * {Array(Array(int))} An array containing n-dimensional arrays of
+ * coordinates.
+ */
+ decode: function(encoded, dims, opt_factor) {
+ var factor = opt_factor || 1e5;
+ var flatPoints = this.decodeDeltas(encoded, dims, factor);
+ var flatPointsLength = flatPoints.length;
+
+ var points = [];
+ for (var i = 0; i + (dims - 1) < flatPointsLength;) {
+ var point = [];
+
+ for (var dim = 0; dim < dims; ++dim) {
+ point.push(flatPoints[i++])
+ }
+
+ points.push(point);
+ }
+
+ return points;
+ },
+
+ /**
+ * APIMethod: write
+ * Serialize a feature or array of features into a WKT string.
+ *
+ * Parameters:
+ * features - {<OpenLayers.Feature.Vector>|Array} A feature or array of
+ * features
+ *
+ * Returns:
+ * {String} The WKT string representation of the input geometries
+ */
+ write: function(features) {
+ var feature;
+ if (features.constructor == Array)
+ feature = features[0];
+ else
+ feature = features;
+
+ var geometry = feature.geometry;
+ var type = geometry.CLASS_NAME.split('.')[2].toLowerCase();
+
+ var pointGeometries;
+ if (type == "point")
+ pointGeometries = new Array(geometry);
+ else if (type == "linestring" ||
+ type == "linearring" ||
+ type == "multipoint")
+ pointGeometries = geometry.components;
+ else if (type == "polygon")
+ pointGeometries = geometry.components[0].components;
+ else
+ return null;
+
+ var flatPoints = [];
+
+ var pointGeometriesLength = pointGeometries.length;
+ for (var i = 0; i < pointGeometriesLength; ++i) {
+ var pointGeometry = pointGeometries[i];
+ flatPoints.push(pointGeometry.y);
+ flatPoints.push(pointGeometry.x);
+ }
+
+ return this.encodeDeltas(flatPoints, 2);
+ },
+
+ /**
+ * APIMethod: encode
+ * Serialize an array of n-dimensional points and return an encoded string
+ *
+ * Parameters:
+ * points - {Array(Array(int))} An array containing n-dimensional
+ * arrays of coordinates
+ * dims - {int} The dimension of the points that should be read
+ *
+ * Returns:
+ * {String} An encoded string
+ */
+ encode: function (points, dims, opt_factor) {
+ var factor = opt_factor || 1e5;
+ var flatPoints = [];
+
+ var pointsLength = points.length;
+ for (var i = 0; i < pointsLength; ++i) {
+ var point = points[i];
+
+ for (var dim = 0; dim < dims; ++dim) {
+ flatPoints.push(point[dim]);
+ }
+ }
+
+ return this.encodeDeltas(flatPoints, dims, factor);
+ },
+
+ /**
+ * APIMethod: encodeDeltas
+ * Encode a list of n-dimensional points and return an encoded string
+ *
+ * Attention: This function will modify the passed array!
+ *
+ * Parameters:
+ * numbers - {Array.<number>} A list of n-dimensional points.
+ * dimension - {number} The dimension of the points in the list.
+ * opt_factor - {number=} The factor by which the numbers will be
+ * multiplied. The remaining decimal places will get rounded away.
+ *
+ * Returns:
+ * {string} The encoded string.
+ */
+ encodeDeltas: function(numbers, dimension, opt_factor) {
+ var factor = opt_factor || 1e5;
+ var d;
+
+ var lastNumbers = new Array(dimension);
+ for (d = 0; d < dimension; ++d) {
+ lastNumbers[d] = 0;
+ }
+
+ var numbersLength = numbers.length;
+ for (var i = 0; i < numbersLength;) {
+ for (d = 0; d < dimension; ++d, ++i) {
+ var num = numbers[i];
+ var delta = num - lastNumbers[d];
+ lastNumbers[d] = num;
+
+ numbers[i] = delta;
+ }
+ }
+
+ return this.encodeFloats(numbers, factor);
+ },
+
+
+ /**
+ * APIMethod: decodeDeltas
+ * Decode a list of n-dimensional points from an encoded string
+ *
+ * Parameters:
+ * encoded - {string} An encoded string.
+ * dimension - {number} The dimension of the points in the encoded string.
+ * opt_factor - {number=} The factor by which the resulting numbers will
+ * be divided.
+ *
+ * Returns:
+ * {Array.<number>} A list of n-dimensional points.
+ */
+ decodeDeltas: function(encoded, dimension, opt_factor) {
+ var factor = opt_factor || 1e5;
+ var d;
+
+ var lastNumbers = new Array(dimension);
+ for (d = 0; d < dimension; ++d) {
+ lastNumbers[d] = 0;
+ }
+
+ var numbers = this.decodeFloats(encoded, factor);
+
+ var numbersLength = numbers.length;
+ for (var i = 0; i < numbersLength;) {
+ for (d = 0; d < dimension; ++d, ++i) {
+ lastNumbers[d] += numbers[i];
+
+ numbers[i] = lastNumbers[d];
+ }
+ }
+
+ return numbers;
+ },
+
+
+ /**
+ * APIMethod: encodeFloats
+ * Encode a list of floating point numbers and return an encoded string
+ *
+ * Attention: This function will modify the passed array!
+ *
+ * Parameters:
+ * numbers - {Array.<number>} A list of floating point numbers.
+ * opt_factor - {number=} The factor by which the numbers will be
+ * multiplied. The remaining decimal places will get rounded away.
+ *
+ * Returns:
+ * {string} The encoded string.
+ */
+ encodeFloats: function(numbers, opt_factor) {
+ var factor = opt_factor || 1e5;
+
+ var numbersLength = numbers.length;
+ for (var i = 0; i < numbersLength; ++i) {
+ numbers[i] = Math.round(numbers[i] * factor);
+ }
+
+ return this.encodeSignedIntegers(numbers);
+ },
+
+
+ /**
+ * APIMethod: decodeFloats
+ * Decode a list of floating point numbers from an encoded string
+ *
+ * Parameters:
+ * encoded - {string} An encoded string.
+ * opt_factor - {number=} The factor by which the result will be divided.
+ *
+ * Returns:
+ * {Array.<number>} A list of floating point numbers.
+ */
+ decodeFloats: function(encoded, opt_factor) {
+ var factor = opt_factor || 1e5;
+
+ var numbers = this.decodeSignedIntegers(encoded);
+
+ var numbersLength = numbers.length;
+ for (var i = 0; i < numbersLength; ++i) {
+ numbers[i] /= factor;
+ }
+
+ return numbers;
+ },
+
+
+ /**
+ * APIMethod: encodeSignedIntegers
+ * Encode a list of signed integers and return an encoded string
+ *
+ * Attention: This function will modify the passed array!
+ *
+ * Parameters:
+ * numbers - {Array.<number>} A list of signed integers.
+ *
+ * Returns:
+ * {string} The encoded string.
+ */
+ encodeSignedIntegers: function(numbers) {
+ var numbersLength = numbers.length;
+ for (var i = 0; i < numbersLength; ++i) {
+ var num = numbers[i];
+
+ var signedNum = num << 1;
+ if (num < 0) {
+ signedNum = ~(signedNum);
+ }
+
+ numbers[i] = signedNum;
+ }
+
+ return this.encodeUnsignedIntegers(numbers);
+ },
+
+
+ /**
+ * APIMethod: decodeSignedIntegers
+ * Decode a list of signed integers from an encoded string
+ *
+ * Parameters:
+ * encoded - {string} An encoded string.
+ *
+ * Returns:
+ * {Array.<number>} A list of signed integers.
+ */
+ decodeSignedIntegers: function(encoded) {
+ var numbers = this.decodeUnsignedIntegers(encoded);
+
+ var numbersLength = numbers.length;
+ for (var i = 0; i < numbersLength; ++i) {
+ var num = numbers[i];
+ numbers[i] = (num & 1) ? ~(num >> 1) : (num >> 1);
+ }
+
+ return numbers;
+ },
+
+
+ /**
+ * APIMethod: encodeUnsignedIntegers
+ * Encode a list of unsigned integers and return an encoded string
+ *
+ * Parameters:
+ * numbers - {Array.<number>} A list of unsigned integers.
+ *
+ * Returns:
+ * {string} The encoded string.
+ */
+ encodeUnsignedIntegers: function(numbers) {
+ var encoded = '';
+
+ var numbersLength = numbers.length;
+ for (var i = 0; i < numbersLength; ++i) {
+ encoded += this.encodeUnsignedInteger(numbers[i]);
+ }
+
+ return encoded;
+ },
+
+
+ /**
+ * APIMethod: decodeUnsignedIntegers
+ * Decode a list of unsigned integers from an encoded string
+ *
+ * Parameters:
+ * encoded - {string} An encoded string.
+ *
+ * Returns:
+ * {Array.<number>} A list of unsigned integers.
+ */
+ decodeUnsignedIntegers: function(encoded) {
+ var numbers = [];
+
+ var current = 0;
+ var shift = 0;
+
+ var encodedLength = encoded.length;
+ for (var i = 0; i < encodedLength; ++i) {
+ var b = encoded.charCodeAt(i) - 63;
+
+ current |= (b & 0x1f) << shift;
+
+ if (b < 0x20) {
+ numbers.push(current);
+ current = 0;
+ shift = 0;
+ } else {
+ shift += 5;
+ }
+ }
+
+ return numbers;
+ },
+
+
+ /**
+ * Method: encodeFloat
+ * Encode one single floating point number and return an encoded string
+ *
+ * Parameters:
+ * num - {number} Floating point number that should be encoded.
+ * opt_factor - {number=} The factor by which num will be multiplied.
+ * The remaining decimal places will get rounded away.
+ *
+ * Returns:
+ * {string} The encoded string.
+ */
+ encodeFloat: function(num, opt_factor) {
+ num = Math.round(num * (opt_factor || 1e5));
+ return this.encodeSignedInteger(num);
+ },
+
+
+ /**
+ * Method: decodeFloat
+ * Decode one single floating point number from an encoded string
+ *
+ * Parameters:
+ * encoded - {string} An encoded string.
+ * opt_factor - {number=} The factor by which the result will be divided.
+ *
+ * Returns:
+ * {number} The decoded floating point number.
+ */
+ decodeFloat: function(encoded, opt_factor) {
+ var result = this.decodeSignedInteger(encoded);
+ return result / (opt_factor || 1e5);
+ },
+
+
+ /**
+ * Method: encodeSignedInteger
+ * Encode one single signed integer and return an encoded string
+ *
+ * Parameters:
+ * num - {number} Signed integer that should be encoded.
+ *
+ * Returns:
+ * {string} The encoded string.
+ */
+ encodeSignedInteger: function(num) {
+ var signedNum = num << 1;
+ if (num < 0) {
+ signedNum = ~(signedNum);
+ }
+
+ return this.encodeUnsignedInteger(signedNum);
+ },
+
+
+ /**
+ * Method: decodeSignedInteger
+ * Decode one single signed integer from an encoded string
+ *
+ * Parameters:
+ * encoded - {string} An encoded string.
+ *
+ * Returns:
+ * {number} The decoded signed integer.
+ */
+ decodeSignedInteger: function(encoded) {
+ var result = this.decodeUnsignedInteger(encoded);
+ return ((result & 1) ? ~(result >> 1) : (result >> 1));
+ },
+
+
+ /**
+ * Method: encodeUnsignedInteger
+ * Encode one single unsigned integer and return an encoded string
+ *
+ * Parameters:
+ * num - {number} Unsigned integer that should be encoded.
+ *
+ * Returns:
+ * {string} The encoded string.
+ */
+ encodeUnsignedInteger: function(num) {
+ var value, encoded = '';
+ while (num >= 0x20) {
+ value = (0x20 | (num & 0x1f)) + 63;
+ encoded += (String.fromCharCode(value));
+ num >>= 5;
+ }
+ value = num + 63;
+ encoded += (String.fromCharCode(value));
+ return encoded;
+ },
+
+
+ /**
+ * Method: decodeUnsignedInteger
+ * Decode one single unsigned integer from an encoded string
+ *
+ * Parameters:
+ * encoded - {string} An encoded string.
+ *
+ * Returns:
+ * {number} The decoded unsigned integer.
+ */
+ decodeUnsignedInteger: function(encoded) {
+ var result = 0;
+ var shift = 0;
+
+ var encodedLength = encoded.length;
+ for (var i = 0; i < encodedLength; ++i) {
+ var b = encoded.charCodeAt(i) - 63;
+
+ result |= (b & 0x1f) << shift;
+
+ if (b < 0x20)
+ break;
+
+ shift += 5;
+ }
+
+ return result;
+ },
+
+ CLASS_NAME: "OpenLayers.Format.EncodedPolyline"
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/Filter.js b/misc/openlayers/lib/OpenLayers/Format/Filter.js
new file mode 100644
index 0000000..59c06a8
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/Filter.js
@@ -0,0 +1,53 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML/VersionedOGC.js
+ * @requires OpenLayers/Filter/FeatureId.js
+ * @requires OpenLayers/Filter/Logical.js
+ * @requires OpenLayers/Filter/Comparison.js
+ */
+
+/**
+ * Class: OpenLayers.Format.Filter
+ * Read/Write ogc:Filter. Create a new instance with the <OpenLayers.Format.Filter>
+ * constructor.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML.VersionedOGC>
+ */
+OpenLayers.Format.Filter = OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC, {
+
+ /**
+ * APIProperty: defaultVersion
+ * {String} Version number to assume if none found. Default is "1.0.0".
+ */
+ defaultVersion: "1.0.0",
+
+ /**
+ * APIMethod: write
+ * Write an ogc:Filter given a filter object.
+ *
+ * Parameters:
+ * filter - {<OpenLayers.Filter>} An filter.
+ * options - {Object} Optional configuration object.
+ *
+ * Returns:
+ * {Elment} An ogc:Filter element node.
+ */
+
+ /**
+ * APIMethod: read
+ * Read and Filter doc and return an object representing the Filter.
+ *
+ * Parameters:
+ * data - {String | DOMElement} Data to read.
+ *
+ * Returns:
+ * {<OpenLayers.Filter>} A filter object.
+ */
+
+ CLASS_NAME: "OpenLayers.Format.Filter"
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/Filter/v1.js b/misc/openlayers/lib/OpenLayers/Format/Filter/v1.js
new file mode 100644
index 0000000..539ec0f
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/Filter/v1.js
@@ -0,0 +1,504 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+/**
+ * @requires OpenLayers/Format/Filter.js
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Filter/Function.js
+ * @requires OpenLayers/BaseTypes/Date.js
+ */
+
+/**
+ * Class: OpenLayers.Format.Filter.v1
+ * Superclass for Filter version 1 parsers.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.Filter.v1 = OpenLayers.Class(OpenLayers.Format.XML, {
+
+ /**
+ * Property: namespaces
+ * {Object} Mapping of namespace aliases to namespace URIs.
+ */
+ namespaces: {
+ ogc: "http://www.opengis.net/ogc",
+ gml: "http://www.opengis.net/gml",
+ xlink: "http://www.w3.org/1999/xlink",
+ xsi: "http://www.w3.org/2001/XMLSchema-instance"
+ },
+
+ /**
+ * Property: defaultPrefix
+ */
+ defaultPrefix: "ogc",
+
+ /**
+ * Property: schemaLocation
+ * {String} Schema location for a particular minor version.
+ */
+ schemaLocation: null,
+
+ /**
+ * Constructor: OpenLayers.Format.Filter.v1
+ * Instances of this class are not created directly. Use the
+ * <OpenLayers.Format.Filter> constructor instead.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+ initialize: function(options) {
+ OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+ },
+
+ /**
+ * Method: read
+ *
+ * Parameters:
+ * data - {DOMElement} A Filter document element.
+ *
+ * Returns:
+ * {<OpenLayers.Filter>} A filter object.
+ */
+ read: function(data) {
+ var obj = {};
+ this.readers.ogc["Filter"].apply(this, [data, obj]);
+ return obj.filter;
+ },
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "ogc": {
+ "_expression": function(node) {
+ // only the simplest of ogc:expression handled
+ // "some text and an <PropertyName>attribute</PropertyName>"}
+ var obj, value = "";
+ for(var child=node.firstChild; child; child=child.nextSibling) {
+ switch(child.nodeType) {
+ case 1:
+ obj = this.readNode(child);
+ if (obj.property) {
+ value += "${" + obj.property + "}";
+ } else if (obj.value !== undefined) {
+ value += obj.value;
+ }
+ break;
+ case 3: // text node
+ case 4: // cdata section
+ value += child.nodeValue;
+ }
+ }
+ return value;
+ },
+ "Filter": function(node, parent) {
+ // Filters correspond to subclasses of OpenLayers.Filter.
+ // Since they contain information we don't persist, we
+ // create a temporary object and then pass on the filter
+ // (ogc:Filter) to the parent obj.
+ var obj = {
+ fids: [],
+ filters: []
+ };
+ this.readChildNodes(node, obj);
+ if(obj.fids.length > 0) {
+ parent.filter = new OpenLayers.Filter.FeatureId({
+ fids: obj.fids
+ });
+ } else if(obj.filters.length > 0) {
+ parent.filter = obj.filters[0];
+ }
+ },
+ "FeatureId": function(node, obj) {
+ var fid = node.getAttribute("fid");
+ if(fid) {
+ obj.fids.push(fid);
+ }
+ },
+ "And": function(node, obj) {
+ var filter = new OpenLayers.Filter.Logical({
+ type: OpenLayers.Filter.Logical.AND
+ });
+ this.readChildNodes(node, filter);
+ obj.filters.push(filter);
+ },
+ "Or": function(node, obj) {
+ var filter = new OpenLayers.Filter.Logical({
+ type: OpenLayers.Filter.Logical.OR
+ });
+ this.readChildNodes(node, filter);
+ obj.filters.push(filter);
+ },
+ "Not": function(node, obj) {
+ var filter = new OpenLayers.Filter.Logical({
+ type: OpenLayers.Filter.Logical.NOT
+ });
+ this.readChildNodes(node, filter);
+ obj.filters.push(filter);
+ },
+ "PropertyIsLessThan": function(node, obj) {
+ var filter = new OpenLayers.Filter.Comparison({
+ type: OpenLayers.Filter.Comparison.LESS_THAN
+ });
+ this.readChildNodes(node, filter);
+ obj.filters.push(filter);
+ },
+ "PropertyIsGreaterThan": function(node, obj) {
+ var filter = new OpenLayers.Filter.Comparison({
+ type: OpenLayers.Filter.Comparison.GREATER_THAN
+ });
+ this.readChildNodes(node, filter);
+ obj.filters.push(filter);
+ },
+ "PropertyIsLessThanOrEqualTo": function(node, obj) {
+ var filter = new OpenLayers.Filter.Comparison({
+ type: OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO
+ });
+ this.readChildNodes(node, filter);
+ obj.filters.push(filter);
+ },
+ "PropertyIsGreaterThanOrEqualTo": function(node, obj) {
+ var filter = new OpenLayers.Filter.Comparison({
+ type: OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO
+ });
+ this.readChildNodes(node, filter);
+ obj.filters.push(filter);
+ },
+ "PropertyIsBetween": function(node, obj) {
+ var filter = new OpenLayers.Filter.Comparison({
+ type: OpenLayers.Filter.Comparison.BETWEEN
+ });
+ this.readChildNodes(node, filter);
+ obj.filters.push(filter);
+ },
+ "Literal": function(node, obj) {
+ obj.value = OpenLayers.String.numericIf(
+ this.getChildValue(node), true);
+ },
+ "PropertyName": function(node, filter) {
+ filter.property = this.getChildValue(node);
+ },
+ "LowerBoundary": function(node, filter) {
+ filter.lowerBoundary = OpenLayers.String.numericIf(
+ this.readers.ogc._expression.call(this, node), true);
+ },
+ "UpperBoundary": function(node, filter) {
+ filter.upperBoundary = OpenLayers.String.numericIf(
+ this.readers.ogc._expression.call(this, node), true);
+ },
+ "Intersects": function(node, obj) {
+ this.readSpatial(node, obj, OpenLayers.Filter.Spatial.INTERSECTS);
+ },
+ "Within": function(node, obj) {
+ this.readSpatial(node, obj, OpenLayers.Filter.Spatial.WITHIN);
+ },
+ "Contains": function(node, obj) {
+ this.readSpatial(node, obj, OpenLayers.Filter.Spatial.CONTAINS);
+ },
+ "DWithin": function(node, obj) {
+ this.readSpatial(node, obj, OpenLayers.Filter.Spatial.DWITHIN);
+ },
+ "Distance": function(node, obj) {
+ obj.distance = parseInt(this.getChildValue(node));
+ obj.distanceUnits = node.getAttribute("units");
+ },
+ "Function": function(node, obj) {
+ //TODO write decoder for it
+ return;
+ },
+ "PropertyIsNull": function(node, obj) {
+ var filter = new OpenLayers.Filter.Comparison({
+ type: OpenLayers.Filter.Comparison.IS_NULL
+ });
+ this.readChildNodes(node, filter);
+ obj.filters.push(filter);
+ }
+ }
+ },
+
+ /**
+ * Method: readSpatial
+ *
+ * Read a {<OpenLayers.Filter.Spatial>} filter.
+ *
+ * Parameters:
+ * node - {DOMElement} A DOM element that contains an ogc:expression.
+ * obj - {Object} The target object.
+ * type - {String} One of the OpenLayers.Filter.Spatial.* constants.
+ *
+ * Returns:
+ * {<OpenLayers.Filter.Spatial>} The created filter.
+ */
+ readSpatial: function(node, obj, type) {
+ var filter = new OpenLayers.Filter.Spatial({
+ type: type
+ });
+ this.readChildNodes(node, filter);
+ filter.value = filter.components[0];
+ delete filter.components;
+ obj.filters.push(filter);
+ },
+
+ /**
+ * APIMethod: encodeLiteral
+ * Generates the string representation of a value for use in <Literal>
+ * elements. The default encoder writes Date values as ISO 8601
+ * strings.
+ *
+ * Parameters:
+ * value - {Object} Literal value to encode
+ *
+ * Returns:
+ * {String} String representation of the provided value.
+ */
+ encodeLiteral: function(value) {
+ if (value instanceof Date) {
+ value = OpenLayers.Date.toISOString(value);
+ }
+ return value;
+ },
+
+ /**
+ * Method: writeOgcExpression
+ * Limited support for writing OGC expressions. Currently it supports
+ * (<OpenLayers.Filter.Function> || String || Number)
+ *
+ * Parameters:
+ * value - (<OpenLayers.Filter.Function> || String || Number)
+ * node - {DOMElement} A parent DOM element
+ *
+ * Returns:
+ * {DOMElement} Updated node element.
+ */
+ writeOgcExpression: function(value, node) {
+ if (value instanceof OpenLayers.Filter.Function){
+ this.writeNode("Function", value, node);
+ } else {
+ this.writeNode("Literal", value, node);
+ }
+ return node;
+ },
+
+ /**
+ * Method: write
+ *
+ * Parameters:
+ * filter - {<OpenLayers.Filter>} A filter object.
+ *
+ * Returns:
+ * {DOMElement} An ogc:Filter element.
+ */
+ write: function(filter) {
+ return this.writers.ogc["Filter"].apply(this, [filter]);
+ },
+
+ /**
+ * Property: writers
+ * As a compliment to the readers property, this structure contains public
+ * writing functions grouped by namespace alias and named like the
+ * node names they produce.
+ */
+ writers: {
+ "ogc": {
+ "Filter": function(filter) {
+ var node = this.createElementNSPlus("ogc:Filter");
+ this.writeNode(this.getFilterType(filter), filter, node);
+ return node;
+ },
+ "_featureIds": function(filter) {
+ var node = this.createDocumentFragment();
+ for (var i=0, ii=filter.fids.length; i<ii; ++i) {
+ this.writeNode("ogc:FeatureId", filter.fids[i], node);
+ }
+ return node;
+ },
+ "FeatureId": function(fid) {
+ return this.createElementNSPlus("ogc:FeatureId", {
+ attributes: {fid: fid}
+ });
+ },
+ "And": function(filter) {
+ var node = this.createElementNSPlus("ogc:And");
+ var childFilter;
+ for (var i=0, ii=filter.filters.length; i<ii; ++i) {
+ childFilter = filter.filters[i];
+ this.writeNode(
+ this.getFilterType(childFilter), childFilter, node
+ );
+ }
+ return node;
+ },
+ "Or": function(filter) {
+ var node = this.createElementNSPlus("ogc:Or");
+ var childFilter;
+ for (var i=0, ii=filter.filters.length; i<ii; ++i) {
+ childFilter = filter.filters[i];
+ this.writeNode(
+ this.getFilterType(childFilter), childFilter, node
+ );
+ }
+ return node;
+ },
+ "Not": function(filter) {
+ var node = this.createElementNSPlus("ogc:Not");
+ var childFilter = filter.filters[0];
+ this.writeNode(
+ this.getFilterType(childFilter), childFilter, node
+ );
+ return node;
+ },
+ "PropertyIsLessThan": function(filter) {
+ var node = this.createElementNSPlus("ogc:PropertyIsLessThan");
+ // no ogc:expression handling for PropertyName for now
+ this.writeNode("PropertyName", filter, node);
+ // handle Literals or Functions for now
+ this.writeOgcExpression(filter.value, node);
+ return node;
+ },
+ "PropertyIsGreaterThan": function(filter) {
+ var node = this.createElementNSPlus("ogc:PropertyIsGreaterThan");
+ // no ogc:expression handling for PropertyName for now
+ this.writeNode("PropertyName", filter, node);
+ // handle Literals or Functions for now
+ this.writeOgcExpression(filter.value, node);
+ return node;
+ },
+ "PropertyIsLessThanOrEqualTo": function(filter) {
+ var node = this.createElementNSPlus("ogc:PropertyIsLessThanOrEqualTo");
+ // no ogc:expression handling for PropertyName for now
+ this.writeNode("PropertyName", filter, node);
+ // handle Literals or Functions for now
+ this.writeOgcExpression(filter.value, node);
+ return node;
+ },
+ "PropertyIsGreaterThanOrEqualTo": function(filter) {
+ var node = this.createElementNSPlus("ogc:PropertyIsGreaterThanOrEqualTo");
+ // no ogc:expression handling for PropertyName for now
+ this.writeNode("PropertyName", filter, node);
+ // handle Literals or Functions for now
+ this.writeOgcExpression(filter.value, node);
+ return node;
+ },
+ "PropertyIsBetween": function(filter) {
+ var node = this.createElementNSPlus("ogc:PropertyIsBetween");
+ // no ogc:expression handling for PropertyName for now
+ this.writeNode("PropertyName", filter, node);
+ this.writeNode("LowerBoundary", filter, node);
+ this.writeNode("UpperBoundary", filter, node);
+ return node;
+ },
+ "PropertyName": function(filter) {
+ // no ogc:expression handling for now
+ return this.createElementNSPlus("ogc:PropertyName", {
+ value: filter.property
+ });
+ },
+ "Literal": function(value) {
+ var encode = this.encodeLiteral ||
+ OpenLayers.Format.Filter.v1.prototype.encodeLiteral;
+ return this.createElementNSPlus("ogc:Literal", {
+ value: encode(value)
+ });
+ },
+ "LowerBoundary": function(filter) {
+ // handle Literals or Functions for now
+ var node = this.createElementNSPlus("ogc:LowerBoundary");
+ this.writeOgcExpression(filter.lowerBoundary, node);
+ return node;
+ },
+ "UpperBoundary": function(filter) {
+ // handle Literals or Functions for now
+ var node = this.createElementNSPlus("ogc:UpperBoundary");
+ this.writeNode("Literal", filter.upperBoundary, node);
+ return node;
+ },
+ "INTERSECTS": function(filter) {
+ return this.writeSpatial(filter, "Intersects");
+ },
+ "WITHIN": function(filter) {
+ return this.writeSpatial(filter, "Within");
+ },
+ "CONTAINS": function(filter) {
+ return this.writeSpatial(filter, "Contains");
+ },
+ "DWITHIN": function(filter) {
+ var node = this.writeSpatial(filter, "DWithin");
+ this.writeNode("Distance", filter, node);
+ return node;
+ },
+ "Distance": function(filter) {
+ return this.createElementNSPlus("ogc:Distance", {
+ attributes: {
+ units: filter.distanceUnits
+ },
+ value: filter.distance
+ });
+ },
+ "Function": function(filter) {
+ var node = this.createElementNSPlus("ogc:Function", {
+ attributes: {
+ name: filter.name
+ }
+ });
+ var params = filter.params;
+ for(var i=0, len=params.length; i<len; i++){
+ this.writeOgcExpression(params[i], node);
+ }
+ return node;
+ },
+ "PropertyIsNull": function(filter) {
+ var node = this.createElementNSPlus("ogc:PropertyIsNull");
+ this.writeNode("PropertyName", filter, node);
+ return node;
+ }
+ }
+ },
+
+ /**
+ * Method: getFilterType
+ */
+ getFilterType: function(filter) {
+ var filterType = this.filterMap[filter.type];
+ if(!filterType) {
+ throw "Filter writing not supported for rule type: " + filter.type;
+ }
+ return filterType;
+ },
+
+ /**
+ * Property: filterMap
+ * {Object} Contains a member for each filter type. Values are node names
+ * for corresponding OGC Filter child elements.
+ */
+ filterMap: {
+ "&&": "And",
+ "||": "Or",
+ "!": "Not",
+ "==": "PropertyIsEqualTo",
+ "!=": "PropertyIsNotEqualTo",
+ "<": "PropertyIsLessThan",
+ ">": "PropertyIsGreaterThan",
+ "<=": "PropertyIsLessThanOrEqualTo",
+ ">=": "PropertyIsGreaterThanOrEqualTo",
+ "..": "PropertyIsBetween",
+ "~": "PropertyIsLike",
+ "NULL": "PropertyIsNull",
+ "BBOX": "BBOX",
+ "DWITHIN": "DWITHIN",
+ "WITHIN": "WITHIN",
+ "CONTAINS": "CONTAINS",
+ "INTERSECTS": "INTERSECTS",
+ "FID": "_featureIds"
+ },
+
+ CLASS_NAME: "OpenLayers.Format.Filter.v1"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/Filter/v1_0_0.js b/misc/openlayers/lib/OpenLayers/Format/Filter/v1_0_0.js
new file mode 100644
index 0000000..52e650e
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/Filter/v1_0_0.js
@@ -0,0 +1,184 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/GML/v2.js
+ * @requires OpenLayers/Format/Filter/v1.js
+ */
+
+/**
+ * Class: OpenLayers.Format.Filter.v1_0_0
+ * Write ogc:Filter version 1.0.0.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.GML.v2>
+ * - <OpenLayers.Format.Filter.v1>
+ */
+OpenLayers.Format.Filter.v1_0_0 = OpenLayers.Class(
+ OpenLayers.Format.GML.v2, OpenLayers.Format.Filter.v1, {
+
+ /**
+ * Constant: VERSION
+ * {String} 1.0.0
+ */
+ VERSION: "1.0.0",
+
+ /**
+ * Property: schemaLocation
+ * {String} http://www.opengis.net/ogc/filter/1.0.0/filter.xsd
+ */
+ schemaLocation: "http://www.opengis.net/ogc/filter/1.0.0/filter.xsd",
+
+ /**
+ * Constructor: OpenLayers.Format.Filter.v1_0_0
+ * Instances of this class are not created directly. Use the
+ * <OpenLayers.Format.Filter> constructor instead.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+ initialize: function(options) {
+ OpenLayers.Format.GML.v2.prototype.initialize.apply(
+ this, [options]
+ );
+ },
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "ogc": OpenLayers.Util.applyDefaults({
+ "PropertyIsEqualTo": function(node, obj) {
+ var filter = new OpenLayers.Filter.Comparison({
+ type: OpenLayers.Filter.Comparison.EQUAL_TO
+ });
+ this.readChildNodes(node, filter);
+ obj.filters.push(filter);
+ },
+ "PropertyIsNotEqualTo": function(node, obj) {
+ var filter = new OpenLayers.Filter.Comparison({
+ type: OpenLayers.Filter.Comparison.NOT_EQUAL_TO
+ });
+ this.readChildNodes(node, filter);
+ obj.filters.push(filter);
+ },
+ "PropertyIsLike": function(node, obj) {
+ var filter = new OpenLayers.Filter.Comparison({
+ type: OpenLayers.Filter.Comparison.LIKE
+ });
+ this.readChildNodes(node, filter);
+ var wildCard = node.getAttribute("wildCard");
+ var singleChar = node.getAttribute("singleChar");
+ var esc = node.getAttribute("escape");
+ filter.value2regex(wildCard, singleChar, esc);
+ obj.filters.push(filter);
+ }
+ }, OpenLayers.Format.Filter.v1.prototype.readers["ogc"]),
+ "gml": OpenLayers.Format.GML.v2.prototype.readers["gml"],
+ "feature": OpenLayers.Format.GML.v2.prototype.readers["feature"]
+ },
+
+ /**
+ * Property: writers
+ * As a compliment to the readers property, this structure contains public
+ * writing functions grouped by namespace alias and named like the
+ * node names they produce.
+ */
+ writers: {
+ "ogc": OpenLayers.Util.applyDefaults({
+ "PropertyIsEqualTo": function(filter) {
+ var node = this.createElementNSPlus("ogc:PropertyIsEqualTo");
+ // no ogc:expression handling for PropertyName for now
+ this.writeNode("PropertyName", filter, node);
+ // handle Literals or Functions for now
+ this.writeOgcExpression(filter.value, node);
+ return node;
+ },
+ "PropertyIsNotEqualTo": function(filter) {
+ var node = this.createElementNSPlus("ogc:PropertyIsNotEqualTo");
+ // no ogc:expression handling for PropertyName for now
+ this.writeNode("PropertyName", filter, node);
+ // handle Literals or Functions for now
+ this.writeOgcExpression(filter.value, node);
+ return node;
+ },
+ "PropertyIsLike": function(filter) {
+ var node = this.createElementNSPlus("ogc:PropertyIsLike", {
+ attributes: {
+ wildCard: "*", singleChar: ".", escape: "!"
+ }
+ });
+ // no ogc:expression handling for now
+ this.writeNode("PropertyName", filter, node);
+ // convert regex string to ogc string
+ this.writeNode("Literal", filter.regex2value(), node);
+ return node;
+ },
+ "BBOX": function(filter) {
+ var node = this.createElementNSPlus("ogc:BBOX");
+ // PropertyName is mandatory in 1.0.0, but e.g. GeoServer also
+ // accepts filters without it. When this is used with
+ // OpenLayers.Protocol.WFS, OpenLayers.Format.WFST will set a
+ // missing filter.property to the geometryName that is
+ // configured with the protocol, which defaults to "the_geom".
+ // So the only way to omit this mandatory property is to not
+ // set the property on the filter and to set the geometryName
+ // on the WFS protocol to null. The latter also happens when
+ // the protocol is configured without a geometryName and a
+ // featureNS.
+ filter.property && this.writeNode("PropertyName", filter, node);
+ var box = this.writeNode("gml:Box", filter.value, node);
+ if(filter.projection) {
+ box.setAttribute("srsName", filter.projection);
+ }
+ return node;
+ }
+ }, OpenLayers.Format.Filter.v1.prototype.writers["ogc"]),
+ "gml": OpenLayers.Format.GML.v2.prototype.writers["gml"],
+ "feature": OpenLayers.Format.GML.v2.prototype.writers["feature"]
+ },
+
+ /**
+ * Method: writeSpatial
+ *
+ * Read a {<OpenLayers.Filter.Spatial>} filter and converts it into XML.
+ *
+ * Parameters:
+ * filter - {<OpenLayers.Filter.Spatial>} The filter.
+ * name - {String} Name of the generated XML element.
+ *
+ * Returns:
+ * {DOMElement} The created XML element.
+ */
+ writeSpatial: function(filter, name) {
+ var node = this.createElementNSPlus("ogc:"+name);
+ this.writeNode("PropertyName", filter, node);
+ if(filter.value instanceof OpenLayers.Filter.Function) {
+ this.writeNode("Function", filter.value, node);
+ } else {
+ var child;
+ if(filter.value instanceof OpenLayers.Geometry) {
+ child = this.writeNode("feature:_geometry", filter.value).firstChild;
+ } else {
+ child = this.writeNode("gml:Box", filter.value);
+ }
+ if(filter.projection) {
+ child.setAttribute("srsName", filter.projection);
+ }
+ node.appendChild(child);
+ }
+ return node;
+ },
+
+
+ CLASS_NAME: "OpenLayers.Format.Filter.v1_0_0"
+
+}); \ No newline at end of file
diff --git a/misc/openlayers/lib/OpenLayers/Format/Filter/v1_1_0.js b/misc/openlayers/lib/OpenLayers/Format/Filter/v1_1_0.js
new file mode 100644
index 0000000..628c489
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/Filter/v1_1_0.js
@@ -0,0 +1,222 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/Filter/v1.js
+ * @requires OpenLayers/Format/GML/v3.js
+ */
+
+/**
+ * Class: OpenLayers.Format.Filter.v1_1_0
+ * Write ogc:Filter version 1.1.0.
+ *
+ * Differences from the v1.0.0 parser:
+ * - uses GML v3 instead of GML v2
+ * - reads matchCase attribute on ogc:PropertyIsEqual and
+ * ogc:PropertyIsNotEqual elements.
+ * - writes matchCase attribute from comparison filters of type EQUAL_TO,
+ * NOT_EQUAL_TO and LIKE.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.GML.v3>
+ * - <OpenLayers.Format.Filter.v1>
+ */
+OpenLayers.Format.Filter.v1_1_0 = OpenLayers.Class(
+ OpenLayers.Format.GML.v3, OpenLayers.Format.Filter.v1, {
+
+ /**
+ * Constant: VERSION
+ * {String} 1.1.0
+ */
+ VERSION: "1.1.0",
+
+ /**
+ * Property: schemaLocation
+ * {String} http://www.opengis.net/ogc/filter/1.1.0/filter.xsd
+ */
+ schemaLocation: "http://www.opengis.net/ogc/filter/1.1.0/filter.xsd",
+
+ /**
+ * Constructor: OpenLayers.Format.Filter.v1_1_0
+ * Instances of this class are not created directly. Use the
+ * <OpenLayers.Format.Filter> constructor instead.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+ initialize: function(options) {
+ OpenLayers.Format.GML.v3.prototype.initialize.apply(
+ this, [options]
+ );
+ },
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "ogc": OpenLayers.Util.applyDefaults({
+ "PropertyIsEqualTo": function(node, obj) {
+ var matchCase = node.getAttribute("matchCase");
+ var filter = new OpenLayers.Filter.Comparison({
+ type: OpenLayers.Filter.Comparison.EQUAL_TO,
+ matchCase: !(matchCase === "false" || matchCase === "0")
+ });
+ this.readChildNodes(node, filter);
+ obj.filters.push(filter);
+ },
+ "PropertyIsNotEqualTo": function(node, obj) {
+ var matchCase = node.getAttribute("matchCase");
+ var filter = new OpenLayers.Filter.Comparison({
+ type: OpenLayers.Filter.Comparison.NOT_EQUAL_TO,
+ matchCase: !(matchCase === "false" || matchCase === "0")
+ });
+ this.readChildNodes(node, filter);
+ obj.filters.push(filter);
+ },
+ "PropertyIsLike": function(node, obj) {
+ var filter = new OpenLayers.Filter.Comparison({
+ type: OpenLayers.Filter.Comparison.LIKE
+ });
+ this.readChildNodes(node, filter);
+ var wildCard = node.getAttribute("wildCard");
+ var singleChar = node.getAttribute("singleChar");
+ var esc = node.getAttribute("escapeChar");
+ filter.value2regex(wildCard, singleChar, esc);
+ obj.filters.push(filter);
+ }
+ }, OpenLayers.Format.Filter.v1.prototype.readers["ogc"]),
+ "gml": OpenLayers.Format.GML.v3.prototype.readers["gml"],
+ "feature": OpenLayers.Format.GML.v3.prototype.readers["feature"]
+ },
+
+ /**
+ * Property: writers
+ * As a compliment to the readers property, this structure contains public
+ * writing functions grouped by namespace alias and named like the
+ * node names they produce.
+ */
+ writers: {
+ "ogc": OpenLayers.Util.applyDefaults({
+ "PropertyIsEqualTo": function(filter) {
+ var node = this.createElementNSPlus("ogc:PropertyIsEqualTo", {
+ attributes: {matchCase: filter.matchCase}
+ });
+ // no ogc:expression handling for PropertyName for now
+ this.writeNode("PropertyName", filter, node);
+ // handle Literals or Functions for now
+ this.writeOgcExpression(filter.value, node);
+ return node;
+ },
+ "PropertyIsNotEqualTo": function(filter) {
+ var node = this.createElementNSPlus("ogc:PropertyIsNotEqualTo", {
+ attributes: {matchCase: filter.matchCase}
+ });
+ // no ogc:expression handling for PropertyName for now
+ this.writeNode("PropertyName", filter, node);
+ // handle Literals or Functions for now
+ this.writeOgcExpression(filter.value, node);
+ return node;
+ },
+ "PropertyIsLike": function(filter) {
+ var node = this.createElementNSPlus("ogc:PropertyIsLike", {
+ attributes: {
+ matchCase: filter.matchCase,
+ wildCard: "*", singleChar: ".", escapeChar: "!"
+ }
+ });
+ // no ogc:expression handling for now
+ this.writeNode("PropertyName", filter, node);
+ // convert regex string to ogc string
+ this.writeNode("Literal", filter.regex2value(), node);
+ return node;
+ },
+ "BBOX": function(filter) {
+ var node = this.createElementNSPlus("ogc:BBOX");
+ // PropertyName is optional in 1.1.0
+ filter.property && this.writeNode("PropertyName", filter, node);
+ var box = this.writeNode("gml:Envelope", filter.value);
+ if(filter.projection) {
+ box.setAttribute("srsName", filter.projection);
+ }
+ node.appendChild(box);
+ return node;
+ },
+ "SortBy": function(sortProperties) {
+ var node = this.createElementNSPlus("ogc:SortBy");
+ for (var i=0,l=sortProperties.length;i<l;i++) {
+ this.writeNode(
+ "ogc:SortProperty",
+ sortProperties[i],
+ node
+ );
+ }
+ return node;
+ },
+ "SortProperty": function(sortProperty) {
+ var node = this.createElementNSPlus("ogc:SortProperty");
+ this.writeNode(
+ "ogc:PropertyName",
+ sortProperty,
+ node
+ );
+ this.writeNode(
+ "ogc:SortOrder",
+ (sortProperty.order == 'DESC') ? 'DESC' : 'ASC',
+ node
+ );
+ return node;
+ },
+ "SortOrder": function(value) {
+ var node = this.createElementNSPlus("ogc:SortOrder", {
+ value: value
+ });
+ return node;
+ }
+ }, OpenLayers.Format.Filter.v1.prototype.writers["ogc"]),
+ "gml": OpenLayers.Format.GML.v3.prototype.writers["gml"],
+ "feature": OpenLayers.Format.GML.v3.prototype.writers["feature"]
+ },
+
+ /**
+ * Method: writeSpatial
+ *
+ * Read a {<OpenLayers.Filter.Spatial>} filter and converts it into XML.
+ *
+ * Parameters:
+ * filter - {<OpenLayers.Filter.Spatial>} The filter.
+ * name - {String} Name of the generated XML element.
+ *
+ * Returns:
+ * {DOMElement} The created XML element.
+ */
+ writeSpatial: function(filter, name) {
+ var node = this.createElementNSPlus("ogc:"+name);
+ this.writeNode("PropertyName", filter, node);
+ if(filter.value instanceof OpenLayers.Filter.Function) {
+ this.writeNode("Function", filter.value, node);
+ } else {
+ var child;
+ if(filter.value instanceof OpenLayers.Geometry) {
+ child = this.writeNode("feature:_geometry", filter.value).firstChild;
+ } else {
+ child = this.writeNode("gml:Envelope", filter.value);
+ }
+ if(filter.projection) {
+ child.setAttribute("srsName", filter.projection);
+ }
+ node.appendChild(child);
+ }
+ return node;
+ },
+
+ CLASS_NAME: "OpenLayers.Format.Filter.v1_1_0"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/GML.js b/misc/openlayers/lib/OpenLayers/Format/GML.js
new file mode 100644
index 0000000..467f875
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/GML.js
@@ -0,0 +1,923 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Feature/Vector.js
+ * @requires OpenLayers/Geometry/Point.js
+ * @requires OpenLayers/Geometry/MultiPoint.js
+ * @requires OpenLayers/Geometry/LineString.js
+ * @requires OpenLayers/Geometry/MultiLineString.js
+ * @requires OpenLayers/Geometry/Polygon.js
+ * @requires OpenLayers/Geometry/MultiPolygon.js
+ */
+
+/**
+ * Class: OpenLayers.Format.GML
+ * Read/Write GML. Create a new instance with the <OpenLayers.Format.GML>
+ * constructor. Supports the GML simple features profile.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.GML = OpenLayers.Class(OpenLayers.Format.XML, {
+
+ /**
+ * APIProperty: featureNS
+ * {String} Namespace used for feature attributes. Default is
+ * "http://mapserver.gis.umn.edu/mapserver".
+ */
+ featureNS: "http://mapserver.gis.umn.edu/mapserver",
+
+ /**
+ * APIProperty: featurePrefix
+ * {String} Namespace alias (or prefix) for feature nodes. Default is
+ * "feature".
+ */
+ featurePrefix: "feature",
+
+ /**
+ * APIProperty: featureName
+ * {String} Element name for features. Default is "featureMember".
+ */
+ featureName: "featureMember",
+
+ /**
+ * APIProperty: layerName
+ * {String} Name of data layer. Default is "features".
+ */
+ layerName: "features",
+
+ /**
+ * APIProperty: geometryName
+ * {String} Name of geometry element. Defaults to "geometry".
+ */
+ geometryName: "geometry",
+
+ /**
+ * APIProperty: collectionName
+ * {String} Name of featureCollection element.
+ */
+ collectionName: "FeatureCollection",
+
+ /**
+ * APIProperty: gmlns
+ * {String} GML Namespace.
+ */
+ gmlns: "http://www.opengis.net/gml",
+
+ /**
+ * APIProperty: extractAttributes
+ * {Boolean} Extract attributes from GML.
+ */
+ extractAttributes: true,
+
+ /**
+ * APIProperty: xy
+ * {Boolean} Order of the GML coordinate true:(x,y) or false:(y,x)
+ * Changing is not recommended, a new Format should be instantiated.
+ */
+ xy: true,
+
+ /**
+ * Constructor: OpenLayers.Format.GML
+ * Create a new parser for GML.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+ initialize: function(options) {
+ // compile regular expressions once instead of every time they are used
+ this.regExes = {
+ trimSpace: (/^\s*|\s*$/g),
+ removeSpace: (/\s*/g),
+ splitSpace: (/\s+/),
+ trimComma: (/\s*,\s*/g)
+ };
+ OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+ },
+
+ /**
+ * APIMethod: read
+ * Read data from a string, and return a list of features.
+ *
+ * Parameters:
+ * data - {String} or {DOMElement} data to read/parse.
+ *
+ * Returns:
+ * {Array(<OpenLayers.Feature.Vector>)} An array of features.
+ */
+ read: function(data) {
+ if(typeof data == "string") {
+ data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+ }
+ var featureNodes = this.getElementsByTagNameNS(data.documentElement,
+ this.gmlns,
+ this.featureName);
+ var features = [];
+ for(var i=0; i<featureNodes.length; i++) {
+ var feature = this.parseFeature(featureNodes[i]);
+ if(feature) {
+ features.push(feature);
+ }
+ }
+ return features;
+ },
+
+ /**
+ * Method: parseFeature
+ * This function is the core of the GML parsing code in OpenLayers.
+ * It creates the geometries that are then attached to the returned
+ * feature, and calls parseAttributes() to get attribute data out.
+ *
+ * Parameters:
+ * node - {DOMElement} A GML feature node.
+ */
+ parseFeature: function(node) {
+ // only accept one geometry per feature - look for highest "order"
+ var order = ["MultiPolygon", "Polygon",
+ "MultiLineString", "LineString",
+ "MultiPoint", "Point", "Envelope"];
+ // FIXME: In case we parse a feature with no geometry, but boundedBy an Envelope,
+ // this code creates a geometry derived from the Envelope. This is not correct.
+ var type, nodeList, geometry, parser;
+ for(var i=0; i<order.length; ++i) {
+ type = order[i];
+ nodeList = this.getElementsByTagNameNS(node, this.gmlns, type);
+ if(nodeList.length > 0) {
+ // only deal with first geometry of this type
+ parser = this.parseGeometry[type.toLowerCase()];
+ if(parser) {
+ geometry = parser.apply(this, [nodeList[0]]);
+ if (this.internalProjection && this.externalProjection) {
+ geometry.transform(this.externalProjection,
+ this.internalProjection);
+ }
+ } else {
+ throw new TypeError("Unsupported geometry type: " + type);
+ }
+ // stop looking for different geometry types
+ break;
+ }
+ }
+
+ var bounds;
+ var boxNodes = this.getElementsByTagNameNS(node, this.gmlns, "Box");
+ for(i=0; i<boxNodes.length; ++i) {
+ var boxNode = boxNodes[i];
+ var box = this.parseGeometry["box"].apply(this, [boxNode]);
+ var parentNode = boxNode.parentNode;
+ var parentName = parentNode.localName ||
+ parentNode.nodeName.split(":").pop();
+ if(parentName === "boundedBy") {
+ bounds = box;
+ } else {
+ geometry = box.toGeometry();
+ }
+ }
+
+ // construct feature (optionally with attributes)
+ var attributes;
+ if(this.extractAttributes) {
+ attributes = this.parseAttributes(node);
+ }
+ var feature = new OpenLayers.Feature.Vector(geometry, attributes);
+ feature.bounds = bounds;
+
+ feature.gml = {
+ featureType: node.firstChild.nodeName.split(":")[1],
+ featureNS: node.firstChild.namespaceURI,
+ featureNSPrefix: node.firstChild.prefix
+ };
+
+ // assign fid - this can come from a "fid" or "id" attribute
+ var childNode = node.firstChild;
+ var fid;
+ while(childNode) {
+ if(childNode.nodeType == 1) {
+ fid = childNode.getAttribute("fid") ||
+ childNode.getAttribute("id");
+ if(fid) {
+ break;
+ }
+ }
+ childNode = childNode.nextSibling;
+ }
+ feature.fid = fid;
+ return feature;
+ },
+
+ /**
+ * Property: parseGeometry
+ * Properties of this object are the functions that parse geometries based
+ * on their type.
+ */
+ parseGeometry: {
+
+ /**
+ * Method: parseGeometry.point
+ * Given a GML node representing a point geometry, create an OpenLayers
+ * point geometry.
+ *
+ * Parameters:
+ * node - {DOMElement} A GML node.
+ *
+ * Returns:
+ * {<OpenLayers.Geometry.Point>} A point geometry.
+ */
+ point: function(node) {
+ /**
+ * Three coordinate variations to consider:
+ * 1) <gml:pos>x y z</gml:pos>
+ * 2) <gml:coordinates>x, y, z</gml:coordinates>
+ * 3) <gml:coord><gml:X>x</gml:X><gml:Y>y</gml:Y></gml:coord>
+ */
+ var nodeList, coordString;
+ var coords = [];
+
+ // look for <gml:pos>
+ var nodeList = this.getElementsByTagNameNS(node, this.gmlns, "pos");
+ if(nodeList.length > 0) {
+ coordString = nodeList[0].firstChild.nodeValue;
+ coordString = coordString.replace(this.regExes.trimSpace, "");
+ coords = coordString.split(this.regExes.splitSpace);
+ }
+
+ // look for <gml:coordinates>
+ if(coords.length == 0) {
+ nodeList = this.getElementsByTagNameNS(node, this.gmlns,
+ "coordinates");
+ if(nodeList.length > 0) {
+ coordString = nodeList[0].firstChild.nodeValue;
+ coordString = coordString.replace(this.regExes.removeSpace,
+ "");
+ coords = coordString.split(",");
+ }
+ }
+
+ // look for <gml:coord>
+ if(coords.length == 0) {
+ nodeList = this.getElementsByTagNameNS(node, this.gmlns,
+ "coord");
+ if(nodeList.length > 0) {
+ var xList = this.getElementsByTagNameNS(nodeList[0],
+ this.gmlns, "X");
+ var yList = this.getElementsByTagNameNS(nodeList[0],
+ this.gmlns, "Y");
+ if(xList.length > 0 && yList.length > 0) {
+ coords = [xList[0].firstChild.nodeValue,
+ yList[0].firstChild.nodeValue];
+ }
+ }
+ }
+
+ // preserve third dimension
+ if(coords.length == 2) {
+ coords[2] = null;
+ }
+
+ if (this.xy) {
+ return new OpenLayers.Geometry.Point(coords[0], coords[1],
+ coords[2]);
+ }
+ else{
+ return new OpenLayers.Geometry.Point(coords[1], coords[0],
+ coords[2]);
+ }
+ },
+
+ /**
+ * Method: parseGeometry.multipoint
+ * Given a GML node representing a multipoint geometry, create an
+ * OpenLayers multipoint geometry.
+ *
+ * Parameters:
+ * node - {DOMElement} A GML node.
+ *
+ * Returns:
+ * {<OpenLayers.Geometry.MultiPoint>} A multipoint geometry.
+ */
+ multipoint: function(node) {
+ var nodeList = this.getElementsByTagNameNS(node, this.gmlns,
+ "Point");
+ var components = [];
+ if(nodeList.length > 0) {
+ var point;
+ for(var i=0; i<nodeList.length; ++i) {
+ point = this.parseGeometry.point.apply(this, [nodeList[i]]);
+ if(point) {
+ components.push(point);
+ }
+ }
+ }
+ return new OpenLayers.Geometry.MultiPoint(components);
+ },
+
+ /**
+ * Method: parseGeometry.linestring
+ * Given a GML node representing a linestring geometry, create an
+ * OpenLayers linestring geometry.
+ *
+ * Parameters:
+ * node - {DOMElement} A GML node.
+ *
+ * Returns:
+ * {<OpenLayers.Geometry.LineString>} A linestring geometry.
+ */
+ linestring: function(node, ring) {
+ /**
+ * Two coordinate variations to consider:
+ * 1) <gml:posList dimension="d">x0 y0 z0 x1 y1 z1</gml:posList>
+ * 2) <gml:coordinates>x0, y0, z0 x1, y1, z1</gml:coordinates>
+ */
+ var nodeList, coordString;
+ var coords = [];
+ var points = [];
+
+ // look for <gml:posList>
+ nodeList = this.getElementsByTagNameNS(node, this.gmlns, "posList");
+ if(nodeList.length > 0) {
+ coordString = this.getChildValue(nodeList[0]);
+ coordString = coordString.replace(this.regExes.trimSpace, "");
+ coords = coordString.split(this.regExes.splitSpace);
+ var dim = parseInt(nodeList[0].getAttribute("dimension"));
+ var j, x, y, z;
+ for(var i=0; i<coords.length/dim; ++i) {
+ j = i * dim;
+ x = coords[j];
+ y = coords[j+1];
+ z = (dim == 2) ? null : coords[j+2];
+ if (this.xy) {
+ points.push(new OpenLayers.Geometry.Point(x, y, z));
+ } else {
+ points.push(new OpenLayers.Geometry.Point(y, x, z));
+ }
+ }
+ }
+
+ // look for <gml:coordinates>
+ if(coords.length == 0) {
+ nodeList = this.getElementsByTagNameNS(node, this.gmlns,
+ "coordinates");
+ if(nodeList.length > 0) {
+ coordString = this.getChildValue(nodeList[0]);
+ coordString = coordString.replace(this.regExes.trimSpace,
+ "");
+ coordString = coordString.replace(this.regExes.trimComma,
+ ",");
+ var pointList = coordString.split(this.regExes.splitSpace);
+ for(var i=0; i<pointList.length; ++i) {
+ coords = pointList[i].split(",");
+ if(coords.length == 2) {
+ coords[2] = null;
+ }
+ if (this.xy) {
+ points.push(new OpenLayers.Geometry.Point(coords[0],
+ coords[1],
+ coords[2]));
+ } else {
+ points.push(new OpenLayers.Geometry.Point(coords[1],
+ coords[0],
+ coords[2]));
+ }
+ }
+ }
+ }
+
+ var line = null;
+ if(points.length != 0) {
+ if(ring) {
+ line = new OpenLayers.Geometry.LinearRing(points);
+ } else {
+ line = new OpenLayers.Geometry.LineString(points);
+ }
+ }
+ return line;
+ },
+
+ /**
+ * Method: parseGeometry.multilinestring
+ * Given a GML node representing a multilinestring geometry, create an
+ * OpenLayers multilinestring geometry.
+ *
+ * Parameters:
+ * node - {DOMElement} A GML node.
+ *
+ * Returns:
+ * {<OpenLayers.Geometry.MultiLineString>} A multilinestring geometry.
+ */
+ multilinestring: function(node) {
+ var nodeList = this.getElementsByTagNameNS(node, this.gmlns,
+ "LineString");
+ var components = [];
+ if(nodeList.length > 0) {
+ var line;
+ for(var i=0; i<nodeList.length; ++i) {
+ line = this.parseGeometry.linestring.apply(this,
+ [nodeList[i]]);
+ if(line) {
+ components.push(line);
+ }
+ }
+ }
+ return new OpenLayers.Geometry.MultiLineString(components);
+ },
+
+ /**
+ * Method: parseGeometry.polygon
+ * Given a GML node representing a polygon geometry, create an
+ * OpenLayers polygon geometry.
+ *
+ * Parameters:
+ * node - {DOMElement} A GML node.
+ *
+ * Returns:
+ * {<OpenLayers.Geometry.Polygon>} A polygon geometry.
+ */
+ polygon: function(node) {
+ var nodeList = this.getElementsByTagNameNS(node, this.gmlns,
+ "LinearRing");
+ var components = [];
+ if(nodeList.length > 0) {
+ // this assumes exterior ring first, inner rings after
+ var ring;
+ for(var i=0; i<nodeList.length; ++i) {
+ ring = this.parseGeometry.linestring.apply(this,
+ [nodeList[i], true]);
+ if(ring) {
+ components.push(ring);
+ }
+ }
+ }
+ return new OpenLayers.Geometry.Polygon(components);
+ },
+
+ /**
+ * Method: parseGeometry.multipolygon
+ * Given a GML node representing a multipolygon geometry, create an
+ * OpenLayers multipolygon geometry.
+ *
+ * Parameters:
+ * node - {DOMElement} A GML node.
+ *
+ * Returns:
+ * {<OpenLayers.Geometry.MultiPolygon>} A multipolygon geometry.
+ */
+ multipolygon: function(node) {
+ var nodeList = this.getElementsByTagNameNS(node, this.gmlns,
+ "Polygon");
+ var components = [];
+ if(nodeList.length > 0) {
+ var polygon;
+ for(var i=0; i<nodeList.length; ++i) {
+ polygon = this.parseGeometry.polygon.apply(this,
+ [nodeList[i]]);
+ if(polygon) {
+ components.push(polygon);
+ }
+ }
+ }
+ return new OpenLayers.Geometry.MultiPolygon(components);
+ },
+
+ envelope: function(node) {
+ var components = [];
+ var coordString;
+ var envelope;
+
+ var lpoint = this.getElementsByTagNameNS(node, this.gmlns, "lowerCorner");
+ if (lpoint.length > 0) {
+ var coords = [];
+
+ if(lpoint.length > 0) {
+ coordString = lpoint[0].firstChild.nodeValue;
+ coordString = coordString.replace(this.regExes.trimSpace, "");
+ coords = coordString.split(this.regExes.splitSpace);
+ }
+
+ if(coords.length == 2) {
+ coords[2] = null;
+ }
+ if (this.xy) {
+ var lowerPoint = new OpenLayers.Geometry.Point(coords[0], coords[1],coords[2]);
+ } else {
+ var lowerPoint = new OpenLayers.Geometry.Point(coords[1], coords[0],coords[2]);
+ }
+ }
+
+ var upoint = this.getElementsByTagNameNS(node, this.gmlns, "upperCorner");
+ if (upoint.length > 0) {
+ var coords = [];
+
+ if(upoint.length > 0) {
+ coordString = upoint[0].firstChild.nodeValue;
+ coordString = coordString.replace(this.regExes.trimSpace, "");
+ coords = coordString.split(this.regExes.splitSpace);
+ }
+
+ if(coords.length == 2) {
+ coords[2] = null;
+ }
+ if (this.xy) {
+ var upperPoint = new OpenLayers.Geometry.Point(coords[0], coords[1],coords[2]);
+ } else {
+ var upperPoint = new OpenLayers.Geometry.Point(coords[1], coords[0],coords[2]);
+ }
+ }
+
+ if (lowerPoint && upperPoint) {
+ components.push(new OpenLayers.Geometry.Point(lowerPoint.x, lowerPoint.y));
+ components.push(new OpenLayers.Geometry.Point(upperPoint.x, lowerPoint.y));
+ components.push(new OpenLayers.Geometry.Point(upperPoint.x, upperPoint.y));
+ components.push(new OpenLayers.Geometry.Point(lowerPoint.x, upperPoint.y));
+ components.push(new OpenLayers.Geometry.Point(lowerPoint.x, lowerPoint.y));
+
+ var ring = new OpenLayers.Geometry.LinearRing(components);
+ envelope = new OpenLayers.Geometry.Polygon([ring]);
+ }
+ return envelope;
+ },
+
+ /**
+ * Method: parseGeometry.box
+ * Given a GML node representing a box geometry, create an
+ * OpenLayers.Bounds.
+ *
+ * Parameters:
+ * node - {DOMElement} A GML node.
+ *
+ * Returns:
+ * {<OpenLayers.Bounds>} A bounds representing the box.
+ */
+ box: function(node) {
+ var nodeList = this.getElementsByTagNameNS(node, this.gmlns,
+ "coordinates");
+ var coordString;
+ var coords, beginPoint = null, endPoint = null;
+ if (nodeList.length > 0) {
+ coordString = nodeList[0].firstChild.nodeValue;
+ coords = coordString.split(" ");
+ if (coords.length == 2) {
+ beginPoint = coords[0].split(",");
+ endPoint = coords[1].split(",");
+ }
+ }
+ if (beginPoint !== null && endPoint !== null) {
+ return new OpenLayers.Bounds(parseFloat(beginPoint[0]),
+ parseFloat(beginPoint[1]),
+ parseFloat(endPoint[0]),
+ parseFloat(endPoint[1]) );
+ }
+ }
+
+ },
+
+ /**
+ * Method: parseAttributes
+ *
+ * Parameters:
+ * node - {DOMElement}
+ *
+ * Returns:
+ * {Object} An attributes object.
+ */
+ parseAttributes: function(node) {
+ var attributes = {};
+ // assume attributes are children of the first type 1 child
+ var childNode = node.firstChild;
+ var children, i, child, grandchildren, grandchild, name, value;
+ while(childNode) {
+ if(childNode.nodeType == 1) {
+ // attributes are type 1 children with one type 3 child
+ children = childNode.childNodes;
+ for(i=0; i<children.length; ++i) {
+ child = children[i];
+ if(child.nodeType == 1) {
+ grandchildren = child.childNodes;
+ if(grandchildren.length == 1) {
+ grandchild = grandchildren[0];
+ if(grandchild.nodeType == 3 ||
+ grandchild.nodeType == 4) {
+ name = (child.prefix) ?
+ child.nodeName.split(":")[1] :
+ child.nodeName;
+ value = grandchild.nodeValue.replace(
+ this.regExes.trimSpace, "");
+ attributes[name] = value;
+ }
+ } else {
+ // If child has no childNodes (grandchildren),
+ // set an attribute with null value.
+ // e.g. <prefix:fieldname/> becomes
+ // {fieldname: null}
+ attributes[child.nodeName.split(":").pop()] = null;
+ }
+ }
+ }
+ break;
+ }
+ childNode = childNode.nextSibling;
+ }
+ return attributes;
+ },
+
+ /**
+ * APIMethod: write
+ * Generate a GML document string given a list of features.
+ *
+ * Parameters:
+ * features - {Array(<OpenLayers.Feature.Vector>)} List of features to
+ * serialize into a string.
+ *
+ * Returns:
+ * {String} A string representing the GML document.
+ */
+ write: function(features) {
+ if(!(OpenLayers.Util.isArray(features))) {
+ features = [features];
+ }
+ var gml = this.createElementNS("http://www.opengis.net/wfs",
+ "wfs:" + this.collectionName);
+ for(var i=0; i<features.length; i++) {
+ gml.appendChild(this.createFeatureXML(features[i]));
+ }
+ return OpenLayers.Format.XML.prototype.write.apply(this, [gml]);
+ },
+
+ /**
+ * Method: createFeatureXML
+ * Accept an OpenLayers.Feature.Vector, and build a GML node for it.
+ *
+ * Parameters:
+ * feature - {<OpenLayers.Feature.Vector>} The feature to be built as GML.
+ *
+ * Returns:
+ * {DOMElement} A node reprensting the feature in GML.
+ */
+ createFeatureXML: function(feature) {
+ var geometry = feature.geometry;
+ var geometryNode = this.buildGeometryNode(geometry);
+ var geomContainer = this.createElementNS(this.featureNS,
+ this.featurePrefix + ":" +
+ this.geometryName);
+ geomContainer.appendChild(geometryNode);
+ var featureNode = this.createElementNS(this.gmlns,
+ "gml:" + this.featureName);
+ var featureContainer = this.createElementNS(this.featureNS,
+ this.featurePrefix + ":" +
+ this.layerName);
+ var fid = feature.fid || feature.id;
+ featureContainer.setAttribute("fid", fid);
+ featureContainer.appendChild(geomContainer);
+ for(var attr in feature.attributes) {
+ var attrText = this.createTextNode(feature.attributes[attr]);
+ var nodename = attr.substring(attr.lastIndexOf(":") + 1);
+ var attrContainer = this.createElementNS(this.featureNS,
+ this.featurePrefix + ":" +
+ nodename);
+ attrContainer.appendChild(attrText);
+ featureContainer.appendChild(attrContainer);
+ }
+ featureNode.appendChild(featureContainer);
+ return featureNode;
+ },
+
+ /**
+ * APIMethod: buildGeometryNode
+ */
+ buildGeometryNode: function(geometry) {
+ if (this.externalProjection && this.internalProjection) {
+ geometry = geometry.clone();
+ geometry.transform(this.internalProjection,
+ this.externalProjection);
+ }
+ var className = geometry.CLASS_NAME;
+ var type = className.substring(className.lastIndexOf(".") + 1);
+ var builder = this.buildGeometry[type.toLowerCase()];
+ return builder.apply(this, [geometry]);
+ },
+
+ /**
+ * Property: buildGeometry
+ * Object containing methods to do the actual geometry node building
+ * based on geometry type.
+ */
+ buildGeometry: {
+ // TBD retrieve the srs from layer
+ // srsName is non-standard, so not including it until it's right.
+ // gml.setAttribute("srsName",
+ // "http://www.opengis.net/gml/srs/epsg.xml#4326");
+
+ /**
+ * Method: buildGeometry.point
+ * Given an OpenLayers point geometry, create a GML point.
+ *
+ * Parameters:
+ * geometry - {<OpenLayers.Geometry.Point>} A point geometry.
+ *
+ * Returns:
+ * {DOMElement} A GML point node.
+ */
+ point: function(geometry) {
+ var gml = this.createElementNS(this.gmlns, "gml:Point");
+ gml.appendChild(this.buildCoordinatesNode(geometry));
+ return gml;
+ },
+
+ /**
+ * Method: buildGeometry.multipoint
+ * Given an OpenLayers multipoint geometry, create a GML multipoint.
+ *
+ * Parameters:
+ * geometry - {<OpenLayers.Geometry.MultiPoint>} A multipoint geometry.
+ *
+ * Returns:
+ * {DOMElement} A GML multipoint node.
+ */
+ multipoint: function(geometry) {
+ var gml = this.createElementNS(this.gmlns, "gml:MultiPoint");
+ var points = geometry.components;
+ var pointMember, pointGeom;
+ for(var i=0; i<points.length; i++) {
+ pointMember = this.createElementNS(this.gmlns,
+ "gml:pointMember");
+ pointGeom = this.buildGeometry.point.apply(this,
+ [points[i]]);
+ pointMember.appendChild(pointGeom);
+ gml.appendChild(pointMember);
+ }
+ return gml;
+ },
+
+ /**
+ * Method: buildGeometry.linestring
+ * Given an OpenLayers linestring geometry, create a GML linestring.
+ *
+ * Parameters:
+ * geometry - {<OpenLayers.Geometry.LineString>} A linestring geometry.
+ *
+ * Returns:
+ * {DOMElement} A GML linestring node.
+ */
+ linestring: function(geometry) {
+ var gml = this.createElementNS(this.gmlns, "gml:LineString");
+ gml.appendChild(this.buildCoordinatesNode(geometry));
+ return gml;
+ },
+
+ /**
+ * Method: buildGeometry.multilinestring
+ * Given an OpenLayers multilinestring geometry, create a GML
+ * multilinestring.
+ *
+ * Parameters:
+ * geometry - {<OpenLayers.Geometry.MultiLineString>} A multilinestring
+ * geometry.
+ *
+ * Returns:
+ * {DOMElement} A GML multilinestring node.
+ */
+ multilinestring: function(geometry) {
+ var gml = this.createElementNS(this.gmlns, "gml:MultiLineString");
+ var lines = geometry.components;
+ var lineMember, lineGeom;
+ for(var i=0; i<lines.length; ++i) {
+ lineMember = this.createElementNS(this.gmlns,
+ "gml:lineStringMember");
+ lineGeom = this.buildGeometry.linestring.apply(this,
+ [lines[i]]);
+ lineMember.appendChild(lineGeom);
+ gml.appendChild(lineMember);
+ }
+ return gml;
+ },
+
+ /**
+ * Method: buildGeometry.linearring
+ * Given an OpenLayers linearring geometry, create a GML linearring.
+ *
+ * Parameters:
+ * geometry - {<OpenLayers.Geometry.LinearRing>} A linearring geometry.
+ *
+ * Returns:
+ * {DOMElement} A GML linearring node.
+ */
+ linearring: function(geometry) {
+ var gml = this.createElementNS(this.gmlns, "gml:LinearRing");
+ gml.appendChild(this.buildCoordinatesNode(geometry));
+ return gml;
+ },
+
+ /**
+ * Method: buildGeometry.polygon
+ * Given an OpenLayers polygon geometry, create a GML polygon.
+ *
+ * Parameters:
+ * geometry - {<OpenLayers.Geometry.Polygon>} A polygon geometry.
+ *
+ * Returns:
+ * {DOMElement} A GML polygon node.
+ */
+ polygon: function(geometry) {
+ var gml = this.createElementNS(this.gmlns, "gml:Polygon");
+ var rings = geometry.components;
+ var ringMember, ringGeom, type;
+ for(var i=0; i<rings.length; ++i) {
+ type = (i==0) ? "outerBoundaryIs" : "innerBoundaryIs";
+ ringMember = this.createElementNS(this.gmlns,
+ "gml:" + type);
+ ringGeom = this.buildGeometry.linearring.apply(this,
+ [rings[i]]);
+ ringMember.appendChild(ringGeom);
+ gml.appendChild(ringMember);
+ }
+ return gml;
+ },
+
+ /**
+ * Method: buildGeometry.multipolygon
+ * Given an OpenLayers multipolygon geometry, create a GML multipolygon.
+ *
+ * Parameters:
+ * geometry - {<OpenLayers.Geometry.MultiPolygon>} A multipolygon
+ * geometry.
+ *
+ * Returns:
+ * {DOMElement} A GML multipolygon node.
+ */
+ multipolygon: function(geometry) {
+ var gml = this.createElementNS(this.gmlns, "gml:MultiPolygon");
+ var polys = geometry.components;
+ var polyMember, polyGeom;
+ for(var i=0; i<polys.length; ++i) {
+ polyMember = this.createElementNS(this.gmlns,
+ "gml:polygonMember");
+ polyGeom = this.buildGeometry.polygon.apply(this,
+ [polys[i]]);
+ polyMember.appendChild(polyGeom);
+ gml.appendChild(polyMember);
+ }
+ return gml;
+
+ },
+
+ /**
+ * Method: buildGeometry.bounds
+ * Given an OpenLayers bounds, create a GML box.
+ *
+ * Parameters:
+ * bounds - {<OpenLayers.Geometry.Bounds>} A bounds object.
+ *
+ * Returns:
+ * {DOMElement} A GML box node.
+ */
+ bounds: function(bounds) {
+ var gml = this.createElementNS(this.gmlns, "gml:Box");
+ gml.appendChild(this.buildCoordinatesNode(bounds));
+ return gml;
+ }
+ },
+
+ /**
+ * Method: buildCoordinates
+ * builds the coordinates XmlNode
+ * (code)
+ * <gml:coordinates decimal="." cs="," ts=" ">...</gml:coordinates>
+ * (end)
+ *
+ * Parameters:
+ * geometry - {<OpenLayers.Geometry>}
+ *
+ * Returns:
+ * {XmlNode} created xmlNode
+ */
+ buildCoordinatesNode: function(geometry) {
+ var coordinatesNode = this.createElementNS(this.gmlns,
+ "gml:coordinates");
+ coordinatesNode.setAttribute("decimal", ".");
+ coordinatesNode.setAttribute("cs", ",");
+ coordinatesNode.setAttribute("ts", " ");
+
+ var parts = [];
+
+ if(geometry instanceof OpenLayers.Bounds){
+ parts.push(geometry.left + "," + geometry.bottom);
+ parts.push(geometry.right + "," + geometry.top);
+ } else {
+ var points = (geometry.components) ? geometry.components : [geometry];
+ for(var i=0; i<points.length; i++) {
+ parts.push(points[i].x + "," + points[i].y);
+ }
+ }
+
+ var txtNode = this.createTextNode(parts.join(" "));
+ coordinatesNode.appendChild(txtNode);
+
+ return coordinatesNode;
+ },
+
+ CLASS_NAME: "OpenLayers.Format.GML"
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/GML/Base.js b/misc/openlayers/lib/OpenLayers/Format/GML/Base.js
new file mode 100644
index 0000000..6c49969
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/GML/Base.js
@@ -0,0 +1,645 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Format/GML.js
+ */
+
+/**
+ * Though required in the full build, if the GML format is excluded, we set
+ * the namespace here.
+ */
+if(!OpenLayers.Format.GML) {
+ OpenLayers.Format.GML = {};
+}
+
+/**
+ * Class: OpenLayers.Format.GML.Base
+ * Superclass for GML parsers.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.GML.Base = OpenLayers.Class(OpenLayers.Format.XML, {
+
+ /**
+ * Property: namespaces
+ * {Object} Mapping of namespace aliases to namespace URIs.
+ */
+ namespaces: {
+ gml: "http://www.opengis.net/gml",
+ xlink: "http://www.w3.org/1999/xlink",
+ xsi: "http://www.w3.org/2001/XMLSchema-instance",
+ wfs: "http://www.opengis.net/wfs" // this is a convenience for reading wfs:FeatureCollection
+ },
+
+ /**
+ * Property: defaultPrefix
+ */
+ defaultPrefix: "gml",
+
+ /**
+ * Property: schemaLocation
+ * {String} Schema location for a particular minor version.
+ */
+ schemaLocation: null,
+
+ /**
+ * APIProperty: featureType
+ * {Array(String) or String} The local (without prefix) feature typeName(s).
+ */
+ featureType: null,
+
+ /**
+ * APIProperty: featureNS
+ * {String} The feature namespace. Must be set in the options at
+ * construction.
+ */
+ featureNS: null,
+
+ /**
+ * APIProperty: geometry
+ * {String} Name of geometry element. Defaults to "geometry". If null, it
+ * will be set on <read> when the first geometry is parsed.
+ */
+ geometryName: "geometry",
+
+ /**
+ * APIProperty: extractAttributes
+ * {Boolean} Extract attributes from GML. Default is true.
+ */
+ extractAttributes: true,
+
+ /**
+ * APIProperty: srsName
+ * {String} URI for spatial reference system. This is optional for
+ * single part geometries and mandatory for collections and multis.
+ * If set, the srsName attribute will be written for all geometries.
+ * Default is null.
+ */
+ srsName: null,
+
+ /**
+ * APIProperty: xy
+ * {Boolean} Order of the GML coordinate true:(x,y) or false:(y,x)
+ * Changing is not recommended, a new Format should be instantiated.
+ */
+ xy: true,
+
+ /**
+ * Property: geometryTypes
+ * {Object} Maps OpenLayers geometry class names to GML element names.
+ * Use <setGeometryTypes> before accessing this property.
+ */
+ geometryTypes: null,
+
+ /**
+ * Property: singleFeatureType
+ * {Boolean} True if there is only 1 featureType, and not an array
+ * of featuretypes.
+ */
+ singleFeatureType: null,
+
+ /**
+ * Property: autoConfig
+ * {Boolean} Indicates if the format was configured without a <featureNS>,
+ * but auto-configured <featureNS> and <featureType> during read.
+ * Subclasses making use of <featureType> auto-configuration should make
+ * the first call to the <readNode> method (usually in the read method)
+ * with true as 3rd argument, so the auto-configured featureType can be
+ * reset and the format can be reused for subsequent reads with data from
+ * different featureTypes. Set to false after read if you want to keep the
+ * auto-configured values.
+ */
+
+ /**
+ * Property: regExes
+ * Compiled regular expressions for manipulating strings.
+ */
+ regExes: {
+ trimSpace: (/^\s*|\s*$/g),
+ removeSpace: (/\s*/g),
+ splitSpace: (/\s+/),
+ trimComma: (/\s*,\s*/g),
+ featureMember: (/^(.*:)?featureMembers?$/)
+ },
+
+ /**
+ * Constructor: OpenLayers.Format.GML.Base
+ * Instances of this class are not created directly. Use the
+ * <OpenLayers.Format.GML.v2> or <OpenLayers.Format.GML.v3> constructor
+ * instead.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ *
+ * Valid options properties:
+ * featureType - {Array(String) or String} Local (without prefix) feature
+ * typeName(s) (required for write).
+ * featureNS - {String} Feature namespace (required for write).
+ * geometryName - {String} Geometry element name (required for write).
+ */
+ initialize: function(options) {
+ OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+ this.setGeometryTypes();
+ if(options && options.featureNS) {
+ this.setNamespace("feature", options.featureNS);
+ }
+ this.singleFeatureType = !options || (typeof options.featureType === "string");
+ },
+
+ /**
+ * Method: read
+ *
+ * Parameters:
+ * data - {DOMElement} A gml:featureMember element, a gml:featureMembers
+ * element, or an element containing either of the above at any level.
+ *
+ * Returns:
+ * {Array(<OpenLayers.Feature.Vector>)} An array of features.
+ */
+ read: function(data) {
+ if(typeof data == "string") {
+ data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+ }
+ if(data && data.nodeType == 9) {
+ data = data.documentElement;
+ }
+ var features = [];
+ this.readNode(data, {features: features}, true);
+ if(features.length == 0) {
+ // look for gml:featureMember elements
+ var elements = this.getElementsByTagNameNS(
+ data, this.namespaces.gml, "featureMember"
+ );
+ if(elements.length) {
+ for(var i=0, len=elements.length; i<len; ++i) {
+ this.readNode(elements[i], {features: features}, true);
+ }
+ } else {
+ // look for gml:featureMembers elements (this is v3, but does no harm here)
+ var elements = this.getElementsByTagNameNS(
+ data, this.namespaces.gml, "featureMembers"
+ );
+ if(elements.length) {
+ // there can be only one
+ this.readNode(elements[0], {features: features}, true);
+ }
+ }
+ }
+ return features;
+ },
+
+ /**
+ * Method: readNode
+ * Shorthand for applying one of the named readers given the node
+ * namespace and local name. Readers take two args (node, obj) and
+ * generally extend or modify the second.
+ *
+ * Parameters:
+ * node - {DOMElement} The node to be read (required).
+ * obj - {Object} The object to be modified (optional).
+ * first - {Boolean} Should be set to true for the first node read. This
+ * is usually the readNode call in the read method. Without this being
+ * set, auto-configured properties will stick on subsequent reads.
+ *
+ * Returns:
+ * {Object} The input object, modified (or a new one if none was provided).
+ */
+ readNode: function(node, obj, first) {
+ // on subsequent calls of format.read(), we want to reset auto-
+ // configured properties and auto-configure again.
+ if (first === true && this.autoConfig === true) {
+ this.featureType = null;
+ delete this.namespaceAlias[this.featureNS];
+ delete this.namespaces["feature"];
+ this.featureNS = null;
+ }
+ // featureType auto-configuration
+ if (!this.featureNS && (!(node.prefix in this.namespaces) &&
+ node.parentNode.namespaceURI == this.namespaces["gml"] &&
+ this.regExes.featureMember.test(node.parentNode.nodeName))) {
+ this.featureType = node.nodeName.split(":").pop();
+ this.setNamespace("feature", node.namespaceURI);
+ this.featureNS = node.namespaceURI;
+ this.autoConfig = true;
+ }
+ return OpenLayers.Format.XML.prototype.readNode.apply(this, [node, obj]);
+ },
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "gml": {
+ "_inherit": function(node, obj, container) {
+ // To be implemented by version specific parsers
+ },
+ "featureMember": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "featureMembers": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "name": function(node, obj) {
+ obj.name = this.getChildValue(node);
+ },
+ "boundedBy": function(node, obj) {
+ var container = {};
+ this.readChildNodes(node, container);
+ if(container.components && container.components.length > 0) {
+ obj.bounds = container.components[0];
+ }
+ },
+ "Point": function(node, container) {
+ var obj = {points: []};
+ this.readChildNodes(node, obj);
+ if(!container.components) {
+ container.components = [];
+ }
+ container.components.push(obj.points[0]);
+ },
+ "coordinates": function(node, obj) {
+ var str = this.getChildValue(node).replace(
+ this.regExes.trimSpace, ""
+ );
+ str = str.replace(this.regExes.trimComma, ",");
+ var pointList = str.split(this.regExes.splitSpace);
+ var coords;
+ var numPoints = pointList.length;
+ var points = new Array(numPoints);
+ for(var i=0; i<numPoints; ++i) {
+ coords = pointList[i].split(",");
+ if (this.xy) {
+ points[i] = new OpenLayers.Geometry.Point(
+ coords[0], coords[1], coords[2]
+ );
+ } else {
+ points[i] = new OpenLayers.Geometry.Point(
+ coords[1], coords[0], coords[2]
+ );
+ }
+ }
+ obj.points = points;
+ },
+ "coord": function(node, obj) {
+ var coord = {};
+ this.readChildNodes(node, coord);
+ if(!obj.points) {
+ obj.points = [];
+ }
+ obj.points.push(new OpenLayers.Geometry.Point(
+ coord.x, coord.y, coord.z
+ ));
+ },
+ "X": function(node, coord) {
+ coord.x = this.getChildValue(node);
+ },
+ "Y": function(node, coord) {
+ coord.y = this.getChildValue(node);
+ },
+ "Z": function(node, coord) {
+ coord.z = this.getChildValue(node);
+ },
+ "MultiPoint": function(node, container) {
+ var obj = {components: []};
+ this.readers.gml._inherit.apply(this, [node, obj, container]);
+ this.readChildNodes(node, obj);
+ container.components = [
+ new OpenLayers.Geometry.MultiPoint(obj.components)
+ ];
+ },
+ "pointMember": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "LineString": function(node, container) {
+ var obj = {};
+ this.readers.gml._inherit.apply(this, [node, obj, container]);
+ this.readChildNodes(node, obj);
+ if(!container.components) {
+ container.components = [];
+ }
+ container.components.push(
+ new OpenLayers.Geometry.LineString(obj.points)
+ );
+ },
+ "MultiLineString": function(node, container) {
+ var obj = {components: []};
+ this.readers.gml._inherit.apply(this, [node, obj, container]);
+ this.readChildNodes(node, obj);
+ container.components = [
+ new OpenLayers.Geometry.MultiLineString(obj.components)
+ ];
+ },
+ "lineStringMember": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "Polygon": function(node, container) {
+ var obj = {outer: null, inner: []};
+ this.readers.gml._inherit.apply(this, [node, obj, container]);
+ this.readChildNodes(node, obj);
+ obj.inner.unshift(obj.outer);
+ if(!container.components) {
+ container.components = [];
+ }
+ container.components.push(
+ new OpenLayers.Geometry.Polygon(obj.inner)
+ );
+ },
+ "LinearRing": function(node, obj) {
+ var container = {};
+ this.readers.gml._inherit.apply(this, [node, container]);
+ this.readChildNodes(node, container);
+ obj.components = [new OpenLayers.Geometry.LinearRing(
+ container.points
+ )];
+ },
+ "MultiPolygon": function(node, container) {
+ var obj = {components: []};
+ this.readers.gml._inherit.apply(this, [node, obj, container]);
+ this.readChildNodes(node, obj);
+ container.components = [
+ new OpenLayers.Geometry.MultiPolygon(obj.components)
+ ];
+ },
+ "polygonMember": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "GeometryCollection": function(node, container) {
+ var obj = {components: []};
+ this.readers.gml._inherit.apply(this, [node, obj, container]);
+ this.readChildNodes(node, obj);
+ container.components = [
+ new OpenLayers.Geometry.Collection(obj.components)
+ ];
+ },
+ "geometryMember": function(node, obj) {
+ this.readChildNodes(node, obj);
+ }
+ },
+ "feature": {
+ "*": function(node, obj) {
+ // The node can either be named like the featureType, or it
+ // can be a child of the feature:featureType. Children can be
+ // geometry or attributes.
+ var name;
+ var local = node.localName || node.nodeName.split(":").pop();
+ // Since an attribute can have the same name as the feature type
+ // we only want to read the node as a feature if the parent
+ // node can have feature nodes as children. In this case, the
+ // obj.features property is set.
+ if (obj.features) {
+ if (!this.singleFeatureType &&
+ (OpenLayers.Util.indexOf(this.featureType, local) !== -1)) {
+ name = "_typeName";
+ } else if(local === this.featureType) {
+ name = "_typeName";
+ }
+ } else {
+ // Assume attribute elements have one child node and that the child
+ // is a text node. Otherwise assume it is a geometry node.
+ if(node.childNodes.length == 0 ||
+ (node.childNodes.length == 1 && node.firstChild.nodeType == 3)) {
+ if(this.extractAttributes) {
+ name = "_attribute";
+ }
+ } else {
+ name = "_geometry";
+ }
+ }
+ if(name) {
+ this.readers.feature[name].apply(this, [node, obj]);
+ }
+ },
+ "_typeName": function(node, obj) {
+ var container = {components: [], attributes: {}};
+ this.readChildNodes(node, container);
+ // look for common gml namespaced elements
+ if(container.name) {
+ container.attributes.name = container.name;
+ }
+ var feature = new OpenLayers.Feature.Vector(
+ container.components[0], container.attributes
+ );
+ if (!this.singleFeatureType) {
+ feature.type = node.nodeName.split(":").pop();
+ feature.namespace = node.namespaceURI;
+ }
+ var fid = node.getAttribute("fid") ||
+ this.getAttributeNS(node, this.namespaces["gml"], "id");
+ if(fid) {
+ feature.fid = fid;
+ }
+ if(this.internalProjection && this.externalProjection &&
+ feature.geometry) {
+ feature.geometry.transform(
+ this.externalProjection, this.internalProjection
+ );
+ }
+ if(container.bounds) {
+ feature.bounds = container.bounds;
+ }
+ obj.features.push(feature);
+ },
+ "_geometry": function(node, obj) {
+ if (!this.geometryName) {
+ this.geometryName = node.nodeName.split(":").pop();
+ }
+ this.readChildNodes(node, obj);
+ },
+ "_attribute": function(node, obj) {
+ var local = node.localName || node.nodeName.split(":").pop();
+ var value = this.getChildValue(node);
+ obj.attributes[local] = value;
+ }
+ },
+ "wfs": {
+ "FeatureCollection": function(node, obj) {
+ this.readChildNodes(node, obj);
+ }
+ }
+ },
+
+ /**
+ * Method: write
+ *
+ * Parameters:
+ * features - {Array(<OpenLayers.Feature.Vector>) | OpenLayers.Feature.Vector}
+ * An array of features or a single feature.
+ *
+ * Returns:
+ * {String} Given an array of features, a doc with a gml:featureMembers
+ * element will be returned. Given a single feature, a doc with a
+ * gml:featureMember element will be returned.
+ */
+ write: function(features) {
+ var name;
+ if(OpenLayers.Util.isArray(features)) {
+ name = "featureMembers";
+ } else {
+ name = "featureMember";
+ }
+ var root = this.writeNode("gml:" + name, features);
+ this.setAttributeNS(
+ root, this.namespaces["xsi"],
+ "xsi:schemaLocation", this.schemaLocation
+ );
+
+ return OpenLayers.Format.XML.prototype.write.apply(this, [root]);
+ },
+
+ /**
+ * Property: writers
+ * As a compliment to the readers property, this structure contains public
+ * writing functions grouped by namespace alias and named like the
+ * node names they produce.
+ */
+ writers: {
+ "gml": {
+ "featureMember": function(feature) {
+ var node = this.createElementNSPlus("gml:featureMember");
+ this.writeNode("feature:_typeName", feature, node);
+ return node;
+ },
+ "MultiPoint": function(geometry) {
+ var node = this.createElementNSPlus("gml:MultiPoint");
+ var components = geometry.components || [geometry];
+ for(var i=0, ii=components.length; i<ii; ++i) {
+ this.writeNode("pointMember", components[i], node);
+ }
+ return node;
+ },
+ "pointMember": function(geometry) {
+ var node = this.createElementNSPlus("gml:pointMember");
+ this.writeNode("Point", geometry, node);
+ return node;
+ },
+ "MultiLineString": function(geometry) {
+ var node = this.createElementNSPlus("gml:MultiLineString");
+ var components = geometry.components || [geometry];
+ for(var i=0, ii=components.length; i<ii; ++i) {
+ this.writeNode("lineStringMember", components[i], node);
+ }
+ return node;
+ },
+ "lineStringMember": function(geometry) {
+ var node = this.createElementNSPlus("gml:lineStringMember");
+ this.writeNode("LineString", geometry, node);
+ return node;
+ },
+ "MultiPolygon": function(geometry) {
+ var node = this.createElementNSPlus("gml:MultiPolygon");
+ var components = geometry.components || [geometry];
+ for(var i=0, ii=components.length; i<ii; ++i) {
+ this.writeNode(
+ "polygonMember", components[i], node
+ );
+ }
+ return node;
+ },
+ "polygonMember": function(geometry) {
+ var node = this.createElementNSPlus("gml:polygonMember");
+ this.writeNode("Polygon", geometry, node);
+ return node;
+ },
+ "GeometryCollection": function(geometry) {
+ var node = this.createElementNSPlus("gml:GeometryCollection");
+ for(var i=0, len=geometry.components.length; i<len; ++i) {
+ this.writeNode("geometryMember", geometry.components[i], node);
+ }
+ return node;
+ },
+ "geometryMember": function(geometry) {
+ var node = this.createElementNSPlus("gml:geometryMember");
+ var child = this.writeNode("feature:_geometry", geometry);
+ node.appendChild(child.firstChild);
+ return node;
+ }
+ },
+ "feature": {
+ "_typeName": function(feature) {
+ var node = this.createElementNSPlus("feature:" + this.featureType, {
+ attributes: {fid: feature.fid}
+ });
+ if(feature.geometry) {
+ this.writeNode("feature:_geometry", feature.geometry, node);
+ }
+ for(var name in feature.attributes) {
+ var value = feature.attributes[name];
+ if(value != null) {
+ this.writeNode(
+ "feature:_attribute",
+ {name: name, value: value}, node
+ );
+ }
+ }
+ return node;
+ },
+ "_geometry": function(geometry) {
+ if(this.externalProjection && this.internalProjection) {
+ geometry = geometry.clone().transform(
+ this.internalProjection, this.externalProjection
+ );
+ }
+ var node = this.createElementNSPlus(
+ "feature:" + this.geometryName
+ );
+ var type = this.geometryTypes[geometry.CLASS_NAME];
+ var child = this.writeNode("gml:" + type, geometry, node);
+ if(this.srsName) {
+ child.setAttribute("srsName", this.srsName);
+ }
+ return node;
+ },
+ "_attribute": function(obj) {
+ return this.createElementNSPlus("feature:" + obj.name, {
+ value: obj.value
+ });
+ }
+ },
+ "wfs": {
+ "FeatureCollection": function(features) {
+ /**
+ * This is only here because GML2 only describes abstract
+ * feature collections. Typically, you would not be using
+ * the GML format to write wfs elements. This just provides
+ * some way to write out lists of features. GML3 defines the
+ * featureMembers element, so that is used by default instead.
+ */
+ var node = this.createElementNSPlus("wfs:FeatureCollection");
+ for(var i=0, len=features.length; i<len; ++i) {
+ this.writeNode("gml:featureMember", features[i], node);
+ }
+ return node;
+ }
+ }
+ },
+
+ /**
+ * Method: setGeometryTypes
+ * Sets the <geometryTypes> mapping.
+ */
+ setGeometryTypes: function() {
+ this.geometryTypes = {
+ "OpenLayers.Geometry.Point": "Point",
+ "OpenLayers.Geometry.MultiPoint": "MultiPoint",
+ "OpenLayers.Geometry.LineString": "LineString",
+ "OpenLayers.Geometry.MultiLineString": "MultiLineString",
+ "OpenLayers.Geometry.Polygon": "Polygon",
+ "OpenLayers.Geometry.MultiPolygon": "MultiPolygon",
+ "OpenLayers.Geometry.Collection": "GeometryCollection"
+ };
+ },
+
+ CLASS_NAME: "OpenLayers.Format.GML.Base"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/GML/v2.js b/misc/openlayers/lib/OpenLayers/Format/GML/v2.js
new file mode 100644
index 0000000..bd26b99
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/GML/v2.js
@@ -0,0 +1,193 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/GML/Base.js
+ */
+
+/**
+ * Class: OpenLayers.Format.GML.v2
+ * Parses GML version 2.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.GML.Base>
+ */
+OpenLayers.Format.GML.v2 = OpenLayers.Class(OpenLayers.Format.GML.Base, {
+
+ /**
+ * Property: schemaLocation
+ * {String} Schema location for a particular minor version.
+ */
+ schemaLocation: "http://www.opengis.net/gml http://schemas.opengis.net/gml/2.1.2/feature.xsd",
+
+ /**
+ * Constructor: OpenLayers.Format.GML.v2
+ * Create a parser for GML v2.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ *
+ * Valid options properties:
+ * featureType - {String} Local (without prefix) feature typeName (required).
+ * featureNS - {String} Feature namespace (required).
+ * geometryName - {String} Geometry element name.
+ */
+ initialize: function(options) {
+ OpenLayers.Format.GML.Base.prototype.initialize.apply(this, [options]);
+ },
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "gml": OpenLayers.Util.applyDefaults({
+ "outerBoundaryIs": function(node, container) {
+ var obj = {};
+ this.readChildNodes(node, obj);
+ container.outer = obj.components[0];
+ },
+ "innerBoundaryIs": function(node, container) {
+ var obj = {};
+ this.readChildNodes(node, obj);
+ container.inner.push(obj.components[0]);
+ },
+ "Box": function(node, container) {
+ var obj = {};
+ this.readChildNodes(node, obj);
+ if(!container.components) {
+ container.components = [];
+ }
+ var min = obj.points[0];
+ var max = obj.points[1];
+ container.components.push(
+ new OpenLayers.Bounds(min.x, min.y, max.x, max.y)
+ );
+ }
+ }, OpenLayers.Format.GML.Base.prototype.readers["gml"]),
+ "feature": OpenLayers.Format.GML.Base.prototype.readers["feature"],
+ "wfs": OpenLayers.Format.GML.Base.prototype.readers["wfs"]
+ },
+
+ /**
+ * Method: write
+ *
+ * Parameters:
+ * features - {Array(<OpenLayers.Feature.Vector>) | OpenLayers.Feature.Vector}
+ * An array of features or a single feature.
+ *
+ * Returns:
+ * {String} Given an array of features, a doc with a gml:featureMembers
+ * element will be returned. Given a single feature, a doc with a
+ * gml:featureMember element will be returned.
+ */
+ write: function(features) {
+ var name;
+ if(OpenLayers.Util.isArray(features)) {
+ // GML2 only has abstract feature collections
+ // wfs provides a feature collection from a well-known schema
+ name = "wfs:FeatureCollection";
+ } else {
+ name = "gml:featureMember";
+ }
+ var root = this.writeNode(name, features);
+ this.setAttributeNS(
+ root, this.namespaces["xsi"],
+ "xsi:schemaLocation", this.schemaLocation
+ );
+
+ return OpenLayers.Format.XML.prototype.write.apply(this, [root]);
+ },
+
+ /**
+ * Property: writers
+ * As a compliment to the readers property, this structure contains public
+ * writing functions grouped by namespace alias and named like the
+ * node names they produce.
+ */
+ writers: {
+ "gml": OpenLayers.Util.applyDefaults({
+ "Point": function(geometry) {
+ var node = this.createElementNSPlus("gml:Point");
+ this.writeNode("coordinates", [geometry], node);
+ return node;
+ },
+ "coordinates": function(points) {
+ var numPoints = points.length;
+ var parts = new Array(numPoints);
+ var point;
+ for(var i=0; i<numPoints; ++i) {
+ point = points[i];
+ if(this.xy) {
+ parts[i] = point.x + "," + point.y;
+ } else {
+ parts[i] = point.y + "," + point.x;
+ }
+ if(point.z != undefined) { // allow null or undefined
+ parts[i] += "," + point.z;
+ }
+ }
+ return this.createElementNSPlus("gml:coordinates", {
+ attributes: {
+ decimal: ".", cs: ",", ts: " "
+ },
+ value: (numPoints == 1) ? parts[0] : parts.join(" ")
+ });
+ },
+ "LineString": function(geometry) {
+ var node = this.createElementNSPlus("gml:LineString");
+ this.writeNode("coordinates", geometry.components, node);
+ return node;
+ },
+ "Polygon": function(geometry) {
+ var node = this.createElementNSPlus("gml:Polygon");
+ this.writeNode("outerBoundaryIs", geometry.components[0], node);
+ for(var i=1; i<geometry.components.length; ++i) {
+ this.writeNode(
+ "innerBoundaryIs", geometry.components[i], node
+ );
+ }
+ return node;
+ },
+ "outerBoundaryIs": function(ring) {
+ var node = this.createElementNSPlus("gml:outerBoundaryIs");
+ this.writeNode("LinearRing", ring, node);
+ return node;
+ },
+ "innerBoundaryIs": function(ring) {
+ var node = this.createElementNSPlus("gml:innerBoundaryIs");
+ this.writeNode("LinearRing", ring, node);
+ return node;
+ },
+ "LinearRing": function(ring) {
+ var node = this.createElementNSPlus("gml:LinearRing");
+ this.writeNode("coordinates", ring.components, node);
+ return node;
+ },
+ "Box": function(bounds) {
+ var node = this.createElementNSPlus("gml:Box");
+ this.writeNode("coordinates", [
+ {x: bounds.left, y: bounds.bottom},
+ {x: bounds.right, y: bounds.top}
+ ], node);
+ // srsName attribute is optional for gml:Box
+ if(this.srsName) {
+ node.setAttribute("srsName", this.srsName);
+ }
+ return node;
+ }
+ }, OpenLayers.Format.GML.Base.prototype.writers["gml"]),
+ "feature": OpenLayers.Format.GML.Base.prototype.writers["feature"],
+ "wfs": OpenLayers.Format.GML.Base.prototype.writers["wfs"]
+ },
+
+ CLASS_NAME: "OpenLayers.Format.GML.v2"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/GML/v3.js b/misc/openlayers/lib/OpenLayers/Format/GML/v3.js
new file mode 100644
index 0000000..82c7b1e
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/GML/v3.js
@@ -0,0 +1,477 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/GML/Base.js
+ */
+
+/**
+ * Class: OpenLayers.Format.GML.v3
+ * Parses GML version 3.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.GML.Base>
+ */
+OpenLayers.Format.GML.v3 = OpenLayers.Class(OpenLayers.Format.GML.Base, {
+
+ /**
+ * Property: schemaLocation
+ * {String} Schema location for a particular minor version. The writers
+ * conform with the Simple Features Profile for GML.
+ */
+ schemaLocation: "http://www.opengis.net/gml http://schemas.opengis.net/gml/3.1.1/profiles/gmlsfProfile/1.0.0/gmlsf.xsd",
+
+ /**
+ * Property: curve
+ * {Boolean} Write gml:Curve instead of gml:LineString elements. This also
+ * affects the elements in multi-part geometries. Default is false.
+ * To write gml:Curve elements instead of gml:LineString, set curve
+ * to true in the options to the contstructor (cannot be changed after
+ * instantiation).
+ */
+ curve: false,
+
+ /**
+ * Property: multiCurve
+ * {Boolean} Write gml:MultiCurve instead of gml:MultiLineString. Since
+ * the latter is deprecated in GML 3, the default is true. To write
+ * gml:MultiLineString instead of gml:MultiCurve, set multiCurve to
+ * false in the options to the constructor (cannot be changed after
+ * instantiation).
+ */
+ multiCurve: true,
+
+ /**
+ * Property: surface
+ * {Boolean} Write gml:Surface instead of gml:Polygon elements. This also
+ * affects the elements in multi-part geometries. Default is false.
+ * To write gml:Surface elements instead of gml:Polygon, set surface
+ * to true in the options to the contstructor (cannot be changed after
+ * instantiation).
+ */
+ surface: false,
+
+ /**
+ * Property: multiSurface
+ * {Boolean} Write gml:multiSurface instead of gml:MultiPolygon. Since
+ * the latter is deprecated in GML 3, the default is true. To write
+ * gml:MultiPolygon instead of gml:multiSurface, set multiSurface to
+ * false in the options to the constructor (cannot be changed after
+ * instantiation).
+ */
+ multiSurface: true,
+
+ /**
+ * Constructor: OpenLayers.Format.GML.v3
+ * Create a parser for GML v3.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ *
+ * Valid options properties:
+ * featureType - {String} Local (without prefix) feature typeName (required).
+ * featureNS - {String} Feature namespace (required).
+ * geometryName - {String} Geometry element name.
+ */
+ initialize: function(options) {
+ OpenLayers.Format.GML.Base.prototype.initialize.apply(this, [options]);
+ },
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "gml": OpenLayers.Util.applyDefaults({
+ "_inherit": function(node, obj, container) {
+ // SRSReferenceGroup attributes
+ var dim = parseInt(node.getAttribute("srsDimension"), 10) ||
+ (container && container.srsDimension);
+ if (dim) {
+ obj.srsDimension = dim;
+ }
+ },
+ "featureMembers": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "Curve": function(node, container) {
+ var obj = {points: []};
+ this.readers.gml._inherit.apply(this, [node, obj, container]);
+ this.readChildNodes(node, obj);
+ if(!container.components) {
+ container.components = [];
+ }
+ container.components.push(
+ new OpenLayers.Geometry.LineString(obj.points)
+ );
+ },
+ "segments": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "LineStringSegment": function(node, container) {
+ var obj = {};
+ this.readChildNodes(node, obj);
+ if(obj.points) {
+ Array.prototype.push.apply(container.points, obj.points);
+ }
+ },
+ "pos": function(node, obj) {
+ var str = this.getChildValue(node).replace(
+ this.regExes.trimSpace, ""
+ );
+ var coords = str.split(this.regExes.splitSpace);
+ var point;
+ if(this.xy) {
+ point = new OpenLayers.Geometry.Point(
+ coords[0], coords[1], coords[2]
+ );
+ } else {
+ point = new OpenLayers.Geometry.Point(
+ coords[1], coords[0], coords[2]
+ );
+ }
+ obj.points = [point];
+ },
+ "posList": function(node, obj) {
+ var str = this.getChildValue(node).replace(
+ this.regExes.trimSpace, ""
+ );
+ var coords = str.split(this.regExes.splitSpace);
+ // The "dimension" attribute is from the GML 3.0.1 spec.
+ var dim = obj.srsDimension ||
+ parseInt(node.getAttribute("srsDimension") || node.getAttribute("dimension"), 10) || 2;
+ var j, x, y, z;
+ var numPoints = coords.length / dim;
+ var points = new Array(numPoints);
+ for(var i=0, len=coords.length; i<len; i += dim) {
+ x = coords[i];
+ y = coords[i+1];
+ z = (dim == 2) ? undefined : coords[i+2];
+ if (this.xy) {
+ points[i/dim] = new OpenLayers.Geometry.Point(x, y, z);
+ } else {
+ points[i/dim] = new OpenLayers.Geometry.Point(y, x, z);
+ }
+ }
+ obj.points = points;
+ },
+ "Surface": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "patches": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "PolygonPatch": function(node, obj) {
+ this.readers.gml.Polygon.apply(this, [node, obj]);
+ },
+ "exterior": function(node, container) {
+ var obj = {};
+ this.readChildNodes(node, obj);
+ container.outer = obj.components[0];
+ },
+ "interior": function(node, container) {
+ var obj = {};
+ this.readChildNodes(node, obj);
+ container.inner.push(obj.components[0]);
+ },
+ "MultiCurve": function(node, container) {
+ var obj = {components: []};
+ this.readers.gml._inherit.apply(this, [node, obj, container]);
+ this.readChildNodes(node, obj);
+ if(obj.components.length > 0) {
+ container.components = [
+ new OpenLayers.Geometry.MultiLineString(obj.components)
+ ];
+ }
+ },
+ "curveMember": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "MultiSurface": function(node, container) {
+ var obj = {components: []};
+ this.readers.gml._inherit.apply(this, [node, obj, container]);
+ this.readChildNodes(node, obj);
+ if(obj.components.length > 0) {
+ container.components = [
+ new OpenLayers.Geometry.MultiPolygon(obj.components)
+ ];
+ }
+ },
+ "surfaceMember": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "surfaceMembers": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "pointMembers": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "lineStringMembers": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "polygonMembers": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "geometryMembers": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "Envelope": function(node, container) {
+ var obj = {points: new Array(2)};
+ this.readChildNodes(node, obj);
+ if(!container.components) {
+ container.components = [];
+ }
+ var min = obj.points[0];
+ var max = obj.points[1];
+ container.components.push(
+ new OpenLayers.Bounds(min.x, min.y, max.x, max.y)
+ );
+ },
+ "lowerCorner": function(node, container) {
+ var obj = {};
+ this.readers.gml.pos.apply(this, [node, obj]);
+ container.points[0] = obj.points[0];
+ },
+ "upperCorner": function(node, container) {
+ var obj = {};
+ this.readers.gml.pos.apply(this, [node, obj]);
+ container.points[1] = obj.points[0];
+ }
+ }, OpenLayers.Format.GML.Base.prototype.readers["gml"]),
+ "feature": OpenLayers.Format.GML.Base.prototype.readers["feature"],
+ "wfs": OpenLayers.Format.GML.Base.prototype.readers["wfs"]
+ },
+
+ /**
+ * Method: write
+ *
+ * Parameters:
+ * features - {Array(<OpenLayers.Feature.Vector>) | OpenLayers.Feature.Vector}
+ * An array of features or a single feature.
+ *
+ * Returns:
+ * {String} Given an array of features, a doc with a gml:featureMembers
+ * element will be returned. Given a single feature, a doc with a
+ * gml:featureMember element will be returned.
+ */
+ write: function(features) {
+ var name;
+ if(OpenLayers.Util.isArray(features)) {
+ name = "featureMembers";
+ } else {
+ name = "featureMember";
+ }
+ var root = this.writeNode("gml:" + name, features);
+ this.setAttributeNS(
+ root, this.namespaces["xsi"],
+ "xsi:schemaLocation", this.schemaLocation
+ );
+
+ return OpenLayers.Format.XML.prototype.write.apply(this, [root]);
+ },
+
+ /**
+ * Property: writers
+ * As a compliment to the readers property, this structure contains public
+ * writing functions grouped by namespace alias and named like the
+ * node names they produce.
+ */
+ writers: {
+ "gml": OpenLayers.Util.applyDefaults({
+ "featureMembers": function(features) {
+ var node = this.createElementNSPlus("gml:featureMembers");
+ for(var i=0, len=features.length; i<len; ++i) {
+ this.writeNode("feature:_typeName", features[i], node);
+ }
+ return node;
+ },
+ "Point": function(geometry) {
+ var node = this.createElementNSPlus("gml:Point");
+ this.writeNode("pos", geometry, node);
+ return node;
+ },
+ "pos": function(point) {
+ // only 2d for simple features profile
+ var pos = (this.xy) ?
+ (point.x + " " + point.y) : (point.y + " " + point.x);
+ return this.createElementNSPlus("gml:pos", {
+ value: pos
+ });
+ },
+ "LineString": function(geometry) {
+ var node = this.createElementNSPlus("gml:LineString");
+ this.writeNode("posList", geometry.components, node);
+ return node;
+ },
+ "Curve": function(geometry) {
+ var node = this.createElementNSPlus("gml:Curve");
+ this.writeNode("segments", geometry, node);
+ return node;
+ },
+ "segments": function(geometry) {
+ var node = this.createElementNSPlus("gml:segments");
+ this.writeNode("LineStringSegment", geometry, node);
+ return node;
+ },
+ "LineStringSegment": function(geometry) {
+ var node = this.createElementNSPlus("gml:LineStringSegment");
+ this.writeNode("posList", geometry.components, node);
+ return node;
+ },
+ "posList": function(points) {
+ // only 2d for simple features profile
+ var len = points.length;
+ var parts = new Array(len);
+ var point;
+ for(var i=0; i<len; ++i) {
+ point = points[i];
+ if(this.xy) {
+ parts[i] = point.x + " " + point.y;
+ } else {
+ parts[i] = point.y + " " + point.x;
+ }
+ }
+ return this.createElementNSPlus("gml:posList", {
+ value: parts.join(" ")
+ });
+ },
+ "Surface": function(geometry) {
+ var node = this.createElementNSPlus("gml:Surface");
+ this.writeNode("patches", geometry, node);
+ return node;
+ },
+ "patches": function(geometry) {
+ var node = this.createElementNSPlus("gml:patches");
+ this.writeNode("PolygonPatch", geometry, node);
+ return node;
+ },
+ "PolygonPatch": function(geometry) {
+ var node = this.createElementNSPlus("gml:PolygonPatch", {
+ attributes: {interpolation: "planar"}
+ });
+ this.writeNode("exterior", geometry.components[0], node);
+ for(var i=1, len=geometry.components.length; i<len; ++i) {
+ this.writeNode(
+ "interior", geometry.components[i], node
+ );
+ }
+ return node;
+ },
+ "Polygon": function(geometry) {
+ var node = this.createElementNSPlus("gml:Polygon");
+ this.writeNode("exterior", geometry.components[0], node);
+ for(var i=1, len=geometry.components.length; i<len; ++i) {
+ this.writeNode(
+ "interior", geometry.components[i], node
+ );
+ }
+ return node;
+ },
+ "exterior": function(ring) {
+ var node = this.createElementNSPlus("gml:exterior");
+ this.writeNode("LinearRing", ring, node);
+ return node;
+ },
+ "interior": function(ring) {
+ var node = this.createElementNSPlus("gml:interior");
+ this.writeNode("LinearRing", ring, node);
+ return node;
+ },
+ "LinearRing": function(ring) {
+ var node = this.createElementNSPlus("gml:LinearRing");
+ this.writeNode("posList", ring.components, node);
+ return node;
+ },
+ "MultiCurve": function(geometry) {
+ var node = this.createElementNSPlus("gml:MultiCurve");
+ var components = geometry.components || [geometry];
+ for(var i=0, len=components.length; i<len; ++i) {
+ this.writeNode("curveMember", components[i], node);
+ }
+ return node;
+ },
+ "curveMember": function(geometry) {
+ var node = this.createElementNSPlus("gml:curveMember");
+ if(this.curve) {
+ this.writeNode("Curve", geometry, node);
+ } else {
+ this.writeNode("LineString", geometry, node);
+ }
+ return node;
+ },
+ "MultiSurface": function(geometry) {
+ var node = this.createElementNSPlus("gml:MultiSurface");
+ var components = geometry.components || [geometry];
+ for(var i=0, len=components.length; i<len; ++i) {
+ this.writeNode("surfaceMember", components[i], node);
+ }
+ return node;
+ },
+ "surfaceMember": function(polygon) {
+ var node = this.createElementNSPlus("gml:surfaceMember");
+ if(this.surface) {
+ this.writeNode("Surface", polygon, node);
+ } else {
+ this.writeNode("Polygon", polygon, node);
+ }
+ return node;
+ },
+ "Envelope": function(bounds) {
+ var node = this.createElementNSPlus("gml:Envelope");
+ this.writeNode("lowerCorner", bounds, node);
+ this.writeNode("upperCorner", bounds, node);
+ // srsName attribute is required for gml:Envelope
+ if(this.srsName) {
+ node.setAttribute("srsName", this.srsName);
+ }
+ return node;
+ },
+ "lowerCorner": function(bounds) {
+ // only 2d for simple features profile
+ var pos = (this.xy) ?
+ (bounds.left + " " + bounds.bottom) :
+ (bounds.bottom + " " + bounds.left);
+ return this.createElementNSPlus("gml:lowerCorner", {
+ value: pos
+ });
+ },
+ "upperCorner": function(bounds) {
+ // only 2d for simple features profile
+ var pos = (this.xy) ?
+ (bounds.right + " " + bounds.top) :
+ (bounds.top + " " + bounds.right);
+ return this.createElementNSPlus("gml:upperCorner", {
+ value: pos
+ });
+ }
+ }, OpenLayers.Format.GML.Base.prototype.writers["gml"]),
+ "feature": OpenLayers.Format.GML.Base.prototype.writers["feature"],
+ "wfs": OpenLayers.Format.GML.Base.prototype.writers["wfs"]
+ },
+
+ /**
+ * Method: setGeometryTypes
+ * Sets the <geometryTypes> mapping.
+ */
+ setGeometryTypes: function() {
+ this.geometryTypes = {
+ "OpenLayers.Geometry.Point": "Point",
+ "OpenLayers.Geometry.MultiPoint": "MultiPoint",
+ "OpenLayers.Geometry.LineString": (this.curve === true) ? "Curve": "LineString",
+ "OpenLayers.Geometry.MultiLineString": (this.multiCurve === false) ? "MultiLineString" : "MultiCurve",
+ "OpenLayers.Geometry.Polygon": (this.surface === true) ? "Surface" : "Polygon",
+ "OpenLayers.Geometry.MultiPolygon": (this.multiSurface === false) ? "MultiPolygon" : "MultiSurface",
+ "OpenLayers.Geometry.Collection": "GeometryCollection"
+ };
+ },
+
+ CLASS_NAME: "OpenLayers.Format.GML.v3"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/GPX.js b/misc/openlayers/lib/OpenLayers/Format/GPX.js
new file mode 100644
index 0000000..16a8056
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/GPX.js
@@ -0,0 +1,385 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Feature/Vector.js
+ * @requires OpenLayers/Geometry/Point.js
+ * @requires OpenLayers/Geometry/LineString.js
+ * @requires OpenLayers/Projection.js
+ */
+
+/**
+ * Class: OpenLayers.Format.GPX
+ * Read/write GPX parser. Create a new instance with the
+ * <OpenLayers.Format.GPX> constructor.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.GPX = OpenLayers.Class(OpenLayers.Format.XML, {
+
+
+ /**
+ * APIProperty: defaultDesc
+ * {String} Default description for the waypoints/tracks in the case
+ * where the feature has no "description" attribute.
+ * Default is "No description available".
+ */
+ defaultDesc: "No description available",
+
+ /**
+ * APIProperty: extractWaypoints
+ * {Boolean} Extract waypoints from GPX. (default: true)
+ */
+ extractWaypoints: true,
+
+ /**
+ * APIProperty: extractTracks
+ * {Boolean} Extract tracks from GPX. (default: true)
+ */
+ extractTracks: true,
+
+ /**
+ * APIProperty: extractRoutes
+ * {Boolean} Extract routes from GPX. (default: true)
+ */
+ extractRoutes: true,
+
+ /**
+ * APIProperty: extractAttributes
+ * {Boolean} Extract feature attributes from GPX. (default: true)
+ * NOTE: Attributes as part of extensions to the GPX standard may not
+ * be extracted.
+ */
+ extractAttributes: true,
+
+ /**
+ * Property: namespaces
+ * {Object} Mapping of namespace aliases to namespace URIs.
+ */
+ namespaces: {
+ gpx: "http://www.topografix.com/GPX/1/1",
+ xsi: "http://www.w3.org/2001/XMLSchema-instance"
+ },
+
+ /**
+ * Property: schemaLocation
+ * {String} Schema location. Defaults to
+ * "http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd"
+ */
+ schemaLocation: "http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd",
+
+ /**
+ * APIProperty: creator
+ * {String} The creator attribute to be added to the written GPX files.
+ * Defaults to "OpenLayers"
+ */
+ creator: "OpenLayers",
+
+ /**
+ * Constructor: OpenLayers.Format.GPX
+ * Create a new parser for GPX.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+ initialize: function(options) {
+ // GPX coordinates are always in longlat WGS84
+ this.externalProjection = new OpenLayers.Projection("EPSG:4326");
+
+ OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+ },
+
+ /**
+ * APIMethod: read
+ * Return a list of features from a GPX doc
+ *
+ * Parameters:
+ * doc - {Element}
+ *
+ * Returns:
+ * Array({<OpenLayers.Feature.Vector>})
+ */
+ read: function(doc) {
+ if (typeof doc == "string") {
+ doc = OpenLayers.Format.XML.prototype.read.apply(this, [doc]);
+ }
+ var features = [];
+
+ if(this.extractTracks) {
+ var tracks = doc.getElementsByTagName("trk");
+ for (var i=0, len=tracks.length; i<len; i++) {
+ // Attributes are only in trk nodes, not trkseg nodes
+ var attrs = {};
+ if(this.extractAttributes) {
+ attrs = this.parseAttributes(tracks[i]);
+ }
+
+ var segs = this.getElementsByTagNameNS(tracks[i], tracks[i].namespaceURI, "trkseg");
+ for (var j = 0, seglen = segs.length; j < seglen; j++) {
+ // We don't yet support extraction of trkpt attributes
+ // All trksegs of a trk get that trk's attributes
+ var track = this.extractSegment(segs[j], "trkpt");
+ features.push(new OpenLayers.Feature.Vector(track, attrs));
+ }
+ }
+ }
+
+ if(this.extractRoutes) {
+ var routes = doc.getElementsByTagName("rte");
+ for (var k=0, klen=routes.length; k<klen; k++) {
+ var attrs = {};
+ if(this.extractAttributes) {
+ attrs = this.parseAttributes(routes[k]);
+ }
+ var route = this.extractSegment(routes[k], "rtept");
+ features.push(new OpenLayers.Feature.Vector(route, attrs));
+ }
+ }
+
+ if(this.extractWaypoints) {
+ var waypoints = doc.getElementsByTagName("wpt");
+ for (var l = 0, len = waypoints.length; l < len; l++) {
+ var attrs = {};
+ if(this.extractAttributes) {
+ attrs = this.parseAttributes(waypoints[l]);
+ }
+ var wpt = new OpenLayers.Geometry.Point(waypoints[l].getAttribute("lon"), waypoints[l].getAttribute("lat"));
+ features.push(new OpenLayers.Feature.Vector(wpt, attrs));
+ }
+ }
+
+ if (this.internalProjection && this.externalProjection) {
+ for (var g = 0, featLength = features.length; g < featLength; g++) {
+ features[g].geometry.transform(this.externalProjection,
+ this.internalProjection);
+ }
+ }
+
+ return features;
+ },
+
+ /**
+ * Method: extractSegment
+ *
+ * Parameters:
+ * segment - {DOMElement} a trkseg or rte node to parse
+ * segmentType - {String} nodeName of waypoints that form the line
+ *
+ * Returns:
+ * {<OpenLayers.Geometry.LineString>} A linestring geometry
+ */
+ extractSegment: function(segment, segmentType) {
+ var points = this.getElementsByTagNameNS(segment, segment.namespaceURI, segmentType);
+ var point_features = [];
+ for (var i = 0, len = points.length; i < len; i++) {
+ point_features.push(new OpenLayers.Geometry.Point(points[i].getAttribute("lon"), points[i].getAttribute("lat")));
+ }
+ return new OpenLayers.Geometry.LineString(point_features);
+ },
+
+ /**
+ * Method: parseAttributes
+ *
+ * Parameters:
+ * node - {<DOMElement>}
+ *
+ * Returns:
+ * {Object} An attributes object.
+ */
+ parseAttributes: function(node) {
+ // node is either a wpt, trk or rte
+ // attributes are children of the form <attr>value</attr>
+ var attributes = {};
+ var attrNode = node.firstChild, value, name;
+ while(attrNode) {
+ if(attrNode.nodeType == 1 && attrNode.firstChild) {
+ value = attrNode.firstChild;
+ if(value.nodeType == 3 || value.nodeType == 4) {
+ name = (attrNode.prefix) ?
+ attrNode.nodeName.split(":")[1] :
+ attrNode.nodeName;
+ if(name != "trkseg" && name != "rtept") {
+ attributes[name] = value.nodeValue;
+ }
+ }
+ }
+ attrNode = attrNode.nextSibling;
+ }
+ return attributes;
+ },
+
+ /**
+ * APIMethod: write
+ * Accepts Feature Collection, and returns a string.
+ *
+ * Parameters:
+ * features - {Array(<OpenLayers.Feature.Vector>)} List of features to serialize into a string.
+ * metadata - {Object} A key/value pairs object to build a metadata node to
+ * add to the gpx. Supported keys are 'name', 'desc', 'author'.
+ */
+ write: function(features, metadata) {
+ features = OpenLayers.Util.isArray(features) ?
+ features : [features];
+ var gpx = this.createElementNS(this.namespaces.gpx, "gpx");
+ gpx.setAttribute("version", "1.1");
+ gpx.setAttribute("creator", this.creator);
+ this.setAttributes(gpx, {
+ "xsi:schemaLocation": this.schemaLocation
+ });
+
+ if (metadata && typeof metadata == 'object') {
+ gpx.appendChild(this.buildMetadataNode(metadata));
+ }
+ for(var i=0, len=features.length; i<len; i++) {
+ gpx.appendChild(this.buildFeatureNode(features[i]));
+ }
+ return OpenLayers.Format.XML.prototype.write.apply(this, [gpx]);
+ },
+
+ /**
+ * Method: buildMetadataNode
+ * Creates a "metadata" node.
+ *
+ * Returns:
+ * {DOMElement}
+ */
+ buildMetadataNode: function(metadata) {
+ var types = ['name', 'desc', 'author'],
+ node = this.createElementNS(this.namespaces.gpx, 'metadata');
+ for (var i=0; i < types.length; i++) {
+ var type = types[i];
+ if (metadata[type]) {
+ var n = this.createElementNS(this.namespaces.gpx, type);
+ n.appendChild(this.createTextNode(metadata[type]));
+ node.appendChild(n);
+ }
+ }
+ return node;
+ },
+
+ /**
+ * Method: buildFeatureNode
+ * Accepts an <OpenLayers.Feature.Vector>, and builds a node for it.
+ *
+ * Parameters:
+ * feature - {<OpenLayers.Feature.Vector>}
+ *
+ * Returns:
+ * {DOMElement} - The created node, either a 'wpt' or a 'trk'.
+ */
+ buildFeatureNode: function(feature) {
+ var geometry = feature.geometry;
+ geometry = geometry.clone();
+ if (this.internalProjection && this.externalProjection) {
+ geometry.transform(this.internalProjection,
+ this.externalProjection);
+ }
+ if (geometry.CLASS_NAME == "OpenLayers.Geometry.Point") {
+ var wpt = this.buildWptNode(geometry);
+ this.appendAttributesNode(wpt, feature);
+ return wpt;
+ } else {
+ var trkNode = this.createElementNS(this.namespaces.gpx, "trk");
+ this.appendAttributesNode(trkNode, feature);
+ var trkSegNodes = this.buildTrkSegNode(geometry);
+ trkSegNodes = OpenLayers.Util.isArray(trkSegNodes) ?
+ trkSegNodes : [trkSegNodes];
+ for (var i = 0, len = trkSegNodes.length; i < len; i++) {
+ trkNode.appendChild(trkSegNodes[i]);
+ }
+ return trkNode;
+ }
+ },
+
+ /**
+ * Method: buildTrkSegNode
+ * Builds trkseg node(s) given a geometry
+ *
+ * Parameters:
+ * trknode
+ * geometry - {<OpenLayers.Geometry>}
+ */
+ buildTrkSegNode: function(geometry) {
+ var node,
+ i,
+ len,
+ point,
+ nodes;
+ if (geometry.CLASS_NAME == "OpenLayers.Geometry.LineString" ||
+ geometry.CLASS_NAME == "OpenLayers.Geometry.LinearRing") {
+ node = this.createElementNS(this.namespaces.gpx, "trkseg");
+ for (i = 0, len=geometry.components.length; i < len; i++) {
+ point = geometry.components[i];
+ node.appendChild(this.buildTrkPtNode(point));
+ }
+ return node;
+ } else {
+ nodes = [];
+ for (i = 0, len = geometry.components.length; i < len; i++) {
+ nodes.push(this.buildTrkSegNode(geometry.components[i]));
+ }
+ return nodes;
+ }
+ },
+
+ /**
+ * Method: buildTrkPtNode
+ * Builds a trkpt node given a point
+ *
+ * Parameters:
+ * point - {<OpenLayers.Geometry.Point>}
+ *
+ * Returns:
+ * {DOMElement} A trkpt node
+ */
+ buildTrkPtNode: function(point) {
+ var node = this.createElementNS(this.namespaces.gpx, "trkpt");
+ node.setAttribute("lon", point.x);
+ node.setAttribute("lat", point.y);
+ return node;
+ },
+
+ /**
+ * Method: buildWptNode
+ * Builds a wpt node given a point
+ *
+ * Parameters:
+ * geometry - {<OpenLayers.Geometry.Point>}
+ *
+ * Returns:
+ * {DOMElement} A wpt node
+ */
+ buildWptNode: function(geometry) {
+ var node = this.createElementNS(this.namespaces.gpx, "wpt");
+ node.setAttribute("lon", geometry.x);
+ node.setAttribute("lat", geometry.y);
+ return node;
+ },
+
+ /**
+ * Method: appendAttributesNode
+ * Adds some attributes node.
+ *
+ * Parameters:
+ * node - {DOMElement} the node to append the attribute nodes to.
+ * feature - {<OpenLayers.Feature.Vector>}
+ */
+ appendAttributesNode: function(node, feature) {
+ var name = this.createElementNS(this.namespaces.gpx, 'name');
+ name.appendChild(this.createTextNode(
+ feature.attributes.name || feature.id));
+ node.appendChild(name);
+ var desc = this.createElementNS(this.namespaces.gpx, 'desc');
+ desc.appendChild(this.createTextNode(
+ feature.attributes.description || this.defaultDesc));
+ node.appendChild(desc);
+ // TBD - deal with remaining (non name/description) attributes.
+ },
+
+ CLASS_NAME: "OpenLayers.Format.GPX"
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/GeoJSON.js b/misc/openlayers/lib/OpenLayers/Format/GeoJSON.js
new file mode 100644
index 0000000..0e02377
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/GeoJSON.js
@@ -0,0 +1,716 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/JSON.js
+ * @requires OpenLayers/Feature/Vector.js
+ * @requires OpenLayers/Geometry/Point.js
+ * @requires OpenLayers/Geometry/MultiPoint.js
+ * @requires OpenLayers/Geometry/LineString.js
+ * @requires OpenLayers/Geometry/MultiLineString.js
+ * @requires OpenLayers/Geometry/Polygon.js
+ * @requires OpenLayers/Geometry/MultiPolygon.js
+ * @requires OpenLayers/Console.js
+ */
+
+/**
+ * Class: OpenLayers.Format.GeoJSON
+ * Read and write GeoJSON. Create a new parser with the
+ * <OpenLayers.Format.GeoJSON> constructor.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.JSON>
+ */
+OpenLayers.Format.GeoJSON = OpenLayers.Class(OpenLayers.Format.JSON, {
+
+ /**
+ * APIProperty: ignoreExtraDims
+ * {Boolean} Ignore dimensions higher than 2 when reading geometry
+ * coordinates.
+ */
+ ignoreExtraDims: false,
+
+ /**
+ * Constructor: OpenLayers.Format.GeoJSON
+ * Create a new parser for GeoJSON.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * APIMethod: read
+ * Deserialize a GeoJSON string.
+ *
+ * Parameters:
+ * json - {String} A GeoJSON string
+ * type - {String} Optional string that determines the structure of
+ * the output. Supported values are "Geometry", "Feature", and
+ * "FeatureCollection". If absent or null, a default of
+ * "FeatureCollection" is assumed.
+ * filter - {Function} A function which will be called for every key and
+ * value at every level of the final result. Each value will be
+ * replaced by the result of the filter function. This can be used to
+ * reform generic objects into instances of classes, or to transform
+ * date strings into Date objects.
+ *
+ * Returns:
+ * {Object} The return depends on the value of the type argument. If type
+ * is "FeatureCollection" (the default), the return will be an array
+ * of <OpenLayers.Feature.Vector>. If type is "Geometry", the input json
+ * must represent a single geometry, and the return will be an
+ * <OpenLayers.Geometry>. If type is "Feature", the input json must
+ * represent a single feature, and the return will be an
+ * <OpenLayers.Feature.Vector>.
+ */
+ read: function(json, type, filter) {
+ type = (type) ? type : "FeatureCollection";
+ var results = null;
+ var obj = null;
+ if (typeof json == "string") {
+ obj = OpenLayers.Format.JSON.prototype.read.apply(this,
+ [json, filter]);
+ } else {
+ obj = json;
+ }
+ if(!obj) {
+ OpenLayers.Console.error("Bad JSON: " + json);
+ } else if(typeof(obj.type) != "string") {
+ OpenLayers.Console.error("Bad GeoJSON - no type: " + json);
+ } else if(this.isValidType(obj, type)) {
+ switch(type) {
+ case "Geometry":
+ try {
+ results = this.parseGeometry(obj);
+ } catch(err) {
+ OpenLayers.Console.error(err);
+ }
+ break;
+ case "Feature":
+ try {
+ results = this.parseFeature(obj);
+ results.type = "Feature";
+ } catch(err) {
+ OpenLayers.Console.error(err);
+ }
+ break;
+ case "FeatureCollection":
+ // for type FeatureCollection, we allow input to be any type
+ results = [];
+ switch(obj.type) {
+ case "Feature":
+ try {
+ results.push(this.parseFeature(obj));
+ } catch(err) {
+ results = null;
+ OpenLayers.Console.error(err);
+ }
+ break;
+ case "FeatureCollection":
+ for(var i=0, len=obj.features.length; i<len; ++i) {
+ try {
+ results.push(this.parseFeature(obj.features[i]));
+ } catch(err) {
+ results = null;
+ OpenLayers.Console.error(err);
+ }
+ }
+ break;
+ default:
+ try {
+ var geom = this.parseGeometry(obj);
+ results.push(new OpenLayers.Feature.Vector(geom));
+ } catch(err) {
+ results = null;
+ OpenLayers.Console.error(err);
+ }
+ }
+ break;
+ }
+ }
+ return results;
+ },
+
+ /**
+ * Method: isValidType
+ * Check if a GeoJSON object is a valid representative of the given type.
+ *
+ * Returns:
+ * {Boolean} The object is valid GeoJSON object of the given type.
+ */
+ isValidType: function(obj, type) {
+ var valid = false;
+ switch(type) {
+ case "Geometry":
+ if(OpenLayers.Util.indexOf(
+ ["Point", "MultiPoint", "LineString", "MultiLineString",
+ "Polygon", "MultiPolygon", "Box", "GeometryCollection"],
+ obj.type) == -1) {
+ // unsupported geometry type
+ OpenLayers.Console.error("Unsupported geometry type: " +
+ obj.type);
+ } else {
+ valid = true;
+ }
+ break;
+ case "FeatureCollection":
+ // allow for any type to be converted to a feature collection
+ valid = true;
+ break;
+ default:
+ // for Feature types must match
+ if(obj.type == type) {
+ valid = true;
+ } else {
+ OpenLayers.Console.error("Cannot convert types from " +
+ obj.type + " to " + type);
+ }
+ }
+ return valid;
+ },
+
+ /**
+ * Method: parseFeature
+ * Convert a feature object from GeoJSON into an
+ * <OpenLayers.Feature.Vector>.
+ *
+ * Parameters:
+ * obj - {Object} An object created from a GeoJSON object
+ *
+ * Returns:
+ * {<OpenLayers.Feature.Vector>} A feature.
+ */
+ parseFeature: function(obj) {
+ var feature, geometry, attributes, bbox;
+ attributes = (obj.properties) ? obj.properties : {};
+ bbox = (obj.geometry && obj.geometry.bbox) || obj.bbox;
+ try {
+ geometry = this.parseGeometry(obj.geometry);
+ } catch(err) {
+ // deal with bad geometries
+ throw err;
+ }
+ feature = new OpenLayers.Feature.Vector(geometry, attributes);
+ if(bbox) {
+ feature.bounds = OpenLayers.Bounds.fromArray(bbox);
+ }
+ if(obj.id) {
+ feature.fid = obj.id;
+ }
+ return feature;
+ },
+
+ /**
+ * Method: parseGeometry
+ * Convert a geometry object from GeoJSON into an <OpenLayers.Geometry>.
+ *
+ * Parameters:
+ * obj - {Object} An object created from a GeoJSON object
+ *
+ * Returns:
+ * {<OpenLayers.Geometry>} A geometry.
+ */
+ parseGeometry: function(obj) {
+ if (obj == null) {
+ return null;
+ }
+ var geometry, collection = false;
+ if(obj.type == "GeometryCollection") {
+ if(!(OpenLayers.Util.isArray(obj.geometries))) {
+ throw "GeometryCollection must have geometries array: " + obj;
+ }
+ var numGeom = obj.geometries.length;
+ var components = new Array(numGeom);
+ for(var i=0; i<numGeom; ++i) {
+ components[i] = this.parseGeometry.apply(
+ this, [obj.geometries[i]]
+ );
+ }
+ geometry = new OpenLayers.Geometry.Collection(components);
+ collection = true;
+ } else {
+ if(!(OpenLayers.Util.isArray(obj.coordinates))) {
+ throw "Geometry must have coordinates array: " + obj;
+ }
+ if(!this.parseCoords[obj.type.toLowerCase()]) {
+ throw "Unsupported geometry type: " + obj.type;
+ }
+ try {
+ geometry = this.parseCoords[obj.type.toLowerCase()].apply(
+ this, [obj.coordinates]
+ );
+ } catch(err) {
+ // deal with bad coordinates
+ throw err;
+ }
+ }
+ // We don't reproject collections because the children are reprojected
+ // for us when they are created.
+ if (this.internalProjection && this.externalProjection && !collection) {
+ geometry.transform(this.externalProjection,
+ this.internalProjection);
+ }
+ return geometry;
+ },
+
+ /**
+ * Property: parseCoords
+ * Object with properties corresponding to the GeoJSON geometry types.
+ * Property values are functions that do the actual parsing.
+ */
+ parseCoords: {
+ /**
+ * Method: parseCoords.point
+ * Convert a coordinate array from GeoJSON into an
+ * <OpenLayers.Geometry>.
+ *
+ * Parameters:
+ * array - {Object} The coordinates array from the GeoJSON fragment.
+ *
+ * Returns:
+ * {<OpenLayers.Geometry>} A geometry.
+ */
+ "point": function(array) {
+ if (this.ignoreExtraDims == false &&
+ array.length != 2) {
+ throw "Only 2D points are supported: " + array;
+ }
+ return new OpenLayers.Geometry.Point(array[0], array[1]);
+ },
+
+ /**
+ * Method: parseCoords.multipoint
+ * Convert a coordinate array from GeoJSON into an
+ * <OpenLayers.Geometry>.
+ *
+ * Parameters:
+ * array - {Object} The coordinates array from the GeoJSON fragment.
+ *
+ * Returns:
+ * {<OpenLayers.Geometry>} A geometry.
+ */
+ "multipoint": function(array) {
+ var points = [];
+ var p = null;
+ for(var i=0, len=array.length; i<len; ++i) {
+ try {
+ p = this.parseCoords["point"].apply(this, [array[i]]);
+ } catch(err) {
+ throw err;
+ }
+ points.push(p);
+ }
+ return new OpenLayers.Geometry.MultiPoint(points);
+ },
+
+ /**
+ * Method: parseCoords.linestring
+ * Convert a coordinate array from GeoJSON into an
+ * <OpenLayers.Geometry>.
+ *
+ * Parameters:
+ * array - {Object} The coordinates array from the GeoJSON fragment.
+ *
+ * Returns:
+ * {<OpenLayers.Geometry>} A geometry.
+ */
+ "linestring": function(array) {
+ var points = [];
+ var p = null;
+ for(var i=0, len=array.length; i<len; ++i) {
+ try {
+ p = this.parseCoords["point"].apply(this, [array[i]]);
+ } catch(err) {
+ throw err;
+ }
+ points.push(p);
+ }
+ return new OpenLayers.Geometry.LineString(points);
+ },
+
+ /**
+ * Method: parseCoords.multilinestring
+ * Convert a coordinate array from GeoJSON into an
+ * <OpenLayers.Geometry>.
+ *
+ * Parameters:
+ * array - {Object} The coordinates array from the GeoJSON fragment.
+ *
+ * Returns:
+ * {<OpenLayers.Geometry>} A geometry.
+ */
+ "multilinestring": function(array) {
+ var lines = [];
+ var l = null;
+ for(var i=0, len=array.length; i<len; ++i) {
+ try {
+ l = this.parseCoords["linestring"].apply(this, [array[i]]);
+ } catch(err) {
+ throw err;
+ }
+ lines.push(l);
+ }
+ return new OpenLayers.Geometry.MultiLineString(lines);
+ },
+
+ /**
+ * Method: parseCoords.polygon
+ * Convert a coordinate array from GeoJSON into an
+ * <OpenLayers.Geometry>.
+ *
+ * Returns:
+ * {<OpenLayers.Geometry>} A geometry.
+ */
+ "polygon": function(array) {
+ var rings = [];
+ var r, l;
+ for(var i=0, len=array.length; i<len; ++i) {
+ try {
+ l = this.parseCoords["linestring"].apply(this, [array[i]]);
+ } catch(err) {
+ throw err;
+ }
+ r = new OpenLayers.Geometry.LinearRing(l.components);
+ rings.push(r);
+ }
+ return new OpenLayers.Geometry.Polygon(rings);
+ },
+
+ /**
+ * Method: parseCoords.multipolygon
+ * Convert a coordinate array from GeoJSON into an
+ * <OpenLayers.Geometry>.
+ *
+ * Parameters:
+ * array - {Object} The coordinates array from the GeoJSON fragment.
+ *
+ * Returns:
+ * {<OpenLayers.Geometry>} A geometry.
+ */
+ "multipolygon": function(array) {
+ var polys = [];
+ var p = null;
+ for(var i=0, len=array.length; i<len; ++i) {
+ try {
+ p = this.parseCoords["polygon"].apply(this, [array[i]]);
+ } catch(err) {
+ throw err;
+ }
+ polys.push(p);
+ }
+ return new OpenLayers.Geometry.MultiPolygon(polys);
+ },
+
+ /**
+ * Method: parseCoords.box
+ * Convert a coordinate array from GeoJSON into an
+ * <OpenLayers.Geometry>.
+ *
+ * Parameters:
+ * array - {Object} The coordinates array from the GeoJSON fragment.
+ *
+ * Returns:
+ * {<OpenLayers.Geometry>} A geometry.
+ */
+ "box": function(array) {
+ if(array.length != 2) {
+ throw "GeoJSON box coordinates must have 2 elements";
+ }
+ return new OpenLayers.Geometry.Polygon([
+ new OpenLayers.Geometry.LinearRing([
+ new OpenLayers.Geometry.Point(array[0][0], array[0][1]),
+ new OpenLayers.Geometry.Point(array[1][0], array[0][1]),
+ new OpenLayers.Geometry.Point(array[1][0], array[1][1]),
+ new OpenLayers.Geometry.Point(array[0][0], array[1][1]),
+ new OpenLayers.Geometry.Point(array[0][0], array[0][1])
+ ])
+ ]);
+ }
+
+ },
+
+ /**
+ * APIMethod: write
+ * Serialize a feature, geometry, array of features into a GeoJSON string.
+ *
+ * Parameters:
+ * obj - {Object} An <OpenLayers.Feature.Vector>, <OpenLayers.Geometry>,
+ * or an array of features.
+ * pretty - {Boolean} Structure the output with newlines and indentation.
+ * Default is false.
+ *
+ * Returns:
+ * {String} The GeoJSON string representation of the input geometry,
+ * features, or array of features.
+ */
+ write: function(obj, pretty) {
+ var geojson = {
+ "type": null
+ };
+ if(OpenLayers.Util.isArray(obj)) {
+ geojson.type = "FeatureCollection";
+ var numFeatures = obj.length;
+ geojson.features = new Array(numFeatures);
+ for(var i=0; i<numFeatures; ++i) {
+ var element = obj[i];
+ if(!element instanceof OpenLayers.Feature.Vector) {
+ var msg = "FeatureCollection only supports collections " +
+ "of features: " + element;
+ throw msg;
+ }
+ geojson.features[i] = this.extract.feature.apply(
+ this, [element]
+ );
+ }
+ } else if (obj.CLASS_NAME.indexOf("OpenLayers.Geometry") == 0) {
+ geojson = this.extract.geometry.apply(this, [obj]);
+ } else if (obj instanceof OpenLayers.Feature.Vector) {
+ geojson = this.extract.feature.apply(this, [obj]);
+ if(obj.layer && obj.layer.projection) {
+ geojson.crs = this.createCRSObject(obj);
+ }
+ }
+ return OpenLayers.Format.JSON.prototype.write.apply(this,
+ [geojson, pretty]);
+ },
+
+ /**
+ * Method: createCRSObject
+ * Create the CRS object for an object.
+ *
+ * Parameters:
+ * object - {<OpenLayers.Feature.Vector>}
+ *
+ * Returns:
+ * {Object} An object which can be assigned to the crs property
+ * of a GeoJSON object.
+ */
+ createCRSObject: function(object) {
+ var proj = object.layer.projection.toString();
+ var crs = {};
+ if (proj.match(/epsg:/i)) {
+ var code = parseInt(proj.substring(proj.indexOf(":") + 1));
+ if (code == 4326) {
+ crs = {
+ "type": "name",
+ "properties": {
+ "name": "urn:ogc:def:crs:OGC:1.3:CRS84"
+ }
+ };
+ } else {
+ crs = {
+ "type": "name",
+ "properties": {
+ "name": "EPSG:" + code
+ }
+ };
+ }
+ }
+ return crs;
+ },
+
+ /**
+ * Property: extract
+ * Object with properties corresponding to the GeoJSON types.
+ * Property values are functions that do the actual value extraction.
+ */
+ extract: {
+ /**
+ * Method: extract.feature
+ * Return a partial GeoJSON object representing a single feature.
+ *
+ * Parameters:
+ * feature - {<OpenLayers.Feature.Vector>}
+ *
+ * Returns:
+ * {Object} An object representing the point.
+ */
+ 'feature': function(feature) {
+ var geom = this.extract.geometry.apply(this, [feature.geometry]);
+ var json = {
+ "type": "Feature",
+ "properties": feature.attributes,
+ "geometry": geom
+ };
+ if (feature.fid != null) {
+ json.id = feature.fid;
+ }
+ return json;
+ },
+
+ /**
+ * Method: extract.geometry
+ * Return a GeoJSON object representing a single geometry.
+ *
+ * Parameters:
+ * geometry - {<OpenLayers.Geometry>}
+ *
+ * Returns:
+ * {Object} An object representing the geometry.
+ */
+ 'geometry': function(geometry) {
+ if (geometry == null) {
+ return null;
+ }
+ if (this.internalProjection && this.externalProjection) {
+ geometry = geometry.clone();
+ geometry.transform(this.internalProjection,
+ this.externalProjection);
+ }
+ var geometryType = geometry.CLASS_NAME.split('.')[2];
+ var data = this.extract[geometryType.toLowerCase()].apply(this, [geometry]);
+ var json;
+ if(geometryType == "Collection") {
+ json = {
+ "type": "GeometryCollection",
+ "geometries": data
+ };
+ } else {
+ json = {
+ "type": geometryType,
+ "coordinates": data
+ };
+ }
+
+ return json;
+ },
+
+ /**
+ * Method: extract.point
+ * Return an array of coordinates from a point.
+ *
+ * Parameters:
+ * point - {<OpenLayers.Geometry.Point>}
+ *
+ * Returns:
+ * {Array} An array of coordinates representing the point.
+ */
+ 'point': function(point) {
+ return [point.x, point.y];
+ },
+
+ /**
+ * Method: extract.multipoint
+ * Return an array of point coordinates from a multipoint.
+ *
+ * Parameters:
+ * multipoint - {<OpenLayers.Geometry.MultiPoint>}
+ *
+ * Returns:
+ * {Array} An array of point coordinate arrays representing
+ * the multipoint.
+ */
+ 'multipoint': function(multipoint) {
+ var array = [];
+ for(var i=0, len=multipoint.components.length; i<len; ++i) {
+ array.push(this.extract.point.apply(this, [multipoint.components[i]]));
+ }
+ return array;
+ },
+
+ /**
+ * Method: extract.linestring
+ * Return an array of coordinate arrays from a linestring.
+ *
+ * Parameters:
+ * linestring - {<OpenLayers.Geometry.LineString>}
+ *
+ * Returns:
+ * {Array} An array of coordinate arrays representing
+ * the linestring.
+ */
+ 'linestring': function(linestring) {
+ var array = [];
+ for(var i=0, len=linestring.components.length; i<len; ++i) {
+ array.push(this.extract.point.apply(this, [linestring.components[i]]));
+ }
+ return array;
+ },
+
+ /**
+ * Method: extract.multilinestring
+ * Return an array of linestring arrays from a linestring.
+ *
+ * Parameters:
+ * multilinestring - {<OpenLayers.Geometry.MultiLineString>}
+ *
+ * Returns:
+ * {Array} An array of linestring arrays representing
+ * the multilinestring.
+ */
+ 'multilinestring': function(multilinestring) {
+ var array = [];
+ for(var i=0, len=multilinestring.components.length; i<len; ++i) {
+ array.push(this.extract.linestring.apply(this, [multilinestring.components[i]]));
+ }
+ return array;
+ },
+
+ /**
+ * Method: extract.polygon
+ * Return an array of linear ring arrays from a polygon.
+ *
+ * Parameters:
+ * polygon - {<OpenLayers.Geometry.Polygon>}
+ *
+ * Returns:
+ * {Array} An array of linear ring arrays representing the polygon.
+ */
+ 'polygon': function(polygon) {
+ var array = [];
+ for(var i=0, len=polygon.components.length; i<len; ++i) {
+ array.push(this.extract.linestring.apply(this, [polygon.components[i]]));
+ }
+ return array;
+ },
+
+ /**
+ * Method: extract.multipolygon
+ * Return an array of polygon arrays from a multipolygon.
+ *
+ * Parameters:
+ * multipolygon - {<OpenLayers.Geometry.MultiPolygon>}
+ *
+ * Returns:
+ * {Array} An array of polygon arrays representing
+ * the multipolygon
+ */
+ 'multipolygon': function(multipolygon) {
+ var array = [];
+ for(var i=0, len=multipolygon.components.length; i<len; ++i) {
+ array.push(this.extract.polygon.apply(this, [multipolygon.components[i]]));
+ }
+ return array;
+ },
+
+ /**
+ * Method: extract.collection
+ * Return an array of geometries from a geometry collection.
+ *
+ * Parameters:
+ * collection - {<OpenLayers.Geometry.Collection>}
+ *
+ * Returns:
+ * {Array} An array of geometry objects representing the geometry
+ * collection.
+ */
+ 'collection': function(collection) {
+ var len = collection.components.length;
+ var array = new Array(len);
+ for(var i=0; i<len; ++i) {
+ array[i] = this.extract.geometry.apply(
+ this, [collection.components[i]]
+ );
+ }
+ return array;
+ }
+
+
+ },
+
+ CLASS_NAME: "OpenLayers.Format.GeoJSON"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/GeoRSS.js b/misc/openlayers/lib/OpenLayers/Format/GeoRSS.js
new file mode 100644
index 0000000..cbbb4d8
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/GeoRSS.js
@@ -0,0 +1,409 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Feature/Vector.js
+ * @requires OpenLayers/Geometry/Point.js
+ * @requires OpenLayers/Geometry/LineString.js
+ * @requires OpenLayers/Geometry/Polygon.js
+ */
+
+/**
+ * Class: OpenLayers.Format.GeoRSS
+ * Read/write GeoRSS parser. Create a new instance with the
+ * <OpenLayers.Format.GeoRSS> constructor.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.GeoRSS = OpenLayers.Class(OpenLayers.Format.XML, {
+
+ /**
+ * APIProperty: rssns
+ * {String} RSS namespace to use. Defaults to
+ * "http://backend.userland.com/rss2"
+ */
+ rssns: "http://backend.userland.com/rss2",
+
+ /**
+ * APIProperty: featurens
+ * {String} Feature Attributes namespace. Defaults to
+ * "http://mapserver.gis.umn.edu/mapserver"
+ */
+ featureNS: "http://mapserver.gis.umn.edu/mapserver",
+
+ /**
+ * APIProperty: georssns
+ * {String} GeoRSS namespace to use. Defaults to
+ * "http://www.georss.org/georss"
+ */
+ georssns: "http://www.georss.org/georss",
+
+ /**
+ * APIProperty: geons
+ * {String} W3C Geo namespace to use. Defaults to
+ * "http://www.w3.org/2003/01/geo/wgs84_pos#"
+ */
+ geons: "http://www.w3.org/2003/01/geo/wgs84_pos#",
+
+ /**
+ * APIProperty: featureTitle
+ * {String} Default title for features. Defaults to "Untitled"
+ */
+ featureTitle: "Untitled",
+
+ /**
+ * APIProperty: featureDescription
+ * {String} Default description for features. Defaults to "No Description"
+ */
+ featureDescription: "No Description",
+
+ /**
+ * Property: gmlParse
+ * {Object} GML Format object for parsing features
+ * Non-API and only created if necessary
+ */
+ gmlParser: null,
+
+ /**
+ * APIProperty: xy
+ * {Boolean} Order of the GML coordinate: true:(x,y) or false:(y,x)
+ * For GeoRSS the default is (y,x), therefore: false
+ */
+ xy: false,
+
+ /**
+ * Constructor: OpenLayers.Format.GeoRSS
+ * Create a new parser for GeoRSS.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * Method: createGeometryFromItem
+ * Return a geometry from a GeoRSS Item.
+ *
+ * Parameters:
+ * item - {DOMElement} A GeoRSS item node.
+ *
+ * Returns:
+ * {<OpenLayers.Geometry>} A geometry representing the node.
+ */
+ createGeometryFromItem: function(item) {
+ var point = this.getElementsByTagNameNS(item, this.georssns, "point");
+ var lat = this.getElementsByTagNameNS(item, this.geons, 'lat');
+ var lon = this.getElementsByTagNameNS(item, this.geons, 'long');
+
+ var line = this.getElementsByTagNameNS(item,
+ this.georssns,
+ "line");
+ var polygon = this.getElementsByTagNameNS(item,
+ this.georssns,
+ "polygon");
+ var where = this.getElementsByTagNameNS(item,
+ this.georssns,
+ "where");
+ var box = this.getElementsByTagNameNS(item,
+ this.georssns,
+ "box");
+
+ if (point.length > 0 || (lat.length > 0 && lon.length > 0)) {
+ var location;
+ if (point.length > 0) {
+ location = OpenLayers.String.trim(
+ point[0].firstChild.nodeValue).split(/\s+/);
+ if (location.length !=2) {
+ location = OpenLayers.String.trim(
+ point[0].firstChild.nodeValue).split(/\s*,\s*/);
+ }
+ } else {
+ location = [parseFloat(lat[0].firstChild.nodeValue),
+ parseFloat(lon[0].firstChild.nodeValue)];
+ }
+
+ var geometry = new OpenLayers.Geometry.Point(location[1], location[0]);
+
+ } else if (line.length > 0) {
+ var coords = OpenLayers.String.trim(this.getChildValue(line[0])).split(/\s+/);
+ var components = [];
+ var point;
+ for (var i=0, len=coords.length; i<len; i+=2) {
+ point = new OpenLayers.Geometry.Point(coords[i+1], coords[i]);
+ components.push(point);
+ }
+ geometry = new OpenLayers.Geometry.LineString(components);
+ } else if (polygon.length > 0) {
+ var coords = OpenLayers.String.trim(this.getChildValue(polygon[0])).split(/\s+/);
+ var components = [];
+ var point;
+ for (var i=0, len=coords.length; i<len; i+=2) {
+ point = new OpenLayers.Geometry.Point(coords[i+1], coords[i]);
+ components.push(point);
+ }
+ geometry = new OpenLayers.Geometry.Polygon([new OpenLayers.Geometry.LinearRing(components)]);
+ } else if (where.length > 0) {
+ if (!this.gmlParser) {
+ this.gmlParser = new OpenLayers.Format.GML({'xy': this.xy});
+ }
+ var feature = this.gmlParser.parseFeature(where[0]);
+ geometry = feature.geometry;
+ } else if (box.length > 0) {
+ var coords = OpenLayers.String.trim(box[0].firstChild.nodeValue).split(/\s+/);
+ var components = [];
+ var point;
+ if (coords.length > 3) {
+ point = new OpenLayers.Geometry.Point(coords[1], coords[0]);
+ components.push(point);
+ point = new OpenLayers.Geometry.Point(coords[1], coords[2]);
+ components.push(point);
+ point = new OpenLayers.Geometry.Point(coords[3], coords[2]);
+ components.push(point);
+ point = new OpenLayers.Geometry.Point(coords[3], coords[0]);
+ components.push(point);
+ point = new OpenLayers.Geometry.Point(coords[1], coords[0]);
+ components.push(point);
+ }
+ geometry = new OpenLayers.Geometry.Polygon([new OpenLayers.Geometry.LinearRing(components)]);
+ }
+
+ if (geometry && this.internalProjection && this.externalProjection) {
+ geometry.transform(this.externalProjection,
+ this.internalProjection);
+ }
+
+ return geometry;
+ },
+
+ /**
+ * Method: createFeatureFromItem
+ * Return a feature from a GeoRSS Item.
+ *
+ * Parameters:
+ * item - {DOMElement} A GeoRSS item node.
+ *
+ * Returns:
+ * {<OpenLayers.Feature.Vector>} A feature representing the item.
+ */
+ createFeatureFromItem: function(item) {
+ var geometry = this.createGeometryFromItem(item);
+
+ /* Provide defaults for title and description */
+ var title = this._getChildValue(item, "*", "title", this.featureTitle);
+
+ /* First try RSS descriptions, then Atom summaries */
+ var description = this._getChildValue(
+ item, "*", "description",
+ this._getChildValue(item, "*", "content",
+ this._getChildValue(item, "*", "summary", this.featureDescription)));
+
+ /* If no link URL is found in the first child node, try the
+ href attribute */
+ var link = this._getChildValue(item, "*", "link");
+ if(!link) {
+ try {
+ link = this.getElementsByTagNameNS(item, "*", "link")[0].getAttribute("href");
+ } catch(e) {
+ link = null;
+ }
+ }
+
+ var id = this._getChildValue(item, "*", "id", null);
+
+ var data = {
+ "title": title,
+ "description": description,
+ "link": link
+ };
+ var feature = new OpenLayers.Feature.Vector(geometry, data);
+ feature.fid = id;
+ return feature;
+ },
+
+ /**
+ * Method: _getChildValue
+ *
+ * Parameters:
+ * node - {DOMElement}
+ * nsuri - {String} Child node namespace uri ("*" for any).
+ * name - {String} Child node name.
+ * def - {String} Optional string default to return if no child found.
+ *
+ * Returns:
+ * {String} The value of the first child with the given tag name. Returns
+ * default value or empty string if none found.
+ */
+ _getChildValue: function(node, nsuri, name, def) {
+ var value;
+ var eles = this.getElementsByTagNameNS(node, nsuri, name);
+ if(eles && eles[0] && eles[0].firstChild
+ && eles[0].firstChild.nodeValue) {
+ value = this.getChildValue(eles[0]);
+ } else {
+ value = (def == undefined) ? "" : def;
+ }
+ return value;
+ },
+
+ /**
+ * APIMethod: read
+ * Return a list of features from a GeoRSS doc
+ *
+ * Parameters:
+ * doc - {Element}
+ *
+ * Returns:
+ * {Array(<OpenLayers.Feature.Vector>)}
+ */
+ read: function(doc) {
+ if (typeof doc == "string") {
+ doc = OpenLayers.Format.XML.prototype.read.apply(this, [doc]);
+ }
+
+ /* Try RSS items first, then Atom entries */
+ var itemlist = null;
+ itemlist = this.getElementsByTagNameNS(doc, '*', 'item');
+ if (itemlist.length == 0) {
+ itemlist = this.getElementsByTagNameNS(doc, '*', 'entry');
+ }
+
+ var numItems = itemlist.length;
+ var features = new Array(numItems);
+ for(var i=0; i<numItems; i++) {
+ features[i] = this.createFeatureFromItem(itemlist[i]);
+ }
+ return features;
+ },
+
+
+ /**
+ * APIMethod: write
+ * Accept Feature Collection, and return a string.
+ *
+ * Parameters:
+ * features - {Array(<OpenLayers.Feature.Vector>)} List of features to serialize into a string.
+ */
+ write: function(features) {
+ var georss;
+ if(OpenLayers.Util.isArray(features)) {
+ georss = this.createElementNS(this.rssns, "rss");
+ for(var i=0, len=features.length; i<len; i++) {
+ georss.appendChild(this.createFeatureXML(features[i]));
+ }
+ } else {
+ georss = this.createFeatureXML(features);
+ }
+ return OpenLayers.Format.XML.prototype.write.apply(this, [georss]);
+ },
+
+ /**
+ * Method: createFeatureXML
+ * Accept an <OpenLayers.Feature.Vector>, and build a geometry for it.
+ *
+ * Parameters:
+ * feature - {<OpenLayers.Feature.Vector>}
+ *
+ * Returns:
+ * {DOMElement}
+ */
+ createFeatureXML: function(feature) {
+ var geometryNode = this.buildGeometryNode(feature.geometry);
+ var featureNode = this.createElementNS(this.rssns, "item");
+ var titleNode = this.createElementNS(this.rssns, "title");
+ titleNode.appendChild(this.createTextNode(feature.attributes.title ? feature.attributes.title : ""));
+ var descNode = this.createElementNS(this.rssns, "description");
+ descNode.appendChild(this.createTextNode(feature.attributes.description ? feature.attributes.description : ""));
+ featureNode.appendChild(titleNode);
+ featureNode.appendChild(descNode);
+ if (feature.attributes.link) {
+ var linkNode = this.createElementNS(this.rssns, "link");
+ linkNode.appendChild(this.createTextNode(feature.attributes.link));
+ featureNode.appendChild(linkNode);
+ }
+ for(var attr in feature.attributes) {
+ if (attr == "link" || attr == "title" || attr == "description") { continue; }
+ var attrText = this.createTextNode(feature.attributes[attr]);
+ var nodename = attr;
+ if (attr.search(":") != -1) {
+ nodename = attr.split(":")[1];
+ }
+ var attrContainer = this.createElementNS(this.featureNS, "feature:"+nodename);
+ attrContainer.appendChild(attrText);
+ featureNode.appendChild(attrContainer);
+ }
+ featureNode.appendChild(geometryNode);
+ return featureNode;
+ },
+
+ /**
+ * Method: buildGeometryNode
+ * builds a GeoRSS node with a given geometry
+ *
+ * Parameters:
+ * geometry - {<OpenLayers.Geometry>}
+ *
+ * Returns:
+ * {DOMElement} A gml node.
+ */
+ buildGeometryNode: function(geometry) {
+ if (this.internalProjection && this.externalProjection) {
+ geometry = geometry.clone();
+ geometry.transform(this.internalProjection,
+ this.externalProjection);
+ }
+ var node;
+ // match Polygon
+ if (geometry.CLASS_NAME == "OpenLayers.Geometry.Polygon") {
+ node = this.createElementNS(this.georssns, 'georss:polygon');
+
+ node.appendChild(this.buildCoordinatesNode(geometry.components[0]));
+ }
+ // match LineString
+ else if (geometry.CLASS_NAME == "OpenLayers.Geometry.LineString") {
+ node = this.createElementNS(this.georssns, 'georss:line');
+
+ node.appendChild(this.buildCoordinatesNode(geometry));
+ }
+ // match Point
+ else if (geometry.CLASS_NAME == "OpenLayers.Geometry.Point") {
+ node = this.createElementNS(this.georssns, 'georss:point');
+ node.appendChild(this.buildCoordinatesNode(geometry));
+ } else {
+ throw "Couldn't parse " + geometry.CLASS_NAME;
+ }
+ return node;
+ },
+
+ /**
+ * Method: buildCoordinatesNode
+ *
+ * Parameters:
+ * geometry - {<OpenLayers.Geometry>}
+ */
+ buildCoordinatesNode: function(geometry) {
+ var points = null;
+
+ if (geometry.components) {
+ points = geometry.components;
+ }
+
+ var path;
+ if (points) {
+ var numPoints = points.length;
+ var parts = new Array(numPoints);
+ for (var i = 0; i < numPoints; i++) {
+ parts[i] = points[i].y + " " + points[i].x;
+ }
+ path = parts.join(" ");
+ } else {
+ path = geometry.y + " " + geometry.x;
+ }
+ return this.createTextNode(path);
+ },
+
+ CLASS_NAME: "OpenLayers.Format.GeoRSS"
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/JSON.js b/misc/openlayers/lib/OpenLayers/Format/JSON.js
new file mode 100644
index 0000000..5b25e6a
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/JSON.js
@@ -0,0 +1,398 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * Note:
+ * This work draws heavily from the public domain JSON serializer/deserializer
+ * at http://www.json.org/json.js. Rewritten so that it doesn't modify
+ * basic data prototypes.
+ */
+
+/**
+ * @requires OpenLayers/Format.js
+ */
+
+/**
+ * Class: OpenLayers.Format.JSON
+ * A parser to read/write JSON safely. Create a new instance with the
+ * <OpenLayers.Format.JSON> constructor.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format>
+ */
+OpenLayers.Format.JSON = OpenLayers.Class(OpenLayers.Format, {
+
+ /**
+ * APIProperty: indent
+ * {String} For "pretty" printing, the indent string will be used once for
+ * each indentation level.
+ */
+ indent: " ",
+
+ /**
+ * APIProperty: space
+ * {String} For "pretty" printing, the space string will be used after
+ * the ":" separating a name/value pair.
+ */
+ space: " ",
+
+ /**
+ * APIProperty: newline
+ * {String} For "pretty" printing, the newline string will be used at the
+ * end of each name/value pair or array item.
+ */
+ newline: "\n",
+
+ /**
+ * Property: level
+ * {Integer} For "pretty" printing, this is incremented/decremented during
+ * serialization.
+ */
+ level: 0,
+
+ /**
+ * Property: pretty
+ * {Boolean} Serialize with extra whitespace for structure. This is set
+ * by the <write> method.
+ */
+ pretty: false,
+
+ /**
+ * Property: nativeJSON
+ * {Boolean} Does the browser support native json?
+ */
+ nativeJSON: (function() {
+ return !!(window.JSON && typeof JSON.parse == "function" && typeof JSON.stringify == "function");
+ })(),
+
+ /**
+ * Constructor: OpenLayers.Format.JSON
+ * Create a new parser for JSON.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * APIMethod: read
+ * Deserialize a json string.
+ *
+ * Parameters:
+ * json - {String} A JSON string
+ * filter - {Function} A function which will be called for every key and
+ * value at every level of the final result. Each value will be
+ * replaced by the result of the filter function. This can be used to
+ * reform generic objects into instances of classes, or to transform
+ * date strings into Date objects.
+ *
+ * Returns:
+ * {Object} An object, array, string, or number .
+ */
+ read: function(json, filter) {
+ var object;
+ if (this.nativeJSON) {
+ object = JSON.parse(json, filter);
+ } else try {
+ /**
+ * Parsing happens in three stages. In the first stage, we run the
+ * text against a regular expression which looks for non-JSON
+ * characters. We are especially concerned with '()' and 'new'
+ * because they can cause invocation, and '=' because it can
+ * cause mutation. But just to be safe, we will reject all
+ * unexpected characters.
+ */
+ if (/^[\],:{}\s]*$/.test(json.replace(/\\["\\\/bfnrtu]/g, '@').
+ replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
+ replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
+
+ /**
+ * In the second stage we use the eval function to compile the
+ * text into a JavaScript structure. The '{' operator is
+ * subject to a syntactic ambiguity in JavaScript - it can
+ * begin a block or an object literal. We wrap the text in
+ * parens to eliminate the ambiguity.
+ */
+ object = eval('(' + json + ')');
+
+ /**
+ * In the optional third stage, we recursively walk the new
+ * structure, passing each name/value pair to a filter
+ * function for possible transformation.
+ */
+ if(typeof filter === 'function') {
+ function walk(k, v) {
+ if(v && typeof v === 'object') {
+ for(var i in v) {
+ if(v.hasOwnProperty(i)) {
+ v[i] = walk(i, v[i]);
+ }
+ }
+ }
+ return filter(k, v);
+ }
+ object = walk('', object);
+ }
+ }
+ } catch(e) {
+ // Fall through if the regexp test fails.
+ }
+
+ if(this.keepData) {
+ this.data = object;
+ }
+
+ return object;
+ },
+
+ /**
+ * APIMethod: write
+ * Serialize an object into a JSON string.
+ *
+ * Parameters:
+ * value - {String} The object, array, string, number, boolean or date
+ * to be serialized.
+ * pretty - {Boolean} Structure the output with newlines and indentation.
+ * Default is false.
+ *
+ * Returns:
+ * {String} The JSON string representation of the input value.
+ */
+ write: function(value, pretty) {
+ this.pretty = !!pretty;
+ var json = null;
+ var type = typeof value;
+ if(this.serialize[type]) {
+ try {
+ json = (!this.pretty && this.nativeJSON) ?
+ JSON.stringify(value) :
+ this.serialize[type].apply(this, [value]);
+ } catch(err) {
+ OpenLayers.Console.error("Trouble serializing: " + err);
+ }
+ }
+ return json;
+ },
+
+ /**
+ * Method: writeIndent
+ * Output an indentation string depending on the indentation level.
+ *
+ * Returns:
+ * {String} An appropriate indentation string.
+ */
+ writeIndent: function() {
+ var pieces = [];
+ if(this.pretty) {
+ for(var i=0; i<this.level; ++i) {
+ pieces.push(this.indent);
+ }
+ }
+ return pieces.join('');
+ },
+
+ /**
+ * Method: writeNewline
+ * Output a string representing a newline if in pretty printing mode.
+ *
+ * Returns:
+ * {String} A string representing a new line.
+ */
+ writeNewline: function() {
+ return (this.pretty) ? this.newline : '';
+ },
+
+ /**
+ * Method: writeSpace
+ * Output a string representing a space if in pretty printing mode.
+ *
+ * Returns:
+ * {String} A space.
+ */
+ writeSpace: function() {
+ return (this.pretty) ? this.space : '';
+ },
+
+ /**
+ * Property: serialize
+ * Object with properties corresponding to the serializable data types.
+ * Property values are functions that do the actual serializing.
+ */
+ serialize: {
+ /**
+ * Method: serialize.object
+ * Transform an object into a JSON string.
+ *
+ * Parameters:
+ * object - {Object} The object to be serialized.
+ *
+ * Returns:
+ * {String} A JSON string representing the object.
+ */
+ 'object': function(object) {
+ // three special objects that we want to treat differently
+ if(object == null) {
+ return "null";
+ }
+ if(object.constructor == Date) {
+ return this.serialize.date.apply(this, [object]);
+ }
+ if(object.constructor == Array) {
+ return this.serialize.array.apply(this, [object]);
+ }
+ var pieces = ['{'];
+ this.level += 1;
+ var key, keyJSON, valueJSON;
+
+ var addComma = false;
+ for(key in object) {
+ if(object.hasOwnProperty(key)) {
+ // recursive calls need to allow for sub-classing
+ keyJSON = OpenLayers.Format.JSON.prototype.write.apply(this,
+ [key, this.pretty]);
+ valueJSON = OpenLayers.Format.JSON.prototype.write.apply(this,
+ [object[key], this.pretty]);
+ if(keyJSON != null && valueJSON != null) {
+ if(addComma) {
+ pieces.push(',');
+ }
+ pieces.push(this.writeNewline(), this.writeIndent(),
+ keyJSON, ':', this.writeSpace(), valueJSON);
+ addComma = true;
+ }
+ }
+ }
+
+ this.level -= 1;
+ pieces.push(this.writeNewline(), this.writeIndent(), '}');
+ return pieces.join('');
+ },
+
+ /**
+ * Method: serialize.array
+ * Transform an array into a JSON string.
+ *
+ * Parameters:
+ * array - {Array} The array to be serialized
+ *
+ * Returns:
+ * {String} A JSON string representing the array.
+ */
+ 'array': function(array) {
+ var json;
+ var pieces = ['['];
+ this.level += 1;
+
+ for(var i=0, len=array.length; i<len; ++i) {
+ // recursive calls need to allow for sub-classing
+ json = OpenLayers.Format.JSON.prototype.write.apply(this,
+ [array[i], this.pretty]);
+ if(json != null) {
+ if(i > 0) {
+ pieces.push(',');
+ }
+ pieces.push(this.writeNewline(), this.writeIndent(), json);
+ }
+ }
+
+ this.level -= 1;
+ pieces.push(this.writeNewline(), this.writeIndent(), ']');
+ return pieces.join('');
+ },
+
+ /**
+ * Method: serialize.string
+ * Transform a string into a JSON string.
+ *
+ * Parameters:
+ * string - {String} The string to be serialized
+ *
+ * Returns:
+ * {String} A JSON string representing the string.
+ */
+ 'string': function(string) {
+ // If the string contains no control characters, no quote characters, and no
+ // backslash characters, then we can simply slap some quotes around it.
+ // Otherwise we must also replace the offending characters with safe
+ // sequences.
+ var m = {
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '"' : '\\"',
+ '\\': '\\\\'
+ };
+ if(/["\\\x00-\x1f]/.test(string)) {
+ return '"' + string.replace(/([\x00-\x1f\\"])/g, function(a, b) {
+ var c = m[b];
+ if(c) {
+ return c;
+ }
+ c = b.charCodeAt();
+ return '\\u00' +
+ Math.floor(c / 16).toString(16) +
+ (c % 16).toString(16);
+ }) + '"';
+ }
+ return '"' + string + '"';
+ },
+
+ /**
+ * Method: serialize.number
+ * Transform a number into a JSON string.
+ *
+ * Parameters:
+ * number - {Number} The number to be serialized.
+ *
+ * Returns:
+ * {String} A JSON string representing the number.
+ */
+ 'number': function(number) {
+ return isFinite(number) ? String(number) : "null";
+ },
+
+ /**
+ * Method: serialize.boolean
+ * Transform a boolean into a JSON string.
+ *
+ * Parameters:
+ * bool - {Boolean} The boolean to be serialized.
+ *
+ * Returns:
+ * {String} A JSON string representing the boolean.
+ */
+ 'boolean': function(bool) {
+ return String(bool);
+ },
+
+ /**
+ * Method: serialize.object
+ * Transform a date into a JSON string.
+ *
+ * Parameters:
+ * date - {Date} The date to be serialized.
+ *
+ * Returns:
+ * {String} A JSON string representing the date.
+ */
+ 'date': function(date) {
+ function format(number) {
+ // Format integers to have at least two digits.
+ return (number < 10) ? '0' + number : number;
+ }
+ return '"' + date.getFullYear() + '-' +
+ format(date.getMonth() + 1) + '-' +
+ format(date.getDate()) + 'T' +
+ format(date.getHours()) + ':' +
+ format(date.getMinutes()) + ':' +
+ format(date.getSeconds()) + '"';
+ }
+ },
+
+ CLASS_NAME: "OpenLayers.Format.JSON"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/KML.js b/misc/openlayers/lib/OpenLayers/Format/KML.js
new file mode 100644
index 0000000..e10bce7
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/KML.js
@@ -0,0 +1,1517 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/BaseTypes/Date.js
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Feature/Vector.js
+ * @requires OpenLayers/Geometry/Point.js
+ * @requires OpenLayers/Geometry/LineString.js
+ * @requires OpenLayers/Geometry/Polygon.js
+ * @requires OpenLayers/Geometry/Collection.js
+ * @requires OpenLayers/Request/XMLHttpRequest.js
+ * @requires OpenLayers/Projection.js
+ */
+
+/**
+ * Class: OpenLayers.Format.KML
+ * Read/Write KML. Create a new instance with the <OpenLayers.Format.KML>
+ * constructor.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.KML = OpenLayers.Class(OpenLayers.Format.XML, {
+
+ /**
+ * Property: namespaces
+ * {Object} Mapping of namespace aliases to namespace URIs.
+ */
+ namespaces: {
+ kml: "http://www.opengis.net/kml/2.2",
+ gx: "http://www.google.com/kml/ext/2.2"
+ },
+
+ /**
+ * APIProperty: kmlns
+ * {String} KML Namespace to use. Defaults to 2.0 namespace.
+ */
+ kmlns: "http://earth.google.com/kml/2.0",
+
+ /**
+ * APIProperty: placemarksDesc
+ * {String} Name of the placemarks. Default is "No description available".
+ */
+ placemarksDesc: "No description available",
+
+ /**
+ * APIProperty: foldersName
+ * {String} Name of the folders. Default is "OpenLayers export".
+ * If set to null, no name element will be created.
+ */
+ foldersName: "OpenLayers export",
+
+ /**
+ * APIProperty: foldersDesc
+ * {String} Description of the folders. Default is "Exported on [date]."
+ * If set to null, no description element will be created.
+ */
+ foldersDesc: "Exported on " + new Date(),
+
+ /**
+ * APIProperty: extractAttributes
+ * {Boolean} Extract attributes from KML. Default is true.
+ * Extracting styleUrls requires this to be set to true
+ * Note that currently only Data and SimpleData
+ * elements are handled.
+ */
+ extractAttributes: true,
+
+ /**
+ * APIProperty: kvpAttributes
+ * {Boolean} Only used if extractAttributes is true.
+ * If set to true, attributes will be simple
+ * key-value pairs, compatible with other formats,
+ * Any displayName elements will be ignored.
+ * If set to false, attributes will be objects,
+ * retaining any displayName elements, but not
+ * compatible with other formats. Any CDATA in
+ * displayName will be read in as a string value.
+ * Default is false.
+ */
+ kvpAttributes: false,
+
+ /**
+ * Property: extractStyles
+ * {Boolean} Extract styles from KML. Default is false.
+ * Extracting styleUrls also requires extractAttributes to be
+ * set to true
+ */
+ extractStyles: false,
+
+ /**
+ * APIProperty: extractTracks
+ * {Boolean} Extract gx:Track elements from Placemark elements. Default
+ * is false. If true, features will be generated for all points in
+ * all gx:Track elements. Features will have a when (Date) attribute
+ * based on when elements in the track. If tracks include angle
+ * elements, features will have heading, tilt, and roll attributes.
+ * If track point coordinates have three values, features will have
+ * an altitude attribute with the third coordinate value.
+ */
+ extractTracks: false,
+
+ /**
+ * APIProperty: trackAttributes
+ * {Array} If <extractTracks> is true, points within gx:Track elements will
+ * be parsed as features with when, heading, tilt, and roll attributes.
+ * Any additional attribute names can be provided in <trackAttributes>.
+ */
+ trackAttributes: null,
+
+ /**
+ * Property: internalns
+ * {String} KML Namespace to use -- defaults to the namespace of the
+ * Placemark node being parsed, but falls back to kmlns.
+ */
+ internalns: null,
+
+ /**
+ * Property: features
+ * {Array} Array of features
+ *
+ */
+ features: null,
+
+ /**
+ * Property: styles
+ * {Object} Storage of style objects
+ *
+ */
+ styles: null,
+
+ /**
+ * Property: styleBaseUrl
+ * {String}
+ */
+ styleBaseUrl: "",
+
+ /**
+ * Property: fetched
+ * {Object} Storage of KML URLs that have been fetched before
+ * in order to prevent reloading them.
+ */
+ fetched: null,
+
+ /**
+ * APIProperty: maxDepth
+ * {Integer} Maximum depth for recursive loading external KML URLs
+ * Defaults to 0: do no external fetching
+ */
+ maxDepth: 0,
+
+ /**
+ * Constructor: OpenLayers.Format.KML
+ * Create a new parser for KML.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+ initialize: function(options) {
+ // compile regular expressions once instead of every time they are used
+ this.regExes = {
+ trimSpace: (/^\s*|\s*$/g),
+ removeSpace: (/\s*/g),
+ splitSpace: (/\s+/),
+ trimComma: (/\s*,\s*/g),
+ kmlColor: (/(\w{2})(\w{2})(\w{2})(\w{2})/),
+ kmlIconPalette: (/root:\/\/icons\/palette-(\d+)(\.\w+)/),
+ straightBracket: (/\$\[(.*?)\]/g)
+ };
+ // KML coordinates are always in longlat WGS84
+ this.externalProjection = new OpenLayers.Projection("EPSG:4326");
+
+ OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+ },
+
+ /**
+ * APIMethod: read
+ * Read data from a string, and return a list of features.
+ *
+ * Parameters:
+ * data - {String} or {DOMElement} data to read/parse.
+ *
+ * Returns:
+ * {Array(<OpenLayers.Feature.Vector>)} List of features.
+ */
+ read: function(data) {
+ this.features = [];
+ this.styles = {};
+ this.fetched = {};
+
+ // Set default options
+ var options = {
+ depth: 0,
+ styleBaseUrl: this.styleBaseUrl
+ };
+
+ return this.parseData(data, options);
+ },
+
+ /**
+ * Method: parseData
+ * Read data from a string, and return a list of features.
+ *
+ * Parameters:
+ * data - {String} or {DOMElement} data to read/parse.
+ * options - {Object} Hash of options
+ *
+ * Returns:
+ * {Array(<OpenLayers.Feature.Vector>)} List of features.
+ */
+ parseData: function(data, options) {
+ if(typeof data == "string") {
+ data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+ }
+
+ // Loop throught the following node types in this order and
+ // process the nodes found
+ var types = ["Link", "NetworkLink", "Style", "StyleMap", "Placemark"];
+ for(var i=0, len=types.length; i<len; ++i) {
+ var type = types[i];
+
+ var nodes = this.getElementsByTagNameNS(data, "*", type);
+
+ // skip to next type if no nodes are found
+ if(nodes.length == 0) {
+ continue;
+ }
+
+ switch (type.toLowerCase()) {
+
+ // Fetch external links
+ case "link":
+ case "networklink":
+ this.parseLinks(nodes, options);
+ break;
+
+ // parse style information
+ case "style":
+ if (this.extractStyles) {
+ this.parseStyles(nodes, options);
+ }
+ break;
+ case "stylemap":
+ if (this.extractStyles) {
+ this.parseStyleMaps(nodes, options);
+ }
+ break;
+
+ // parse features
+ case "placemark":
+ this.parseFeatures(nodes, options);
+ break;
+ }
+ }
+
+ return this.features;
+ },
+
+ /**
+ * Method: parseLinks
+ * Finds URLs of linked KML documents and fetches them
+ *
+ * Parameters:
+ * nodes - {Array} of {DOMElement} data to read/parse.
+ * options - {Object} Hash of options
+ *
+ */
+ parseLinks: function(nodes, options) {
+
+ // Fetch external links <NetworkLink> and <Link>
+ // Don't do anything if we have reached our maximum depth for recursion
+ if (options.depth >= this.maxDepth) {
+ return false;
+ }
+
+ // increase depth
+ var newOptions = OpenLayers.Util.extend({}, options);
+ newOptions.depth++;
+
+ for(var i=0, len=nodes.length; i<len; i++) {
+ var href = this.parseProperty(nodes[i], "*", "href");
+ if(href && !this.fetched[href]) {
+ this.fetched[href] = true; // prevent reloading the same urls
+ var data = this.fetchLink(href);
+ if (data) {
+ this.parseData(data, newOptions);
+ }
+ }
+ }
+
+ },
+
+ /**
+ * Method: fetchLink
+ * Fetches a URL and returns the result
+ *
+ * Parameters:
+ * href - {String} url to be fetched
+ *
+ */
+ fetchLink: function(href) {
+ var request = OpenLayers.Request.GET({url: href, async: false});
+ if (request) {
+ return request.responseText;
+ }
+ },
+
+ /**
+ * Method: parseStyles
+ * Parses <Style> nodes
+ *
+ * Parameters:
+ * nodes - {Array} of {DOMElement} data to read/parse.
+ * options - {Object} Hash of options
+ *
+ */
+ parseStyles: function(nodes, options) {
+ for(var i=0, len=nodes.length; i<len; i++) {
+ var style = this.parseStyle(nodes[i]);
+ if(style) {
+ var styleName = (options.styleBaseUrl || "") + "#" + style.id;
+
+ this.styles[styleName] = style;
+ }
+ }
+ },
+
+ /**
+ * Method: parseKmlColor
+ * Parses a kml color (in 'aabbggrr' format) and returns the corresponding
+ * color and opacity or null if the color is invalid.
+ *
+ * Parameters:
+ * kmlColor - {String} a kml formated color
+ *
+ * Returns:
+ * {Object}
+ */
+ parseKmlColor: function(kmlColor) {
+ var color = null;
+ if (kmlColor) {
+ var matches = kmlColor.match(this.regExes.kmlColor);
+ if (matches) {
+ color = {
+ color: '#' + matches[4] + matches[3] + matches[2],
+ opacity: parseInt(matches[1], 16) / 255
+ };
+ }
+ }
+ return color;
+ },
+
+ /**
+ * Method: parseStyle
+ * Parses the children of a <Style> node and builds the style hash
+ * accordingly
+ *
+ * Parameters:
+ * node - {DOMElement} <Style> node
+ *
+ */
+ parseStyle: function(node) {
+ var style = {};
+
+ var types = ["LineStyle", "PolyStyle", "IconStyle", "BalloonStyle",
+ "LabelStyle"];
+ var type, styleTypeNode, nodeList, geometry, parser;
+ for(var i=0, len=types.length; i<len; ++i) {
+ type = types[i];
+ styleTypeNode = this.getElementsByTagNameNS(node, "*", type)[0];
+ if(!styleTypeNode) {
+ continue;
+ }
+
+ // only deal with first geometry of this type
+ switch (type.toLowerCase()) {
+ case "linestyle":
+ var kmlColor = this.parseProperty(styleTypeNode, "*", "color");
+ var color = this.parseKmlColor(kmlColor);
+ if (color) {
+ style["strokeColor"] = color.color;
+ style["strokeOpacity"] = color.opacity;
+ }
+
+ var width = this.parseProperty(styleTypeNode, "*", "width");
+ if (width) {
+ style["strokeWidth"] = width;
+ }
+ break;
+
+ case "polystyle":
+ var kmlColor = this.parseProperty(styleTypeNode, "*", "color");
+ var color = this.parseKmlColor(kmlColor);
+ if (color) {
+ style["fillOpacity"] = color.opacity;
+ style["fillColor"] = color.color;
+ }
+ // Check if fill is disabled
+ var fill = this.parseProperty(styleTypeNode, "*", "fill");
+ if (fill == "0") {
+ style["fillColor"] = "none";
+ }
+ // Check if outline is disabled
+ var outline = this.parseProperty(styleTypeNode, "*", "outline");
+ if (outline == "0") {
+ style["strokeWidth"] = "0";
+ }
+
+ break;
+
+ case "iconstyle":
+ // set scale
+ var scale = parseFloat(this.parseProperty(styleTypeNode,
+ "*", "scale") || 1);
+
+ // set default width and height of icon
+ var width = 32 * scale;
+ var height = 32 * scale;
+
+ var iconNode = this.getElementsByTagNameNS(styleTypeNode,
+ "*",
+ "Icon")[0];
+ if (iconNode) {
+ var href = this.parseProperty(iconNode, "*", "href");
+ if (href) {
+
+ var w = this.parseProperty(iconNode, "*", "w");
+ var h = this.parseProperty(iconNode, "*", "h");
+
+ // Settings for Google specific icons that are 64x64
+ // We set the width and height to 64 and halve the
+ // scale to prevent icons from being too big
+ var google = "http://maps.google.com/mapfiles/kml";
+ if (OpenLayers.String.startsWith(
+ href, google) && !w && !h) {
+ w = 64;
+ h = 64;
+ scale = scale / 2;
+ }
+
+ // if only dimension is defined, make sure the
+ // other one has the same value
+ w = w || h;
+ h = h || w;
+
+ if (w) {
+ width = parseInt(w) * scale;
+ }
+
+ if (h) {
+ height = parseInt(h) * scale;
+ }
+
+ // support for internal icons
+ // (/root://icons/palette-x.png)
+ // x and y tell the position on the palette:
+ // - in pixels
+ // - starting from the left bottom
+ // We translate that to a position in the list
+ // and request the appropriate icon from the
+ // google maps website
+ var matches = href.match(this.regExes.kmlIconPalette);
+ if (matches) {
+ var palette = matches[1];
+ var file_extension = matches[2];
+
+ var x = this.parseProperty(iconNode, "*", "x");
+ var y = this.parseProperty(iconNode, "*", "y");
+
+ var posX = x ? x/32 : 0;
+ var posY = y ? (7 - y/32) : 7;
+
+ var pos = posY * 8 + posX;
+ href = "http://maps.google.com/mapfiles/kml/pal"
+ + palette + "/icon" + pos + file_extension;
+ }
+
+ style["graphicOpacity"] = 1; // fully opaque
+ style["externalGraphic"] = href;
+ }
+
+ }
+
+
+ // hotSpots define the offset for an Icon
+ var hotSpotNode = this.getElementsByTagNameNS(styleTypeNode,
+ "*",
+ "hotSpot")[0];
+ if (hotSpotNode) {
+ var x = parseFloat(hotSpotNode.getAttribute("x"));
+ var y = parseFloat(hotSpotNode.getAttribute("y"));
+
+ var xUnits = hotSpotNode.getAttribute("xunits");
+ if (xUnits == "pixels") {
+ style["graphicXOffset"] = -x * scale;
+ }
+ else if (xUnits == "insetPixels") {
+ style["graphicXOffset"] = -width + (x * scale);
+ }
+ else if (xUnits == "fraction") {
+ style["graphicXOffset"] = -width * x;
+ }
+
+ var yUnits = hotSpotNode.getAttribute("yunits");
+ if (yUnits == "pixels") {
+ style["graphicYOffset"] = -height + (y * scale) + 1;
+ }
+ else if (yUnits == "insetPixels") {
+ style["graphicYOffset"] = -(y * scale) + 1;
+ }
+ else if (yUnits == "fraction") {
+ style["graphicYOffset"] = -height * (1 - y) + 1;
+ }
+ }
+
+ style["graphicWidth"] = width;
+ style["graphicHeight"] = height;
+ break;
+
+ case "balloonstyle":
+ var balloonStyle = OpenLayers.Util.getXmlNodeValue(
+ styleTypeNode);
+ if (balloonStyle) {
+ style["balloonStyle"] = balloonStyle.replace(
+ this.regExes.straightBracket, "${$1}");
+ }
+ break;
+ case "labelstyle":
+ var kmlColor = this.parseProperty(styleTypeNode, "*", "color");
+ var color = this.parseKmlColor(kmlColor);
+ if (color) {
+ style["fontColor"] = color.color;
+ style["fontOpacity"] = color.opacity;
+ }
+ break;
+
+ default:
+ }
+ }
+
+ // Some polygons have no line color, so we use the fillColor for that
+ if (!style["strokeColor"] && style["fillColor"]) {
+ style["strokeColor"] = style["fillColor"];
+ }
+
+ var id = node.getAttribute("id");
+ if (id && style) {
+ style.id = id;
+ }
+
+ return style;
+ },
+
+ /**
+ * Method: parseStyleMaps
+ * Parses <StyleMap> nodes, but only uses the 'normal' key
+ *
+ * Parameters:
+ * nodes - {Array} of {DOMElement} data to read/parse.
+ * options - {Object} Hash of options
+ *
+ */
+ parseStyleMaps: function(nodes, options) {
+ // Only the default or "normal" part of the StyleMap is processed now
+ // To do the select or "highlight" bit, we'd need to change lots more
+
+ for(var i=0, len=nodes.length; i<len; i++) {
+ var node = nodes[i];
+ var pairs = this.getElementsByTagNameNS(node, "*",
+ "Pair");
+
+ var id = node.getAttribute("id");
+ for (var j=0, jlen=pairs.length; j<jlen; j++) {
+ var pair = pairs[j];
+ // Use the shortcut in the SLD format to quickly retrieve the
+ // value of a node. Maybe it's good to have a method in
+ // Format.XML to do this
+ var key = this.parseProperty(pair, "*", "key");
+ var styleUrl = this.parseProperty(pair, "*", "styleUrl");
+
+ if (styleUrl && key == "normal") {
+ this.styles[(options.styleBaseUrl || "") + "#" + id] =
+ this.styles[(options.styleBaseUrl || "") + styleUrl];
+ }
+
+ // TODO: implement the "select" part
+ //if (styleUrl && key == "highlight") {
+ //}
+
+ }
+ }
+
+ },
+
+
+ /**
+ * Method: parseFeatures
+ * Loop through all Placemark nodes and parse them.
+ * Will create a list of features
+ *
+ * Parameters:
+ * nodes - {Array} of {DOMElement} data to read/parse.
+ * options - {Object} Hash of options
+ *
+ */
+ parseFeatures: function(nodes, options) {
+ var features = [];
+ for(var i=0, len=nodes.length; i<len; i++) {
+ var featureNode = nodes[i];
+ var feature = this.parseFeature.apply(this,[featureNode]) ;
+ if(feature) {
+
+ // Create reference to styleUrl
+ if (this.extractStyles && feature.attributes &&
+ feature.attributes.styleUrl) {
+ feature.style = this.getStyle(feature.attributes.styleUrl, options);
+ }
+
+ if (this.extractStyles) {
+ // Make sure that <Style> nodes within a placemark are
+ // processed as well
+ var inlineStyleNode = this.getElementsByTagNameNS(featureNode,
+ "*",
+ "Style")[0];
+ if (inlineStyleNode) {
+ var inlineStyle= this.parseStyle(inlineStyleNode);
+ if (inlineStyle) {
+ feature.style = OpenLayers.Util.extend(
+ feature.style, inlineStyle
+ );
+ }
+ }
+ }
+
+ // check if gx:Track elements should be parsed
+ if (this.extractTracks) {
+ var tracks = this.getElementsByTagNameNS(
+ featureNode, this.namespaces.gx, "Track"
+ );
+ if (tracks && tracks.length > 0) {
+ var track = tracks[0];
+ var container = {
+ features: [],
+ feature: feature
+ };
+ this.readNode(track, container);
+ if (container.features.length > 0) {
+ features.push.apply(features, container.features);
+ }
+ }
+ } else {
+ // add feature to list of features
+ features.push(feature);
+ }
+ } else {
+ throw "Bad Placemark: " + i;
+ }
+ }
+
+ // add new features to existing feature list
+ this.features = this.features.concat(features);
+ },
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "kml": {
+ "when": function(node, container) {
+ container.whens.push(OpenLayers.Date.parse(
+ this.getChildValue(node)
+ ));
+ },
+ "_trackPointAttribute": function(node, container) {
+ var name = node.nodeName.split(":").pop();
+ container.attributes[name].push(this.getChildValue(node));
+ }
+ },
+ "gx": {
+ "Track": function(node, container) {
+ var obj = {
+ whens: [],
+ points: [],
+ angles: []
+ };
+ if (this.trackAttributes) {
+ var name;
+ obj.attributes = {};
+ for (var i=0, ii=this.trackAttributes.length; i<ii; ++i) {
+ name = this.trackAttributes[i];
+ obj.attributes[name] = [];
+ if (!(name in this.readers.kml)) {
+ this.readers.kml[name] = this.readers.kml._trackPointAttribute;
+ }
+ }
+ }
+ this.readChildNodes(node, obj);
+ if (obj.whens.length !== obj.points.length) {
+ throw new Error("gx:Track with unequal number of when (" +
+ obj.whens.length + ") and gx:coord (" +
+ obj.points.length + ") elements.");
+ }
+ var hasAngles = obj.angles.length > 0;
+ if (hasAngles && obj.whens.length !== obj.angles.length) {
+ throw new Error("gx:Track with unequal number of when (" +
+ obj.whens.length + ") and gx:angles (" +
+ obj.angles.length + ") elements.");
+ }
+ var feature, point, angles;
+ for (var i=0, ii=obj.whens.length; i<ii; ++i) {
+ feature = container.feature.clone();
+ feature.fid = container.feature.fid || container.feature.id;
+ point = obj.points[i];
+ feature.geometry = point;
+ if ("z" in point) {
+ feature.attributes.altitude = point.z;
+ }
+ if (this.internalProjection && this.externalProjection) {
+ feature.geometry.transform(
+ this.externalProjection, this.internalProjection
+ );
+ }
+ if (this.trackAttributes) {
+ for (var j=0, jj=this.trackAttributes.length; j<jj; ++j) {
+ var name = this.trackAttributes[j];
+ feature.attributes[name] = obj.attributes[name][i];
+ }
+ }
+ feature.attributes.when = obj.whens[i];
+ feature.attributes.trackId = container.feature.id;
+ if (hasAngles) {
+ angles = obj.angles[i];
+ feature.attributes.heading = parseFloat(angles[0]);
+ feature.attributes.tilt = parseFloat(angles[1]);
+ feature.attributes.roll = parseFloat(angles[2]);
+ }
+ container.features.push(feature);
+ }
+ },
+ "coord": function(node, container) {
+ var str = this.getChildValue(node);
+ var coords = str.replace(this.regExes.trimSpace, "").split(/\s+/);
+ var point = new OpenLayers.Geometry.Point(coords[0], coords[1]);
+ if (coords.length > 2) {
+ point.z = parseFloat(coords[2]);
+ }
+ container.points.push(point);
+ },
+ "angles": function(node, container) {
+ var str = this.getChildValue(node);
+ var parts = str.replace(this.regExes.trimSpace, "").split(/\s+/);
+ container.angles.push(parts);
+ }
+ }
+ },
+
+ /**
+ * Method: parseFeature
+ * This function is the core of the KML parsing code in OpenLayers.
+ * It creates the geometries that are then attached to the returned
+ * feature, and calls parseAttributes() to get attribute data out.
+ *
+ * Parameters:
+ * node - {DOMElement}
+ *
+ * Returns:
+ * {<OpenLayers.Feature.Vector>} A vector feature.
+ */
+ parseFeature: function(node) {
+ // only accept one geometry per feature - look for highest "order"
+ var order = ["MultiGeometry", "Polygon", "LineString", "Point"];
+ var type, nodeList, geometry, parser;
+ for(var i=0, len=order.length; i<len; ++i) {
+ type = order[i];
+ this.internalns = node.namespaceURI ?
+ node.namespaceURI : this.kmlns;
+ nodeList = this.getElementsByTagNameNS(node,
+ this.internalns, type);
+ if(nodeList.length > 0) {
+ // only deal with first geometry of this type
+ var parser = this.parseGeometry[type.toLowerCase()];
+ if(parser) {
+ geometry = parser.apply(this, [nodeList[0]]);
+ if (this.internalProjection && this.externalProjection) {
+ geometry.transform(this.externalProjection,
+ this.internalProjection);
+ }
+ } else {
+ throw new TypeError("Unsupported geometry type: " + type);
+ }
+ // stop looking for different geometry types
+ break;
+ }
+ }
+
+ // construct feature (optionally with attributes)
+ var attributes;
+ if(this.extractAttributes) {
+ attributes = this.parseAttributes(node);
+ }
+ var feature = new OpenLayers.Feature.Vector(geometry, attributes);
+
+ var fid = node.getAttribute("id") || node.getAttribute("name");
+ if(fid != null) {
+ feature.fid = fid;
+ }
+
+ return feature;
+ },
+
+ /**
+ * Method: getStyle
+ * Retrieves a style from a style hash using styleUrl as the key
+ * If the styleUrl doesn't exist yet, we try to fetch it
+ * Internet
+ *
+ * Parameters:
+ * styleUrl - {String} URL of style
+ * options - {Object} Hash of options
+ *
+ * Returns:
+ * {Object} - (reference to) Style hash
+ */
+ getStyle: function(styleUrl, options) {
+
+ var styleBaseUrl = OpenLayers.Util.removeTail(styleUrl);
+
+ var newOptions = OpenLayers.Util.extend({}, options);
+ newOptions.depth++;
+ newOptions.styleBaseUrl = styleBaseUrl;
+
+ // Fetch remote Style URLs (if not fetched before)
+ if (!this.styles[styleUrl]
+ && !OpenLayers.String.startsWith(styleUrl, "#")
+ && newOptions.depth <= this.maxDepth
+ && !this.fetched[styleBaseUrl] ) {
+
+ var data = this.fetchLink(styleBaseUrl);
+ if (data) {
+ this.parseData(data, newOptions);
+ }
+
+ }
+
+ // return requested style
+ var style = OpenLayers.Util.extend({}, this.styles[styleUrl]);
+ return style;
+ },
+
+ /**
+ * Property: parseGeometry
+ * Properties of this object are the functions that parse geometries based
+ * on their type.
+ */
+ parseGeometry: {
+
+ /**
+ * Method: parseGeometry.point
+ * Given a KML node representing a point geometry, create an OpenLayers
+ * point geometry.
+ *
+ * Parameters:
+ * node - {DOMElement} A KML Point node.
+ *
+ * Returns:
+ * {<OpenLayers.Geometry.Point>} A point geometry.
+ */
+ point: function(node) {
+ var nodeList = this.getElementsByTagNameNS(node, this.internalns,
+ "coordinates");
+ var coords = [];
+ if(nodeList.length > 0) {
+ var coordString = nodeList[0].firstChild.nodeValue;
+ coordString = coordString.replace(this.regExes.removeSpace, "");
+ coords = coordString.split(",");
+ }
+
+ var point = null;
+ if(coords.length > 1) {
+ // preserve third dimension
+ if(coords.length == 2) {
+ coords[2] = null;
+ }
+ point = new OpenLayers.Geometry.Point(coords[0], coords[1],
+ coords[2]);
+ } else {
+ throw "Bad coordinate string: " + coordString;
+ }
+ return point;
+ },
+
+ /**
+ * Method: parseGeometry.linestring
+ * Given a KML node representing a linestring geometry, create an
+ * OpenLayers linestring geometry.
+ *
+ * Parameters:
+ * node - {DOMElement} A KML LineString node.
+ *
+ * Returns:
+ * {<OpenLayers.Geometry.LineString>} A linestring geometry.
+ */
+ linestring: function(node, ring) {
+ var nodeList = this.getElementsByTagNameNS(node, this.internalns,
+ "coordinates");
+ var line = null;
+ if(nodeList.length > 0) {
+ var coordString = this.getChildValue(nodeList[0]);
+
+ coordString = coordString.replace(this.regExes.trimSpace,
+ "");
+ coordString = coordString.replace(this.regExes.trimComma,
+ ",");
+ var pointList = coordString.split(this.regExes.splitSpace);
+ var numPoints = pointList.length;
+ var points = new Array(numPoints);
+ var coords, numCoords;
+ for(var i=0; i<numPoints; ++i) {
+ coords = pointList[i].split(",");
+ numCoords = coords.length;
+ if(numCoords > 1) {
+ if(coords.length == 2) {
+ coords[2] = null;
+ }
+ points[i] = new OpenLayers.Geometry.Point(coords[0],
+ coords[1],
+ coords[2]);
+ } else {
+ throw "Bad LineString point coordinates: " +
+ pointList[i];
+ }
+ }
+ if(numPoints) {
+ if(ring) {
+ line = new OpenLayers.Geometry.LinearRing(points);
+ } else {
+ line = new OpenLayers.Geometry.LineString(points);
+ }
+ } else {
+ throw "Bad LineString coordinates: " + coordString;
+ }
+ }
+
+ return line;
+ },
+
+ /**
+ * Method: parseGeometry.polygon
+ * Given a KML node representing a polygon geometry, create an
+ * OpenLayers polygon geometry.
+ *
+ * Parameters:
+ * node - {DOMElement} A KML Polygon node.
+ *
+ * Returns:
+ * {<OpenLayers.Geometry.Polygon>} A polygon geometry.
+ */
+ polygon: function(node) {
+ var nodeList = this.getElementsByTagNameNS(node, this.internalns,
+ "LinearRing");
+ var numRings = nodeList.length;
+ var components = new Array(numRings);
+ if(numRings > 0) {
+ // this assumes exterior ring first, inner rings after
+ var ring;
+ for(var i=0, len=nodeList.length; i<len; ++i) {
+ ring = this.parseGeometry.linestring.apply(this,
+ [nodeList[i], true]);
+ if(ring) {
+ components[i] = ring;
+ } else {
+ throw "Bad LinearRing geometry: " + i;
+ }
+ }
+ }
+ return new OpenLayers.Geometry.Polygon(components);
+ },
+
+ /**
+ * Method: parseGeometry.multigeometry
+ * Given a KML node representing a multigeometry, create an
+ * OpenLayers geometry collection.
+ *
+ * Parameters:
+ * node - {DOMElement} A KML MultiGeometry node.
+ *
+ * Returns:
+ * {<OpenLayers.Geometry.Collection>} A geometry collection.
+ */
+ multigeometry: function(node) {
+ var child, parser;
+ var parts = [];
+ var children = node.childNodes;
+ for(var i=0, len=children.length; i<len; ++i ) {
+ child = children[i];
+ if(child.nodeType == 1) {
+ var type = (child.prefix) ?
+ child.nodeName.split(":")[1] :
+ child.nodeName;
+ var parser = this.parseGeometry[type.toLowerCase()];
+ if(parser) {
+ parts.push(parser.apply(this, [child]));
+ }
+ }
+ }
+ return new OpenLayers.Geometry.Collection(parts);
+ }
+
+ },
+
+ /**
+ * Method: parseAttributes
+ *
+ * Parameters:
+ * node - {DOMElement}
+ *
+ * Returns:
+ * {Object} An attributes object.
+ */
+ parseAttributes: function(node) {
+ var attributes = {};
+
+ // Extended Data is parsed first.
+ var edNodes = node.getElementsByTagName("ExtendedData");
+ if (edNodes.length) {
+ attributes = this.parseExtendedData(edNodes[0]);
+ }
+
+ // assume attribute nodes are type 1 children with a type 3 or 4 child
+ var child, grandchildren, grandchild;
+ var children = node.childNodes;
+
+ for(var i=0, len=children.length; i<len; ++i) {
+ child = children[i];
+ if(child.nodeType == 1) {
+ grandchildren = child.childNodes;
+ if(grandchildren.length >= 1 && grandchildren.length <= 3) {
+ var grandchild;
+ switch (grandchildren.length) {
+ case 1:
+ grandchild = grandchildren[0];
+ break;
+ case 2:
+ var c1 = grandchildren[0];
+ var c2 = grandchildren[1];
+ grandchild = (c1.nodeType == 3 || c1.nodeType == 4) ?
+ c1 : c2;
+ break;
+ case 3:
+ default:
+ grandchild = grandchildren[1];
+ break;
+ }
+ if(grandchild.nodeType == 3 || grandchild.nodeType == 4) {
+ var name = (child.prefix) ?
+ child.nodeName.split(":")[1] :
+ child.nodeName;
+ var value = OpenLayers.Util.getXmlNodeValue(grandchild);
+ if (value) {
+ value = value.replace(this.regExes.trimSpace, "");
+ attributes[name] = value;
+ }
+ }
+ }
+ }
+ }
+ return attributes;
+ },
+
+ /**
+ * Method: parseExtendedData
+ * Parse ExtendedData from KML. Limited support for schemas/datatypes.
+ * See http://code.google.com/apis/kml/documentation/kmlreference.html#extendeddata
+ * for more information on extendeddata.
+ */
+ parseExtendedData: function(node) {
+ var attributes = {};
+ var i, len, data, key;
+ var dataNodes = node.getElementsByTagName("Data");
+ for (i = 0, len = dataNodes.length; i < len; i++) {
+ data = dataNodes[i];
+ key = data.getAttribute("name");
+ var ed = {};
+ var valueNode = data.getElementsByTagName("value");
+ if (valueNode.length) {
+ ed['value'] = this.getChildValue(valueNode[0]);
+ }
+ if (this.kvpAttributes) {
+ attributes[key] = ed['value'];
+ } else {
+ var nameNode = data.getElementsByTagName("displayName");
+ if (nameNode.length) {
+ ed['displayName'] = this.getChildValue(nameNode[0]);
+ }
+ attributes[key] = ed;
+ }
+ }
+ var simpleDataNodes = node.getElementsByTagName("SimpleData");
+ for (i = 0, len = simpleDataNodes.length; i < len; i++) {
+ var ed = {};
+ data = simpleDataNodes[i];
+ key = data.getAttribute("name");
+ ed['value'] = this.getChildValue(data);
+ if (this.kvpAttributes) {
+ attributes[key] = ed['value'];
+ } else {
+ ed['displayName'] = key;
+ attributes[key] = ed;
+ }
+ }
+
+ return attributes;
+ },
+
+ /**
+ * Method: parseProperty
+ * Convenience method to find a node and return its value
+ *
+ * Parameters:
+ * xmlNode - {<DOMElement>}
+ * namespace - {String} namespace of the node to find
+ * tagName - {String} name of the property to parse
+ *
+ * Returns:
+ * {String} The value for the requested property (defaults to null)
+ */
+ parseProperty: function(xmlNode, namespace, tagName) {
+ var value;
+ var nodeList = this.getElementsByTagNameNS(xmlNode, namespace, tagName);
+ try {
+ value = OpenLayers.Util.getXmlNodeValue(nodeList[0]);
+ } catch(e) {
+ value = null;
+ }
+
+ return value;
+ },
+
+ /**
+ * APIMethod: write
+ * Accept Feature Collection, and return a string.
+ *
+ * Parameters:
+ * features - {Array(<OpenLayers.Feature.Vector>)} An array of features.
+ *
+ * Returns:
+ * {String} A KML string.
+ */
+ write: function(features) {
+ if(!(OpenLayers.Util.isArray(features))) {
+ features = [features];
+ }
+ var kml = this.createElementNS(this.kmlns, "kml");
+ var folder = this.createFolderXML();
+ for(var i=0, len=features.length; i<len; ++i) {
+ folder.appendChild(this.createPlacemarkXML(features[i]));
+ }
+ kml.appendChild(folder);
+ return OpenLayers.Format.XML.prototype.write.apply(this, [kml]);
+ },
+
+ /**
+ * Method: createFolderXML
+ * Creates and returns a KML folder node
+ *
+ * Returns:
+ * {DOMElement}
+ */
+ createFolderXML: function() {
+ // Folder
+ var folder = this.createElementNS(this.kmlns, "Folder");
+
+ // Folder name
+ if (this.foldersName) {
+ var folderName = this.createElementNS(this.kmlns, "name");
+ var folderNameText = this.createTextNode(this.foldersName);
+ folderName.appendChild(folderNameText);
+ folder.appendChild(folderName);
+ }
+
+ // Folder description
+ if (this.foldersDesc) {
+ var folderDesc = this.createElementNS(this.kmlns, "description");
+ var folderDescText = this.createTextNode(this.foldersDesc);
+ folderDesc.appendChild(folderDescText);
+ folder.appendChild(folderDesc);
+ }
+
+ return folder;
+ },
+
+ /**
+ * Method: createPlacemarkXML
+ * Creates and returns a KML placemark node representing the given feature.
+ *
+ * Parameters:
+ * feature - {<OpenLayers.Feature.Vector>}
+ *
+ * Returns:
+ * {DOMElement}
+ */
+ createPlacemarkXML: function(feature) {
+ // Placemark name
+ var placemarkName = this.createElementNS(this.kmlns, "name");
+ var label = (feature.style && feature.style.label) ? feature.style.label : feature.id;
+ var name = feature.attributes.name || label;
+ placemarkName.appendChild(this.createTextNode(name));
+
+ // Placemark description
+ var placemarkDesc = this.createElementNS(this.kmlns, "description");
+ var desc = feature.attributes.description || this.placemarksDesc;
+ placemarkDesc.appendChild(this.createTextNode(desc));
+
+ // Placemark
+ var placemarkNode = this.createElementNS(this.kmlns, "Placemark");
+ if(feature.fid != null) {
+ placemarkNode.setAttribute("id", feature.fid);
+ }
+ placemarkNode.appendChild(placemarkName);
+ placemarkNode.appendChild(placemarkDesc);
+
+ // Geometry node (Point, LineString, etc. nodes)
+ var geometryNode = this.buildGeometryNode(feature.geometry);
+ placemarkNode.appendChild(geometryNode);
+
+ // output attributes as extendedData
+ if (feature.attributes) {
+ var edNode = this.buildExtendedData(feature.attributes);
+ if (edNode) {
+ placemarkNode.appendChild(edNode);
+ }
+ }
+
+ return placemarkNode;
+ },
+
+ /**
+ * Method: buildGeometryNode
+ * Builds and returns a KML geometry node with the given geometry.
+ *
+ * Parameters:
+ * geometry - {<OpenLayers.Geometry>}
+ *
+ * Returns:
+ * {DOMElement}
+ */
+ buildGeometryNode: function(geometry) {
+ var className = geometry.CLASS_NAME;
+ var type = className.substring(className.lastIndexOf(".") + 1);
+ var builder = this.buildGeometry[type.toLowerCase()];
+ var node = null;
+ if(builder) {
+ node = builder.apply(this, [geometry]);
+ }
+ return node;
+ },
+
+ /**
+ * Property: buildGeometry
+ * Object containing methods to do the actual geometry node building
+ * based on geometry type.
+ */
+ buildGeometry: {
+ // TBD: Anybody care about namespace aliases here (these nodes have
+ // no prefixes)?
+
+ /**
+ * Method: buildGeometry.point
+ * Given an OpenLayers point geometry, create a KML point.
+ *
+ * Parameters:
+ * geometry - {<OpenLayers.Geometry.Point>} A point geometry.
+ *
+ * Returns:
+ * {DOMElement} A KML point node.
+ */
+ point: function(geometry) {
+ var kml = this.createElementNS(this.kmlns, "Point");
+ kml.appendChild(this.buildCoordinatesNode(geometry));
+ return kml;
+ },
+
+ /**
+ * Method: buildGeometry.multipoint
+ * Given an OpenLayers multipoint geometry, create a KML
+ * GeometryCollection.
+ *
+ * Parameters:
+ * geometry - {<OpenLayers.Geometry.Point>} A multipoint geometry.
+ *
+ * Returns:
+ * {DOMElement} A KML GeometryCollection node.
+ */
+ multipoint: function(geometry) {
+ return this.buildGeometry.collection.apply(this, [geometry]);
+ },
+
+ /**
+ * Method: buildGeometry.linestring
+ * Given an OpenLayers linestring geometry, create a KML linestring.
+ *
+ * Parameters:
+ * geometry - {<OpenLayers.Geometry.LineString>} A linestring geometry.
+ *
+ * Returns:
+ * {DOMElement} A KML linestring node.
+ */
+ linestring: function(geometry) {
+ var kml = this.createElementNS(this.kmlns, "LineString");
+ kml.appendChild(this.buildCoordinatesNode(geometry));
+ return kml;
+ },
+
+ /**
+ * Method: buildGeometry.multilinestring
+ * Given an OpenLayers multilinestring geometry, create a KML
+ * GeometryCollection.
+ *
+ * Parameters:
+ * geometry - {<OpenLayers.Geometry.Point>} A multilinestring geometry.
+ *
+ * Returns:
+ * {DOMElement} A KML GeometryCollection node.
+ */
+ multilinestring: function(geometry) {
+ return this.buildGeometry.collection.apply(this, [geometry]);
+ },
+
+ /**
+ * Method: buildGeometry.linearring
+ * Given an OpenLayers linearring geometry, create a KML linearring.
+ *
+ * Parameters:
+ * geometry - {<OpenLayers.Geometry.LinearRing>} A linearring geometry.
+ *
+ * Returns:
+ * {DOMElement} A KML linearring node.
+ */
+ linearring: function(geometry) {
+ var kml = this.createElementNS(this.kmlns, "LinearRing");
+ kml.appendChild(this.buildCoordinatesNode(geometry));
+ return kml;
+ },
+
+ /**
+ * Method: buildGeometry.polygon
+ * Given an OpenLayers polygon geometry, create a KML polygon.
+ *
+ * Parameters:
+ * geometry - {<OpenLayers.Geometry.Polygon>} A polygon geometry.
+ *
+ * Returns:
+ * {DOMElement} A KML polygon node.
+ */
+ polygon: function(geometry) {
+ var kml = this.createElementNS(this.kmlns, "Polygon");
+ var rings = geometry.components;
+ var ringMember, ringGeom, type;
+ for(var i=0, len=rings.length; i<len; ++i) {
+ type = (i==0) ? "outerBoundaryIs" : "innerBoundaryIs";
+ ringMember = this.createElementNS(this.kmlns, type);
+ ringGeom = this.buildGeometry.linearring.apply(this,
+ [rings[i]]);
+ ringMember.appendChild(ringGeom);
+ kml.appendChild(ringMember);
+ }
+ return kml;
+ },
+
+ /**
+ * Method: buildGeometry.multipolygon
+ * Given an OpenLayers multipolygon geometry, create a KML
+ * GeometryCollection.
+ *
+ * Parameters:
+ * geometry - {<OpenLayers.Geometry.Point>} A multipolygon geometry.
+ *
+ * Returns:
+ * {DOMElement} A KML GeometryCollection node.
+ */
+ multipolygon: function(geometry) {
+ return this.buildGeometry.collection.apply(this, [geometry]);
+ },
+
+ /**
+ * Method: buildGeometry.collection
+ * Given an OpenLayers geometry collection, create a KML MultiGeometry.
+ *
+ * Parameters:
+ * geometry - {<OpenLayers.Geometry.Collection>} A geometry collection.
+ *
+ * Returns:
+ * {DOMElement} A KML MultiGeometry node.
+ */
+ collection: function(geometry) {
+ var kml = this.createElementNS(this.kmlns, "MultiGeometry");
+ var child;
+ for(var i=0, len=geometry.components.length; i<len; ++i) {
+ child = this.buildGeometryNode.apply(this,
+ [geometry.components[i]]);
+ if(child) {
+ kml.appendChild(child);
+ }
+ }
+ return kml;
+ }
+ },
+
+ /**
+ * Method: buildCoordinatesNode
+ * Builds and returns the KML coordinates node with the given geometry
+ * <coordinates>...</coordinates>
+ *
+ * Parameters:
+ * geometry - {<OpenLayers.Geometry>}
+ *
+ * Returns:
+ * {DOMElement}
+ */
+ buildCoordinatesNode: function(geometry) {
+ var coordinatesNode = this.createElementNS(this.kmlns, "coordinates");
+
+ var path;
+ var points = geometry.components;
+ if(points) {
+ // LineString or LinearRing
+ var point;
+ var numPoints = points.length;
+ var parts = new Array(numPoints);
+ for(var i=0; i<numPoints; ++i) {
+ point = points[i];
+ parts[i] = this.buildCoordinates(point);
+ }
+ path = parts.join(" ");
+ } else {
+ // Point
+ path = this.buildCoordinates(geometry);
+ }
+
+ var txtNode = this.createTextNode(path);
+ coordinatesNode.appendChild(txtNode);
+
+ return coordinatesNode;
+ },
+
+ /**
+ * Method: buildCoordinates
+ *
+ * Parameters:
+ * point - {<OpenLayers.Geometry.Point>}
+ *
+ * Returns
+ * {String} a coordinate pair
+ */
+ buildCoordinates: function(point) {
+ if (this.internalProjection && this.externalProjection) {
+ point = point.clone();
+ point.transform(this.internalProjection,
+ this.externalProjection);
+ }
+ return point.x + "," + point.y;
+ },
+
+ /**
+ * Method: buildExtendedData
+ *
+ * Parameters:
+ * attributes - {Object}
+ *
+ * Returns
+ * {DOMElement} A KML ExtendedData node or {null} if no attributes.
+ */
+ buildExtendedData: function(attributes) {
+ var extendedData = this.createElementNS(this.kmlns, "ExtendedData");
+ for (var attributeName in attributes) {
+ // empty, name, description, styleUrl attributes ignored
+ if (attributes[attributeName] && attributeName != "name" && attributeName != "description" && attributeName != "styleUrl") {
+ var data = this.createElementNS(this.kmlns, "Data");
+ data.setAttribute("name", attributeName);
+ var value = this.createElementNS(this.kmlns, "value");
+ if (typeof attributes[attributeName] == "object") {
+ // cater for object attributes with 'value' properties
+ // other object properties will output an empty node
+ if (attributes[attributeName].value) {
+ value.appendChild(this.createTextNode(attributes[attributeName].value));
+ }
+ if (attributes[attributeName].displayName) {
+ var displayName = this.createElementNS(this.kmlns, "displayName");
+ // displayName always written as CDATA
+ displayName.appendChild(this.getXMLDoc().createCDATASection(attributes[attributeName].displayName));
+ data.appendChild(displayName);
+ }
+ } else {
+ value.appendChild(this.createTextNode(attributes[attributeName]));
+ }
+ data.appendChild(value);
+ extendedData.appendChild(data);
+ }
+ }
+ if (this.isSimpleContent(extendedData)) {
+ return null;
+ } else {
+ return extendedData;
+ }
+ },
+
+ CLASS_NAME: "OpenLayers.Format.KML"
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/OGCExceptionReport.js b/misc/openlayers/lib/OpenLayers/Format/OGCExceptionReport.js
new file mode 100644
index 0000000..61a9da5
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/OGCExceptionReport.js
@@ -0,0 +1,108 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ */
+
+/**
+ * Class: OpenLayers.Format.OGCExceptionReport
+ * Class to read exception reports for various OGC services and versions.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.OGCExceptionReport = OpenLayers.Class(OpenLayers.Format.XML, {
+
+ /**
+ * Property: namespaces
+ * {Object} Mapping of namespace aliases to namespace URIs.
+ */
+ namespaces: {
+ ogc: "http://www.opengis.net/ogc"
+ },
+
+ /**
+ * Property: regExes
+ * Compiled regular expressions for manipulating strings.
+ */
+ regExes: {
+ trimSpace: (/^\s*|\s*$/g),
+ removeSpace: (/\s*/g),
+ splitSpace: (/\s+/),
+ trimComma: (/\s*,\s*/g)
+ },
+
+ /**
+ * Property: defaultPrefix
+ */
+ defaultPrefix: "ogc",
+
+ /**
+ * Constructor: OpenLayers.Format.OGCExceptionReport
+ * Create a new parser for OGC exception reports.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * APIMethod: read
+ * Read OGC exception report data from a string, and return an object with
+ * information about the exceptions.
+ *
+ * Parameters:
+ * data - {String} or {DOMElement} data to read/parse.
+ *
+ * Returns:
+ * {Object} Information about the exceptions that occurred.
+ */
+ read: function(data) {
+ var result;
+ if(typeof data == "string") {
+ data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+ }
+ var root = data.documentElement;
+ var exceptionInfo = {exceptionReport: null};
+ if (root) {
+ this.readChildNodes(data, exceptionInfo);
+ if (exceptionInfo.exceptionReport === null) {
+ // fall-back to OWSCommon since this is a common output format for exceptions
+ // we cannot easily use the ows readers directly since they differ for 1.0 and 1.1
+ exceptionInfo = new OpenLayers.Format.OWSCommon().read(data);
+ }
+ }
+ return exceptionInfo;
+ },
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "ogc": {
+ "ServiceExceptionReport": function(node, obj) {
+ obj.exceptionReport = {exceptions: []};
+ this.readChildNodes(node, obj.exceptionReport);
+ },
+ "ServiceException": function(node, exceptionReport) {
+ var exception = {
+ code: node.getAttribute("code"),
+ locator: node.getAttribute("locator"),
+ text: this.getChildValue(node)
+ };
+ exceptionReport.exceptions.push(exception);
+ }
+ }
+ },
+
+ CLASS_NAME: "OpenLayers.Format.OGCExceptionReport"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/OSM.js b/misc/openlayers/lib/OpenLayers/Format/OSM.js
new file mode 100644
index 0000000..7283348
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/OSM.js
@@ -0,0 +1,465 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Feature/Vector.js
+ * @requires OpenLayers/Geometry/Point.js
+ * @requires OpenLayers/Geometry/LineString.js
+ * @requires OpenLayers/Geometry/Polygon.js
+ * @requires OpenLayers/Projection.js
+ */
+
+/**
+ * Class: OpenLayers.Format.OSM
+ * OSM parser. Create a new instance with the
+ * <OpenLayers.Format.OSM> constructor.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.OSM = OpenLayers.Class(OpenLayers.Format.XML, {
+
+ /**
+ * APIProperty: checkTags
+ * {Boolean} Should tags be checked to determine whether something
+ * should be treated as a seperate node. Will slow down parsing.
+ * Default is false.
+ */
+ checkTags: false,
+
+ /**
+ * Property: interestingTagsExclude
+ * {Array} List of tags to exclude from 'interesting' checks on nodes.
+ * Must be set when creating the format. Will only be used if checkTags
+ * is set.
+ */
+ interestingTagsExclude: null,
+
+ /**
+ * APIProperty: areaTags
+ * {Array} List of tags indicating that something is an area.
+ * Must be set when creating the format. Will only be used if
+ * checkTags is true.
+ */
+ areaTags: null,
+
+ /**
+ * Constructor: OpenLayers.Format.OSM
+ * Create a new parser for OSM.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+ initialize: function(options) {
+ var layer_defaults = {
+ 'interestingTagsExclude': ['source', 'source_ref',
+ 'source:ref', 'history', 'attribution', 'created_by'],
+ 'areaTags': ['area', 'building', 'leisure', 'tourism', 'ruins',
+ 'historic', 'landuse', 'military', 'natural', 'sport']
+ };
+
+ layer_defaults = OpenLayers.Util.extend(layer_defaults, options);
+
+ var interesting = {};
+ for (var i = 0; i < layer_defaults.interestingTagsExclude.length; i++) {
+ interesting[layer_defaults.interestingTagsExclude[i]] = true;
+ }
+ layer_defaults.interestingTagsExclude = interesting;
+
+ var area = {};
+ for (var i = 0; i < layer_defaults.areaTags.length; i++) {
+ area[layer_defaults.areaTags[i]] = true;
+ }
+ layer_defaults.areaTags = area;
+
+ // OSM coordinates are always in longlat WGS84
+ this.externalProjection = new OpenLayers.Projection("EPSG:4326");
+
+ OpenLayers.Format.XML.prototype.initialize.apply(this, [layer_defaults]);
+ },
+
+ /**
+ * APIMethod: read
+ * Return a list of features from a OSM doc
+
+ * Parameters:
+ * doc - {Element}
+ *
+ * Returns:
+ * Array({<OpenLayers.Feature.Vector>})
+ */
+ read: function(doc) {
+ if (typeof doc == "string") {
+ doc = OpenLayers.Format.XML.prototype.read.apply(this, [doc]);
+ }
+
+ var nodes = this.getNodes(doc);
+ var ways = this.getWays(doc);
+
+ // Geoms will contain at least ways.length entries.
+ var feat_list = new Array(ways.length);
+
+ for (var i = 0; i < ways.length; i++) {
+ // We know the minimal of this one ahead of time. (Could be -1
+ // due to areas/polygons)
+ var point_list = new Array(ways[i].nodes.length);
+
+ var poly = this.isWayArea(ways[i]) ? 1 : 0;
+ for (var j = 0; j < ways[i].nodes.length; j++) {
+ var node = nodes[ways[i].nodes[j]];
+
+ var point = new OpenLayers.Geometry.Point(node.lon, node.lat);
+
+ // Since OSM is topological, we stash the node ID internally.
+ point.osm_id = parseInt(ways[i].nodes[j]);
+ point_list[j] = point;
+
+ // We don't display nodes if they're used inside other
+ // elements.
+ node.used = true;
+ }
+ var geometry = null;
+ if (poly) {
+ geometry = new OpenLayers.Geometry.Polygon(
+ new OpenLayers.Geometry.LinearRing(point_list));
+ } else {
+ geometry = new OpenLayers.Geometry.LineString(point_list);
+ }
+ if (this.internalProjection && this.externalProjection) {
+ geometry.transform(this.externalProjection,
+ this.internalProjection);
+ }
+ var feat = new OpenLayers.Feature.Vector(geometry,
+ ways[i].tags);
+ feat.osm_id = parseInt(ways[i].id);
+ feat.fid = "way." + feat.osm_id;
+ feat_list[i] = feat;
+ }
+ for (var node_id in nodes) {
+ var node = nodes[node_id];
+ if (!node.used || this.checkTags) {
+ var tags = null;
+
+ if (this.checkTags) {
+ var result = this.getTags(node.node, true);
+ if (node.used && !result[1]) {
+ continue;
+ }
+ tags = result[0];
+ } else {
+ tags = this.getTags(node.node);
+ }
+
+ var feat = new OpenLayers.Feature.Vector(
+ new OpenLayers.Geometry.Point(node['lon'], node['lat']),
+ tags);
+ if (this.internalProjection && this.externalProjection) {
+ feat.geometry.transform(this.externalProjection,
+ this.internalProjection);
+ }
+ feat.osm_id = parseInt(node_id);
+ feat.fid = "node." + feat.osm_id;
+ feat_list.push(feat);
+ }
+ // Memory cleanup
+ node.node = null;
+ }
+ return feat_list;
+ },
+
+ /**
+ * Method: getNodes
+ * Return the node items from a doc.
+ *
+ * Parameters:
+ * doc - {DOMElement} node to parse tags from
+ */
+ getNodes: function(doc) {
+ var node_list = doc.getElementsByTagName("node");
+ var nodes = {};
+ for (var i = 0; i < node_list.length; i++) {
+ var node = node_list[i];
+ var id = node.getAttribute("id");
+ nodes[id] = {
+ 'lat': node.getAttribute("lat"),
+ 'lon': node.getAttribute("lon"),
+ 'node': node
+ };
+ }
+ return nodes;
+ },
+
+ /**
+ * Method: getWays
+ * Return the way items from a doc.
+ *
+ * Parameters:
+ * doc - {DOMElement} node to parse tags from
+ */
+ getWays: function(doc) {
+ var way_list = doc.getElementsByTagName("way");
+ var return_ways = [];
+ for (var i = 0; i < way_list.length; i++) {
+ var way = way_list[i];
+ var way_object = {
+ id: way.getAttribute("id")
+ };
+
+ way_object.tags = this.getTags(way);
+
+ var node_list = way.getElementsByTagName("nd");
+
+ way_object.nodes = new Array(node_list.length);
+
+ for (var j = 0; j < node_list.length; j++) {
+ way_object.nodes[j] = node_list[j].getAttribute("ref");
+ }
+ return_ways.push(way_object);
+ }
+ return return_ways;
+
+ },
+
+ /**
+ * Method: getTags
+ * Return the tags list attached to a specific DOM element.
+ *
+ * Parameters:
+ * dom_node - {DOMElement} node to parse tags from
+ * interesting_tags - {Boolean} whether the return from this function should
+ * return a boolean indicating that it has 'interesting tags' --
+ * tags like attribution and source are ignored. (To change the list
+ * of tags, see interestingTagsExclude)
+ *
+ * Returns:
+ * tags - {Object} hash of tags
+ * interesting - {Boolean} if interesting_tags is passed, returns
+ * whether there are any interesting tags on this element.
+ */
+ getTags: function(dom_node, interesting_tags) {
+ var tag_list = dom_node.getElementsByTagName("tag");
+ var tags = {};
+ var interesting = false;
+ for (var j = 0; j < tag_list.length; j++) {
+ var key = tag_list[j].getAttribute("k");
+ tags[key] = tag_list[j].getAttribute("v");
+ if (interesting_tags) {
+ if (!this.interestingTagsExclude[key]) {
+ interesting = true;
+ }
+ }
+ }
+ return interesting_tags ? [tags, interesting] : tags;
+ },
+
+ /**
+ * Method: isWayArea
+ * Given a way object from getWays, check whether the tags and geometry
+ * indicate something is an area.
+ *
+ * Returns:
+ * {Boolean}
+ */
+ isWayArea: function(way) {
+ var poly_shaped = false;
+ var poly_tags = false;
+
+ if (way.nodes[0] == way.nodes[way.nodes.length - 1]) {
+ poly_shaped = true;
+ }
+ if (this.checkTags) {
+ for(var key in way.tags) {
+ if (this.areaTags[key]) {
+ poly_tags = true;
+ break;
+ }
+ }
+ }
+ return poly_shaped && (this.checkTags ? poly_tags : true);
+ },
+
+ /**
+ * APIMethod: write
+ * Takes a list of features, returns a serialized OSM format file for use
+ * in tools like JOSM.
+ *
+ * Parameters:
+ * features - {Array(<OpenLayers.Feature.Vector>)}
+ */
+ write: function(features) {
+ if (!(OpenLayers.Util.isArray(features))) {
+ features = [features];
+ }
+
+ this.osm_id = 1;
+ this.created_nodes = {};
+ var root_node = this.createElementNS(null, "osm");
+ root_node.setAttribute("version", "0.5");
+ root_node.setAttribute("generator", "OpenLayers "+ OpenLayers.VERSION_NUMBER);
+
+ // Loop backwards, because the deserializer puts nodes last, and
+ // we want them first if possible
+ for(var i = features.length - 1; i >= 0; i--) {
+ var nodes = this.createFeatureNodes(features[i]);
+ for (var j = 0; j < nodes.length; j++) {
+ root_node.appendChild(nodes[j]);
+ }
+ }
+ return OpenLayers.Format.XML.prototype.write.apply(this, [root_node]);
+ },
+
+ /**
+ * Method: createFeatureNodes
+ * Takes a feature, returns a list of nodes from size 0->n.
+ * Will include all pieces of the serialization that are required which
+ * have not already been created. Calls out to createXML based on geometry
+ * type.
+ *
+ * Parameters:
+ * feature - {<OpenLayers.Feature.Vector>}
+ */
+ createFeatureNodes: function(feature) {
+ var nodes = [];
+ var className = feature.geometry.CLASS_NAME;
+ var type = className.substring(className.lastIndexOf(".") + 1);
+ type = type.toLowerCase();
+ var builder = this.createXML[type];
+ if (builder) {
+ nodes = builder.apply(this, [feature]);
+ }
+ return nodes;
+ },
+
+ /**
+ * Method: createXML
+ * Takes a feature, returns a list of nodes from size 0->n.
+ * Will include all pieces of the serialization that are required which
+ * have not already been created.
+ *
+ * Parameters:
+ * feature - {<OpenLayers.Feature.Vector>}
+ */
+ createXML: {
+ 'point': function(point) {
+ var id = null;
+ var geometry = point.geometry ? point.geometry : point;
+
+ if (this.internalProjection && this.externalProjection) {
+ geometry = geometry.clone();
+ geometry.transform(this.internalProjection,
+ this.externalProjection);
+ }
+
+ var already_exists = false; // We don't return anything if the node
+ // has already been created
+ if (point.osm_id) {
+ id = point.osm_id;
+ if (this.created_nodes[id]) {
+ already_exists = true;
+ }
+ } else {
+ id = -this.osm_id;
+ this.osm_id++;
+ }
+ if (already_exists) {
+ node = this.created_nodes[id];
+ } else {
+ var node = this.createElementNS(null, "node");
+ }
+ this.created_nodes[id] = node;
+ node.setAttribute("id", id);
+ node.setAttribute("lon", geometry.x);
+ node.setAttribute("lat", geometry.y);
+ if (point.attributes) {
+ this.serializeTags(point, node);
+ }
+ this.setState(point, node);
+ return already_exists ? [] : [node];
+ },
+ linestring: function(feature) {
+ var id;
+ var nodes = [];
+ var geometry = feature.geometry;
+ if (feature.osm_id) {
+ id = feature.osm_id;
+ } else {
+ id = -this.osm_id;
+ this.osm_id++;
+ }
+ var way = this.createElementNS(null, "way");
+ way.setAttribute("id", id);
+ for (var i = 0; i < geometry.components.length; i++) {
+ var node = this.createXML['point'].apply(this, [geometry.components[i]]);
+ if (node.length) {
+ node = node[0];
+ var node_ref = node.getAttribute("id");
+ nodes.push(node);
+ } else {
+ node_ref = geometry.components[i].osm_id;
+ node = this.created_nodes[node_ref];
+ }
+ this.setState(feature, node);
+ var nd_dom = this.createElementNS(null, "nd");
+ nd_dom.setAttribute("ref", node_ref);
+ way.appendChild(nd_dom);
+ }
+ this.serializeTags(feature, way);
+ nodes.push(way);
+
+ return nodes;
+ },
+ polygon: function(feature) {
+ var attrs = OpenLayers.Util.extend({'area':'yes'}, feature.attributes);
+ var feat = new OpenLayers.Feature.Vector(feature.geometry.components[0], attrs);
+ feat.osm_id = feature.osm_id;
+ return this.createXML['linestring'].apply(this, [feat]);
+ }
+ },
+
+ /**
+ * Method: serializeTags
+ * Given a feature, serialize the attributes onto the given node.
+ *
+ * Parameters:
+ * feature - {<OpenLayers.Feature.Vector>}
+ * node - {DOMNode}
+ */
+ serializeTags: function(feature, node) {
+ for (var key in feature.attributes) {
+ var tag = this.createElementNS(null, "tag");
+ tag.setAttribute("k", key);
+ tag.setAttribute("v", feature.attributes[key]);
+ node.appendChild(tag);
+ }
+ },
+
+ /**
+ * Method: setState
+ * OpenStreetMap has a convention that 'state' is stored for modification or deletion.
+ * This allows the file to be uploaded via JOSM or the bulk uploader tool.
+ *
+ * Parameters:
+ * feature - {<OpenLayers.Feature.Vector>}
+ * node - {DOMNode}
+ */
+ setState: function(feature, node) {
+ if (feature.state) {
+ var state = null;
+ switch(feature.state) {
+ case OpenLayers.State.UPDATE:
+ state = "modify";
+ case OpenLayers.State.DELETE:
+ state = "delete";
+ }
+ if (state) {
+ node.setAttribute("action", state);
+ }
+ }
+ },
+
+ CLASS_NAME: "OpenLayers.Format.OSM"
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/OWSCommon.js b/misc/openlayers/lib/OpenLayers/Format/OWSCommon.js
new file mode 100644
index 0000000..fd71820
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/OWSCommon.js
@@ -0,0 +1,78 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML/VersionedOGC.js
+ */
+
+/**
+ * Class: OpenLayers.Format.OWSCommon
+ * Read OWSCommon. Create a new instance with the <OpenLayers.Format.OWSCommon>
+ * constructor.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML.VersionedOGC>
+ */
+OpenLayers.Format.OWSCommon = OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC, {
+
+ /**
+ * APIProperty: defaultVersion
+ * {String} Version number to assume if none found. Default is "1.0.0".
+ */
+ defaultVersion: "1.0.0",
+
+ /**
+ * Constructor: OpenLayers.Format.OWSCommon
+ * Create a new parser for OWSCommon.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * Method: getVersion
+ * Returns the version to use. Subclasses can override this function
+ * if a different version detection is needed.
+ *
+ * Parameters:
+ * root - {DOMElement}
+ * options - {Object} Optional configuration object.
+ *
+ * Returns:
+ * {String} The version to use.
+ */
+ getVersion: function(root, options) {
+ var version = this.version;
+ if(!version) {
+ // remember version does not correspond to the OWS version
+ // it corresponds to the WMS/WFS/WCS etc. request version
+ var uri = root.getAttribute("xmlns:ows");
+ // the above will fail if the namespace prefix is different than
+ // ows and if the namespace is declared on a different element
+ if (uri && uri.substring(uri.lastIndexOf("/")+1) === "1.1") {
+ version ="1.1.0";
+ }
+ if(!version) {
+ version = this.defaultVersion;
+ }
+ }
+ return version;
+ },
+
+ /**
+ * APIMethod: read
+ * Read an OWSCommon document and return an object.
+ *
+ * Parameters:
+ * data - {String | DOMElement} Data to read.
+ * options - {Object} Options for the reader.
+ *
+ * Returns:
+ * {Object} An object representing the structure of the document.
+ */
+
+ CLASS_NAME: "OpenLayers.Format.OWSCommon"
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/OWSCommon/v1.js b/misc/openlayers/lib/OpenLayers/Format/OWSCommon/v1.js
new file mode 100644
index 0000000..57ae9d2
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/OWSCommon/v1.js
@@ -0,0 +1,318 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/OWSCommon.js
+ */
+
+/**
+ * Class: OpenLayers.Format.OWSCommon.v1
+ * Common readers and writers for OWSCommon v1.X formats
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.OWSCommon.v1 = OpenLayers.Class(OpenLayers.Format.XML, {
+
+ /**
+ * Property: regExes
+ * Compiled regular expressions for manipulating strings.
+ */
+ regExes: {
+ trimSpace: (/^\s*|\s*$/g),
+ removeSpace: (/\s*/g),
+ splitSpace: (/\s+/),
+ trimComma: (/\s*,\s*/g)
+ },
+
+ /**
+ * Method: read
+ *
+ * Parameters:
+ * data - {DOMElement} An OWSCommon document element.
+ * options - {Object} Options for the reader.
+ *
+ * Returns:
+ * {Object} An object representing the OWSCommon document.
+ */
+ read: function(data, options) {
+ options = OpenLayers.Util.applyDefaults(options, this.options);
+ var ows = {};
+ this.readChildNodes(data, ows);
+ return ows;
+ },
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "ows": {
+ "Exception": function(node, exceptionReport) {
+ var exception = {
+ code: node.getAttribute('exceptionCode'),
+ locator: node.getAttribute('locator'),
+ texts: []
+ };
+ exceptionReport.exceptions.push(exception);
+ this.readChildNodes(node, exception);
+ },
+ "ExceptionText": function(node, exception) {
+ var text = this.getChildValue(node);
+ exception.texts.push(text);
+ },
+ "ServiceIdentification": function(node, obj) {
+ obj.serviceIdentification = {};
+ this.readChildNodes(node, obj.serviceIdentification);
+ },
+ "Title": function(node, obj) {
+ obj.title = this.getChildValue(node);
+ },
+ "Abstract": function(node, serviceIdentification) {
+ serviceIdentification["abstract"] = this.getChildValue(node);
+ },
+ "Keywords": function(node, serviceIdentification) {
+ serviceIdentification.keywords = {};
+ this.readChildNodes(node, serviceIdentification.keywords);
+ },
+ "Keyword": function(node, keywords) {
+ keywords[this.getChildValue(node)] = true;
+ },
+ "ServiceType": function(node, serviceIdentification) {
+ serviceIdentification.serviceType = {
+ codeSpace: node.getAttribute('codeSpace'),
+ value: this.getChildValue(node)};
+ },
+ "ServiceTypeVersion": function(node, serviceIdentification) {
+ serviceIdentification.serviceTypeVersion = this.getChildValue(node);
+ },
+ "Fees": function(node, serviceIdentification) {
+ serviceIdentification.fees = this.getChildValue(node);
+ },
+ "AccessConstraints": function(node, serviceIdentification) {
+ serviceIdentification.accessConstraints =
+ this.getChildValue(node);
+ },
+ "ServiceProvider": function(node, obj) {
+ obj.serviceProvider = {};
+ this.readChildNodes(node, obj.serviceProvider);
+ },
+ "ProviderName": function(node, serviceProvider) {
+ serviceProvider.providerName = this.getChildValue(node);
+ },
+ "ProviderSite": function(node, serviceProvider) {
+ serviceProvider.providerSite = this.getAttributeNS(node,
+ this.namespaces.xlink, "href");
+ },
+ "ServiceContact": function(node, serviceProvider) {
+ serviceProvider.serviceContact = {};
+ this.readChildNodes(node, serviceProvider.serviceContact);
+ },
+ "IndividualName": function(node, serviceContact) {
+ serviceContact.individualName = this.getChildValue(node);
+ },
+ "PositionName": function(node, serviceContact) {
+ serviceContact.positionName = this.getChildValue(node);
+ },
+ "ContactInfo": function(node, serviceContact) {
+ serviceContact.contactInfo = {};
+ this.readChildNodes(node, serviceContact.contactInfo);
+ },
+ "Phone": function(node, contactInfo) {
+ contactInfo.phone = {};
+ this.readChildNodes(node, contactInfo.phone);
+ },
+ "Voice": function(node, phone) {
+ phone.voice = this.getChildValue(node);
+ },
+ "Address": function(node, contactInfo) {
+ contactInfo.address = {};
+ this.readChildNodes(node, contactInfo.address);
+ },
+ "DeliveryPoint": function(node, address) {
+ address.deliveryPoint = this.getChildValue(node);
+ },
+ "City": function(node, address) {
+ address.city = this.getChildValue(node);
+ },
+ "AdministrativeArea": function(node, address) {
+ address.administrativeArea = this.getChildValue(node);
+ },
+ "PostalCode": function(node, address) {
+ address.postalCode = this.getChildValue(node);
+ },
+ "Country": function(node, address) {
+ address.country = this.getChildValue(node);
+ },
+ "ElectronicMailAddress": function(node, address) {
+ address.electronicMailAddress = this.getChildValue(node);
+ },
+ "Role": function(node, serviceContact) {
+ serviceContact.role = this.getChildValue(node);
+ },
+ "OperationsMetadata": function(node, obj) {
+ obj.operationsMetadata = {};
+ this.readChildNodes(node, obj.operationsMetadata);
+ },
+ "Operation": function(node, operationsMetadata) {
+ var name = node.getAttribute("name");
+ operationsMetadata[name] = {};
+ this.readChildNodes(node, operationsMetadata[name]);
+ },
+ "DCP": function(node, operation) {
+ operation.dcp = {};
+ this.readChildNodes(node, operation.dcp);
+ },
+ "HTTP": function(node, dcp) {
+ dcp.http = {};
+ this.readChildNodes(node, dcp.http);
+ },
+ "Get": function(node, http) {
+ if (!http.get) {
+ http.get = [];
+ }
+ var obj = {
+ url: this.getAttributeNS(node, this.namespaces.xlink, "href")
+ };
+ this.readChildNodes(node, obj);
+ http.get.push(obj);
+ },
+ "Post": function(node, http) {
+ if (!http.post) {
+ http.post = [];
+ }
+ var obj = {
+ url: this.getAttributeNS(node, this.namespaces.xlink, "href")
+ };
+ this.readChildNodes(node, obj);
+ http.post.push(obj);
+ },
+ "Parameter": function(node, operation) {
+ if (!operation.parameters) {
+ operation.parameters = {};
+ }
+ var name = node.getAttribute("name");
+ operation.parameters[name] = {};
+ this.readChildNodes(node, operation.parameters[name]);
+ },
+ "Constraint": function(node, obj) {
+ if (!obj.constraints) {
+ obj.constraints = {};
+ }
+ var name = node.getAttribute("name");
+ obj.constraints[name] = {};
+ this.readChildNodes(node, obj.constraints[name]);
+ },
+ "Value": function(node, allowedValues) {
+ allowedValues[this.getChildValue(node)] = true;
+ },
+ "OutputFormat": function(node, obj) {
+ obj.formats.push({value: this.getChildValue(node)});
+ this.readChildNodes(node, obj);
+ },
+ "WGS84BoundingBox": function(node, obj) {
+ var boundingBox = {};
+ boundingBox.crs = node.getAttribute("crs");
+ if (obj.BoundingBox) {
+ obj.BoundingBox.push(boundingBox);
+ } else {
+ obj.projection = boundingBox.crs;
+ boundingBox = obj;
+ }
+ this.readChildNodes(node, boundingBox);
+ },
+ "BoundingBox": function(node, obj) {
+ // FIXME: We consider that BoundingBox is the same as WGS84BoundingBox
+ // LowerCorner = "min_x min_y"
+ // UpperCorner = "max_x max_y"
+ // It should normally depend on the projection
+ this.readers['ows']['WGS84BoundingBox'].apply(this, [node, obj]);
+ },
+ "LowerCorner": function(node, obj) {
+ var str = this.getChildValue(node).replace(
+ this.regExes.trimSpace, "");
+ str = str.replace(this.regExes.trimComma, ",");
+ var pointList = str.split(this.regExes.splitSpace);
+ obj.left = pointList[0];
+ obj.bottom = pointList[1];
+ },
+ "UpperCorner": function(node, obj) {
+ var str = this.getChildValue(node).replace(
+ this.regExes.trimSpace, "");
+ str = str.replace(this.regExes.trimComma, ",");
+ var pointList = str.split(this.regExes.splitSpace);
+ obj.right = pointList[0];
+ obj.top = pointList[1];
+ obj.bounds = new OpenLayers.Bounds(obj.left, obj.bottom,
+ obj.right, obj.top);
+ delete obj.left;
+ delete obj.bottom;
+ delete obj.right;
+ delete obj.top;
+ },
+ "Language": function(node, obj) {
+ obj.language = this.getChildValue(node);
+ }
+ }
+ },
+
+ /**
+ * Property: writers
+ * As a compliment to the readers property, this structure contains public
+ * writing functions grouped by namespace alias and named like the
+ * node names they produce.
+ */
+ writers: {
+ "ows": {
+ "BoundingBox": function(options, nodeName) {
+ var node = this.createElementNSPlus(nodeName || "ows:BoundingBox", {
+ attributes: {
+ crs: options.projection
+ }
+ });
+ this.writeNode("ows:LowerCorner", options, node);
+ this.writeNode("ows:UpperCorner", options, node);
+ return node;
+ },
+ "LowerCorner": function(options) {
+ var node = this.createElementNSPlus("ows:LowerCorner", {
+ value: options.bounds.left + " " + options.bounds.bottom });
+ return node;
+ },
+ "UpperCorner": function(options) {
+ var node = this.createElementNSPlus("ows:UpperCorner", {
+ value: options.bounds.right + " " + options.bounds.top });
+ return node;
+ },
+ "Identifier": function(identifier) {
+ var node = this.createElementNSPlus("ows:Identifier", {
+ value: identifier });
+ return node;
+ },
+ "Title": function(title) {
+ var node = this.createElementNSPlus("ows:Title", {
+ value: title });
+ return node;
+ },
+ "Abstract": function(abstractValue) {
+ var node = this.createElementNSPlus("ows:Abstract", {
+ value: abstractValue });
+ return node;
+ },
+ "OutputFormat": function(format) {
+ var node = this.createElementNSPlus("ows:OutputFormat", {
+ value: format });
+ return node;
+ }
+ }
+ },
+
+ CLASS_NAME: "OpenLayers.Format.OWSCommon.v1"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/OWSCommon/v1_0_0.js b/misc/openlayers/lib/OpenLayers/Format/OWSCommon/v1_0_0.js
new file mode 100644
index 0000000..bc9852d
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/OWSCommon/v1_0_0.js
@@ -0,0 +1,62 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/OWSCommon/v1.js
+ */
+
+/**
+ * Class: OpenLayers.Format.OWSCommon.v1_0_0
+ * Parser for OWS Common version 1.0.0.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.OWSCommon.v1>
+ */
+OpenLayers.Format.OWSCommon.v1_0_0 = OpenLayers.Class(OpenLayers.Format.OWSCommon.v1, {
+
+ /**
+ * Property: namespaces
+ * {Object} Mapping of namespace aliases to namespace URIs.
+ */
+ namespaces: {
+ ows: "http://www.opengis.net/ows",
+ xlink: "http://www.w3.org/1999/xlink"
+ },
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "ows": OpenLayers.Util.applyDefaults({
+ "ExceptionReport": function(node, obj) {
+ obj.success = false;
+ obj.exceptionReport = {
+ version: node.getAttribute('version'),
+ language: node.getAttribute('language'),
+ exceptions: []
+ };
+ this.readChildNodes(node, obj.exceptionReport);
+ }
+ }, OpenLayers.Format.OWSCommon.v1.prototype.readers.ows)
+ },
+
+ /**
+ * Property: writers
+ * As a compliment to the readers property, this structure contains public
+ * writing functions grouped by namespace alias and named like the
+ * node names they produce.
+ */
+ writers: {
+ "ows": OpenLayers.Format.OWSCommon.v1.prototype.writers.ows
+ },
+
+ CLASS_NAME: "OpenLayers.Format.OWSCommon.v1_0_0"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/OWSCommon/v1_1_0.js b/misc/openlayers/lib/OpenLayers/Format/OWSCommon/v1_1_0.js
new file mode 100644
index 0000000..9da216c
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/OWSCommon/v1_1_0.js
@@ -0,0 +1,116 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/OWSCommon/v1.js
+ */
+
+/**
+ * Class: OpenLayers.Format.OWSCommon.v1_1_0
+ * Parser for OWS Common version 1.1.0.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.OWSCommon.v1>
+ */
+OpenLayers.Format.OWSCommon.v1_1_0 = OpenLayers.Class(OpenLayers.Format.OWSCommon.v1, {
+
+ /**
+ * Property: namespaces
+ * {Object} Mapping of namespace aliases to namespace URIs.
+ */
+ namespaces: {
+ ows: "http://www.opengis.net/ows/1.1",
+ xlink: "http://www.w3.org/1999/xlink"
+ },
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "ows": OpenLayers.Util.applyDefaults({
+ "ExceptionReport": function(node, obj) {
+ obj.exceptionReport = {
+ version: node.getAttribute('version'),
+ language: node.getAttribute('xml:lang'),
+ exceptions: []
+ };
+ this.readChildNodes(node, obj.exceptionReport);
+ },
+ "AllowedValues": function(node, parameter) {
+ parameter.allowedValues = {};
+ this.readChildNodes(node, parameter.allowedValues);
+ },
+ "AnyValue": function(node, parameter) {
+ parameter.anyValue = true;
+ },
+ "DataType": function(node, parameter) {
+ parameter.dataType = this.getChildValue(node);
+ },
+ "Range": function(node, allowedValues) {
+ allowedValues.range = {};
+ this.readChildNodes(node, allowedValues.range);
+ },
+ "MinimumValue": function(node, range) {
+ range.minValue = this.getChildValue(node);
+ },
+ "MaximumValue": function(node, range) {
+ range.maxValue = this.getChildValue(node);
+ },
+ "Identifier": function(node, obj) {
+ obj.identifier = this.getChildValue(node);
+ },
+ "SupportedCRS": function(node, obj) {
+ obj.supportedCRS = this.getChildValue(node);
+ }
+ }, OpenLayers.Format.OWSCommon.v1.prototype.readers["ows"])
+ },
+
+ /**
+ * Property: writers
+ * As a compliment to the readers property, this structure contains public
+ * writing functions grouped by namespace alias and named like the
+ * node names they produce.
+ */
+ writers: {
+ "ows": OpenLayers.Util.applyDefaults({
+ "Range": function(range) {
+ var node = this.createElementNSPlus("ows:Range", {
+ attributes: {
+ 'ows:rangeClosure': range.closure
+ }
+ });
+ this.writeNode("ows:MinimumValue", range.minValue, node);
+ this.writeNode("ows:MaximumValue", range.maxValue, node);
+ return node;
+ },
+ "MinimumValue": function(minValue) {
+ var node = this.createElementNSPlus("ows:MinimumValue", {
+ value: minValue
+ });
+ return node;
+ },
+ "MaximumValue": function(maxValue) {
+ var node = this.createElementNSPlus("ows:MaximumValue", {
+ value: maxValue
+ });
+ return node;
+ },
+ "Value": function(value) {
+ var node = this.createElementNSPlus("ows:Value", {
+ value: value
+ });
+ return node;
+ }
+ }, OpenLayers.Format.OWSCommon.v1.prototype.writers["ows"])
+ },
+
+ CLASS_NAME: "OpenLayers.Format.OWSCommon.v1_1_0"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/OWSContext.js b/misc/openlayers/lib/OpenLayers/Format/OWSContext.js
new file mode 100644
index 0000000..ab38734
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/OWSContext.js
@@ -0,0 +1,86 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/Context.js
+ */
+
+/**
+ * Class: OpenLayers.Format.OWSContext
+ * Read and write OWS Context documents. OWS Context documents are a
+ * preliminary OGC (Open Geospatial Consortium) standard for storing the
+ * state of a web mapping application. In a way it is the successor to
+ * Web Map Context (WMC), since it is more generic and more types of layers
+ * can be stored. Also, nesting of layers is supported since version 0.3.1.
+ * For more information see: http://www.ogcnetwork.net/context
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.Context>
+ */
+OpenLayers.Format.OWSContext = OpenLayers.Class(OpenLayers.Format.Context,{
+
+ /**
+ * APIProperty: defaultVersion
+ * {String} Version number to assume if none found. Default is "0.3.1".
+ */
+ defaultVersion: "0.3.1",
+
+ /**
+ * Constructor: OpenLayers.Format.OWSContext
+ * Create a new parser for OWS Context documents.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * Method: getVersion
+ * Returns the version to use. Subclasses can override this function
+ * if a different version detection is needed.
+ *
+ * Parameters:
+ * root - {DOMElement}
+ * options - {Object} Optional configuration object.
+ *
+ * Returns:
+ * {String} The version to use.
+ */
+ getVersion: function(root, options) {
+ var version = OpenLayers.Format.XML.VersionedOGC.prototype.getVersion.apply(
+ this, arguments);
+ // 0.3.1 is backwards compatible with 0.3.0
+ if (version === "0.3.0") {
+ version = this.defaultVersion;
+ }
+ return version;
+ },
+
+ /**
+ * Method: toContext
+ * Create a context object free from layer given a map or a
+ * context object.
+ *
+ * Parameters:
+ * obj - {<OpenLayers.Map> | Object} The map or context.
+ *
+ * Returns:
+ * {Object} A context object.
+ */
+ toContext: function(obj) {
+ var context = {};
+ if(obj.CLASS_NAME == "OpenLayers.Map") {
+ context.bounds = obj.getExtent();
+ context.maxExtent = obj.maxExtent;
+ context.projection = obj.projection;
+ context.size = obj.getSize();
+ context.layers = obj.layers;
+ }
+ return context;
+ },
+
+ CLASS_NAME: "OpenLayers.Format.OWSContext"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/OWSContext/v0_3_1.js b/misc/openlayers/lib/OpenLayers/Format/OWSContext/v0_3_1.js
new file mode 100644
index 0000000..d6487e8
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/OWSContext/v0_3_1.js
@@ -0,0 +1,595 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Format/KML.js
+ * @requires OpenLayers/Format/GML.js
+ * @requires OpenLayers/Format/GML/v2.js
+ * @requires OpenLayers/Format/SLD/v1_0_0.js
+ * @requires OpenLayers/Format/OWSContext.js
+ * @requires OpenLayers/Format/OWSCommon/v1_0_0.js
+ */
+
+/**
+ * Class: OpenLayers.Format.OWSContext.v0_3_1
+ * Read and write OWSContext version 0.3.1.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.OWSContext.v0_3_1 = OpenLayers.Class(OpenLayers.Format.XML, {
+
+ /**
+ * Property: namespaces
+ * {Object} Mapping of namespace aliases to namespace URIs.
+ */
+ namespaces: {
+ owc: "http://www.opengis.net/ows-context",
+ gml: "http://www.opengis.net/gml",
+ kml: "http://www.opengis.net/kml/2.2",
+ ogc: "http://www.opengis.net/ogc",
+ ows: "http://www.opengis.net/ows",
+ sld: "http://www.opengis.net/sld",
+ xlink: "http://www.w3.org/1999/xlink",
+ xsi: "http://www.w3.org/2001/XMLSchema-instance"
+ },
+
+ /**
+ * Constant: VERSION
+ * {String} 0.3.1
+ */
+ VERSION: "0.3.1",
+
+ /**
+ * Property: schemaLocation
+ * {String} Schema location
+ */
+ schemaLocation: "http://www.opengis.net/ows-context http://www.ogcnetwork.net/schemas/owc/0.3.1/owsContext.xsd",
+
+ /**
+ * Property: defaultPrefix
+ * {String} Default namespace prefix to use.
+ */
+ defaultPrefix: "owc",
+
+ /**
+ * APIProperty: extractAttributes
+ * {Boolean} Extract attributes from GML. Default is true.
+ */
+ extractAttributes: true,
+
+ /**
+ * APIProperty: xy
+ * {Boolean} Order of the GML coordinate true:(x,y) or false:(y,x)
+ * Changing is not recommended, a new Format should be instantiated.
+ */
+ xy: true,
+
+ /**
+ * Property: regExes
+ * Compiled regular expressions for manipulating strings.
+ */
+ regExes: {
+ trimSpace: (/^\s*|\s*$/g),
+ removeSpace: (/\s*/g),
+ splitSpace: (/\s+/),
+ trimComma: (/\s*,\s*/g)
+ },
+
+ /**
+ * Property: featureNS
+ * {String} The namespace uri to use for writing InlineGeometry
+ */
+ featureNS: "http://mapserver.gis.umn.edu/mapserver",
+
+ /**
+ * Property: featureType
+ * {String} The name to use as the feature type when writing out
+ * InlineGeometry
+ */
+ featureType: 'vector',
+
+ /**
+ * Property: geometryName
+ * {String} The name to use for the geometry attribute when writing out
+ * InlineGeometry
+ */
+ geometryName: 'geometry',
+
+ /**
+ * Property: nestingLayerLookup
+ * {Object} Hashtable lookup for nesting layer nodes. Used while writing
+ * the OWS context document. It is necessary to keep track of the
+ * nestingPaths for which nesting layer nodes have already been
+ * created, so (nesting) layer nodes are added to those nodes.
+ *
+ * For example:
+ *
+ * If there are three layers with nestingPaths:
+ * layer1.metadata.nestingPath = "a/b/"
+ * layer2.metadata.nestingPath = "a/b/"
+ * layer2.metadata.nestingPath = "a/c"
+ *
+ * then a nesting layer node "a" should be created once and added
+ * to the resource list, a nesting layer node "b" should be created
+ * once and added under "a", and a nesting layer node "c" should be
+ * created and added under "a". The lookup paths for these nodes
+ * will be "a", "a/b", and "a/c" respectively.
+ */
+ nestingLayerLookup: null,
+
+ /**
+ * Constructor: OpenLayers.Format.OWSContext.v0_3_1
+ * Instances of this class are not created directly. Use the
+ * <OpenLayers.Format.OWSContext> constructor instead.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+ initialize: function(options) {
+ OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+ OpenLayers.Format.GML.v2.prototype.setGeometryTypes.call(this);
+ },
+
+ /**
+ * Method: setNestingPath
+ * Set the nestingPath property of the layer depending on the position
+ * of the layer in hierarchy of layers.
+ *
+ * Parameters:
+ * l - {Object} An object that may have a layersContext array property.
+ *
+ */
+ setNestingPath : function(l){
+ if(l.layersContext){
+ for (var i = 0, len = l.layersContext.length; i < len; i++) {
+ var layerContext = l.layersContext[i];
+ var nPath = [];
+ var nTitle = l.title || "";
+ if(l.metadata && l.metadata.nestingPath){
+ nPath = l.metadata.nestingPath.slice();
+ }
+ if (nTitle != "") {
+ nPath.push(nTitle);
+ }
+ layerContext.metadata.nestingPath = nPath;
+ if(layerContext.layersContext){
+ this.setNestingPath(layerContext);
+ }
+ }
+ }
+ },
+
+ /**
+ * Function: decomposeNestingPath
+ * Takes a nestingPath like "a/b/c" and decomposes it into subpaths:
+ * "a", "a/b", "a/b/c"
+ *
+ * Parameters:
+ * nPath - {Array} the nesting path
+ *
+ * Returns:
+ * Array({String}) Array with subpaths, or empty array if there is nothing
+ * to decompose
+ */
+ decomposeNestingPath: function(nPath){
+ var a = [];
+ if (OpenLayers.Util.isArray(nPath)) {
+ var path = nPath.slice();
+ while (path.length > 0) {
+ a.push(path.slice());
+ path.pop();
+ }
+ a.reverse();
+ }
+ return a;
+ },
+
+ /**
+ * APIMethod: read
+ * Read OWS context data from a string or DOMElement, and return a list
+ * of layers.
+ *
+ * Parameters:
+ * data - {String} or {DOMElement} data to read/parse.
+ *
+ * Returns:
+ * {Object} The context object with a flat layer list as a property named
+ * layersContext.
+ */
+ read: function(data) {
+ if(typeof data == "string") {
+ data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+ }
+ if(data && data.nodeType == 9) {
+ data = data.documentElement;
+ }
+ var context = {};
+ this.readNode(data, context);
+ // since an OWSContext can be nested we need to go through this
+ // structure recursively
+ this.setNestingPath({layersContext : context.layersContext});
+ // after nesting path has been set, create a flat list of layers
+ var layers = [];
+ this.processLayer(layers, context);
+ delete context.layersContext;
+ context.layersContext = layers;
+ return context;
+ },
+
+ /**
+ * Method: processLayer
+ * Recursive function to get back a flat list of layers from the hierarchic
+ * layer structure.
+ *
+ * Parameters:
+ * layerArray - {Array({Object})} Array of layerContext objects
+ * layer - {Object} layerContext object
+ */
+ processLayer: function(layerArray, layer) {
+ if (layer.layersContext) {
+ for (var i=0, len = layer.layersContext.length; i<len; i++) {
+ var l = layer.layersContext[i];
+ layerArray.push(l);
+ if (l.layersContext) {
+ this.processLayer(layerArray, l);
+ }
+ }
+ }
+ },
+
+ /**
+ * APIMethod: write
+ *
+ * Parameters:
+ * context - {Object} An object representing the map context.
+ * options - {Object} Optional object.
+ *
+ * Returns:
+ * {String} An OWS Context document string.
+ */
+ write: function(context, options) {
+ var name = "OWSContext";
+ this.nestingLayerLookup = {}; //start with empty lookup
+ options = options || {};
+ OpenLayers.Util.applyDefaults(options, context);
+ var root = this.writeNode(name, options);
+ this.nestingLayerLookup = null; //clear lookup
+ this.setAttributeNS(
+ root, this.namespaces["xsi"],
+ "xsi:schemaLocation", this.schemaLocation
+ );
+ return OpenLayers.Format.XML.prototype.write.apply(this, [root]);
+ },
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "kml": {
+ "Document": function(node, obj) {
+ obj.features = new OpenLayers.Format.KML(
+ {kmlns: this.namespaces.kml,
+ extractStyles: true}).read(node);
+ }
+ },
+ "owc": {
+ "OWSContext": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "General": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "ResourceList": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "Layer": function(node, obj) {
+ var layerContext = {
+ metadata: {},
+ visibility: (node.getAttribute("hidden") != "1"),
+ queryable: (node.getAttribute("queryable") == "1"),
+ opacity: ((node.getAttribute("opacity") != null) ?
+ parseFloat(node.getAttribute("opacity")) : null),
+ name: node.getAttribute("name"),
+ /* A category layer is a dummy layer meant for creating
+ hierarchies. It is not a physical layer in the
+ OpenLayers sense. The assumption we make here is that
+ category layers do not have a name attribute */
+ categoryLayer: (node.getAttribute("name") == null),
+ formats: [],
+ styles: []
+ };
+ if (!obj.layersContext) {
+ obj.layersContext = [];
+ }
+ obj.layersContext.push(layerContext);
+ this.readChildNodes(node, layerContext);
+ },
+ "InlineGeometry": function(node, obj) {
+ obj.features = [];
+ var elements = this.getElementsByTagNameNS(node,
+ this.namespaces.gml, "featureMember");
+ var el;
+ if (elements.length >= 1) {
+ el = elements[0];
+ }
+ if (el && el.firstChild) {
+ var featurenode = (el.firstChild.nextSibling) ?
+ el.firstChild.nextSibling : el.firstChild;
+ this.setNamespace("feature", featurenode.namespaceURI);
+ this.featureType = featurenode.localName ||
+ featurenode.nodeName.split(":").pop();
+ this.readChildNodes(node, obj);
+ }
+ },
+ "Server": function(node, obj) {
+ // when having multiple Server types, we prefer WMS
+ if ((!obj.service && !obj.version) ||
+ (obj.service !=
+ OpenLayers.Format.Context.serviceTypes.WMS)) {
+ obj.service = node.getAttribute("service");
+ obj.version = node.getAttribute("version");
+ this.readChildNodes(node, obj);
+ }
+ },
+ "Name": function(node, obj) {
+ obj.name = this.getChildValue(node);
+ this.readChildNodes(node, obj);
+ },
+ "Title": function(node, obj) {
+ obj.title = this.getChildValue(node);
+ this.readChildNodes(node, obj);
+ },
+ "StyleList": function(node, obj) {
+ this.readChildNodes(node, obj.styles);
+ },
+ "Style": function(node, obj) {
+ var style = {};
+ obj.push(style);
+ this.readChildNodes(node, style);
+ },
+ "LegendURL": function(node, obj) {
+ var legend = {};
+ obj.legend = legend;
+ this.readChildNodes(node, legend);
+ },
+ "OnlineResource": function(node, obj) {
+ obj.url = this.getAttributeNS(node, this.namespaces.xlink,
+ "href");
+ this.readChildNodes(node, obj);
+ }
+ },
+ "ows": OpenLayers.Format.OWSCommon.v1_0_0.prototype.readers.ows,
+ "gml": OpenLayers.Format.GML.v2.prototype.readers.gml,
+ "sld": OpenLayers.Format.SLD.v1_0_0.prototype.readers.sld,
+ "feature": OpenLayers.Format.GML.v2.prototype.readers.feature
+ },
+
+ /**
+ * Property: writers
+ * As a compliment to the readers property, this structure contains public
+ * writing functions grouped by namespace alias and named like the
+ * node names they produce.
+ */
+ writers: {
+ "owc": {
+ "OWSContext": function(options) {
+ var node = this.createElementNSPlus("OWSContext", {
+ attributes: {
+ version: this.VERSION,
+ id: options.id || OpenLayers.Util.createUniqueID("OpenLayers_OWSContext_")
+ }
+ });
+ this.writeNode("General", options, node);
+ this.writeNode("ResourceList", options, node);
+ return node;
+ },
+ "General": function(options) {
+ var node = this.createElementNSPlus("General");
+ this.writeNode("ows:BoundingBox", options, node);
+ this.writeNode("ows:Title", options.title || 'OpenLayers OWSContext', node);
+ return node;
+ },
+ "ResourceList": function(options) {
+ var node = this.createElementNSPlus("ResourceList");
+ for (var i=0, len=options.layers.length; i<len; i++) {
+ var layer = options.layers[i];
+ var decomposedPath = this.decomposeNestingPath(layer.metadata.nestingPath);
+ this.writeNode("_Layer", {layer: layer, subPaths: decomposedPath}, node);
+ }
+ return node;
+ },
+ "Server": function(options) {
+ var node = this.createElementNSPlus("Server", {attributes: {
+ version: options.version,
+ service: options.service }
+ });
+ this.writeNode("OnlineResource", options, node);
+ return node;
+ },
+ "OnlineResource": function(options) {
+ var node = this.createElementNSPlus("OnlineResource", {attributes: {
+ "xlink:href": options.url }
+ });
+ return node;
+ },
+ "InlineGeometry": function(layer) {
+ var node = this.createElementNSPlus("InlineGeometry"),
+ dataExtent = layer.getDataExtent();
+ if (dataExtent !== null) {
+ this.writeNode("gml:boundedBy", dataExtent, node);
+ }
+ for (var i=0, len=layer.features.length; i<len; i++) {
+ this.writeNode("gml:featureMember", layer.features[i], node);
+ }
+ return node;
+ },
+ "StyleList": function(styles) {
+ var node = this.createElementNSPlus("StyleList");
+ for (var i=0, len=styles.length; i<len; i++) {
+ this.writeNode("Style", styles[i], node);
+ }
+ return node;
+ },
+ "Style": function(style) {
+ var node = this.createElementNSPlus("Style");
+ this.writeNode("Name", style, node);
+ this.writeNode("Title", style, node);
+ if (style.legend) {
+ this.writeNode("LegendURL", style, node);
+ }
+ return node;
+ },
+ "Name": function(obj) {
+ var node = this.createElementNSPlus("Name", {
+ value: obj.name });
+ return node;
+ },
+ "Title": function(obj) {
+ var node = this.createElementNSPlus("Title", {
+ value: obj.title });
+ return node;
+ },
+ "LegendURL": function(style) {
+ var node = this.createElementNSPlus("LegendURL");
+ this.writeNode("OnlineResource", style.legend, node);
+ return node;
+ },
+ "_WMS": function(layer) {
+ var node = this.createElementNSPlus("Layer", {attributes: {
+ name: layer.params.LAYERS,
+ queryable: layer.queryable ? "1" : "0",
+ hidden: layer.visibility ? "0" : "1",
+ opacity: layer.hasOwnProperty("opacity") ? layer.opacity : null}
+ });
+ this.writeNode("ows:Title", layer.name, node);
+ this.writeNode("ows:OutputFormat", layer.params.FORMAT, node);
+ this.writeNode("Server", {service:
+ OpenLayers.Format.Context.serviceTypes.WMS,
+ version: layer.params.VERSION, url: layer.url}, node);
+ if (layer.metadata.styles && layer.metadata.styles.length > 0) {
+ this.writeNode("StyleList", layer.metadata.styles, node);
+ }
+ return node;
+ },
+ "_Layer": function(options) {
+ var layer, subPaths, node, title;
+ layer = options.layer;
+ subPaths = options.subPaths;
+ node = null;
+ title = null;
+ // subPaths is an array of an array
+ // recursively calling _Layer writer eats up subPaths, until a
+ // real writer is called and nodes are returned.
+ if(subPaths.length > 0){
+ var path = subPaths[0].join("/");
+ var index = path.lastIndexOf("/");
+ node = this.nestingLayerLookup[path];
+ title = (index > 0)?path.substring(index + 1, path.length):path;
+ if(!node){
+ // category layer
+ node = this.createElementNSPlus("Layer");
+ this.writeNode("ows:Title", title, node);
+ this.nestingLayerLookup[path] = node;
+ }
+ options.subPaths.shift();//remove a path after each call
+ this.writeNode("_Layer", options, node);
+ return node;
+ } else {
+ // write out the actual layer
+ if (layer instanceof OpenLayers.Layer.WMS) {
+ node = this.writeNode("_WMS", layer);
+ } else if (layer instanceof OpenLayers.Layer.Vector) {
+ if (layer.protocol instanceof OpenLayers.Protocol.WFS.v1) {
+ node = this.writeNode("_WFS", layer);
+ } else if (layer.protocol instanceof OpenLayers.Protocol.HTTP) {
+ if (layer.protocol.format instanceof OpenLayers.Format.GML) {
+ layer.protocol.format.version = "2.1.2";
+ node = this.writeNode("_GML", layer);
+ } else if (layer.protocol.format instanceof OpenLayers.Format.KML) {
+ layer.protocol.format.version = "2.2";
+ node = this.writeNode("_KML", layer);
+ }
+ } else {
+ // write out as inline GML since we have no idea
+ // about the original Format
+ this.setNamespace("feature", this.featureNS);
+ node = this.writeNode("_InlineGeometry", layer);
+ }
+ }
+ if (layer.options.maxScale) {
+ this.writeNode("sld:MinScaleDenominator",
+ layer.options.maxScale, node);
+ }
+ if (layer.options.minScale) {
+ this.writeNode("sld:MaxScaleDenominator",
+ layer.options.minScale, node);
+ }
+ this.nestingLayerLookup[layer.name] = node;
+ return node;
+ }
+ },
+ "_WFS": function(layer) {
+ var node = this.createElementNSPlus("Layer", {attributes: {
+ name: layer.protocol.featurePrefix + ":" + layer.protocol.featureType,
+ hidden: layer.visibility ? "0" : "1" }
+ });
+ this.writeNode("ows:Title", layer.name, node);
+ this.writeNode("Server", {service:
+ OpenLayers.Format.Context.serviceTypes.WFS,
+ version: layer.protocol.version,
+ url: layer.protocol.url}, node);
+ return node;
+ },
+ "_InlineGeometry": function(layer) {
+ var node = this.createElementNSPlus("Layer", {attributes: {
+ name: this.featureType,
+ hidden: layer.visibility ? "0" : "1" }
+ });
+ this.writeNode("ows:Title", layer.name, node);
+ this.writeNode("InlineGeometry", layer, node);
+ return node;
+ },
+ "_GML": function(layer) {
+ var node = this.createElementNSPlus("Layer");
+ this.writeNode("ows:Title", layer.name, node);
+ this.writeNode("Server", {service:
+ OpenLayers.Format.Context.serviceTypes.GML,
+ url: layer.protocol.url, version:
+ layer.protocol.format.version}, node);
+ return node;
+ },
+ "_KML": function(layer) {
+ var node = this.createElementNSPlus("Layer");
+ this.writeNode("ows:Title", layer.name, node);
+ this.writeNode("Server", {service:
+ OpenLayers.Format.Context.serviceTypes.KML,
+ version: layer.protocol.format.version, url:
+ layer.protocol.url}, node);
+ return node;
+ }
+ },
+ "gml": OpenLayers.Util.applyDefaults({
+ "boundedBy": function(bounds) {
+ var node = this.createElementNSPlus("gml:boundedBy");
+ this.writeNode("gml:Box", bounds, node);
+ return node;
+ }
+ }, OpenLayers.Format.GML.v2.prototype.writers.gml),
+ "ows": OpenLayers.Format.OWSCommon.v1_0_0.prototype.writers.ows,
+ "sld": OpenLayers.Format.SLD.v1_0_0.prototype.writers.sld,
+ "feature": OpenLayers.Format.GML.v2.prototype.writers.feature
+ },
+
+ CLASS_NAME: "OpenLayers.Format.OWSContext.v0_3_1"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/QueryStringFilter.js b/misc/openlayers/lib/OpenLayers/Format/QueryStringFilter.js
new file mode 100644
index 0000000..e33f722
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/QueryStringFilter.js
@@ -0,0 +1,183 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Console.js
+ * @requires OpenLayers/Format.js
+ * @requires OpenLayers/Filter/Spatial.js
+ * @requires OpenLayers/Filter/Comparison.js
+ * @requires OpenLayers/Filter/Logical.js
+ */
+
+/**
+ * Class: OpenLayers.Format.QueryStringFilter
+ * Parser for reading a query string and creating a simple filter.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format>
+ */
+OpenLayers.Format.QueryStringFilter = (function() {
+
+ /**
+ * Map the OpenLayers.Filter.Comparison types to the operation strings of
+ * the protocol.
+ */
+ var cmpToStr = {};
+ cmpToStr[OpenLayers.Filter.Comparison.EQUAL_TO] = "eq";
+ cmpToStr[OpenLayers.Filter.Comparison.NOT_EQUAL_TO] = "ne";
+ cmpToStr[OpenLayers.Filter.Comparison.LESS_THAN] = "lt";
+ cmpToStr[OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO] = "lte";
+ cmpToStr[OpenLayers.Filter.Comparison.GREATER_THAN] = "gt";
+ cmpToStr[OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO] = "gte";
+ cmpToStr[OpenLayers.Filter.Comparison.LIKE] = "ilike";
+
+ /**
+ * Function: regex2value
+ * Convert the value from a regular expression string to a LIKE/ILIKE
+ * string known to the web service.
+ *
+ * Parameters:
+ * value - {String} The regex string.
+ *
+ * Returns:
+ * {String} The converted string.
+ */
+ function regex2value(value) {
+
+ // highly sensitive!! Do not change this without running the
+ // Protocol/HTTP.html unit tests
+
+ // convert % to \%
+ value = value.replace(/%/g, "\\%");
+
+ // convert \\. to \\_ (\\.* occurences converted later)
+ value = value.replace(/\\\\\.(\*)?/g, function($0, $1) {
+ return $1 ? $0 : "\\\\_";
+ });
+
+ // convert \\.* to \\%
+ value = value.replace(/\\\\\.\*/g, "\\\\%");
+
+ // convert . to _ (\. and .* occurences converted later)
+ value = value.replace(/(\\)?\.(\*)?/g, function($0, $1, $2) {
+ return $1 || $2 ? $0 : "_";
+ });
+
+ // convert .* to % (\.* occurnces converted later)
+ value = value.replace(/(\\)?\.\*/g, function($0, $1) {
+ return $1 ? $0 : "%";
+ });
+
+ // convert \. to .
+ value = value.replace(/\\\./g, ".");
+
+ // replace \* with * (watching out for \\*)
+ value = value.replace(/(\\)?\\\*/g, function($0, $1) {
+ return $1 ? $0 : "*";
+ });
+
+ return value;
+ }
+
+ return OpenLayers.Class(OpenLayers.Format, {
+
+ /**
+ * Property: wildcarded.
+ * {Boolean} If true percent signs are added around values
+ * read from LIKE filters, for example if the protocol
+ * read method is passed a LIKE filter whose property
+ * is "foo" and whose value is "bar" the string
+ * "foo__ilike=%bar%" will be sent in the query string;
+ * defaults to false.
+ */
+ wildcarded: false,
+
+ /**
+ * APIProperty: srsInBBOX
+ * {Boolean} Include the SRS identifier in BBOX query string parameter.
+ * Default is false. If true and the layer has a projection object set,
+ * any BBOX filter will be serialized with a fifth item identifying the
+ * projection. E.g. bbox=-1000,-1000,1000,1000,EPSG:900913
+ */
+ srsInBBOX: false,
+
+ /**
+ * APIMethod: write
+ * Serialize an <OpenLayers.Filter> objects using the "simple" filter syntax for
+ * query string parameters. This function must be called as a method of
+ * a protocol instance.
+ *
+ * Parameters:
+ * filter - {<OpenLayers.Filter>} filter to convert.
+ * params - {Object} The parameters object.
+ *
+ * Returns:
+ * {Object} The resulting parameters object.
+ */
+ write: function(filter, params) {
+ params = params || {};
+ var className = filter.CLASS_NAME;
+ var filterType = className.substring(className.lastIndexOf(".") + 1);
+ switch (filterType) {
+ case "Spatial":
+ switch (filter.type) {
+ case OpenLayers.Filter.Spatial.BBOX:
+ params.bbox = filter.value.toArray();
+ if (this.srsInBBOX && filter.projection) {
+ params.bbox.push(filter.projection.getCode());
+ }
+ break;
+ case OpenLayers.Filter.Spatial.DWITHIN:
+ params.tolerance = filter.distance;
+ // no break here
+ case OpenLayers.Filter.Spatial.WITHIN:
+ params.lon = filter.value.x;
+ params.lat = filter.value.y;
+ break;
+ default:
+ OpenLayers.Console.warn(
+ "Unknown spatial filter type " + filter.type);
+ }
+ break;
+ case "Comparison":
+ var op = cmpToStr[filter.type];
+ if (op !== undefined) {
+ var value = filter.value;
+ if (filter.type == OpenLayers.Filter.Comparison.LIKE) {
+ value = regex2value(value);
+ if (this.wildcarded) {
+ value = "%" + value + "%";
+ }
+ }
+ params[filter.property + "__" + op] = value;
+ params.queryable = params.queryable || [];
+ params.queryable.push(filter.property);
+ } else {
+ OpenLayers.Console.warn(
+ "Unknown comparison filter type " + filter.type);
+ }
+ break;
+ case "Logical":
+ if (filter.type === OpenLayers.Filter.Logical.AND) {
+ for (var i=0,len=filter.filters.length; i<len; i++) {
+ params = this.write(filter.filters[i], params);
+ }
+ } else {
+ OpenLayers.Console.warn(
+ "Unsupported logical filter type " + filter.type);
+ }
+ break;
+ default:
+ OpenLayers.Console.warn("Unknown filter type " + filterType);
+ }
+ return params;
+ },
+
+ CLASS_NAME: "OpenLayers.Format.QueryStringFilter"
+
+ });
+
+
+})();
diff --git a/misc/openlayers/lib/OpenLayers/Format/SLD.js b/misc/openlayers/lib/OpenLayers/Format/SLD.js
new file mode 100644
index 0000000..56e59d0
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/SLD.js
@@ -0,0 +1,81 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML/VersionedOGC.js
+ * @requires OpenLayers/Style.js
+ * @requires OpenLayers/Rule.js
+ * @requires OpenLayers/Filter/FeatureId.js
+ * @requires OpenLayers/Filter/Logical.js
+ * @requires OpenLayers/Filter/Comparison.js
+ * @requires OpenLayers/Filter/Spatial.js
+ */
+
+/**
+ * Class: OpenLayers.Format.SLD
+ * Read/Write SLD. Create a new instance with the <OpenLayers.Format.SLD>
+ * constructor.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML.VersionedOGC>
+ */
+OpenLayers.Format.SLD = OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC, {
+
+ /**
+ * APIProperty: profile
+ * {String} If provided, use a custom profile.
+ *
+ * Currently supported profiles:
+ * - GeoServer - parses GeoServer vendor specific capabilities for SLD.
+ */
+ profile: null,
+
+ /**
+ * APIProperty: defaultVersion
+ * {String} Version number to assume if none found. Default is "1.0.0".
+ */
+ defaultVersion: "1.0.0",
+
+ /**
+ * APIProperty: stringifyOutput
+ * {Boolean} If true, write will return a string otherwise a DOMElement.
+ * Default is true.
+ */
+ stringifyOutput: true,
+
+ /**
+ * APIProperty: namedLayersAsArray
+ * {Boolean} Generate a namedLayers array. If false, the namedLayers
+ * property value will be an object keyed by layer name. Default is
+ * false.
+ */
+ namedLayersAsArray: false,
+
+ /**
+ * APIMethod: write
+ * Write a SLD document given a list of styles.
+ *
+ * Parameters:
+ * sld - {Object} An object representing the SLD.
+ * options - {Object} Optional configuration object.
+ *
+ * Returns:
+ * {String} An SLD document string.
+ */
+
+ /**
+ * APIMethod: read
+ * Read and SLD doc and return an object representing the SLD.
+ *
+ * Parameters:
+ * data - {String | DOMElement} Data to read.
+ * options - {Object} Options for the reader.
+ *
+ * Returns:
+ * {Object} An object representing the SLD.
+ */
+
+ CLASS_NAME: "OpenLayers.Format.SLD"
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/SLD/v1.js b/misc/openlayers/lib/OpenLayers/Format/SLD/v1.js
new file mode 100644
index 0000000..c43bac4
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/SLD/v1.js
@@ -0,0 +1,1309 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Rule.js
+ * @requires OpenLayers/Format/SLD.js
+ * @requires OpenLayers/Format/Filter/v1_0_0.js
+ * @requires OpenLayers/Symbolizer/Point.js
+ * @requires OpenLayers/Symbolizer/Line.js
+ * @requires OpenLayers/Symbolizer/Polygon.js
+ * @requires OpenLayers/Symbolizer/Text.js
+ * @requires OpenLayers/Symbolizer/Raster.js
+ */
+
+/**
+ * Class: OpenLayers.Format.SLD.v1
+ * Superclass for SLD version 1 parsers.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.Filter.v1_0_0>
+ */
+OpenLayers.Format.SLD.v1 = OpenLayers.Class(OpenLayers.Format.Filter.v1_0_0, {
+
+ /**
+ * Property: namespaces
+ * {Object} Mapping of namespace aliases to namespace URIs.
+ */
+ namespaces: {
+ sld: "http://www.opengis.net/sld",
+ ogc: "http://www.opengis.net/ogc",
+ gml: "http://www.opengis.net/gml",
+ xlink: "http://www.w3.org/1999/xlink",
+ xsi: "http://www.w3.org/2001/XMLSchema-instance"
+ },
+
+ /**
+ * Property: defaultPrefix
+ */
+ defaultPrefix: "sld",
+
+ /**
+ * Property: schemaLocation
+ * {String} Schema location for a particular minor version.
+ */
+ schemaLocation: null,
+
+ /**
+ * APIProperty: multipleSymbolizers
+ * {Boolean} Support multiple symbolizers per rule. Default is false. if
+ * true, an OpenLayers.Style2 instance will be created to represent
+ * user styles instead of an OpenLayers.Style instace. The
+ * OpenLayers.Style2 class allows collections of rules with multiple
+ * symbolizers, but is not currently useful for client side rendering.
+ * If multiple symbolizers is true, multiple FeatureTypeStyle elements
+ * are preserved in reading/writing by setting symbolizer zIndex values.
+ * In addition, the <defaultSymbolizer> property is ignored if
+ * multiple symbolizers are supported (defaults should be applied
+ * when rendering).
+ */
+ multipleSymbolizers: false,
+
+ /**
+ * Property: featureTypeCounter
+ * {Number} Private counter for multiple feature type styles.
+ */
+ featureTypeCounter: null,
+
+ /**
+ * APIProperty: defaultSymbolizer.
+ * {Object} A symbolizer with the SLD defaults.
+ */
+ defaultSymbolizer: {
+ fillColor: "#808080",
+ fillOpacity: 1,
+ strokeColor: "#000000",
+ strokeOpacity: 1,
+ strokeWidth: 1,
+ strokeDashstyle: "solid",
+ pointRadius: 3,
+ graphicName: "square"
+ },
+
+ /**
+ * Constructor: OpenLayers.Format.SLD.v1
+ * Instances of this class are not created directly. Use the
+ * <OpenLayers.Format.SLD> constructor instead.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * Method: read
+ *
+ * Parameters:
+ * data - {DOMElement} An SLD document element.
+ * options - {Object} Options for the reader.
+ *
+ * Valid options:
+ * namedLayersAsArray - {Boolean} Generate a namedLayers array. If false,
+ * the namedLayers property value will be an object keyed by layer name.
+ * Default is false.
+ *
+ * Returns:
+ * {Object} An object representing the SLD.
+ */
+ read: function(data, options) {
+ options = OpenLayers.Util.applyDefaults(options, this.options);
+ var sld = {
+ namedLayers: options.namedLayersAsArray === true ? [] : {}
+ };
+ this.readChildNodes(data, sld);
+ return sld;
+ },
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: OpenLayers.Util.applyDefaults({
+ "sld": {
+ "StyledLayerDescriptor": function(node, sld) {
+ sld.version = node.getAttribute("version");
+ this.readChildNodes(node, sld);
+ },
+ "Name": function(node, obj) {
+ obj.name = this.getChildValue(node);
+ },
+ "Title": function(node, obj) {
+ obj.title = this.getChildValue(node);
+ },
+ "Abstract": function(node, obj) {
+ obj.description = this.getChildValue(node);
+ },
+ "NamedLayer": function(node, sld) {
+ var layer = {
+ userStyles: [],
+ namedStyles: []
+ };
+ this.readChildNodes(node, layer);
+ // give each of the user styles this layer name
+ for(var i=0, len=layer.userStyles.length; i<len; ++i) {
+ layer.userStyles[i].layerName = layer.name;
+ }
+ if(OpenLayers.Util.isArray(sld.namedLayers)) {
+ sld.namedLayers.push(layer);
+ } else {
+ sld.namedLayers[layer.name] = layer;
+ }
+ },
+ "NamedStyle": function(node, layer) {
+ layer.namedStyles.push(
+ this.getChildName(node.firstChild)
+ );
+ },
+ "UserStyle": function(node, layer) {
+ var obj = {defaultsPerSymbolizer: true, rules: []};
+ this.featureTypeCounter = -1;
+ this.readChildNodes(node, obj);
+ var style;
+ if (this.multipleSymbolizers) {
+ delete obj.defaultsPerSymbolizer;
+ style = new OpenLayers.Style2(obj);
+ } else {
+ style = new OpenLayers.Style(this.defaultSymbolizer, obj);
+ }
+ layer.userStyles.push(style);
+ },
+ "IsDefault": function(node, style) {
+ if(this.getChildValue(node) == "1") {
+ style.isDefault = true;
+ }
+ },
+ "FeatureTypeStyle": function(node, style) {
+ ++this.featureTypeCounter;
+ var obj = {
+ rules: this.multipleSymbolizers ? style.rules : []
+ };
+ this.readChildNodes(node, obj);
+ if (!this.multipleSymbolizers) {
+ style.rules = obj.rules;
+ }
+ },
+ "Rule": function(node, obj) {
+ var config;
+ if (this.multipleSymbolizers) {
+ config = {symbolizers: []};
+ }
+ var rule = new OpenLayers.Rule(config);
+ this.readChildNodes(node, rule);
+ obj.rules.push(rule);
+ },
+ "ElseFilter": function(node, rule) {
+ rule.elseFilter = true;
+ },
+ "MinScaleDenominator": function(node, rule) {
+ rule.minScaleDenominator = parseFloat(this.getChildValue(node));
+ },
+ "MaxScaleDenominator": function(node, rule) {
+ rule.maxScaleDenominator = parseFloat(this.getChildValue(node));
+ },
+ "TextSymbolizer": function(node, rule) {
+ var config = {};
+ this.readChildNodes(node, config);
+ if (this.multipleSymbolizers) {
+ config.zIndex = this.featureTypeCounter;
+ rule.symbolizers.push(
+ new OpenLayers.Symbolizer.Text(config)
+ );
+ } else {
+ rule.symbolizer["Text"] = OpenLayers.Util.applyDefaults(
+ config, rule.symbolizer["Text"]
+ );
+ }
+ },
+ "LabelPlacement": function(node, symbolizer) {
+ this.readChildNodes(node, symbolizer);
+ },
+ "PointPlacement": function(node, symbolizer) {
+ var config = {};
+ this.readChildNodes(node, config);
+ config.labelRotation = config.rotation;
+ delete config.rotation;
+ var labelAlign,
+ x = symbolizer.labelAnchorPointX,
+ y = symbolizer.labelAnchorPointY;
+ if (x <= 1/3) {
+ labelAlign = 'l';
+ } else if (x > 1/3 && x < 2/3) {
+ labelAlign = 'c';
+ } else if (x >= 2/3) {
+ labelAlign = 'r';
+ }
+ if (y <= 1/3) {
+ labelAlign += 'b';
+ } else if (y > 1/3 && y < 2/3) {
+ labelAlign += 'm';
+ } else if (y >= 2/3) {
+ labelAlign += 't';
+ }
+ config.labelAlign = labelAlign;
+ OpenLayers.Util.applyDefaults(symbolizer, config);
+ },
+ "AnchorPoint": function(node, symbolizer) {
+ this.readChildNodes(node, symbolizer);
+ },
+ "AnchorPointX": function(node, symbolizer) {
+ var labelAnchorPointX = this.readers.ogc._expression.call(this, node);
+ // always string, could be empty string
+ if(labelAnchorPointX) {
+ symbolizer.labelAnchorPointX = labelAnchorPointX;
+ }
+ },
+ "AnchorPointY": function(node, symbolizer) {
+ var labelAnchorPointY = this.readers.ogc._expression.call(this, node);
+ // always string, could be empty string
+ if(labelAnchorPointY) {
+ symbolizer.labelAnchorPointY = labelAnchorPointY;
+ }
+ },
+ "Displacement": function(node, symbolizer) {
+ this.readChildNodes(node, symbolizer);
+ },
+ "DisplacementX": function(node, symbolizer) {
+ var labelXOffset = this.readers.ogc._expression.call(this, node);
+ // always string, could be empty string
+ if(labelXOffset) {
+ symbolizer.labelXOffset = labelXOffset;
+ }
+ },
+ "DisplacementY": function(node, symbolizer) {
+ var labelYOffset = this.readers.ogc._expression.call(this, node);
+ // always string, could be empty string
+ if(labelYOffset) {
+ symbolizer.labelYOffset = labelYOffset;
+ }
+ },
+ "LinePlacement": function(node, symbolizer) {
+ this.readChildNodes(node, symbolizer);
+ },
+ "PerpendicularOffset": function(node, symbolizer) {
+ var labelPerpendicularOffset = this.readers.ogc._expression.call(this, node);
+ // always string, could be empty string
+ if(labelPerpendicularOffset) {
+ symbolizer.labelPerpendicularOffset = labelPerpendicularOffset;
+ }
+ },
+ "Label": function(node, symbolizer) {
+ var value = this.readers.ogc._expression.call(this, node);
+ if (value) {
+ symbolizer.label = value;
+ }
+ },
+ "Font": function(node, symbolizer) {
+ this.readChildNodes(node, symbolizer);
+ },
+ "Halo": function(node, symbolizer) {
+ // halo has a fill, so send fresh object
+ var obj = {};
+ this.readChildNodes(node, obj);
+ symbolizer.haloRadius = obj.haloRadius;
+ symbolizer.haloColor = obj.fillColor;
+ symbolizer.haloOpacity = obj.fillOpacity;
+ },
+ "Radius": function(node, symbolizer) {
+ var radius = this.readers.ogc._expression.call(this, node);
+ if(radius != null) {
+ // radius is only used for halo
+ symbolizer.haloRadius = radius;
+ }
+ },
+ "RasterSymbolizer": function(node, rule) {
+ var config = {};
+ this.readChildNodes(node, config);
+ if (this.multipleSymbolizers) {
+ config.zIndex = this.featureTypeCounter;
+ rule.symbolizers.push(
+ new OpenLayers.Symbolizer.Raster(config)
+ );
+ } else {
+ rule.symbolizer["Raster"] = OpenLayers.Util.applyDefaults(
+ config, rule.symbolizer["Raster"]
+ );
+ }
+ },
+ "Geometry": function(node, obj) {
+ obj.geometry = {};
+ this.readChildNodes(node, obj.geometry);
+ },
+ "ColorMap": function(node, symbolizer) {
+ symbolizer.colorMap = [];
+ this.readChildNodes(node, symbolizer.colorMap);
+ },
+ "ColorMapEntry": function(node, colorMap) {
+ var q = node.getAttribute("quantity");
+ var o = node.getAttribute("opacity");
+ colorMap.push({
+ color: node.getAttribute("color"),
+ quantity: q !== null ? parseFloat(q) : undefined,
+ label: node.getAttribute("label") || undefined,
+ opacity: o !== null ? parseFloat(o) : undefined
+ });
+ },
+ "LineSymbolizer": function(node, rule) {
+ var config = {};
+ this.readChildNodes(node, config);
+ if (this.multipleSymbolizers) {
+ config.zIndex = this.featureTypeCounter;
+ rule.symbolizers.push(
+ new OpenLayers.Symbolizer.Line(config)
+ );
+ } else {
+ rule.symbolizer["Line"] = OpenLayers.Util.applyDefaults(
+ config, rule.symbolizer["Line"]
+ );
+ }
+ },
+ "PolygonSymbolizer": function(node, rule) {
+ var config = {
+ fill: false,
+ stroke: false
+ };
+ if (!this.multipleSymbolizers) {
+ config = rule.symbolizer["Polygon"] || config;
+ }
+ this.readChildNodes(node, config);
+ if (this.multipleSymbolizers) {
+ config.zIndex = this.featureTypeCounter;
+ rule.symbolizers.push(
+ new OpenLayers.Symbolizer.Polygon(config)
+ );
+ } else {
+ rule.symbolizer["Polygon"] = config;
+ }
+ },
+ "PointSymbolizer": function(node, rule) {
+ var config = {
+ fill: false,
+ stroke: false,
+ graphic: false
+ };
+ if (!this.multipleSymbolizers) {
+ config = rule.symbolizer["Point"] || config;
+ }
+ this.readChildNodes(node, config);
+ if (this.multipleSymbolizers) {
+ config.zIndex = this.featureTypeCounter;
+ rule.symbolizers.push(
+ new OpenLayers.Symbolizer.Point(config)
+ );
+ } else {
+ rule.symbolizer["Point"] = config;
+ }
+ },
+ "Stroke": function(node, symbolizer) {
+ symbolizer.stroke = true;
+ this.readChildNodes(node, symbolizer);
+ },
+ "Fill": function(node, symbolizer) {
+ symbolizer.fill = true;
+ this.readChildNodes(node, symbolizer);
+ },
+ "CssParameter": function(node, symbolizer) {
+ var cssProperty = node.getAttribute("name");
+ var symProperty = this.cssMap[cssProperty];
+ // for labels, fill should map to fontColor and fill-opacity
+ // to fontOpacity
+ if (symbolizer.label) {
+ if (cssProperty === 'fill') {
+ symProperty = "fontColor";
+ } else if (cssProperty === 'fill-opacity') {
+ symProperty = "fontOpacity";
+ }
+ }
+ if(symProperty) {
+ // Limited support for parsing of OGC expressions
+ var value = this.readers.ogc._expression.call(this, node);
+ // always string, could be an empty string
+ if(value) {
+ symbolizer[symProperty] = value;
+ }
+ }
+ },
+ "Graphic": function(node, symbolizer) {
+ symbolizer.graphic = true;
+ var graphic = {};
+ // painter's order not respected here, clobber previous with next
+ this.readChildNodes(node, graphic);
+ // directly properties with names that match symbolizer properties
+ var properties = [
+ "stroke", "strokeColor", "strokeWidth", "strokeOpacity",
+ "strokeLinecap", "fill", "fillColor", "fillOpacity",
+ "graphicName", "rotation", "graphicFormat"
+ ];
+ var prop, value;
+ for(var i=0, len=properties.length; i<len; ++i) {
+ prop = properties[i];
+ value = graphic[prop];
+ if(value != undefined) {
+ symbolizer[prop] = value;
+ }
+ }
+ // set other generic properties with specific graphic property names
+ if(graphic.opacity != undefined) {
+ symbolizer.graphicOpacity = graphic.opacity;
+ }
+ if(graphic.size != undefined) {
+ var pointRadius = graphic.size / 2;
+ if (isNaN(pointRadius)) {
+ // likely a property name
+ symbolizer.graphicWidth = graphic.size;
+ } else {
+ symbolizer.pointRadius = graphic.size / 2;
+ }
+ }
+ if(graphic.href != undefined) {
+ symbolizer.externalGraphic = graphic.href;
+ }
+ if(graphic.rotation != undefined) {
+ symbolizer.rotation = graphic.rotation;
+ }
+ },
+ "ExternalGraphic": function(node, graphic) {
+ this.readChildNodes(node, graphic);
+ },
+ "Mark": function(node, graphic) {
+ this.readChildNodes(node, graphic);
+ },
+ "WellKnownName": function(node, graphic) {
+ graphic.graphicName = this.getChildValue(node);
+ },
+ "Opacity": function(node, obj) {
+ var opacity = this.readers.ogc._expression.call(this, node);
+ // always string, could be empty string
+ if(opacity) {
+ obj.opacity = opacity;
+ }
+ },
+ "Size": function(node, obj) {
+ var size = this.readers.ogc._expression.call(this, node);
+ // always string, could be empty string
+ if(size) {
+ obj.size = size;
+ }
+ },
+ "Rotation": function(node, obj) {
+ var rotation = this.readers.ogc._expression.call(this, node);
+ // always string, could be empty string
+ if(rotation) {
+ obj.rotation = rotation;
+ }
+ },
+ "OnlineResource": function(node, obj) {
+ obj.href = this.getAttributeNS(
+ node, this.namespaces.xlink, "href"
+ );
+ },
+ "Format": function(node, graphic) {
+ graphic.graphicFormat = this.getChildValue(node);
+ }
+ }
+ }, OpenLayers.Format.Filter.v1_0_0.prototype.readers),
+
+ /**
+ * Property: cssMap
+ * {Object} Object mapping supported css property names to OpenLayers
+ * symbolizer property names.
+ */
+ cssMap: {
+ "stroke": "strokeColor",
+ "stroke-opacity": "strokeOpacity",
+ "stroke-width": "strokeWidth",
+ "stroke-linecap": "strokeLinecap",
+ "stroke-dasharray": "strokeDashstyle",
+ "fill": "fillColor",
+ "fill-opacity": "fillOpacity",
+ "font-family": "fontFamily",
+ "font-size": "fontSize",
+ "font-weight": "fontWeight",
+ "font-style": "fontStyle"
+ },
+
+ /**
+ * Method: getCssProperty
+ * Given a symbolizer property, get the corresponding CSS property
+ * from the <cssMap>.
+ *
+ * Parameters:
+ * sym - {String} A symbolizer property name.
+ *
+ * Returns:
+ * {String} A CSS property name or null if none found.
+ */
+ getCssProperty: function(sym) {
+ var css = null;
+ for(var prop in this.cssMap) {
+ if(this.cssMap[prop] == sym) {
+ css = prop;
+ break;
+ }
+ }
+ return css;
+ },
+
+ /**
+ * Method: getGraphicFormat
+ * Given a href for an external graphic, try to determine the mime-type.
+ * This method doesn't try too hard, and will fall back to
+ * <defaultGraphicFormat> if one of the known <graphicFormats> is not
+ * the file extension of the provided href.
+ *
+ * Parameters:
+ * href - {String}
+ *
+ * Returns:
+ * {String} The graphic format.
+ */
+ getGraphicFormat: function(href) {
+ var format, regex;
+ for(var key in this.graphicFormats) {
+ if(this.graphicFormats[key].test(href)) {
+ format = key;
+ break;
+ }
+ }
+ return format || this.defaultGraphicFormat;
+ },
+
+ /**
+ * Property: defaultGraphicFormat
+ * {String} If none other can be determined from <getGraphicFormat>, this
+ * default will be returned.
+ */
+ defaultGraphicFormat: "image/png",
+
+ /**
+ * Property: graphicFormats
+ * {Object} Mapping of image mime-types to regular extensions matching
+ * well-known file extensions.
+ */
+ graphicFormats: {
+ "image/jpeg": /\.jpe?g$/i,
+ "image/gif": /\.gif$/i,
+ "image/png": /\.png$/i
+ },
+
+ /**
+ * Method: write
+ *
+ * Parameters:
+ * sld - {Object} An object representing the SLD.
+ *
+ * Returns:
+ * {DOMElement} The root of an SLD document.
+ */
+ write: function(sld) {
+ return this.writers.sld.StyledLayerDescriptor.apply(this, [sld]);
+ },
+
+ /**
+ * Property: writers
+ * As a compliment to the readers property, this structure contains public
+ * writing functions grouped by namespace alias and named like the
+ * node names they produce.
+ */
+ writers: OpenLayers.Util.applyDefaults({
+ "sld": {
+ "_OGCExpression": function(nodeName, value) {
+ // only the simplest of ogc:expression handled
+ // {label: "some text and a ${propertyName}"}
+ var node = this.createElementNSPlus(nodeName);
+ var tokens = typeof value == "string" ?
+ value.split("${") :
+ [value];
+ node.appendChild(this.createTextNode(tokens[0]));
+ var item, last;
+ for(var i=1, len=tokens.length; i<len; i++) {
+ item = tokens[i];
+ last = item.indexOf("}");
+ if(last > 0) {
+ this.writeNode(
+ "ogc:PropertyName",
+ {property: item.substring(0, last)},
+ node
+ );
+ node.appendChild(
+ this.createTextNode(item.substring(++last))
+ );
+ } else {
+ // no ending }, so this is a literal ${
+ node.appendChild(
+ this.createTextNode("${" + item)
+ );
+ }
+ }
+ return node;
+ },
+ "StyledLayerDescriptor": function(sld) {
+ var root = this.createElementNSPlus(
+ "sld:StyledLayerDescriptor",
+ {attributes: {
+ "version": this.VERSION,
+ "xsi:schemaLocation": this.schemaLocation
+ }}
+ );
+
+ // For ArcGIS Server it is necessary to define this
+ // at the root level (see ticket:2166).
+ root.setAttribute("xmlns:ogc", this.namespaces.ogc);
+ root.setAttribute("xmlns:gml", this.namespaces.gml);
+
+ // add in optional name
+ if(sld.name) {
+ this.writeNode("Name", sld.name, root);
+ }
+ // add in optional title
+ if(sld.title) {
+ this.writeNode("Title", sld.title, root);
+ }
+ // add in optional description
+ if(sld.description) {
+ this.writeNode("Abstract", sld.description, root);
+ }
+ // add in named layers
+ // allow namedLayers to be an array
+ if(OpenLayers.Util.isArray(sld.namedLayers)) {
+ for(var i=0, len=sld.namedLayers.length; i<len; ++i) {
+ this.writeNode("NamedLayer", sld.namedLayers[i], root);
+ }
+ } else {
+ for(var name in sld.namedLayers) {
+ this.writeNode("NamedLayer", sld.namedLayers[name], root);
+ }
+ }
+ return root;
+ },
+ "Name": function(name) {
+ return this.createElementNSPlus("sld:Name", {value: name});
+ },
+ "Title": function(title) {
+ return this.createElementNSPlus("sld:Title", {value: title});
+ },
+ "Abstract": function(description) {
+ return this.createElementNSPlus(
+ "sld:Abstract", {value: description}
+ );
+ },
+ "NamedLayer": function(layer) {
+ var node = this.createElementNSPlus("sld:NamedLayer");
+
+ // add in required name
+ this.writeNode("Name", layer.name, node);
+
+ // optional sld:LayerFeatureConstraints here
+
+ // add in named styles
+ if(layer.namedStyles) {
+ for(var i=0, len=layer.namedStyles.length; i<len; ++i) {
+ this.writeNode(
+ "NamedStyle", layer.namedStyles[i], node
+ );
+ }
+ }
+
+ // add in user styles
+ if(layer.userStyles) {
+ for(var i=0, len=layer.userStyles.length; i<len; ++i) {
+ this.writeNode(
+ "UserStyle", layer.userStyles[i], node
+ );
+ }
+ }
+
+ return node;
+ },
+ "NamedStyle": function(name) {
+ var node = this.createElementNSPlus("sld:NamedStyle");
+ this.writeNode("Name", name, node);
+ return node;
+ },
+ "UserStyle": function(style) {
+ var node = this.createElementNSPlus("sld:UserStyle");
+
+ // add in optional name
+ if(style.name) {
+ this.writeNode("Name", style.name, node);
+ }
+ // add in optional title
+ if(style.title) {
+ this.writeNode("Title", style.title, node);
+ }
+ // add in optional description
+ if(style.description) {
+ this.writeNode("Abstract", style.description, node);
+ }
+
+ // add isdefault
+ if(style.isDefault) {
+ this.writeNode("IsDefault", style.isDefault, node);
+ }
+
+ // add FeatureTypeStyles
+ if (this.multipleSymbolizers && style.rules) {
+ // group style objects by symbolizer zIndex
+ var rulesByZ = {
+ 0: []
+ };
+ var zValues = [0];
+ var rule, ruleMap, symbolizer, zIndex, clone;
+ for (var i=0, ii=style.rules.length; i<ii; ++i) {
+ rule = style.rules[i];
+ if (rule.symbolizers) {
+ ruleMap = {};
+ for (var j=0, jj=rule.symbolizers.length; j<jj; ++j) {
+ symbolizer = rule.symbolizers[j];
+ zIndex = symbolizer.zIndex;
+ if (!(zIndex in ruleMap)) {
+ clone = rule.clone();
+ clone.symbolizers = [];
+ ruleMap[zIndex] = clone;
+ }
+ ruleMap[zIndex].symbolizers.push(symbolizer.clone());
+ }
+ for (zIndex in ruleMap) {
+ if (!(zIndex in rulesByZ)) {
+ zValues.push(zIndex);
+ rulesByZ[zIndex] = [];
+ }
+ rulesByZ[zIndex].push(ruleMap[zIndex]);
+ }
+ } else {
+ // no symbolizers in rule
+ rulesByZ[0].push(rule.clone());
+ }
+ }
+ // write one FeatureTypeStyle per zIndex
+ zValues.sort();
+ var rules;
+ for (var i=0, ii=zValues.length; i<ii; ++i) {
+ rules = rulesByZ[zValues[i]];
+ if (rules.length > 0) {
+ clone = style.clone();
+ clone.rules = rulesByZ[zValues[i]];
+ this.writeNode("FeatureTypeStyle", clone, node);
+ }
+ }
+ } else {
+ this.writeNode("FeatureTypeStyle", style, node);
+ }
+
+ return node;
+ },
+ "IsDefault": function(bool) {
+ return this.createElementNSPlus(
+ "sld:IsDefault", {value: (bool) ? "1" : "0"}
+ );
+ },
+ "FeatureTypeStyle": function(style) {
+ var node = this.createElementNSPlus("sld:FeatureTypeStyle");
+
+ // OpenLayers currently stores no Name, Title, Abstract,
+ // FeatureTypeName, or SemanticTypeIdentifier information
+ // related to FeatureTypeStyle
+
+ // add in rules
+ for(var i=0, len=style.rules.length; i<len; ++i) {
+ this.writeNode("Rule", style.rules[i], node);
+ }
+
+ return node;
+ },
+ "Rule": function(rule) {
+ var node = this.createElementNSPlus("sld:Rule");
+
+ // add in optional name
+ if(rule.name) {
+ this.writeNode("Name", rule.name, node);
+ }
+ // add in optional title
+ if(rule.title) {
+ this.writeNode("Title", rule.title, node);
+ }
+ // add in optional description
+ if(rule.description) {
+ this.writeNode("Abstract", rule.description, node);
+ }
+
+ // add in LegendGraphic here
+
+ // add in optional filters
+ if(rule.elseFilter) {
+ this.writeNode("ElseFilter", null, node);
+ } else if(rule.filter) {
+ this.writeNode("ogc:Filter", rule.filter, node);
+ }
+
+ // add in scale limits
+ if(rule.minScaleDenominator != undefined) {
+ this.writeNode(
+ "MinScaleDenominator", rule.minScaleDenominator, node
+ );
+ }
+ if(rule.maxScaleDenominator != undefined) {
+ this.writeNode(
+ "MaxScaleDenominator", rule.maxScaleDenominator, node
+ );
+ }
+
+ var type, symbolizer;
+ if (this.multipleSymbolizers && rule.symbolizers) {
+ var symbolizer;
+ for (var i=0, ii=rule.symbolizers.length; i<ii; ++i) {
+ symbolizer = rule.symbolizers[i];
+ type = symbolizer.CLASS_NAME.split(".").pop();
+ this.writeNode(
+ type + "Symbolizer", symbolizer, node
+ );
+ }
+ } else {
+ // add in symbolizers (relies on geometry type keys)
+ var types = OpenLayers.Style.SYMBOLIZER_PREFIXES;
+ for(var i=0, len=types.length; i<len; ++i) {
+ type = types[i];
+ symbolizer = rule.symbolizer[type];
+ if(symbolizer) {
+ this.writeNode(
+ type + "Symbolizer", symbolizer, node
+ );
+ }
+ }
+ }
+ return node;
+
+ },
+ "ElseFilter": function() {
+ return this.createElementNSPlus("sld:ElseFilter");
+ },
+ "MinScaleDenominator": function(scale) {
+ return this.createElementNSPlus(
+ "sld:MinScaleDenominator", {value: scale}
+ );
+ },
+ "MaxScaleDenominator": function(scale) {
+ return this.createElementNSPlus(
+ "sld:MaxScaleDenominator", {value: scale}
+ );
+ },
+ "LineSymbolizer": function(symbolizer) {
+ var node = this.createElementNSPlus("sld:LineSymbolizer");
+ this.writeNode("Stroke", symbolizer, node);
+ return node;
+ },
+ "Stroke": function(symbolizer) {
+ var node = this.createElementNSPlus("sld:Stroke");
+
+ // GraphicFill here
+ // GraphicStroke here
+
+ // add in CssParameters
+ if(symbolizer.strokeColor != undefined) {
+ this.writeNode(
+ "CssParameter",
+ {symbolizer: symbolizer, key: "strokeColor"},
+ node
+ );
+ }
+ if(symbolizer.strokeOpacity != undefined) {
+ this.writeNode(
+ "CssParameter",
+ {symbolizer: symbolizer, key: "strokeOpacity"},
+ node
+ );
+ }
+ if(symbolizer.strokeWidth != undefined) {
+ this.writeNode(
+ "CssParameter",
+ {symbolizer: symbolizer, key: "strokeWidth"},
+ node
+ );
+ }
+ if(symbolizer.strokeDashstyle != undefined && symbolizer.strokeDashstyle !== "solid") {
+ // assumes valid stroke-dasharray value
+ this.writeNode(
+ "CssParameter",
+ {symbolizer: symbolizer, key: "strokeDashstyle"},
+ node
+ );
+ }
+ if(symbolizer.strokeLinecap != undefined) {
+ this.writeNode(
+ "CssParameter",
+ {symbolizer: symbolizer, key: "strokeLinecap"},
+ node
+ );
+ }
+ return node;
+ },
+ "CssParameter": function(obj) {
+ // not handling ogc:expressions for now
+ return this.createElementNSPlus("sld:CssParameter", {
+ attributes: {name: this.getCssProperty(obj.key)},
+ value: obj.symbolizer[obj.key]
+ });
+ },
+ "TextSymbolizer": function(symbolizer) {
+ var node = this.createElementNSPlus("sld:TextSymbolizer");
+ // add in optional Label
+ if(symbolizer.label != null) {
+ this.writeNode("Label", symbolizer.label, node);
+ }
+ // add in optional Font
+ if(symbolizer.fontFamily != null ||
+ symbolizer.fontSize != null ||
+ symbolizer.fontWeight != null ||
+ symbolizer.fontStyle != null) {
+ this.writeNode("Font", symbolizer, node);
+ }
+ // add in optional LabelPlacement
+ if (symbolizer.labelAnchorPointX != null ||
+ symbolizer.labelAnchorPointY != null ||
+ symbolizer.labelAlign != null ||
+ symbolizer.labelXOffset != null ||
+ symbolizer.labelYOffset != null ||
+ symbolizer.labelRotation != null ||
+ symbolizer.labelPerpendicularOffset != null) {
+ this.writeNode("LabelPlacement", symbolizer, node);
+ }
+ // add in optional Halo
+ if(symbolizer.haloRadius != null ||
+ symbolizer.haloColor != null ||
+ symbolizer.haloOpacity != null) {
+ this.writeNode("Halo", symbolizer, node);
+ }
+ // add in optional Fill
+ if(symbolizer.fontColor != null ||
+ symbolizer.fontOpacity != null) {
+ this.writeNode("Fill", {
+ fillColor: symbolizer.fontColor,
+ fillOpacity: symbolizer.fontOpacity
+ }, node);
+ }
+ return node;
+ },
+ "LabelPlacement": function(symbolizer) {
+ var node = this.createElementNSPlus("sld:LabelPlacement");
+ // PointPlacement and LinePlacement are choices, so don't output both
+ if ((symbolizer.labelAnchorPointX != null ||
+ symbolizer.labelAnchorPointY != null ||
+ symbolizer.labelAlign != null ||
+ symbolizer.labelXOffset != null ||
+ symbolizer.labelYOffset != null ||
+ symbolizer.labelRotation != null) &&
+ symbolizer.labelPerpendicularOffset == null) {
+ this.writeNode("PointPlacement", symbolizer, node);
+ }
+ if (symbolizer.labelPerpendicularOffset != null) {
+ this.writeNode("LinePlacement", symbolizer, node);
+ }
+ return node;
+ },
+ "LinePlacement": function(symbolizer) {
+ var node = this.createElementNSPlus("sld:LinePlacement");
+ this.writeNode("PerpendicularOffset", symbolizer.labelPerpendicularOffset, node);
+ return node;
+ },
+ "PerpendicularOffset": function(value) {
+ return this.createElementNSPlus("sld:PerpendicularOffset", {
+ value: value
+ });
+ },
+ "PointPlacement": function(symbolizer) {
+ var node = this.createElementNSPlus("sld:PointPlacement");
+ if (symbolizer.labelAnchorPointX != null ||
+ symbolizer.labelAnchorPointY != null ||
+ symbolizer.labelAlign != null) {
+ this.writeNode("AnchorPoint", symbolizer, node);
+ }
+ if (symbolizer.labelXOffset != null ||
+ symbolizer.labelYOffset != null) {
+ this.writeNode("Displacement", symbolizer, node);
+ }
+ if (symbolizer.labelRotation != null) {
+ this.writeNode("Rotation", symbolizer.labelRotation, node);
+ }
+ return node;
+ },
+ "AnchorPoint": function(symbolizer) {
+ var node = this.createElementNSPlus("sld:AnchorPoint");
+ var x = symbolizer.labelAnchorPointX,
+ y = symbolizer.labelAnchorPointY;
+ if (x != null) {
+ this.writeNode("AnchorPointX", x, node);
+ }
+ if (y != null) {
+ this.writeNode("AnchorPointY", y, node);
+ }
+ if (x == null && y == null) {
+ var xAlign = symbolizer.labelAlign.substr(0, 1),
+ yAlign = symbolizer.labelAlign.substr(1, 1);
+ if (xAlign === "l") {
+ x = 0;
+ } else if (xAlign === "c") {
+ x = 0.5;
+ } else if (xAlign === "r") {
+ x = 1;
+ }
+ if (yAlign === "b") {
+ y = 0;
+ } else if (yAlign === "m") {
+ y = 0.5;
+ } else if (yAlign === "t") {
+ y = 1;
+ }
+ this.writeNode("AnchorPointX", x, node);
+ this.writeNode("AnchorPointY", y, node);
+ }
+ return node;
+ },
+ "AnchorPointX": function(value) {
+ return this.createElementNSPlus("sld:AnchorPointX", {
+ value: value
+ });
+ },
+ "AnchorPointY": function(value) {
+ return this.createElementNSPlus("sld:AnchorPointY", {
+ value: value
+ });
+ },
+ "Displacement": function(symbolizer) {
+ var node = this.createElementNSPlus("sld:Displacement");
+ if (symbolizer.labelXOffset != null) {
+ this.writeNode("DisplacementX", symbolizer.labelXOffset, node);
+ }
+ if (symbolizer.labelYOffset != null) {
+ this.writeNode("DisplacementY", symbolizer.labelYOffset, node);
+ }
+ return node;
+ },
+ "DisplacementX": function(value) {
+ return this.createElementNSPlus("sld:DisplacementX", {
+ value: value
+ });
+ },
+ "DisplacementY": function(value) {
+ return this.createElementNSPlus("sld:DisplacementY", {
+ value: value
+ });
+ },
+ "Font": function(symbolizer) {
+ var node = this.createElementNSPlus("sld:Font");
+ // add in CssParameters
+ if(symbolizer.fontFamily) {
+ this.writeNode(
+ "CssParameter",
+ {symbolizer: symbolizer, key: "fontFamily"},
+ node
+ );
+ }
+ if(symbolizer.fontSize) {
+ this.writeNode(
+ "CssParameter",
+ {symbolizer: symbolizer, key: "fontSize"},
+ node
+ );
+ }
+ if(symbolizer.fontWeight) {
+ this.writeNode(
+ "CssParameter",
+ {symbolizer: symbolizer, key: "fontWeight"},
+ node
+ );
+ }
+ if(symbolizer.fontStyle) {
+ this.writeNode(
+ "CssParameter",
+ {symbolizer: symbolizer, key: "fontStyle"},
+ node
+ );
+ }
+ return node;
+ },
+ "Label": function(label) {
+ return this.writers.sld._OGCExpression.call(
+ this, "sld:Label", label
+ );
+ },
+ "Halo": function(symbolizer) {
+ var node = this.createElementNSPlus("sld:Halo");
+ if(symbolizer.haloRadius) {
+ this.writeNode("Radius", symbolizer.haloRadius, node);
+ }
+ if(symbolizer.haloColor || symbolizer.haloOpacity) {
+ this.writeNode("Fill", {
+ fillColor: symbolizer.haloColor,
+ fillOpacity: symbolizer.haloOpacity
+ }, node);
+ }
+ return node;
+ },
+ "Radius": function(value) {
+ return this.createElementNSPlus("sld:Radius", {
+ value: value
+ });
+ },
+ "RasterSymbolizer": function(symbolizer) {
+ var node = this.createElementNSPlus("sld:RasterSymbolizer");
+ if (symbolizer.geometry) {
+ this.writeNode("Geometry", symbolizer.geometry, node);
+ }
+ if (symbolizer.opacity) {
+ this.writeNode("Opacity", symbolizer.opacity, node);
+ }
+ if (symbolizer.colorMap) {
+ this.writeNode("ColorMap", symbolizer.colorMap, node);
+ }
+ return node;
+ },
+ "Geometry": function(geometry) {
+ var node = this.createElementNSPlus("sld:Geometry");
+ if (geometry.property) {
+ this.writeNode("ogc:PropertyName", geometry, node);
+ }
+ return node;
+ },
+ "ColorMap": function(colorMap) {
+ var node = this.createElementNSPlus("sld:ColorMap");
+ for (var i=0, len=colorMap.length; i<len; ++i) {
+ this.writeNode("ColorMapEntry", colorMap[i], node);
+ }
+ return node;
+ },
+ "ColorMapEntry": function(colorMapEntry) {
+ var node = this.createElementNSPlus("sld:ColorMapEntry");
+ var a = colorMapEntry;
+ node.setAttribute("color", a.color);
+ a.opacity !== undefined && node.setAttribute("opacity",
+ parseFloat(a.opacity));
+ a.quantity !== undefined && node.setAttribute("quantity",
+ parseFloat(a.quantity));
+ a.label !== undefined && node.setAttribute("label", a.label);
+ return node;
+ },
+ "PolygonSymbolizer": function(symbolizer) {
+ var node = this.createElementNSPlus("sld:PolygonSymbolizer");
+ if(symbolizer.fill !== false) {
+ this.writeNode("Fill", symbolizer, node);
+ }
+ if(symbolizer.stroke !== false) {
+ this.writeNode("Stroke", symbolizer, node);
+ }
+ return node;
+ },
+ "Fill": function(symbolizer) {
+ var node = this.createElementNSPlus("sld:Fill");
+
+ // GraphicFill here
+
+ // add in CssParameters
+ if(symbolizer.fillColor) {
+ this.writeNode(
+ "CssParameter",
+ {symbolizer: symbolizer, key: "fillColor"},
+ node
+ );
+ }
+ if(symbolizer.fillOpacity != null) {
+ this.writeNode(
+ "CssParameter",
+ {symbolizer: symbolizer, key: "fillOpacity"},
+ node
+ );
+ }
+ return node;
+ },
+ "PointSymbolizer": function(symbolizer) {
+ var node = this.createElementNSPlus("sld:PointSymbolizer");
+ this.writeNode("Graphic", symbolizer, node);
+ return node;
+ },
+ "Graphic": function(symbolizer) {
+ var node = this.createElementNSPlus("sld:Graphic");
+ if(symbolizer.externalGraphic != undefined) {
+ this.writeNode("ExternalGraphic", symbolizer, node);
+ } else {
+ this.writeNode("Mark", symbolizer, node);
+ }
+
+ if(symbolizer.graphicOpacity != undefined) {
+ this.writeNode("Opacity", symbolizer.graphicOpacity, node);
+ }
+ if(symbolizer.pointRadius != undefined) {
+ this.writeNode("Size", symbolizer.pointRadius * 2, node);
+ } else if (symbolizer.graphicWidth != undefined) {
+ this.writeNode("Size", symbolizer.graphicWidth, node);
+ }
+ if(symbolizer.rotation != undefined) {
+ this.writeNode("Rotation", symbolizer.rotation, node);
+ }
+ return node;
+ },
+ "ExternalGraphic": function(symbolizer) {
+ var node = this.createElementNSPlus("sld:ExternalGraphic");
+ this.writeNode(
+ "OnlineResource", symbolizer.externalGraphic, node
+ );
+ var format = symbolizer.graphicFormat ||
+ this.getGraphicFormat(symbolizer.externalGraphic);
+ this.writeNode("Format", format, node);
+ return node;
+ },
+ "Mark": function(symbolizer) {
+ var node = this.createElementNSPlus("sld:Mark");
+ if(symbolizer.graphicName) {
+ this.writeNode("WellKnownName", symbolizer.graphicName, node);
+ }
+ if (symbolizer.fill !== false) {
+ this.writeNode("Fill", symbolizer, node);
+ }
+ if (symbolizer.stroke !== false) {
+ this.writeNode("Stroke", symbolizer, node);
+ }
+ return node;
+ },
+ "WellKnownName": function(name) {
+ return this.createElementNSPlus("sld:WellKnownName", {
+ value: name
+ });
+ },
+ "Opacity": function(value) {
+ return this.createElementNSPlus("sld:Opacity", {
+ value: value
+ });
+ },
+ "Size": function(value) {
+ return this.writers.sld._OGCExpression.call(
+ this, "sld:Size", value
+ );
+ },
+ "Rotation": function(value) {
+ return this.createElementNSPlus("sld:Rotation", {
+ value: value
+ });
+ },
+ "OnlineResource": function(href) {
+ return this.createElementNSPlus("sld:OnlineResource", {
+ attributes: {
+ "xlink:type": "simple",
+ "xlink:href": href
+ }
+ });
+ },
+ "Format": function(format) {
+ return this.createElementNSPlus("sld:Format", {
+ value: format
+ });
+ }
+ }
+ }, OpenLayers.Format.Filter.v1_0_0.prototype.writers),
+
+ CLASS_NAME: "OpenLayers.Format.SLD.v1"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/SLD/v1_0_0.js b/misc/openlayers/lib/OpenLayers/Format/SLD/v1_0_0.js
new file mode 100644
index 0000000..e920b50
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/SLD/v1_0_0.js
@@ -0,0 +1,46 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/SLD/v1.js
+ * @requires OpenLayers/Format/Filter/v1_0_0.js
+ */
+
+/**
+ * Class: OpenLayers.Format.SLD.v1_0_0
+ * Write SLD version 1.0.0.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.SLD.v1>
+ */
+OpenLayers.Format.SLD.v1_0_0 = OpenLayers.Class(
+ OpenLayers.Format.SLD.v1, {
+
+ /**
+ * Constant: VERSION
+ * {String} 1.0.0
+ */
+ VERSION: "1.0.0",
+
+ /**
+ * Property: schemaLocation
+ * {String} http://www.opengis.net/sld
+ * http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd
+ */
+ schemaLocation: "http://www.opengis.net/sld http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd",
+
+ /**
+ * Constructor: OpenLayers.Format.SLD.v1_0_0
+ * Instances of this class are not created directly. Use the
+ * <OpenLayers.Format.SLD> constructor instead.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ CLASS_NAME: "OpenLayers.Format.SLD.v1_0_0"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/SLD/v1_0_0_GeoServer.js b/misc/openlayers/lib/OpenLayers/Format/SLD/v1_0_0_GeoServer.js
new file mode 100644
index 0000000..902da67
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/SLD/v1_0_0_GeoServer.js
@@ -0,0 +1,149 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/SLD/v1_0_0.js
+ */
+
+/**
+ * Class: OpenLayers.Format.SLD/v1_0_0_GeoServer
+ * Read and write SLD version 1.0.0 with GeoServer-specific enhanced options.
+ * See http://svn.osgeo.org/geotools/trunk/modules/extension/xsd/xsd-sld/src/main/resources/org/geotools/sld/bindings/StyledLayerDescriptor.xsd
+ * for more information.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.SLD.v1_0_0>
+ */
+OpenLayers.Format.SLD.v1_0_0_GeoServer = OpenLayers.Class(
+ OpenLayers.Format.SLD.v1_0_0, {
+
+ /**
+ * Property: version
+ * {String} The specific parser version.
+ */
+ version: "1.0.0",
+
+ /**
+ * Property: profile
+ * {String} The specific profile
+ */
+ profile: "GeoServer",
+
+ /**
+ * Constructor: OpenLayers.Format.SLD.v1_0_0_GeoServer
+ * Create a new parser for GeoServer-enhanced SLD version 1.0.0.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: OpenLayers.Util.applyDefaults({
+ "sld": OpenLayers.Util.applyDefaults({
+ "Priority": function(node, obj) {
+ var value = this.readers.ogc._expression.call(this, node);
+ if (value) {
+ obj.priority = value;
+ }
+ },
+ "VendorOption": function(node, obj) {
+ if (!obj.vendorOptions) {
+ obj.vendorOptions = {};
+ }
+ obj.vendorOptions[node.getAttribute("name")] = this.getChildValue(node);
+ },
+ "TextSymbolizer": function(node, rule) {
+ OpenLayers.Format.SLD.v1_0_0.prototype.readers.sld.TextSymbolizer.apply(this, arguments);
+ var symbolizer = this.multipleSymbolizers ? rule.symbolizers[rule.symbolizers.length-1] : rule.symbolizer["Text"];
+ if (symbolizer.graphic === undefined) {
+ symbolizer.graphic = false;
+ }
+ }
+ }, OpenLayers.Format.SLD.v1_0_0.prototype.readers["sld"])
+ }, OpenLayers.Format.SLD.v1_0_0.prototype.readers),
+
+ /**
+ * Property: writers
+ * As a compliment to the readers property, this structure contains public
+ * writing functions grouped by namespace alias and named like the
+ * node names they produce.
+ */
+ writers: OpenLayers.Util.applyDefaults({
+ "sld": OpenLayers.Util.applyDefaults({
+ "Priority": function(priority) {
+ return this.writers.sld._OGCExpression.call(
+ this, "sld:Priority", priority
+ );
+ },
+ "VendorOption": function(option) {
+ return this.createElementNSPlus("sld:VendorOption", {
+ attributes: {name: option.name},
+ value: option.value
+ });
+ },
+ "TextSymbolizer": function(symbolizer) {
+ var writers = OpenLayers.Format.SLD.v1_0_0.prototype.writers;
+ var node = writers["sld"]["TextSymbolizer"].apply(this, arguments);
+ if (symbolizer.graphic !== false && (symbolizer.externalGraphic || symbolizer.graphicName)) {
+ this.writeNode("Graphic", symbolizer, node);
+ }
+ if ("priority" in symbolizer) {
+ this.writeNode("Priority", symbolizer.priority, node);
+ }
+ return this.addVendorOptions(node, symbolizer);
+ },
+ "PointSymbolizer": function(symbolizer) {
+ var writers = OpenLayers.Format.SLD.v1_0_0.prototype.writers;
+ var node = writers["sld"]["PointSymbolizer"].apply(this, arguments);
+ return this.addVendorOptions(node, symbolizer);
+ },
+ "LineSymbolizer": function(symbolizer) {
+ var writers = OpenLayers.Format.SLD.v1_0_0.prototype.writers;
+ var node = writers["sld"]["LineSymbolizer"].apply(this, arguments);
+ return this.addVendorOptions(node, symbolizer);
+ },
+ "PolygonSymbolizer": function(symbolizer) {
+ var writers = OpenLayers.Format.SLD.v1_0_0.prototype.writers;
+ var node = writers["sld"]["PolygonSymbolizer"].apply(this, arguments);
+ return this.addVendorOptions(node, symbolizer);
+ }
+ }, OpenLayers.Format.SLD.v1_0_0.prototype.writers["sld"])
+ }, OpenLayers.Format.SLD.v1_0_0.prototype.writers),
+
+ /**
+ * Method: addVendorOptions
+ * Add in the VendorOption tags and return the node again.
+ *
+ * Parameters:
+ * node - {DOMElement} A DOM node.
+ * symbolizer - {Object}
+ *
+ * Returns:
+ * {DOMElement} A DOM node.
+ */
+ addVendorOptions: function(node, symbolizer) {
+ var options = symbolizer.vendorOptions;
+ if (options) {
+ for (var key in symbolizer.vendorOptions) {
+ this.writeNode("VendorOption", {
+ name: key,
+ value: symbolizer.vendorOptions[key]
+ }, node);
+ }
+ }
+ return node;
+ },
+
+ CLASS_NAME: "OpenLayers.Format.SLD.v1_0_0_GeoServer"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/SOSCapabilities.js b/misc/openlayers/lib/OpenLayers/Format/SOSCapabilities.js
new file mode 100644
index 0000000..1abb1c8
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/SOSCapabilities.js
@@ -0,0 +1,48 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML/VersionedOGC.js
+ */
+
+/**
+ * Class: OpenLayers.Format.SOSCapabilities
+ * Read SOS Capabilities.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML.VersionedOGC>
+ */
+OpenLayers.Format.SOSCapabilities = OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC, {
+
+ /**
+ * APIProperty: defaultVersion
+ * {String} Version number to assume if none found. Default is "1.0.0".
+ */
+ defaultVersion: "1.0.0",
+
+ /**
+ * Constructor: OpenLayers.Format.SOSCapabilities
+ * Create a new parser for SOS Capabilities.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * APIMethod: read
+ * Read capabilities data from a string, and return information about
+ * the service (offering and observedProperty mostly).
+ *
+ * Parameters:
+ * data - {String} or {DOMElement} data to read/parse.
+ *
+ * Returns:
+ * {Object} Info about the SOS
+ */
+
+ CLASS_NAME: "OpenLayers.Format.SOSCapabilities"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/SOSCapabilities/v1_0_0.js b/misc/openlayers/lib/OpenLayers/Format/SOSCapabilities/v1_0_0.js
new file mode 100644
index 0000000..89c0e91
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/SOSCapabilities/v1_0_0.js
@@ -0,0 +1,158 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/SOSCapabilities.js
+ * @requires OpenLayers/Format/OWSCommon/v1_1_0.js
+ * @requires OpenLayers/Format/GML/v3.js
+ */
+
+/**
+ * Class: OpenLayers.Format.SOSCapabilities.v1_0_0
+ * Read SOS Capabilities version 1.0.0.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.SOSCapabilities>
+ */
+OpenLayers.Format.SOSCapabilities.v1_0_0 = OpenLayers.Class(
+ OpenLayers.Format.SOSCapabilities, {
+
+ /**
+ * Property: namespaces
+ * {Object} Mapping of namespace aliases to namespace URIs.
+ */
+ namespaces: {
+ ows: "http://www.opengis.net/ows/1.1",
+ sos: "http://www.opengis.net/sos/1.0",
+ gml: "http://www.opengis.net/gml",
+ xlink: "http://www.w3.org/1999/xlink"
+ },
+
+ /**
+ * Property: regExes
+ * Compiled regular expressions for manipulating strings.
+ */
+ regExes: {
+ trimSpace: (/^\s*|\s*$/g),
+ removeSpace: (/\s*/g),
+ splitSpace: (/\s+/),
+ trimComma: (/\s*,\s*/g)
+ },
+
+ /**
+ * Constructor: OpenLayers.Format.SOSCapabilities.v1_0_0
+ * Create a new parser for SOS capabilities version 1.0.0.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+ initialize: function(options) {
+ OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+ this.options = options;
+ },
+
+ /**
+ * APIMethod: read
+ * Read capabilities data from a string, and return info about the SOS.
+ *
+ * Parameters:
+ * data - {String} or {DOMElement} data to read/parse.
+ *
+ * Returns:
+ * {Object} Information about the SOS service.
+ */
+ read: function(data) {
+ if(typeof data == "string") {
+ data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+ }
+ if(data && data.nodeType == 9) {
+ data = data.documentElement;
+ }
+ var capabilities = {};
+ this.readNode(data, capabilities);
+ return capabilities;
+ },
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "gml": OpenLayers.Util.applyDefaults({
+ "name": function(node, obj) {
+ obj.name = this.getChildValue(node);
+ },
+ "TimePeriod": function(node, obj) {
+ obj.timePeriod = {};
+ this.readChildNodes(node, obj.timePeriod);
+ },
+ "beginPosition": function(node, timePeriod) {
+ timePeriod.beginPosition = this.getChildValue(node);
+ },
+ "endPosition": function(node, timePeriod) {
+ timePeriod.endPosition = this.getChildValue(node);
+ }
+ }, OpenLayers.Format.GML.v3.prototype.readers["gml"]),
+ "sos": {
+ "Capabilities": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "Contents": function(node, obj) {
+ obj.contents = {};
+ this.readChildNodes(node, obj.contents);
+ },
+ "ObservationOfferingList": function(node, contents) {
+ contents.offeringList = {};
+ this.readChildNodes(node, contents.offeringList);
+ },
+ "ObservationOffering": function(node, offeringList) {
+ var id = this.getAttributeNS(node, this.namespaces.gml, "id");
+ offeringList[id] = {
+ procedures: [],
+ observedProperties: [],
+ featureOfInterestIds: [],
+ responseFormats: [],
+ resultModels: [],
+ responseModes: []
+ };
+ this.readChildNodes(node, offeringList[id]);
+ },
+ "time": function(node, offering) {
+ offering.time = {};
+ this.readChildNodes(node, offering.time);
+ },
+ "procedure": function(node, offering) {
+ offering.procedures.push(this.getAttributeNS(node,
+ this.namespaces.xlink, "href"));
+ },
+ "observedProperty": function(node, offering) {
+ offering.observedProperties.push(this.getAttributeNS(node,
+ this.namespaces.xlink, "href"));
+ },
+ "featureOfInterest": function(node, offering) {
+ offering.featureOfInterestIds.push(this.getAttributeNS(node,
+ this.namespaces.xlink, "href"));
+ },
+ "responseFormat": function(node, offering) {
+ offering.responseFormats.push(this.getChildValue(node));
+ },
+ "resultModel": function(node, offering) {
+ offering.resultModels.push(this.getChildValue(node));
+ },
+ "responseMode": function(node, offering) {
+ offering.responseModes.push(this.getChildValue(node));
+ }
+ },
+ "ows": OpenLayers.Format.OWSCommon.v1_1_0.prototype.readers["ows"]
+ },
+
+ CLASS_NAME: "OpenLayers.Format.SOSCapabilities.v1_0_0"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/SOSGetFeatureOfInterest.js b/misc/openlayers/lib/OpenLayers/Format/SOSGetFeatureOfInterest.js
new file mode 100644
index 0000000..aac2030
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/SOSGetFeatureOfInterest.js
@@ -0,0 +1,190 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Format/GML/v3.js
+ */
+
+/**
+ * Class: OpenLayers.Format.SOSGetFeatureOfInterest
+ * Read and write SOS GetFeatureOfInterest. This is used to get to
+ * the location of the features (stations). The stations can have 1 or more
+ * sensors.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.SOSGetFeatureOfInterest = OpenLayers.Class(
+ OpenLayers.Format.XML, {
+
+ /**
+ * Constant: VERSION
+ * {String} 1.0.0
+ */
+ VERSION: "1.0.0",
+
+ /**
+ * Property: namespaces
+ * {Object} Mapping of namespace aliases to namespace URIs.
+ */
+ namespaces: {
+ sos: "http://www.opengis.net/sos/1.0",
+ gml: "http://www.opengis.net/gml",
+ sa: "http://www.opengis.net/sampling/1.0",
+ xsi: "http://www.w3.org/2001/XMLSchema-instance"
+ },
+
+ /**
+ * Property: schemaLocation
+ * {String} Schema location
+ */
+ schemaLocation: "http://www.opengis.net/sos/1.0 http://schemas.opengis.net/sos/1.0.0/sosAll.xsd",
+
+ /**
+ * Property: defaultPrefix
+ */
+ defaultPrefix: "sos",
+
+ /**
+ * Property: regExes
+ * Compiled regular expressions for manipulating strings.
+ */
+ regExes: {
+ trimSpace: (/^\s*|\s*$/g),
+ removeSpace: (/\s*/g),
+ splitSpace: (/\s+/),
+ trimComma: (/\s*,\s*/g)
+ },
+
+ /**
+ * Constructor: OpenLayers.Format.SOSGetFeatureOfInterest
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * APIMethod: read
+ * Parse a GetFeatureOfInterest response and return an array of features
+ *
+ * Parameters:
+ * data - {String} or {DOMElement} data to read/parse.
+ *
+ * Returns:
+ * {Array(<OpenLayers.Feature.Vector>)} An array of features.
+ */
+ read: function(data) {
+ if(typeof data == "string") {
+ data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+ }
+ if(data && data.nodeType == 9) {
+ data = data.documentElement;
+ }
+
+ var info = {features: []};
+ this.readNode(data, info);
+
+ var features = [];
+ for (var i=0, len=info.features.length; i<len; i++) {
+ var container = info.features[i];
+ // reproject features if needed
+ if(this.internalProjection && this.externalProjection &&
+ container.components[0]) {
+ container.components[0].transform(
+ this.externalProjection, this.internalProjection
+ );
+ }
+ var feature = new OpenLayers.Feature.Vector(
+ container.components[0], container.attributes);
+ features.push(feature);
+ }
+ return features;
+ },
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "sa": {
+ "SamplingPoint": function(node, obj) {
+ // sampling point can also be without a featureMember if
+ // there is only 1
+ if (!obj.attributes) {
+ var feature = {attributes: {}};
+ obj.features.push(feature);
+ obj = feature;
+ }
+ obj.attributes.id = this.getAttributeNS(node,
+ this.namespaces.gml, "id");
+ this.readChildNodes(node, obj);
+ },
+ "position": function (node, obj) {
+ this.readChildNodes(node, obj);
+ }
+ },
+ "gml": OpenLayers.Util.applyDefaults({
+ "FeatureCollection": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "featureMember": function(node, obj) {
+ var feature = {attributes: {}};
+ obj.features.push(feature);
+ this.readChildNodes(node, feature);
+ },
+ "name": function(node, obj) {
+ obj.attributes.name = this.getChildValue(node);
+ },
+ "pos": function(node, obj) {
+ // we need to parse the srsName to get to the
+ // externalProjection, that's why we cannot use
+ // GML v3 for this
+ if (!this.externalProjection) {
+ this.externalProjection = new OpenLayers.Projection(
+ node.getAttribute("srsName"));
+ }
+ OpenLayers.Format.GML.v3.prototype.readers.gml.pos.apply(
+ this, [node, obj]);
+ }
+ }, OpenLayers.Format.GML.v3.prototype.readers.gml)
+ },
+
+ /**
+ * Property: writers
+ * As a compliment to the readers property, this structure contains public
+ * writing functions grouped by namespace alias and named like the
+ * node names they produce.
+ */
+ writers: {
+ "sos": {
+ "GetFeatureOfInterest": function(options) {
+ var node = this.createElementNSPlus("GetFeatureOfInterest", {
+ attributes: {
+ version: this.VERSION,
+ service: 'SOS',
+ "xsi:schemaLocation": this.schemaLocation
+ }
+ });
+ for (var i=0, len=options.fois.length; i<len; i++) {
+ this.writeNode("FeatureOfInterestId", {foi: options.fois[i]}, node);
+ }
+ return node;
+ },
+ "FeatureOfInterestId": function(options) {
+ var node = this.createElementNSPlus("FeatureOfInterestId", {value: options.foi});
+ return node;
+ }
+ }
+ },
+
+ CLASS_NAME: "OpenLayers.Format.SOSGetFeatureOfInterest"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/SOSGetObservation.js b/misc/openlayers/lib/OpenLayers/Format/SOSGetObservation.js
new file mode 100644
index 0000000..9a6e2d7
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/SOSGetObservation.js
@@ -0,0 +1,302 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Format/SOSGetFeatureOfInterest.js
+ */
+
+/**
+ * Class: OpenLayers.Format.SOSGetObservation
+ * Read and write SOS GetObersation (to get the actual values from a sensor)
+ * version 1.0.0
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.SOSGetObservation = OpenLayers.Class(OpenLayers.Format.XML, {
+
+ /**
+ * Property: namespaces
+ * {Object} Mapping of namespace aliases to namespace URIs.
+ */
+ namespaces: {
+ ows: "http://www.opengis.net/ows",
+ gml: "http://www.opengis.net/gml",
+ sos: "http://www.opengis.net/sos/1.0",
+ ogc: "http://www.opengis.net/ogc",
+ om: "http://www.opengis.net/om/1.0",
+ sa: "http://www.opengis.net/sampling/1.0",
+ xlink: "http://www.w3.org/1999/xlink",
+ xsi: "http://www.w3.org/2001/XMLSchema-instance"
+ },
+
+ /**
+ * Property: regExes
+ * Compiled regular expressions for manipulating strings.
+ */
+ regExes: {
+ trimSpace: (/^\s*|\s*$/g),
+ removeSpace: (/\s*/g),
+ splitSpace: (/\s+/),
+ trimComma: (/\s*,\s*/g)
+ },
+
+ /**
+ * Constant: VERSION
+ * {String} 1.0.0
+ */
+ VERSION: "1.0.0",
+
+ /**
+ * Property: schemaLocation
+ * {String} Schema location
+ */
+ schemaLocation: "http://www.opengis.net/sos/1.0 http://schemas.opengis.net/sos/1.0.0/sosGetObservation.xsd",
+
+ /**
+ * Property: defaultPrefix
+ */
+ defaultPrefix: "sos",
+
+ /**
+ * Constructor: OpenLayers.Format.SOSGetObservation
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * Method: read
+ *
+ * Parameters:
+ * data - {String} or {DOMElement} data to read/parse.
+ *
+ * Returns:
+ * {Object} An object containing the measurements
+ */
+ read: function(data) {
+ if(typeof data == "string") {
+ data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+ }
+ if(data && data.nodeType == 9) {
+ data = data.documentElement;
+ }
+ var info = {measurements: [], observations: []};
+ this.readNode(data, info);
+ return info;
+ },
+
+ /**
+ * Method: write
+ *
+ * Parameters:
+ * options - {Object} Optional object.
+ *
+ * Returns:
+ * {String} An SOS GetObservation request XML string.
+ */
+ write: function(options) {
+ var node = this.writeNode("sos:GetObservation", options);
+ node.setAttribute("xmlns:om", this.namespaces.om);
+ node.setAttribute("xmlns:ogc", this.namespaces.ogc);
+ this.setAttributeNS(
+ node, this.namespaces.xsi,
+ "xsi:schemaLocation", this.schemaLocation
+ );
+ return OpenLayers.Format.XML.prototype.write.apply(this, [node]);
+ },
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "om": {
+ "ObservationCollection": function(node, obj) {
+ obj.id = this.getAttributeNS(node, this.namespaces.gml, "id");
+ this.readChildNodes(node, obj);
+ },
+ "member": function(node, observationCollection) {
+ this.readChildNodes(node, observationCollection);
+ },
+ "Measurement": function(node, observationCollection) {
+ var measurement = {};
+ observationCollection.measurements.push(measurement);
+ this.readChildNodes(node, measurement);
+ },
+ "Observation": function(node, observationCollection) {
+ var observation = {};
+ observationCollection.observations.push(observation);
+ this.readChildNodes(node, observation);
+ },
+ "samplingTime": function(node, measurement) {
+ var samplingTime = {};
+ measurement.samplingTime = samplingTime;
+ this.readChildNodes(node, samplingTime);
+ },
+ "observedProperty": function(node, measurement) {
+ measurement.observedProperty =
+ this.getAttributeNS(node, this.namespaces.xlink, "href");
+ this.readChildNodes(node, measurement);
+ },
+ "procedure": function(node, measurement) {
+ measurement.procedure =
+ this.getAttributeNS(node, this.namespaces.xlink, "href");
+ this.readChildNodes(node, measurement);
+ },
+ "featureOfInterest": function(node, observation) {
+ var foi = {features: []};
+ observation.fois = [];
+ observation.fois.push(foi);
+ this.readChildNodes(node, foi);
+ // postprocessing to get actual features
+ var features = [];
+ for (var i=0, len=foi.features.length; i<len; i++) {
+ var feature = foi.features[i];
+ features.push(new OpenLayers.Feature.Vector(
+ feature.components[0], feature.attributes));
+ }
+ foi.features = features;
+ },
+ "result": function(node, measurement) {
+ var result = {};
+ measurement.result = result;
+ if (this.getChildValue(node) !== '') {
+ result.value = this.getChildValue(node);
+ result.uom = node.getAttribute("uom");
+ } else {
+ this.readChildNodes(node, result);
+ }
+ }
+ },
+ "sa": OpenLayers.Format.SOSGetFeatureOfInterest.prototype.readers.sa,
+ "gml": OpenLayers.Util.applyDefaults({
+ "TimeInstant": function(node, samplingTime) {
+ var timeInstant = {};
+ samplingTime.timeInstant = timeInstant;
+ this.readChildNodes(node, timeInstant);
+ },
+ "timePosition": function(node, timeInstant) {
+ timeInstant.timePosition = this.getChildValue(node);
+ }
+ }, OpenLayers.Format.SOSGetFeatureOfInterest.prototype.readers.gml)
+ },
+
+ /**
+ * Property: writers
+ * As a compliment to the readers property, this structure contains public
+ * writing functions grouped by namespace alias and named like the
+ * node names they produce.
+ */
+ writers: {
+ "sos": {
+ "GetObservation": function(options) {
+ var node = this.createElementNSPlus("GetObservation", {
+ attributes: {
+ version: this.VERSION,
+ service: 'SOS'
+ }
+ });
+ this.writeNode("offering", options, node);
+ if (options.eventTime) {
+ this.writeNode("eventTime", options, node);
+ }
+ for (var procedure in options.procedures) {
+ this.writeNode("procedure", options.procedures[procedure], node);
+ }
+ for (var observedProperty in options.observedProperties) {
+ this.writeNode("observedProperty", options.observedProperties[observedProperty], node);
+ }
+ if (options.foi) {
+ this.writeNode("featureOfInterest", options.foi, node);
+ }
+ this.writeNode("responseFormat", options, node);
+ if (options.resultModel) {
+ this.writeNode("resultModel", options, node);
+ }
+ if (options.responseMode) {
+ this.writeNode("responseMode", options, node);
+ }
+ return node;
+ },
+ "featureOfInterest": function(foi) {
+ var node = this.createElementNSPlus("featureOfInterest");
+ this.writeNode("ObjectID", foi.objectId, node);
+ return node;
+ },
+ "ObjectID": function(options) {
+ return this.createElementNSPlus("ObjectID",
+ {value: options});
+ },
+ "responseFormat": function(options) {
+ return this.createElementNSPlus("responseFormat",
+ {value: options.responseFormat});
+ },
+ "procedure": function(procedure) {
+ return this.createElementNSPlus("procedure",
+ {value: procedure});
+ },
+ "offering": function(options) {
+ return this.createElementNSPlus("offering", {value:
+ options.offering});
+ },
+ "observedProperty": function(observedProperty) {
+ return this.createElementNSPlus("observedProperty",
+ {value: observedProperty});
+ },
+ "eventTime": function(options) {
+ var node = this.createElementNSPlus("eventTime");
+ if (options.eventTime === 'latest') {
+ this.writeNode("ogc:TM_Equals", options, node);
+ }
+ return node;
+ },
+ "resultModel": function(options) {
+ return this.createElementNSPlus("resultModel", {value:
+ options.resultModel});
+ },
+ "responseMode": function(options) {
+ return this.createElementNSPlus("responseMode", {value:
+ options.responseMode});
+ }
+ },
+ "ogc": {
+ "TM_Equals": function(options) {
+ var node = this.createElementNSPlus("ogc:TM_Equals");
+ this.writeNode("ogc:PropertyName", {property:
+ "urn:ogc:data:time:iso8601"}, node);
+ if (options.eventTime === 'latest') {
+ this.writeNode("gml:TimeInstant", {value: 'latest'}, node);
+ }
+ return node;
+ },
+ "PropertyName": function(options) {
+ return this.createElementNSPlus("ogc:PropertyName",
+ {value: options.property});
+ }
+ },
+ "gml": {
+ "TimeInstant": function(options) {
+ var node = this.createElementNSPlus("gml:TimeInstant");
+ this.writeNode("gml:timePosition", options, node);
+ return node;
+ },
+ "timePosition": function(options) {
+ var node = this.createElementNSPlus("gml:timePosition",
+ {value: options.value});
+ return node;
+ }
+ }
+ },
+
+ CLASS_NAME: "OpenLayers.Format.SOSGetObservation"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/Text.js b/misc/openlayers/lib/OpenLayers/Format/Text.js
new file mode 100644
index 0000000..bf9bcd5
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/Text.js
@@ -0,0 +1,151 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Feature/Vector.js
+ * @requires OpenLayers/Geometry/Point.js
+ */
+
+/**
+ * Class: OpenLayers.Format.Text
+ * Read Text format. Create a new instance with the <OpenLayers.Format.Text>
+ * constructor. This reads text which is formatted like CSV text, using
+ * tabs as the seperator by default. It provides parsing of data originally
+ * used in the MapViewerService, described on the wiki. This Format is used
+ * by the <OpenLayers.Layer.Text> class.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format>
+ */
+OpenLayers.Format.Text = OpenLayers.Class(OpenLayers.Format, {
+
+ /**
+ * APIProperty: defaultStyle
+ * defaultStyle allows one to control the default styling of the features.
+ * It should be a symbolizer hash. By default, this is set to match the
+ * Layer.Text behavior, which is to use the default OpenLayers Icon.
+ */
+ defaultStyle: null,
+
+ /**
+ * APIProperty: extractStyles
+ * set to true to extract styles from the TSV files, using information
+ * from the image or icon, iconSize and iconOffset fields. This will result
+ * in features with a symbolizer (style) property set, using the
+ * default symbolizer specified in <defaultStyle>. Set to false if you
+ * wish to use a styleMap or OpenLayers.Style options to style your
+ * layer instead.
+ */
+ extractStyles: true,
+
+ /**
+ * Constructor: OpenLayers.Format.Text
+ * Create a new parser for TSV Text.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+ initialize: function(options) {
+ options = options || {};
+
+ if(options.extractStyles !== false) {
+ options.defaultStyle = {
+ 'externalGraphic': OpenLayers.Util.getImageLocation("marker.png"),
+ 'graphicWidth': 21,
+ 'graphicHeight': 25,
+ 'graphicXOffset': -10.5,
+ 'graphicYOffset': -12.5
+ };
+ }
+
+ OpenLayers.Format.prototype.initialize.apply(this, [options]);
+ },
+
+ /**
+ * APIMethod: read
+ * Return a list of features from a Tab Seperated Values text string.
+ *
+ * Parameters:
+ * text - {String}
+ *
+ * Returns:
+ * Array({<OpenLayers.Feature.Vector>})
+ */
+ read: function(text) {
+ var lines = text.split('\n');
+ var columns;
+ var features = [];
+ // length - 1 to allow for trailing new line
+ for (var lcv = 0; lcv < (lines.length - 1); lcv++) {
+ var currLine = lines[lcv].replace(/^\s*/,'').replace(/\s*$/,'');
+
+ if (currLine.charAt(0) != '#') { /* not a comment */
+
+ if (!columns) {
+ //First line is columns
+ columns = currLine.split('\t');
+ } else {
+ var vals = currLine.split('\t');
+ var geometry = new OpenLayers.Geometry.Point(0,0);
+ var attributes = {};
+ var style = this.defaultStyle ?
+ OpenLayers.Util.applyDefaults({}, this.defaultStyle) :
+ null;
+ var icon, iconSize, iconOffset, overflow;
+ var set = false;
+ for (var valIndex = 0; valIndex < vals.length; valIndex++) {
+ if (vals[valIndex]) {
+ if (columns[valIndex] == 'point') {
+ var coords = vals[valIndex].split(',');
+ geometry.y = parseFloat(coords[0]);
+ geometry.x = parseFloat(coords[1]);
+ set = true;
+ } else if (columns[valIndex] == 'lat') {
+ geometry.y = parseFloat(vals[valIndex]);
+ set = true;
+ } else if (columns[valIndex] == 'lon') {
+ geometry.x = parseFloat(vals[valIndex]);
+ set = true;
+ } else if (columns[valIndex] == 'title')
+ attributes['title'] = vals[valIndex];
+ else if (columns[valIndex] == 'image' ||
+ columns[valIndex] == 'icon' && style) {
+ style['externalGraphic'] = vals[valIndex];
+ } else if (columns[valIndex] == 'iconSize' && style) {
+ var size = vals[valIndex].split(',');
+ style['graphicWidth'] = parseFloat(size[0]);
+ style['graphicHeight'] = parseFloat(size[1]);
+ } else if (columns[valIndex] == 'iconOffset' && style) {
+ var offset = vals[valIndex].split(',');
+ style['graphicXOffset'] = parseFloat(offset[0]);
+ style['graphicYOffset'] = parseFloat(offset[1]);
+ } else if (columns[valIndex] == 'description') {
+ attributes['description'] = vals[valIndex];
+ } else if (columns[valIndex] == 'overflow') {
+ attributes['overflow'] = vals[valIndex];
+ } else {
+ // For StyleMap filtering, allow additional
+ // columns to be stored as attributes.
+ attributes[columns[valIndex]] = vals[valIndex];
+ }
+ }
+ }
+ if (set) {
+ if (this.internalProjection && this.externalProjection) {
+ geometry.transform(this.externalProjection,
+ this.internalProjection);
+ }
+ var feature = new OpenLayers.Feature.Vector(geometry, attributes, style);
+ features.push(feature);
+ }
+ }
+ }
+ }
+ return features;
+ },
+
+ CLASS_NAME: "OpenLayers.Format.Text"
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/WCSCapabilities.js b/misc/openlayers/lib/OpenLayers/Format/WCSCapabilities.js
new file mode 100644
index 0000000..934aaa5
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/WCSCapabilities.js
@@ -0,0 +1,47 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML/VersionedOGC.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WCSCapabilities
+ * Read WCS Capabilities.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML.VersionedOGC>
+ */
+OpenLayers.Format.WCSCapabilities = OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC, {
+
+ /**
+ * APIProperty: defaultVersion
+ * {String} Version number to assume if none found. Default is "1.1.0".
+ */
+ defaultVersion: "1.1.0",
+
+ /**
+ * Constructor: OpenLayers.Format.WCSCapabilities
+ * Create a new parser for WCS capabilities.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * APIMethod: read
+ * Read capabilities data from a string, and return a list of coverages.
+ *
+ * Parameters:
+ * data - {String} or {DOMElement} data to read/parse.
+ *
+ * Returns:
+ * {Array} List of named coverages.
+ */
+
+ CLASS_NAME: "OpenLayers.Format.WCSCapabilities"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/WCSCapabilities/v1.js b/misc/openlayers/lib/OpenLayers/Format/WCSCapabilities/v1.js
new file mode 100644
index 0000000..bf8da3b
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/WCSCapabilities/v1.js
@@ -0,0 +1,55 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WCSCapabilities.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WCSCapabilities.v1
+ * Abstract class not to be instantiated directly.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.WCSCapabilities.v1 = OpenLayers.Class(
+ OpenLayers.Format.XML, {
+
+ regExes: {
+ trimSpace: (/^\s*|\s*$/g),
+ splitSpace: (/\s+/)
+ },
+
+ /**
+ * Property: defaultPrefix
+ */
+ defaultPrefix: "wcs",
+
+ /**
+ * APIMethod: read
+ * Read capabilities data from a string, and return a list of coverages.
+ *
+ * Parameters:
+ * data - {String} or {DOMElement} data to read/parse.
+ *
+ * Returns:
+ * {Array} List of named coverages.
+ */
+ read: function(data) {
+ if(typeof data == "string") {
+ data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+ }
+ var raw = data;
+ if(data && data.nodeType == 9) {
+ data = data.documentElement;
+ }
+ var capabilities = {};
+ this.readNode(data, capabilities);
+ return capabilities;
+ },
+
+ CLASS_NAME: "OpenLayers.Format.WCSCapabilities.v1"
+
+}); \ No newline at end of file
diff --git a/misc/openlayers/lib/OpenLayers/Format/WCSCapabilities/v1_0_0.js b/misc/openlayers/lib/OpenLayers/Format/WCSCapabilities/v1_0_0.js
new file mode 100644
index 0000000..4dfa0b8
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/WCSCapabilities/v1_0_0.js
@@ -0,0 +1,170 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WCSCapabilities/v1.js
+ * @requires OpenLayers/Format/GML/v3.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WCSCapabilities/v1_0_0
+ * Read WCS Capabilities version 1.0.0.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.WCSCapabilities.v1>
+ */
+OpenLayers.Format.WCSCapabilities.v1_0_0 = OpenLayers.Class(
+ OpenLayers.Format.WCSCapabilities.v1, {
+
+ /**
+ * Constructor: OpenLayers.Format.WCSCapabilities.v1_0_0
+ * Create a new parser for WCS capabilities version 1.0.0.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * Property: namespaces
+ * {Object} Mapping of namespace aliases to namespace URIs.
+ */
+ namespaces: {
+ wcs: "http://www.opengis.net/wcs",
+ xlink: "http://www.w3.org/1999/xlink",
+ xsi: "http://www.w3.org/2001/XMLSchema-instance",
+ ows: "http://www.opengis.net/ows"
+ },
+
+ /**
+ * Property: errorProperty
+ * {String} Which property of the returned object to check for in order to
+ * determine whether or not parsing has failed. In the case that the
+ * errorProperty is undefined on the returned object, the document will be
+ * run through an OGCExceptionReport parser.
+ */
+ errorProperty: "service",
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "wcs": {
+ "WCS_Capabilities": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "Service": function(node, obj) {
+ obj.service = {};
+ this.readChildNodes(node, obj.service);
+ },
+ "name": function(node, service) {
+ service.name = this.getChildValue(node);
+ },
+ "label": function(node, service) {
+ service.label = this.getChildValue(node);
+ },
+ "keywords": function(node, service) {
+ service.keywords = [];
+ this.readChildNodes(node, service.keywords);
+ },
+ "keyword": function(node, keywords) {
+ // Append the keyword to the keywords list
+ keywords.push(this.getChildValue(node));
+ },
+ "responsibleParty": function(node, service) {
+ service.responsibleParty = {};
+ this.readChildNodes(node, service.responsibleParty);
+ },
+ "individualName": function(node, responsibleParty) {
+ responsibleParty.individualName = this.getChildValue(node);
+ },
+ "organisationName": function(node, responsibleParty) {
+ responsibleParty.organisationName = this.getChildValue(node);
+ },
+ "positionName": function(node, responsibleParty) {
+ responsibleParty.positionName = this.getChildValue(node);
+ },
+ "contactInfo": function(node, responsibleParty) {
+ responsibleParty.contactInfo = {};
+ this.readChildNodes(node, responsibleParty.contactInfo);
+ },
+ "phone": function(node, contactInfo) {
+ contactInfo.phone = {};
+ this.readChildNodes(node, contactInfo.phone);
+ },
+ "voice": function(node, phone) {
+ phone.voice = this.getChildValue(node);
+ },
+ "facsimile": function(node, phone) {
+ phone.facsimile = this.getChildValue(node);
+ },
+ "address": function(node, contactInfo) {
+ contactInfo.address = {};
+ this.readChildNodes(node, contactInfo.address);
+ },
+ "deliveryPoint": function(node, address) {
+ address.deliveryPoint = this.getChildValue(node);
+ },
+ "city": function(node, address) {
+ address.city = this.getChildValue(node);
+ },
+ "postalCode": function(node, address) {
+ address.postalCode = this.getChildValue(node);
+ },
+ "country": function(node, address) {
+ address.country = this.getChildValue(node);
+ },
+ "electronicMailAddress": function(node, address) {
+ address.electronicMailAddress = this.getChildValue(node);
+ },
+ "fees": function(node, service) {
+ service.fees = this.getChildValue(node);
+ },
+ "accessConstraints": function(node, service) {
+ service.accessConstraints = this.getChildValue(node);
+ },
+ "ContentMetadata": function(node, obj) {
+ obj.contentMetadata = [];
+ this.readChildNodes(node, obj.contentMetadata);
+ },
+ "CoverageOfferingBrief": function(node, contentMetadata) {
+ var coverageOfferingBrief = {};
+ this.readChildNodes(node, coverageOfferingBrief);
+ contentMetadata.push(coverageOfferingBrief);
+ },
+ "name": function(node, coverageOfferingBrief) {
+ coverageOfferingBrief.name = this.getChildValue(node);
+ },
+ "label": function(node, coverageOfferingBrief) {
+ coverageOfferingBrief.label = this.getChildValue(node);
+ },
+ "lonLatEnvelope": function(node, coverageOfferingBrief) {
+ var nodeList = this.getElementsByTagNameNS(node, "http://www.opengis.net/gml", "pos");
+
+ // We expect two nodes here, to create the corners of a bounding box
+ if(nodeList.length == 2) {
+ var min = {};
+ var max = {};
+
+ OpenLayers.Format.GML.v3.prototype.readers["gml"].pos.apply(this, [nodeList[0], min]);
+ OpenLayers.Format.GML.v3.prototype.readers["gml"].pos.apply(this, [nodeList[1], max]);
+
+ coverageOfferingBrief.lonLatEnvelope = {};
+ coverageOfferingBrief.lonLatEnvelope.srsName = node.getAttribute("srsName");
+ coverageOfferingBrief.lonLatEnvelope.min = min.points[0];
+ coverageOfferingBrief.lonLatEnvelope.max = max.points[0];
+ }
+ }
+ }
+ },
+
+ CLASS_NAME: "OpenLayers.Format.WCSCapabilities.v1_0_0"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/WCSCapabilities/v1_1_0.js b/misc/openlayers/lib/OpenLayers/Format/WCSCapabilities/v1_1_0.js
new file mode 100644
index 0000000..1753c51
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/WCSCapabilities/v1_1_0.js
@@ -0,0 +1,109 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WCSCapabilities/v1.js
+ * @requires OpenLayers/Format/OWSCommon/v1_1_0.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WCSCapabilities/v1_1_0
+ * Read WCS Capabilities version 1.1.0.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.WCSCapabilities.v1>
+ */
+OpenLayers.Format.WCSCapabilities.v1_1_0 = OpenLayers.Class(
+ OpenLayers.Format.WCSCapabilities.v1, {
+
+ /**
+ * Property: namespaces
+ * {Object} Mapping of namespace aliases to namespace URIs.
+ */
+ namespaces: {
+ wcs: "http://www.opengis.net/wcs/1.1",
+ xlink: "http://www.w3.org/1999/xlink",
+ xsi: "http://www.w3.org/2001/XMLSchema-instance",
+ ows: "http://www.opengis.net/ows/1.1"
+ },
+
+ /**
+ * APIProperty: errorProperty
+ * {String} Which property of the returned object to check for in order to
+ * determine whether or not parsing has failed. In the case that the
+ * errorProperty is undefined on the returned object, the document will be
+ * run through an OGCExceptionReport parser.
+ */
+ errorProperty: "operationsMetadata",
+
+ /**
+ * Constructor: OpenLayers.Format.WCSCapabilities.v1_1_0
+ * Create a new parser for WCS capabilities version 1.1.0.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "wcs": OpenLayers.Util.applyDefaults({
+ // In 1.0.0, this was WCS_Capabilties, in 1.1.0, it's Capabilities
+ "Capabilities": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "Contents": function(node, request) {
+ request.contentMetadata = [];
+ this.readChildNodes(node, request.contentMetadata);
+ },
+ "CoverageSummary": function(node, contentMetadata) {
+ var coverageSummary = {};
+ // Read the summary:
+ this.readChildNodes(node, coverageSummary);
+
+ // Add it to the contentMetadata array:
+ contentMetadata.push(coverageSummary);
+ },
+ "Identifier": function(node, coverageSummary) {
+ coverageSummary.identifier = this.getChildValue(node);
+ },
+ "Title": function(node, coverageSummary) {
+ coverageSummary.title = this.getChildValue(node);
+ },
+ "Abstract": function(node, coverageSummary) {
+ coverageSummary["abstract"] = this.getChildValue(node);
+ },
+ "SupportedCRS": function(node, coverageSummary) {
+ var crs = this.getChildValue(node);
+ if(crs) {
+ if(!coverageSummary.supportedCRS) {
+ coverageSummary.supportedCRS = [];
+ }
+ coverageSummary.supportedCRS.push(crs);
+ }
+ },
+ "SupportedFormat": function(node, coverageSummary) {
+ var format = this.getChildValue(node);
+ if(format) {
+ if(!coverageSummary.supportedFormat) {
+ coverageSummary.supportedFormat = [];
+ }
+ coverageSummary.supportedFormat.push(format);
+ }
+ }
+ }, OpenLayers.Format.WCSCapabilities.v1.prototype.readers["wcs"]),
+ "ows": OpenLayers.Format.OWSCommon.v1_1_0.prototype.readers["ows"]
+ },
+
+ CLASS_NAME: "OpenLayers.Format.WCSCapabilities.v1_1_0"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/WCSGetCoverage.js b/misc/openlayers/lib/OpenLayers/Format/WCSGetCoverage.js
new file mode 100644
index 0000000..2817f28
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/WCSGetCoverage.js
@@ -0,0 +1,199 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Format/OWSCommon/v1_1_0.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WCSGetCoverage version 1.1.0
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.WCSGetCoverage = OpenLayers.Class(OpenLayers.Format.XML, {
+
+ /**
+ * Property: namespaces
+ * {Object} Mapping of namespace aliases to namespace URIs.
+ */
+ namespaces: {
+ ows: "http://www.opengis.net/ows/1.1",
+ wcs: "http://www.opengis.net/wcs/1.1",
+ xlink: "http://www.w3.org/1999/xlink",
+ xsi: "http://www.w3.org/2001/XMLSchema-instance"
+ },
+
+ /**
+ * Property: regExes
+ * Compiled regular expressions for manipulating strings.
+ */
+ regExes: {
+ trimSpace: (/^\s*|\s*$/g),
+ removeSpace: (/\s*/g),
+ splitSpace: (/\s+/),
+ trimComma: (/\s*,\s*/g)
+ },
+
+ /**
+ * Constant: VERSION
+ * {String} 1.1.2
+ */
+ VERSION: "1.1.2",
+
+ /**
+ * Property: schemaLocation
+ * {String} Schema location
+ */
+ schemaLocation: "http://www.opengis.net/wcs/1.1 http://schemas.opengis.net/wcs/1.1/wcsGetCoverage.xsd",
+
+ /**
+ * Constructor: OpenLayers.Format.WCSGetCoverage
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * Method: write
+ *
+ * Parameters:
+ * options - {Object} Optional object.
+ *
+ * Returns:
+ * {String} A WCS GetCoverage request XML string.
+ */
+ write: function(options) {
+ var node = this.writeNode("wcs:GetCoverage", options);
+ this.setAttributeNS(
+ node, this.namespaces.xsi,
+ "xsi:schemaLocation", this.schemaLocation
+ );
+ return OpenLayers.Format.XML.prototype.write.apply(this, [node]);
+ },
+
+ /**
+ * Property: writers
+ * As a compliment to the readers property, this structure contains public
+ * writing functions grouped by namespace alias and named like the
+ * node names they produce.
+ */
+ writers: {
+ "wcs": {
+ "GetCoverage": function(options) {
+ var node = this.createElementNSPlus("wcs:GetCoverage", {
+ attributes: {
+ version: options.version || this.VERSION,
+ service: 'WCS'
+ }
+ });
+ this.writeNode("ows:Identifier", options.identifier, node);
+ this.writeNode("wcs:DomainSubset", options.domainSubset, node);
+ this.writeNode("wcs:Output", options.output, node);
+ return node;
+ },
+ "DomainSubset": function(domainSubset) {
+ var node = this.createElementNSPlus("wcs:DomainSubset", {});
+ this.writeNode("ows:BoundingBox", domainSubset.boundingBox, node);
+ if (domainSubset.temporalSubset) {
+ this.writeNode("wcs:TemporalSubset", domainSubset.temporalSubset, node);
+ }
+ return node;
+ },
+ "TemporalSubset": function(temporalSubset) {
+ var node = this.createElementNSPlus("wcs:TemporalSubset", {});
+ for (var i=0, len=temporalSubset.timePeriods.length; i<len; ++i) {
+ this.writeNode("wcs:TimePeriod", temporalSubset.timePeriods[i], node);
+ }
+ return node;
+ },
+ "TimePeriod": function(timePeriod) {
+ var node = this.createElementNSPlus("wcs:TimePeriod", {});
+ this.writeNode("wcs:BeginPosition", timePeriod.begin, node);
+ this.writeNode("wcs:EndPosition", timePeriod.end, node);
+ if (timePeriod.resolution) {
+ this.writeNode("wcs:TimeResolution", timePeriod.resolution, node);
+ }
+ return node;
+ },
+ "BeginPosition": function(begin) {
+ var node = this.createElementNSPlus("wcs:BeginPosition", {
+ value: begin
+ });
+ return node;
+ },
+ "EndPosition": function(end) {
+ var node = this.createElementNSPlus("wcs:EndPosition", {
+ value: end
+ });
+ return node;
+ },
+ "TimeResolution": function(resolution) {
+ var node = this.createElementNSPlus("wcs:TimeResolution", {
+ value: resolution
+ });
+ return node;
+ },
+ "Output": function(output) {
+ var node = this.createElementNSPlus("wcs:Output", {
+ attributes: {
+ format: output.format,
+ store: output.store
+ }
+ });
+ if (output.gridCRS) {
+ this.writeNode("wcs:GridCRS", output.gridCRS, node);
+ }
+ return node;
+ },
+ "GridCRS": function(gridCRS) {
+ var node = this.createElementNSPlus("wcs:GridCRS", {});
+ this.writeNode("wcs:GridBaseCRS", gridCRS.baseCRS, node);
+ if (gridCRS.type) {
+ this.writeNode("wcs:GridType", gridCRS.type, node);
+ }
+ if (gridCRS.origin) {
+ this.writeNode("wcs:GridOrigin", gridCRS.origin, node);
+ }
+ this.writeNode("wcs:GridOffsets", gridCRS.offsets, node);
+ if (gridCRS.CS) {
+ this.writeNode("wcs:GridCS", gridCRS.CS, node);
+ }
+ return node;
+ },
+ "GridBaseCRS": function(baseCRS) {
+ return this.createElementNSPlus("wcs:GridBaseCRS", {
+ value: baseCRS
+ });
+ },
+ "GridOrigin": function(origin) {
+ return this.createElementNSPlus("wcs:GridOrigin", {
+ value: origin
+ });
+ },
+ "GridType": function(type) {
+ return this.createElementNSPlus("wcs:GridType", {
+ value: type
+ });
+ },
+ "GridOffsets": function(offsets) {
+ return this.createElementNSPlus("wcs:GridOffsets", {
+ value: offsets
+ });
+ },
+ "GridCS": function(CS) {
+ return this.createElementNSPlus("wcs:GridCS", {
+ value: CS
+ });
+ }
+ },
+ "ows": OpenLayers.Format.OWSCommon.v1_1_0.prototype.writers.ows
+ },
+
+ CLASS_NAME: "OpenLayers.Format.WCSGetCoverage"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/WFS.js b/misc/openlayers/lib/OpenLayers/Format/WFS.js
new file mode 100644
index 0000000..44b03a3
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/WFS.js
@@ -0,0 +1,223 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/GML.js
+ * @requires OpenLayers/Console.js
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WFS
+ * Read/Write WFS.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.GML>
+ */
+OpenLayers.Format.WFS = OpenLayers.Class(OpenLayers.Format.GML, {
+
+ /**
+ * Property: layer
+ * {<OpenLayers.Layer>}
+ */
+ layer: null,
+
+ /**
+ * APIProperty: wfsns
+ * {String}
+ */
+ wfsns: "http://www.opengis.net/wfs",
+
+ /**
+ * Property: ogcns
+ * {String}
+ */
+ ogcns: "http://www.opengis.net/ogc",
+
+ /**
+ * Constructor: OpenLayers.Format.WFS
+ * Create a WFS-T formatter. This requires a layer: that layer should
+ * have two properties: geometry_column and typename. The parser
+ * for this format is subclassed entirely from GML: There is a writer
+ * only, which uses most of the code from the GML layer, and wraps
+ * it in transactional elements.
+ *
+ * Parameters:
+ * options - {Object}
+ * layer - {<OpenLayers.Layer>}
+ */
+ initialize: function(options, layer) {
+ OpenLayers.Format.GML.prototype.initialize.apply(this, [options]);
+ this.layer = layer;
+ if (this.layer.featureNS) {
+ this.featureNS = this.layer.featureNS;
+ }
+ if (this.layer.options.geometry_column) {
+ this.geometryName = this.layer.options.geometry_column;
+ }
+ if (this.layer.options.typename) {
+ this.featureName = this.layer.options.typename;
+ }
+ },
+
+ /**
+ * Method: write
+ * Takes a feature list, and generates a WFS-T Transaction
+ *
+ * Parameters:
+ * features - {Array(<OpenLayers.Feature.Vector>)}
+ */
+ write: function(features) {
+
+ var transaction = this.createElementNS(this.wfsns, 'wfs:Transaction');
+ transaction.setAttribute("version","1.0.0");
+ transaction.setAttribute("service","WFS");
+ for (var i=0; i < features.length; i++) {
+ switch (features[i].state) {
+ case OpenLayers.State.INSERT:
+ transaction.appendChild(this.insert(features[i]));
+ break;
+ case OpenLayers.State.UPDATE:
+ transaction.appendChild(this.update(features[i]));
+ break;
+ case OpenLayers.State.DELETE:
+ transaction.appendChild(this.remove(features[i]));
+ break;
+ }
+ }
+
+ return OpenLayers.Format.XML.prototype.write.apply(this,[transaction]);
+ },
+
+ /**
+ * Method: createFeatureXML
+ *
+ * Parameters:
+ * feature - {<OpenLayers.Feature.Vector>}
+ */
+ createFeatureXML: function(feature) {
+ var geometryNode = this.buildGeometryNode(feature.geometry);
+ var geomContainer = this.createElementNS(this.featureNS, "feature:" + this.geometryName);
+ geomContainer.appendChild(geometryNode);
+ var featureContainer = this.createElementNS(this.featureNS, "feature:" + this.featureName);
+ featureContainer.appendChild(geomContainer);
+ for(var attr in feature.attributes) {
+ var attrText = this.createTextNode(feature.attributes[attr]);
+ var nodename = attr;
+ if (attr.search(":") != -1) {
+ nodename = attr.split(":")[1];
+ }
+ var attrContainer = this.createElementNS(this.featureNS, "feature:" + nodename);
+ attrContainer.appendChild(attrText);
+ featureContainer.appendChild(attrContainer);
+ }
+ return featureContainer;
+ },
+
+ /**
+ * Method: insert
+ * Takes a feature, and generates a WFS-T Transaction "Insert"
+ *
+ * Parameters:
+ * feature - {<OpenLayers.Feature.Vector>}
+ */
+ insert: function(feature) {
+ var insertNode = this.createElementNS(this.wfsns, 'wfs:Insert');
+ insertNode.appendChild(this.createFeatureXML(feature));
+ return insertNode;
+ },
+
+ /**
+ * Method: update
+ * Takes a feature, and generates a WFS-T Transaction "Update"
+ *
+ * Parameters:
+ * feature - {<OpenLayers.Feature.Vector>}
+ */
+ update: function(feature) {
+ if (!feature.fid) { OpenLayers.Console.userError(OpenLayers.i18n("noFID")); }
+ var updateNode = this.createElementNS(this.wfsns, 'wfs:Update');
+ updateNode.setAttribute("typeName", this.featurePrefix + ':' + this.featureName);
+ updateNode.setAttribute("xmlns:" + this.featurePrefix, this.featureNS);
+
+ var propertyNode = this.createElementNS(this.wfsns, 'wfs:Property');
+ var nameNode = this.createElementNS(this.wfsns, 'wfs:Name');
+
+ var txtNode = this.createTextNode(this.geometryName);
+ nameNode.appendChild(txtNode);
+ propertyNode.appendChild(nameNode);
+
+ var valueNode = this.createElementNS(this.wfsns, 'wfs:Value');
+
+ var geometryNode = this.buildGeometryNode(feature.geometry);
+
+ if(feature.layer){
+ geometryNode.setAttribute(
+ "srsName", feature.layer.projection.getCode()
+ );
+ }
+
+ valueNode.appendChild(geometryNode);
+
+ propertyNode.appendChild(valueNode);
+ updateNode.appendChild(propertyNode);
+
+ // add in attributes
+ for(var propName in feature.attributes) {
+ propertyNode = this.createElementNS(this.wfsns, 'wfs:Property');
+ nameNode = this.createElementNS(this.wfsns, 'wfs:Name');
+ nameNode.appendChild(this.createTextNode(propName));
+ propertyNode.appendChild(nameNode);
+ valueNode = this.createElementNS(this.wfsns, 'wfs:Value');
+ valueNode.appendChild(this.createTextNode(feature.attributes[propName]));
+ propertyNode.appendChild(valueNode);
+ updateNode.appendChild(propertyNode);
+ }
+
+
+ var filterNode = this.createElementNS(this.ogcns, 'ogc:Filter');
+ var filterIdNode = this.createElementNS(this.ogcns, 'ogc:FeatureId');
+ filterIdNode.setAttribute("fid", feature.fid);
+ filterNode.appendChild(filterIdNode);
+ updateNode.appendChild(filterNode);
+
+ return updateNode;
+ },
+
+ /**
+ * Method: remove
+ * Takes a feature, and generates a WFS-T Transaction "Delete"
+ *
+ * Parameters:
+ * feature - {<OpenLayers.Feature.Vector>}
+ */
+ remove: function(feature) {
+ if (!feature.fid) {
+ OpenLayers.Console.userError(OpenLayers.i18n("noFID"));
+ return false;
+ }
+ var deleteNode = this.createElementNS(this.wfsns, 'wfs:Delete');
+ deleteNode.setAttribute("typeName", this.featurePrefix + ':' + this.featureName);
+ deleteNode.setAttribute("xmlns:" + this.featurePrefix, this.featureNS);
+
+ var filterNode = this.createElementNS(this.ogcns, 'ogc:Filter');
+ var filterIdNode = this.createElementNS(this.ogcns, 'ogc:FeatureId');
+ filterIdNode.setAttribute("fid", feature.fid);
+ filterNode.appendChild(filterIdNode);
+ deleteNode.appendChild(filterNode);
+
+ return deleteNode;
+ },
+
+ /**
+ * APIMethod: destroy
+ * Remove ciruclar ref to layer
+ */
+ destroy: function() {
+ this.layer = null;
+ },
+
+ CLASS_NAME: "OpenLayers.Format.WFS"
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/WFSCapabilities.js b/misc/openlayers/lib/OpenLayers/Format/WFSCapabilities.js
new file mode 100644
index 0000000..61af085
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/WFSCapabilities.js
@@ -0,0 +1,47 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML/VersionedOGC.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WFSCapabilities
+ * Read WFS Capabilities.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML.VersionedOGC>
+ */
+OpenLayers.Format.WFSCapabilities = OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC, {
+
+ /**
+ * APIProperty: defaultVersion
+ * {String} Version number to assume if none found. Default is "1.1.0".
+ */
+ defaultVersion: "1.1.0",
+
+ /**
+ * Constructor: OpenLayers.Format.WFSCapabilities
+ * Create a new parser for WFS capabilities.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * APIMethod: read
+ * Read capabilities data from a string, and return a list of layers.
+ *
+ * Parameters:
+ * data - {String} or {DOMElement} data to read/parse.
+ *
+ * Returns:
+ * {Array} List of named layers.
+ */
+
+ CLASS_NAME: "OpenLayers.Format.WFSCapabilities"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/WFSCapabilities/v1.js b/misc/openlayers/lib/OpenLayers/Format/WFSCapabilities/v1.js
new file mode 100644
index 0000000..c4ec517
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/WFSCapabilities/v1.js
@@ -0,0 +1,129 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WFSCapabilities.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WFSCapabilities.v1
+ * Abstract class not to be instantiated directly.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.WFSCapabilities.v1 = OpenLayers.Class(
+ OpenLayers.Format.XML, {
+
+ /**
+ * Property: namespaces
+ * {Object} Mapping of namespace aliases to namespace URIs.
+ */
+ namespaces: {
+ wfs: "http://www.opengis.net/wfs",
+ xlink: "http://www.w3.org/1999/xlink",
+ xsi: "http://www.w3.org/2001/XMLSchema-instance",
+ ows: "http://www.opengis.net/ows"
+ },
+
+
+ /**
+ * APIProperty: errorProperty
+ * {String} Which property of the returned object to check for in order to
+ * determine whether or not parsing has failed. In the case that the
+ * errorProperty is undefined on the returned object, the document will be
+ * run through an OGCExceptionReport parser.
+ */
+ errorProperty: "featureTypeList",
+
+ /**
+ * Property: defaultPrefix
+ */
+ defaultPrefix: "wfs",
+
+ /**
+ * Constructor: OpenLayers.Format.WFSCapabilities.v1_1
+ * Create an instance of one of the subclasses.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * APIMethod: read
+ * Read capabilities data from a string, and return a list of layers.
+ *
+ * Parameters:
+ * data - {String} or {DOMElement} data to read/parse.
+ *
+ * Returns:
+ * {Array} List of named layers.
+ */
+ read: function(data) {
+ if(typeof data == "string") {
+ data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+ }
+ var raw = data;
+ if(data && data.nodeType == 9) {
+ data = data.documentElement;
+ }
+ var capabilities = {};
+ this.readNode(data, capabilities);
+ return capabilities;
+ },
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "wfs": {
+ "WFS_Capabilities": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "FeatureTypeList": function(node, request) {
+ request.featureTypeList = {
+ featureTypes: []
+ };
+ this.readChildNodes(node, request.featureTypeList);
+ },
+ "FeatureType": function(node, featureTypeList) {
+ var featureType = {};
+ this.readChildNodes(node, featureType);
+ featureTypeList.featureTypes.push(featureType);
+ },
+ "Name": function(node, obj) {
+ var name = this.getChildValue(node);
+ if(name) {
+ var parts = name.split(":");
+ obj.name = parts.pop();
+ if(parts.length > 0) {
+ obj.featureNS = this.lookupNamespaceURI(node, parts[0]);
+ }
+ }
+ },
+ "Title": function(node, obj) {
+ var title = this.getChildValue(node);
+ if(title) {
+ obj.title = title;
+ }
+ },
+ "Abstract": function(node, obj) {
+ var abst = this.getChildValue(node);
+ if(abst) {
+ obj["abstract"] = abst;
+ }
+ }
+ }
+ },
+
+ CLASS_NAME: "OpenLayers.Format.WFSCapabilities.v1"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/WFSCapabilities/v1_0_0.js b/misc/openlayers/lib/OpenLayers/Format/WFSCapabilities/v1_0_0.js
new file mode 100644
index 0000000..6b202c7
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/WFSCapabilities/v1_0_0.js
@@ -0,0 +1,115 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WFSCapabilities/v1.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WFSCapabilities/v1_0_0
+ * Read WFS Capabilities version 1.0.0.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.WFSCapabilities.v1>
+ */
+OpenLayers.Format.WFSCapabilities.v1_0_0 = OpenLayers.Class(
+ OpenLayers.Format.WFSCapabilities.v1, {
+
+ /**
+ * Constructor: OpenLayers.Format.WFSCapabilities.v1_0_0
+ * Create a new parser for WFS capabilities version 1.0.0.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "wfs": OpenLayers.Util.applyDefaults({
+ "Service": function(node, capabilities) {
+ capabilities.service = {};
+ this.readChildNodes(node, capabilities.service);
+ },
+ "Fees": function(node, service) {
+ var fees = this.getChildValue(node);
+ if (fees && fees.toLowerCase() != "none") {
+ service.fees = fees;
+ }
+ },
+ "AccessConstraints": function(node, service) {
+ var constraints = this.getChildValue(node);
+ if (constraints && constraints.toLowerCase() != "none") {
+ service.accessConstraints = constraints;
+ }
+ },
+ "OnlineResource": function(node, service) {
+ var onlineResource = this.getChildValue(node);
+ if (onlineResource && onlineResource.toLowerCase() != "none") {
+ service.onlineResource = onlineResource;
+ }
+ },
+ "Keywords": function(node, service) {
+ var keywords = this.getChildValue(node);
+ if (keywords && keywords.toLowerCase() != "none") {
+ service.keywords = keywords.split(', ');
+ }
+ },
+ "Capability": function(node, capabilities) {
+ capabilities.capability = {};
+ this.readChildNodes(node, capabilities.capability);
+ },
+ "Request": function(node, obj) {
+ obj.request = {};
+ this.readChildNodes(node, obj.request);
+ },
+ "GetFeature": function(node, request) {
+ request.getfeature = {
+ href: {}, // DCPType
+ formats: [] // ResultFormat
+ };
+ this.readChildNodes(node, request.getfeature);
+ },
+ "ResultFormat": function(node, obj) {
+ var children = node.childNodes;
+ var childNode;
+ for(var i=0; i<children.length; i++) {
+ childNode = children[i];
+ if(childNode.nodeType == 1) {
+ obj.formats.push(childNode.nodeName);
+ }
+ }
+ },
+ "DCPType": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "HTTP": function(node, obj) {
+ this.readChildNodes(node, obj.href);
+ },
+ "Get": function(node, obj) {
+ obj.get = node.getAttribute("onlineResource");
+ },
+ "Post": function(node, obj) {
+ obj.post = node.getAttribute("onlineResource");
+ },
+ "SRS": function(node, obj) {
+ var srs = this.getChildValue(node);
+ if (srs) {
+ obj.srs = srs;
+ }
+ }
+ }, OpenLayers.Format.WFSCapabilities.v1.prototype.readers["wfs"])
+ },
+
+ CLASS_NAME: "OpenLayers.Format.WFSCapabilities.v1_0_0"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/WFSCapabilities/v1_1_0.js b/misc/openlayers/lib/OpenLayers/Format/WFSCapabilities/v1_1_0.js
new file mode 100644
index 0000000..84f6b4b
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/WFSCapabilities/v1_1_0.js
@@ -0,0 +1,63 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WFSCapabilities/v1.js
+ * @requires OpenLayers/Format/OWSCommon/v1.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WFSCapabilities/v1_1_0
+ * Read WFS Capabilities version 1.1.0.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.WFSCapabilities>
+ */
+OpenLayers.Format.WFSCapabilities.v1_1_0 = OpenLayers.Class(
+ OpenLayers.Format.WFSCapabilities.v1, {
+
+ /**
+ * Property: regExes
+ * Compiled regular expressions for manipulating strings.
+ */
+ regExes: {
+ trimSpace: (/^\s*|\s*$/g),
+ removeSpace: (/\s*/g),
+ splitSpace: (/\s+/),
+ trimComma: (/\s*,\s*/g)
+ },
+
+ /**
+ * Constructor: OpenLayers.Format.WFSCapabilities.v1_1_0
+ * Create a new parser for WFS capabilities version 1.1.0.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "wfs": OpenLayers.Util.applyDefaults({
+ "DefaultSRS": function(node, obj) {
+ var defaultSRS = this.getChildValue(node);
+ if (defaultSRS) {
+ obj.srs = defaultSRS;
+ }
+ }
+ }, OpenLayers.Format.WFSCapabilities.v1.prototype.readers["wfs"]),
+ "ows": OpenLayers.Format.OWSCommon.v1.prototype.readers.ows
+ },
+
+ CLASS_NAME: "OpenLayers.Format.WFSCapabilities.v1_1_0"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/WFSDescribeFeatureType.js b/misc/openlayers/lib/OpenLayers/Format/WFSDescribeFeatureType.js
new file mode 100644
index 0000000..416e845
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/WFSDescribeFeatureType.js
@@ -0,0 +1,234 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Format/OGCExceptionReport.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WFSDescribeFeatureType
+ * Read WFS DescribeFeatureType response
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.WFSDescribeFeatureType = OpenLayers.Class(
+ OpenLayers.Format.XML, {
+
+ /**
+ * Property: regExes
+ * Compiled regular expressions for manipulating strings.
+ */
+ regExes: {
+ trimSpace: (/^\s*|\s*$/g)
+ },
+
+ /**
+ * Property: namespaces
+ * {Object} Mapping of namespace aliases to namespace URIs.
+ */
+ namespaces: {
+ xsd: "http://www.w3.org/2001/XMLSchema"
+ },
+
+ /**
+ * Constructor: OpenLayers.Format.WFSDescribeFeatureType
+ * Create a new parser for WFS DescribeFeatureType responses.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "xsd": {
+ "schema": function(node, obj) {
+ var complexTypes = [];
+ var customTypes = {};
+ var schema = {
+ complexTypes: complexTypes,
+ customTypes: customTypes
+ };
+ var i, len;
+
+ this.readChildNodes(node, schema);
+
+ var attributes = node.attributes;
+ var attr, name;
+ for(i=0, len=attributes.length; i<len; ++i) {
+ attr = attributes[i];
+ name = attr.name;
+ if(name.indexOf("xmlns") === 0) {
+ this.setNamespace(name.split(":")[1] || "", attr.value);
+ } else {
+ obj[name] = attr.value;
+ }
+ }
+ obj.featureTypes = complexTypes;
+ obj.targetPrefix = this.namespaceAlias[obj.targetNamespace];
+
+ // map complexTypes to names of customTypes
+ var complexType, customType;
+ for(i=0, len=complexTypes.length; i<len; ++i) {
+ complexType = complexTypes[i];
+ customType = customTypes[complexType.typeName];
+ if(customTypes[complexType.typeName]) {
+ complexType.typeName = customType.name;
+ }
+ }
+ },
+ "complexType": function(node, obj) {
+ var complexType = {
+ // this is a temporary typeName, it will be overwritten by
+ // the schema reader with the metadata found in the
+ // customTypes hash
+ "typeName": node.getAttribute("name")
+ };
+ this.readChildNodes(node, complexType);
+ obj.complexTypes.push(complexType);
+ },
+ "complexContent": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "extension": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "sequence": function(node, obj) {
+ var sequence = {
+ elements: []
+ };
+ this.readChildNodes(node, sequence);
+ obj.properties = sequence.elements;
+ },
+ "element": function(node, obj) {
+ var type;
+ if(obj.elements) {
+ var element = {};
+ var attributes = node.attributes;
+ var attr;
+ for(var i=0, len=attributes.length; i<len; ++i) {
+ attr = attributes[i];
+ element[attr.name] = attr.value;
+ }
+
+ type = element.type;
+ if(!type) {
+ type = {};
+ this.readChildNodes(node, type);
+ element.restriction = type;
+ element.type = type.base;
+ }
+ var fullType = type.base || type;
+ element.localType = fullType.split(":").pop();
+ obj.elements.push(element);
+ this.readChildNodes(node, element);
+ }
+
+ if(obj.complexTypes) {
+ type = node.getAttribute("type");
+ var localType = type.split(":").pop();
+ obj.customTypes[localType] = {
+ "name": node.getAttribute("name"),
+ "type": type
+ };
+ }
+ },
+ "annotation": function(node, obj) {
+ obj.annotation = {};
+ this.readChildNodes(node, obj.annotation);
+ },
+ "appinfo": function(node, obj) {
+ if (!obj.appinfo) {
+ obj.appinfo = [];
+ }
+ obj.appinfo.push(this.getChildValue(node));
+ },
+ "documentation": function(node, obj) {
+ if (!obj.documentation) {
+ obj.documentation = [];
+ }
+ var value = this.getChildValue(node);
+ obj.documentation.push({
+ lang: node.getAttribute("xml:lang"),
+ textContent: value.replace(this.regExes.trimSpace, "")
+ });
+ },
+ "simpleType": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "restriction": function(node, obj) {
+ obj.base = node.getAttribute("base");
+ this.readRestriction(node, obj);
+ }
+ }
+ },
+
+ /**
+ * Method: readRestriction
+ * Reads restriction defined in the child nodes of a restriction element
+ *
+ * Parameters:
+ * node - {DOMElement} the node to parse
+ * obj - {Object} the object that receives the read result
+ */
+ readRestriction: function(node, obj) {
+ var children = node.childNodes;
+ var child, nodeName, value;
+ for(var i=0, len=children.length; i<len; ++i) {
+ child = children[i];
+ if(child.nodeType == 1) {
+ nodeName = child.nodeName.split(":").pop();
+ value = child.getAttribute("value");
+ if(!obj[nodeName]) {
+ obj[nodeName] = value;
+ } else {
+ if(typeof obj[nodeName] == "string") {
+ obj[nodeName] = [obj[nodeName]];
+ }
+ obj[nodeName].push(value);
+ }
+ }
+ }
+ },
+
+ /**
+ * Method: read
+ *
+ * Parameters:
+ * data - {DOMElement|String} A WFS DescribeFeatureType document.
+ *
+ * Returns:
+ * {Object} An object representing the WFS DescribeFeatureType response.
+ */
+ read: function(data) {
+ if(typeof data == "string") {
+ data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+ }
+ if(data && data.nodeType == 9) {
+ data = data.documentElement;
+ }
+ var schema = {};
+ if (data.nodeName.split(":").pop() === 'ExceptionReport') {
+ // an exception must have occurred, so parse it
+ var parser = new OpenLayers.Format.OGCExceptionReport();
+ schema.error = parser.read(data);
+ } else {
+ this.readNode(data, schema);
+ }
+ return schema;
+ },
+
+ CLASS_NAME: "OpenLayers.Format.WFSDescribeFeatureType"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/WFST.js b/misc/openlayers/lib/OpenLayers/Format/WFST.js
new file mode 100644
index 0000000..eb3d9d9
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/WFST.js
@@ -0,0 +1,34 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format.js
+ */
+
+/**
+ * Function: OpenLayers.Format.WFST
+ * Used to create a versioned WFS protocol. Default version is 1.0.0.
+ *
+ * Returns:
+ * {<OpenLayers.Format>} A WFST format of the given version.
+ */
+OpenLayers.Format.WFST = function(options) {
+ options = OpenLayers.Util.applyDefaults(
+ options, OpenLayers.Format.WFST.DEFAULTS
+ );
+ var cls = OpenLayers.Format.WFST["v"+options.version.replace(/\./g, "_")];
+ if(!cls) {
+ throw "Unsupported WFST version: " + options.version;
+ }
+ return new cls(options);
+};
+
+/**
+ * Constant: OpenLayers.Format.WFST.DEFAULTS
+ * {Object} Default properties for the WFST format.
+ */
+OpenLayers.Format.WFST.DEFAULTS = {
+ "version": "1.0.0"
+};
diff --git a/misc/openlayers/lib/OpenLayers/Format/WFST/v1.js b/misc/openlayers/lib/OpenLayers/Format/WFST/v1.js
new file mode 100644
index 0000000..306ba6f
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/WFST/v1.js
@@ -0,0 +1,446 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Format/WFST.js
+ * @requires OpenLayers/Filter/Spatial.js
+ * @requires OpenLayers/Filter/FeatureId.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WFST.v1
+ * Superclass for WFST parsers.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.WFST.v1 = OpenLayers.Class(OpenLayers.Format.XML, {
+
+ /**
+ * Property: namespaces
+ * {Object} Mapping of namespace aliases to namespace URIs.
+ */
+ namespaces: {
+ xlink: "http://www.w3.org/1999/xlink",
+ xsi: "http://www.w3.org/2001/XMLSchema-instance",
+ wfs: "http://www.opengis.net/wfs",
+ gml: "http://www.opengis.net/gml",
+ ogc: "http://www.opengis.net/ogc",
+ ows: "http://www.opengis.net/ows"
+ },
+
+ /**
+ * Property: defaultPrefix
+ */
+ defaultPrefix: "wfs",
+
+ /**
+ * Property: version
+ * {String} WFS version number.
+ */
+ version: null,
+
+ /**
+ * Property: schemaLocation
+ * {String} Schema location for a particular minor version.
+ */
+ schemaLocations: null,
+
+ /**
+ * APIProperty: srsName
+ * {String} URI for spatial reference system.
+ */
+ srsName: null,
+
+ /**
+ * APIProperty: extractAttributes
+ * {Boolean} Extract attributes from GML. Default is true.
+ */
+ extractAttributes: true,
+
+ /**
+ * APIProperty: xy
+ * {Boolean} Order of the GML coordinate true:(x,y) or false:(y,x)
+ * Changing is not recommended, a new Format should be instantiated.
+ */
+ xy: true,
+
+ /**
+ * Property: stateName
+ * {Object} Maps feature states to node names.
+ */
+ stateName: null,
+
+ /**
+ * Constructor: OpenLayers.Format.WFST.v1
+ * Instances of this class are not created directly. Use the
+ * <OpenLayers.Format.WFST.v1_0_0> or <OpenLayers.Format.WFST.v1_1_0>
+ * constructor instead.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+ initialize: function(options) {
+ // set state name mapping
+ this.stateName = {};
+ this.stateName[OpenLayers.State.INSERT] = "wfs:Insert";
+ this.stateName[OpenLayers.State.UPDATE] = "wfs:Update";
+ this.stateName[OpenLayers.State.DELETE] = "wfs:Delete";
+ OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+ },
+
+ /**
+ * Method: getSrsName
+ */
+ getSrsName: function(feature, options) {
+ var srsName = options && options.srsName;
+ if(!srsName) {
+ if(feature && feature.layer) {
+ srsName = feature.layer.projection.getCode();
+ } else {
+ srsName = this.srsName;
+ }
+ }
+ return srsName;
+ },
+
+ /**
+ * APIMethod: read
+ * Parse the response from a transaction. Because WFS is split into
+ * Transaction requests (create, update, and delete) and GetFeature
+ * requests (read), this method handles parsing of both types of
+ * responses.
+ *
+ * Parameters:
+ * data - {String | Document} The WFST document to read
+ * options - {Object} Options for the reader
+ *
+ * Valid options properties:
+ * output - {String} either "features" or "object". The default is
+ * "features", which means that the method will return an array of
+ * features. If set to "object", an object with a "features" property
+ * and other properties read by the parser will be returned.
+ *
+ * Returns:
+ * {Array | Object} Output depending on the output option.
+ */
+ read: function(data, options) {
+ options = options || {};
+ OpenLayers.Util.applyDefaults(options, {
+ output: "features"
+ });
+
+ if(typeof data == "string") {
+ data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+ }
+ if(data && data.nodeType == 9) {
+ data = data.documentElement;
+ }
+ var obj = {};
+ if(data) {
+ this.readNode(data, obj, true);
+ }
+ if(obj.features && options.output === "features") {
+ obj = obj.features;
+ }
+ return obj;
+ },
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "wfs": {
+ "FeatureCollection": function(node, obj) {
+ obj.features = [];
+ this.readChildNodes(node, obj);
+ }
+ }
+ },
+
+ /**
+ * Method: write
+ * Given an array of features, write a WFS transaction. This assumes
+ * the features have a state property that determines the operation
+ * type - insert, update, or delete.
+ *
+ * Parameters:
+ * features - {Array(<OpenLayers.Feature.Vector>)} A list of features. See
+ * below for a more detailed description of the influence of the
+ * feature's *modified* property.
+ * options - {Object}
+ *
+ * feature.modified rules:
+ * If a feature has a modified property set, the following checks will be
+ * made before a feature's geometry or attribute is included in an Update
+ * transaction:
+ * - *modified* is not set at all: The geometry and all attributes will be
+ * included.
+ * - *modified.geometry* is set (null or a geometry): The geometry will be
+ * included. If *modified.attributes* is not set, all attributes will
+ * be included.
+ * - *modified.attributes* is set: Only the attributes set (i.e. to null or
+ * a value) in *modified.attributes* will be included.
+ * If *modified.geometry* is not set, the geometry will not be included.
+ *
+ * Valid options include:
+ * - *multi* {Boolean} If set to true, geometries will be casted to
+ * Multi geometries before writing.
+ *
+ * Returns:
+ * {String} A serialized WFS transaction.
+ */
+ write: function(features, options) {
+ var node = this.writeNode("wfs:Transaction", {
+ features:features,
+ options: options
+ });
+ var value = this.schemaLocationAttr();
+ if(value) {
+ this.setAttributeNS(
+ node, this.namespaces["xsi"], "xsi:schemaLocation", value
+ );
+ }
+ return OpenLayers.Format.XML.prototype.write.apply(this, [node]);
+ },
+
+ /**
+ * Property: writers
+ * As a compliment to the readers property, this structure contains public
+ * writing functions grouped by namespace alias and named like the
+ * node names they produce.
+ */
+ writers: {
+ "wfs": {
+ "GetFeature": function(options) {
+ var node = this.createElementNSPlus("wfs:GetFeature", {
+ attributes: {
+ service: "WFS",
+ version: this.version,
+ handle: options && options.handle,
+ outputFormat: options && options.outputFormat,
+ maxFeatures: options && options.maxFeatures,
+ "xsi:schemaLocation": this.schemaLocationAttr(options)
+ }
+ });
+ if (typeof this.featureType == "string") {
+ this.writeNode("Query", options, node);
+ } else {
+ for (var i=0,len = this.featureType.length; i<len; i++) {
+ options.featureType = this.featureType[i];
+ this.writeNode("Query", options, node);
+ }
+ }
+ return node;
+ },
+ "Transaction": function(obj) {
+ obj = obj || {};
+ var options = obj.options || {};
+ var node = this.createElementNSPlus("wfs:Transaction", {
+ attributes: {
+ service: "WFS",
+ version: this.version,
+ handle: options.handle
+ }
+ });
+ var i, len;
+ var features = obj.features;
+ if(features) {
+ // temporarily re-assigning geometry types
+ if (options.multi === true) {
+ OpenLayers.Util.extend(this.geometryTypes, {
+ "OpenLayers.Geometry.Point": "MultiPoint",
+ "OpenLayers.Geometry.LineString": (this.multiCurve === true) ? "MultiCurve": "MultiLineString",
+ "OpenLayers.Geometry.Polygon": (this.multiSurface === true) ? "MultiSurface" : "MultiPolygon"
+ });
+ }
+ var name, feature;
+ for(i=0, len=features.length; i<len; ++i) {
+ feature = features[i];
+ name = this.stateName[feature.state];
+ if(name) {
+ this.writeNode(name, {
+ feature: feature,
+ options: options
+ }, node);
+ }
+ }
+ // switch back to original geometry types assignment
+ if (options.multi === true) {
+ this.setGeometryTypes();
+ }
+ }
+ if (options.nativeElements) {
+ for (i=0, len=options.nativeElements.length; i<len; ++i) {
+ this.writeNode("wfs:Native",
+ options.nativeElements[i], node);
+ }
+ }
+ return node;
+ },
+ "Native": function(nativeElement) {
+ var node = this.createElementNSPlus("wfs:Native", {
+ attributes: {
+ vendorId: nativeElement.vendorId,
+ safeToIgnore: nativeElement.safeToIgnore
+ },
+ value: nativeElement.value
+ });
+ return node;
+ },
+ "Insert": function(obj) {
+ var feature = obj.feature;
+ var options = obj.options;
+ var node = this.createElementNSPlus("wfs:Insert", {
+ attributes: {
+ handle: options && options.handle
+ }
+ });
+ this.srsName = this.getSrsName(feature);
+ this.writeNode("feature:_typeName", feature, node);
+ return node;
+ },
+ "Update": function(obj) {
+ var feature = obj.feature;
+ var options = obj.options;
+ var node = this.createElementNSPlus("wfs:Update", {
+ attributes: {
+ handle: options && options.handle,
+ typeName: (this.featureNS ? this.featurePrefix + ":" : "") +
+ this.featureType
+ }
+ });
+ if(this.featureNS) {
+ node.setAttribute("xmlns:" + this.featurePrefix, this.featureNS);
+ }
+
+ // add in geometry
+ var modified = feature.modified;
+ if (this.geometryName !== null && (!modified || modified.geometry !== undefined)) {
+ this.srsName = this.getSrsName(feature);
+ this.writeNode(
+ "Property", {name: this.geometryName, value: feature.geometry}, node
+ );
+ }
+
+ // add in attributes
+ for(var key in feature.attributes) {
+ if(feature.attributes[key] !== undefined &&
+ (!modified || !modified.attributes ||
+ (modified.attributes && modified.attributes[key] !== undefined))) {
+ this.writeNode(
+ "Property", {name: key, value: feature.attributes[key]}, node
+ );
+ }
+ }
+
+ // add feature id filter
+ this.writeNode("ogc:Filter", new OpenLayers.Filter.FeatureId({
+ fids: [feature.fid]
+ }), node);
+
+ return node;
+ },
+ "Property": function(obj) {
+ var node = this.createElementNSPlus("wfs:Property");
+ this.writeNode("Name", obj.name, node);
+ if(obj.value !== null) {
+ this.writeNode("Value", obj.value, node);
+ }
+ return node;
+ },
+ "Name": function(name) {
+ return this.createElementNSPlus("wfs:Name", {value: name});
+ },
+ "Value": function(obj) {
+ var node;
+ if(obj instanceof OpenLayers.Geometry) {
+ node = this.createElementNSPlus("wfs:Value");
+ var geom = this.writeNode("feature:_geometry", obj).firstChild;
+ node.appendChild(geom);
+ } else {
+ node = this.createElementNSPlus("wfs:Value", {value: obj});
+ }
+ return node;
+ },
+ "Delete": function(obj) {
+ var feature = obj.feature;
+ var options = obj.options;
+ var node = this.createElementNSPlus("wfs:Delete", {
+ attributes: {
+ handle: options && options.handle,
+ typeName: (this.featureNS ? this.featurePrefix + ":" : "") +
+ this.featureType
+ }
+ });
+ if(this.featureNS) {
+ node.setAttribute("xmlns:" + this.featurePrefix, this.featureNS);
+ }
+ this.writeNode("ogc:Filter", new OpenLayers.Filter.FeatureId({
+ fids: [feature.fid]
+ }), node);
+ return node;
+ }
+ }
+ },
+
+ /**
+ * Method: schemaLocationAttr
+ * Generate the xsi:schemaLocation attribute value.
+ *
+ * Returns:
+ * {String} The xsi:schemaLocation attribute or undefined if none.
+ */
+ schemaLocationAttr: function(options) {
+ options = OpenLayers.Util.extend({
+ featurePrefix: this.featurePrefix,
+ schema: this.schema
+ }, options);
+ var schemaLocations = OpenLayers.Util.extend({}, this.schemaLocations);
+ if(options.schema) {
+ schemaLocations[options.featurePrefix] = options.schema;
+ }
+ var parts = [];
+ var uri;
+ for(var key in schemaLocations) {
+ uri = this.namespaces[key];
+ if(uri) {
+ parts.push(uri + " " + schemaLocations[key]);
+ }
+ }
+ var value = parts.join(" ") || undefined;
+ return value;
+ },
+
+ /**
+ * Method: setFilterProperty
+ * Set the property of each spatial filter.
+ *
+ * Parameters:
+ * filter - {<OpenLayers.Filter>}
+ */
+ setFilterProperty: function(filter) {
+ if(filter.filters) {
+ for(var i=0, len=filter.filters.length; i<len; ++i) {
+ OpenLayers.Format.WFST.v1.prototype.setFilterProperty.call(this, filter.filters[i]);
+ }
+ } else {
+ if(filter instanceof OpenLayers.Filter.Spatial && !filter.property) {
+ // got a spatial filter without property, so set it
+ filter.property = this.geometryName;
+ }
+ }
+ },
+
+ CLASS_NAME: "OpenLayers.Format.WFST.v1"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/WFST/v1_0_0.js b/misc/openlayers/lib/OpenLayers/Format/WFST/v1_0_0.js
new file mode 100644
index 0000000..ed81a2d
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/WFST/v1_0_0.js
@@ -0,0 +1,174 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WFST/v1.js
+ * @requires OpenLayers/Format/Filter/v1_0_0.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WFST.v1_0_0
+ * A format for creating WFS v1.0.0 transactions. Create a new instance with the
+ * <OpenLayers.Format.WFST.v1_0_0> constructor.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.Filter.v1_0_0>
+ * - <OpenLayers.Format.WFST.v1>
+ */
+OpenLayers.Format.WFST.v1_0_0 = OpenLayers.Class(
+ OpenLayers.Format.Filter.v1_0_0, OpenLayers.Format.WFST.v1, {
+
+ /**
+ * Property: version
+ * {String} WFS version number.
+ */
+ version: "1.0.0",
+
+ /**
+ * APIProperty: srsNameInQuery
+ * {Boolean} If true the reference system is passed in Query requests
+ * via the "srsName" attribute to the "wfs:Query" element, this
+ * property defaults to false as it isn't WFS 1.0.0 compliant.
+ */
+ srsNameInQuery: false,
+
+ /**
+ * Property: schemaLocations
+ * {Object} Properties are namespace aliases, values are schema locations.
+ */
+ schemaLocations: {
+ "wfs": "http://schemas.opengis.net/wfs/1.0.0/WFS-transaction.xsd"
+ },
+
+ /**
+ * Constructor: OpenLayers.Format.WFST.v1_0_0
+ * A class for parsing and generating WFS v1.0.0 transactions.
+ *
+ * Parameters:
+ * options - {Object} Optional object whose properties will be set on the
+ * instance.
+ *
+ * Valid options properties:
+ * featureType - {String} Local (without prefix) feature typeName (required).
+ * featureNS - {String} Feature namespace (optional).
+ * featurePrefix - {String} Feature namespace alias (optional - only used
+ * if featureNS is provided). Default is 'feature'.
+ * geometryName - {String} Name of geometry attribute. Default is 'the_geom'.
+ */
+ initialize: function(options) {
+ OpenLayers.Format.Filter.v1_0_0.prototype.initialize.apply(this, [options]);
+ OpenLayers.Format.WFST.v1.prototype.initialize.apply(this, [options]);
+ },
+
+ /**
+ * Method: readNode
+ * Shorthand for applying one of the named readers given the node
+ * namespace and local name. Readers take two args (node, obj) and
+ * generally extend or modify the second.
+ *
+ * Parameters:
+ * node - {DOMElement} The node to be read (required).
+ * obj - {Object} The object to be modified (optional).
+ * first - {Boolean} Should be set to true for the first node read. This
+ * is usually the readNode call in the read method. Without this being
+ * set, auto-configured properties will stick on subsequent reads.
+ *
+ * Returns:
+ * {Object} The input object, modified (or a new one if none was provided).
+ */
+ readNode: function(node, obj, first) {
+ // Not the superclass, only the mixin classes inherit from
+ // Format.GML.v2. We need this because we don't want to get readNode
+ // from the superclass's superclass, which is OpenLayers.Format.XML.
+ return OpenLayers.Format.GML.v2.prototype.readNode.apply(this, arguments);
+ },
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "wfs": OpenLayers.Util.applyDefaults({
+ "WFS_TransactionResponse": function(node, obj) {
+ obj.insertIds = [];
+ obj.success = false;
+ this.readChildNodes(node, obj);
+ },
+ "InsertResult": function(node, container) {
+ var obj = {fids: []};
+ this.readChildNodes(node, obj);
+ container.insertIds = container.insertIds.concat(obj.fids);
+ },
+ "TransactionResult": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "Status": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "SUCCESS": function(node, obj) {
+ obj.success = true;
+ }
+ }, OpenLayers.Format.WFST.v1.prototype.readers["wfs"]),
+ "gml": OpenLayers.Format.GML.v2.prototype.readers["gml"],
+ "feature": OpenLayers.Format.GML.v2.prototype.readers["feature"],
+ "ogc": OpenLayers.Format.Filter.v1_0_0.prototype.readers["ogc"]
+ },
+
+ /**
+ * Property: writers
+ * As a compliment to the readers property, this structure contains public
+ * writing functions grouped by namespace alias and named like the
+ * node names they produce.
+ */
+ writers: {
+ "wfs": OpenLayers.Util.applyDefaults({
+ "Query": function(options) {
+ options = OpenLayers.Util.extend({
+ featureNS: this.featureNS,
+ featurePrefix: this.featurePrefix,
+ featureType: this.featureType,
+ srsName: this.srsName,
+ srsNameInQuery: this.srsNameInQuery
+ }, options);
+ var prefix = options.featurePrefix;
+ var node = this.createElementNSPlus("wfs:Query", {
+ attributes: {
+ typeName: (prefix ? prefix + ":" : "") +
+ options.featureType
+ }
+ });
+ if(options.srsNameInQuery && options.srsName) {
+ node.setAttribute("srsName", options.srsName);
+ }
+ if(options.featureNS) {
+ node.setAttribute("xmlns:" + prefix, options.featureNS);
+ }
+ if(options.propertyNames) {
+ for(var i=0,len = options.propertyNames.length; i<len; i++) {
+ this.writeNode(
+ "ogc:PropertyName",
+ {property: options.propertyNames[i]},
+ node
+ );
+ }
+ }
+ if(options.filter) {
+ this.setFilterProperty(options.filter);
+ this.writeNode("ogc:Filter", options.filter, node);
+ }
+ return node;
+ }
+ }, OpenLayers.Format.WFST.v1.prototype.writers["wfs"]),
+ "gml": OpenLayers.Format.GML.v2.prototype.writers["gml"],
+ "feature": OpenLayers.Format.GML.v2.prototype.writers["feature"],
+ "ogc": OpenLayers.Format.Filter.v1_0_0.prototype.writers["ogc"]
+ },
+
+ CLASS_NAME: "OpenLayers.Format.WFST.v1_0_0"
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/WFST/v1_1_0.js b/misc/openlayers/lib/OpenLayers/Format/WFST/v1_1_0.js
new file mode 100644
index 0000000..ff2a88d
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/WFST/v1_1_0.js
@@ -0,0 +1,189 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WFST/v1.js
+ * @requires OpenLayers/Format/Filter/v1_1_0.js
+ * @requires OpenLayers/Format/OWSCommon/v1_0_0.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WFST.v1_1_0
+ * A format for creating WFS v1.1.0 transactions. Create a new instance with the
+ * <OpenLayers.Format.WFST.v1_1_0> constructor.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.Filter.v1_1_0>
+ * - <OpenLayers.Format.WFST.v1>
+ */
+OpenLayers.Format.WFST.v1_1_0 = OpenLayers.Class(
+ OpenLayers.Format.Filter.v1_1_0, OpenLayers.Format.WFST.v1, {
+
+ /**
+ * Property: version
+ * {String} WFS version number.
+ */
+ version: "1.1.0",
+
+ /**
+ * Property: schemaLocations
+ * {Object} Properties are namespace aliases, values are schema locations.
+ */
+ schemaLocations: {
+ "wfs": "http://schemas.opengis.net/wfs/1.1.0/wfs.xsd"
+ },
+
+ /**
+ * Constructor: OpenLayers.Format.WFST.v1_1_0
+ * A class for parsing and generating WFS v1.1.0 transactions.
+ *
+ * To read additional information like hit count (numberOfFeatures) from
+ * the FeatureCollection, call the <OpenLayers.Format.WFST.v1.read> method
+ * with {output: "object"} as 2nd argument. Note that it is possible to
+ * just request the hit count from a WFS 1.1.0 server with the
+ * resultType="hits" request parameter.
+ *
+ * Parameters:
+ * options - {Object} Optional object whose properties will be set on the
+ * instance.
+ *
+ * Valid options properties:
+ * featureType - {String} Local (without prefix) feature typeName (required).
+ * featureNS - {String} Feature namespace (optional).
+ * featurePrefix - {String} Feature namespace alias (optional - only used
+ * if featureNS is provided). Default is 'feature'.
+ * geometryName - {String} Name of geometry attribute. Default is 'the_geom'.
+ */
+ initialize: function(options) {
+ OpenLayers.Format.Filter.v1_1_0.prototype.initialize.apply(this, [options]);
+ OpenLayers.Format.WFST.v1.prototype.initialize.apply(this, [options]);
+ },
+
+ /**
+ * Method: readNode
+ * Shorthand for applying one of the named readers given the node
+ * namespace and local name. Readers take two args (node, obj) and
+ * generally extend or modify the second.
+ *
+ * Parameters:
+ * node - {DOMElement} The node to be read (required).
+ * obj - {Object} The object to be modified (optional).
+ * first - {Boolean} Should be set to true for the first node read. This
+ * is usually the readNode call in the read method. Without this being
+ * set, auto-configured properties will stick on subsequent reads.
+ *
+ * Returns:
+ * {Object} The input object, modified (or a new one if none was provided).
+ */
+ readNode: function(node, obj, first) {
+ // Not the superclass, only the mixin classes inherit from
+ // Format.GML.v3. We need this because we don't want to get readNode
+ // from the superclass's superclass, which is OpenLayers.Format.XML.
+ return OpenLayers.Format.GML.v3.prototype.readNode.apply(this, arguments);
+ },
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "wfs": OpenLayers.Util.applyDefaults({
+ "FeatureCollection": function(node, obj) {
+ obj.numberOfFeatures = parseInt(node.getAttribute(
+ "numberOfFeatures"));
+ OpenLayers.Format.WFST.v1.prototype.readers["wfs"]["FeatureCollection"].apply(
+ this, arguments);
+ },
+ "TransactionResponse": function(node, obj) {
+ obj.insertIds = [];
+ obj.success = false;
+ this.readChildNodes(node, obj);
+ },
+ "TransactionSummary": function(node, obj) {
+ // this is a limited test of success
+ obj.success = true;
+ },
+ "InsertResults": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "Feature": function(node, container) {
+ var obj = {fids: []};
+ this.readChildNodes(node, obj);
+ container.insertIds.push(obj.fids[0]);
+ }
+ }, OpenLayers.Format.WFST.v1.prototype.readers["wfs"]),
+ "gml": OpenLayers.Format.GML.v3.prototype.readers["gml"],
+ "feature": OpenLayers.Format.GML.v3.prototype.readers["feature"],
+ "ogc": OpenLayers.Format.Filter.v1_1_0.prototype.readers["ogc"],
+ "ows": OpenLayers.Format.OWSCommon.v1_0_0.prototype.readers["ows"]
+ },
+
+ /**
+ * Property: writers
+ * As a compliment to the readers property, this structure contains public
+ * writing functions grouped by namespace alias and named like the
+ * node names they produce.
+ */
+ writers: {
+ "wfs": OpenLayers.Util.applyDefaults({
+ "GetFeature": function(options) {
+ var node = OpenLayers.Format.WFST.v1.prototype.writers["wfs"]["GetFeature"].apply(this, arguments);
+ options && this.setAttributes(node, {
+ resultType: options.resultType,
+ startIndex: options.startIndex,
+ count: options.count
+ });
+ return node;
+ },
+ "Query": function(options) {
+ options = OpenLayers.Util.extend({
+ featureNS: this.featureNS,
+ featurePrefix: this.featurePrefix,
+ featureType: this.featureType,
+ srsName: this.srsName
+ }, options);
+ var prefix = options.featurePrefix;
+ var node = this.createElementNSPlus("wfs:Query", {
+ attributes: {
+ typeName: (prefix ? prefix + ":" : "") +
+ options.featureType,
+ srsName: options.srsName
+ }
+ });
+ if(options.featureNS) {
+ node.setAttribute("xmlns:" + prefix, options.featureNS);
+ }
+ if(options.propertyNames) {
+ for(var i=0,len = options.propertyNames.length; i<len; i++) {
+ this.writeNode(
+ "wfs:PropertyName",
+ {property: options.propertyNames[i]},
+ node
+ );
+ }
+ }
+ if(options.filter) {
+ OpenLayers.Format.WFST.v1_1_0.prototype.setFilterProperty.call(this, options.filter);
+ this.writeNode("ogc:Filter", options.filter, node);
+ }
+ return node;
+ },
+ "PropertyName": function(obj) {
+ return this.createElementNSPlus("wfs:PropertyName", {
+ value: obj.property
+ });
+ }
+ }, OpenLayers.Format.WFST.v1.prototype.writers["wfs"]),
+ "gml": OpenLayers.Format.GML.v3.prototype.writers["gml"],
+ "feature": OpenLayers.Format.GML.v3.prototype.writers["feature"],
+ "ogc": OpenLayers.Format.Filter.v1_1_0.prototype.writers["ogc"]
+ },
+
+ CLASS_NAME: "OpenLayers.Format.WFST.v1_1_0"
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/WKT.js b/misc/openlayers/lib/OpenLayers/Format/WKT.js
new file mode 100644
index 0000000..a7a7b2e
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/WKT.js
@@ -0,0 +1,392 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format.js
+ * @requires OpenLayers/Feature/Vector.js
+ * @requires OpenLayers/Geometry/Point.js
+ * @requires OpenLayers/Geometry/MultiPoint.js
+ * @requires OpenLayers/Geometry/LineString.js
+ * @requires OpenLayers/Geometry/MultiLineString.js
+ * @requires OpenLayers/Geometry/Polygon.js
+ * @requires OpenLayers/Geometry/MultiPolygon.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WKT
+ * Class for reading and writing Well-Known Text. Create a new instance
+ * with the <OpenLayers.Format.WKT> constructor.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format>
+ */
+OpenLayers.Format.WKT = OpenLayers.Class(OpenLayers.Format, {
+
+ /**
+ * Constructor: OpenLayers.Format.WKT
+ * Create a new parser for WKT
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance
+ *
+ * Returns:
+ * {<OpenLayers.Format.WKT>} A new WKT parser.
+ */
+ initialize: function(options) {
+ this.regExes = {
+ 'typeStr': /^\s*(\w+)\s*\(\s*(.*)\s*\)\s*$/,
+ 'spaces': /\s+/,
+ 'parenComma': /\)\s*,\s*\(/,
+ 'doubleParenComma': /\)\s*\)\s*,\s*\(\s*\(/, // can't use {2} here
+ 'trimParens': /^\s*\(?(.*?)\)?\s*$/
+ };
+ OpenLayers.Format.prototype.initialize.apply(this, [options]);
+ },
+
+ /**
+ * APIMethod: read
+ * Deserialize a WKT string and return a vector feature or an
+ * array of vector features. Supports WKT for POINT, MULTIPOINT,
+ * LINESTRING, MULTILINESTRING, POLYGON, MULTIPOLYGON, and
+ * GEOMETRYCOLLECTION.
+ *
+ * Parameters:
+ * wkt - {String} A WKT string
+ *
+ * Returns:
+ * {<OpenLayers.Feature.Vector>|Array} A feature or array of features for
+ * GEOMETRYCOLLECTION WKT.
+ */
+ read: function(wkt) {
+ var features, type, str;
+ wkt = wkt.replace(/[\n\r]/g, " ");
+ var matches = this.regExes.typeStr.exec(wkt);
+ if(matches) {
+ type = matches[1].toLowerCase();
+ str = matches[2];
+ if(this.parse[type]) {
+ features = this.parse[type].apply(this, [str]);
+ }
+ if (this.internalProjection && this.externalProjection) {
+ if (features &&
+ features.CLASS_NAME == "OpenLayers.Feature.Vector") {
+ features.geometry.transform(this.externalProjection,
+ this.internalProjection);
+ } else if (features &&
+ type != "geometrycollection" &&
+ typeof features == "object") {
+ for (var i=0, len=features.length; i<len; i++) {
+ var component = features[i];
+ component.geometry.transform(this.externalProjection,
+ this.internalProjection);
+ }
+ }
+ }
+ }
+ return features;
+ },
+
+ /**
+ * APIMethod: write
+ * Serialize a feature or array of features into a WKT string.
+ *
+ * Parameters:
+ * features - {<OpenLayers.Feature.Vector>|Array} A feature or array of
+ * features
+ *
+ * Returns:
+ * {String} The WKT string representation of the input geometries
+ */
+ write: function(features) {
+ var collection, geometry, isCollection;
+ if (features.constructor == Array) {
+ collection = features;
+ isCollection = true;
+ } else {
+ collection = [features];
+ isCollection = false;
+ }
+ var pieces = [];
+ if (isCollection) {
+ pieces.push('GEOMETRYCOLLECTION(');
+ }
+ for (var i=0, len=collection.length; i<len; ++i) {
+ if (isCollection && i>0) {
+ pieces.push(',');
+ }
+ geometry = collection[i].geometry;
+ pieces.push(this.extractGeometry(geometry));
+ }
+ if (isCollection) {
+ pieces.push(')');
+ }
+ return pieces.join('');
+ },
+
+ /**
+ * Method: extractGeometry
+ * Entry point to construct the WKT for a single Geometry object.
+ *
+ * Parameters:
+ * geometry - {<OpenLayers.Geometry.Geometry>}
+ *
+ * Returns:
+ * {String} A WKT string of representing the geometry
+ */
+ extractGeometry: function(geometry) {
+ var type = geometry.CLASS_NAME.split('.')[2].toLowerCase();
+ if (!this.extract[type]) {
+ return null;
+ }
+ if (this.internalProjection && this.externalProjection) {
+ geometry = geometry.clone();
+ geometry.transform(this.internalProjection, this.externalProjection);
+ }
+ var wktType = type == 'collection' ? 'GEOMETRYCOLLECTION' : type.toUpperCase();
+ var data = wktType + '(' + this.extract[type].apply(this, [geometry]) + ')';
+ return data;
+ },
+
+ /**
+ * Object with properties corresponding to the geometry types.
+ * Property values are functions that do the actual data extraction.
+ */
+ extract: {
+ /**
+ * Return a space delimited string of point coordinates.
+ * @param {OpenLayers.Geometry.Point} point
+ * @returns {String} A string of coordinates representing the point
+ */
+ 'point': function(point) {
+ return point.x + ' ' + point.y;
+ },
+
+ /**
+ * Return a comma delimited string of point coordinates from a multipoint.
+ * @param {OpenLayers.Geometry.MultiPoint} multipoint
+ * @returns {String} A string of point coordinate strings representing
+ * the multipoint
+ */
+ 'multipoint': function(multipoint) {
+ var array = [];
+ for(var i=0, len=multipoint.components.length; i<len; ++i) {
+ array.push('(' +
+ this.extract.point.apply(this, [multipoint.components[i]]) +
+ ')');
+ }
+ return array.join(',');
+ },
+
+ /**
+ * Return a comma delimited string of point coordinates from a line.
+ * @param {OpenLayers.Geometry.LineString} linestring
+ * @returns {String} A string of point coordinate strings representing
+ * the linestring
+ */
+ 'linestring': function(linestring) {
+ var array = [];
+ for(var i=0, len=linestring.components.length; i<len; ++i) {
+ array.push(this.extract.point.apply(this, [linestring.components[i]]));
+ }
+ return array.join(',');
+ },
+
+ /**
+ * Return a comma delimited string of linestring strings from a multilinestring.
+ * @param {OpenLayers.Geometry.MultiLineString} multilinestring
+ * @returns {String} A string of of linestring strings representing
+ * the multilinestring
+ */
+ 'multilinestring': function(multilinestring) {
+ var array = [];
+ for(var i=0, len=multilinestring.components.length; i<len; ++i) {
+ array.push('(' +
+ this.extract.linestring.apply(this, [multilinestring.components[i]]) +
+ ')');
+ }
+ return array.join(',');
+ },
+
+ /**
+ * Return a comma delimited string of linear ring arrays from a polygon.
+ * @param {OpenLayers.Geometry.Polygon} polygon
+ * @returns {String} An array of linear ring arrays representing the polygon
+ */
+ 'polygon': function(polygon) {
+ var array = [];
+ for(var i=0, len=polygon.components.length; i<len; ++i) {
+ array.push('(' +
+ this.extract.linestring.apply(this, [polygon.components[i]]) +
+ ')');
+ }
+ return array.join(',');
+ },
+
+ /**
+ * Return an array of polygon arrays from a multipolygon.
+ * @param {OpenLayers.Geometry.MultiPolygon} multipolygon
+ * @returns {String} An array of polygon arrays representing
+ * the multipolygon
+ */
+ 'multipolygon': function(multipolygon) {
+ var array = [];
+ for(var i=0, len=multipolygon.components.length; i<len; ++i) {
+ array.push('(' +
+ this.extract.polygon.apply(this, [multipolygon.components[i]]) +
+ ')');
+ }
+ return array.join(',');
+ },
+
+ /**
+ * Return the WKT portion between 'GEOMETRYCOLLECTION(' and ')' for an <OpenLayers.Geometry.Collection>
+ * @param {OpenLayers.Geometry.Collection} collection
+ * @returns {String} internal WKT representation of the collection
+ */
+ 'collection': function(collection) {
+ var array = [];
+ for(var i=0, len=collection.components.length; i<len; ++i) {
+ array.push(this.extractGeometry.apply(this, [collection.components[i]]));
+ }
+ return array.join(',');
+ }
+
+ },
+
+ /**
+ * Object with properties corresponding to the geometry types.
+ * Property values are functions that do the actual parsing.
+ */
+ parse: {
+ /**
+ * Return point feature given a point WKT fragment.
+ * @param {String} str A WKT fragment representing the point
+ * @returns {OpenLayers.Feature.Vector} A point feature
+ * @private
+ */
+ 'point': function(str) {
+ var coords = OpenLayers.String.trim(str).split(this.regExes.spaces);
+ return new OpenLayers.Feature.Vector(
+ new OpenLayers.Geometry.Point(coords[0], coords[1])
+ );
+ },
+
+ /**
+ * Return a multipoint feature given a multipoint WKT fragment.
+ * @param {String} str A WKT fragment representing the multipoint
+ * @returns {OpenLayers.Feature.Vector} A multipoint feature
+ * @private
+ */
+ 'multipoint': function(str) {
+ var point;
+ var points = OpenLayers.String.trim(str).split(',');
+ var components = [];
+ for(var i=0, len=points.length; i<len; ++i) {
+ point = points[i].replace(this.regExes.trimParens, '$1');
+ components.push(this.parse.point.apply(this, [point]).geometry);
+ }
+ return new OpenLayers.Feature.Vector(
+ new OpenLayers.Geometry.MultiPoint(components)
+ );
+ },
+
+ /**
+ * Return a linestring feature given a linestring WKT fragment.
+ * @param {String} str A WKT fragment representing the linestring
+ * @returns {OpenLayers.Feature.Vector} A linestring feature
+ * @private
+ */
+ 'linestring': function(str) {
+ var points = OpenLayers.String.trim(str).split(',');
+ var components = [];
+ for(var i=0, len=points.length; i<len; ++i) {
+ components.push(this.parse.point.apply(this, [points[i]]).geometry);
+ }
+ return new OpenLayers.Feature.Vector(
+ new OpenLayers.Geometry.LineString(components)
+ );
+ },
+
+ /**
+ * Return a multilinestring feature given a multilinestring WKT fragment.
+ * @param {String} str A WKT fragment representing the multilinestring
+ * @returns {OpenLayers.Feature.Vector} A multilinestring feature
+ * @private
+ */
+ 'multilinestring': function(str) {
+ var line;
+ var lines = OpenLayers.String.trim(str).split(this.regExes.parenComma);
+ var components = [];
+ for(var i=0, len=lines.length; i<len; ++i) {
+ line = lines[i].replace(this.regExes.trimParens, '$1');
+ components.push(this.parse.linestring.apply(this, [line]).geometry);
+ }
+ return new OpenLayers.Feature.Vector(
+ new OpenLayers.Geometry.MultiLineString(components)
+ );
+ },
+
+ /**
+ * Return a polygon feature given a polygon WKT fragment.
+ * @param {String} str A WKT fragment representing the polygon
+ * @returns {OpenLayers.Feature.Vector} A polygon feature
+ * @private
+ */
+ 'polygon': function(str) {
+ var ring, linestring, linearring;
+ var rings = OpenLayers.String.trim(str).split(this.regExes.parenComma);
+ var components = [];
+ for(var i=0, len=rings.length; i<len; ++i) {
+ ring = rings[i].replace(this.regExes.trimParens, '$1');
+ linestring = this.parse.linestring.apply(this, [ring]).geometry;
+ linearring = new OpenLayers.Geometry.LinearRing(linestring.components);
+ components.push(linearring);
+ }
+ return new OpenLayers.Feature.Vector(
+ new OpenLayers.Geometry.Polygon(components)
+ );
+ },
+
+ /**
+ * Return a multipolygon feature given a multipolygon WKT fragment.
+ * @param {String} str A WKT fragment representing the multipolygon
+ * @returns {OpenLayers.Feature.Vector} A multipolygon feature
+ * @private
+ */
+ 'multipolygon': function(str) {
+ var polygon;
+ var polygons = OpenLayers.String.trim(str).split(this.regExes.doubleParenComma);
+ var components = [];
+ for(var i=0, len=polygons.length; i<len; ++i) {
+ polygon = polygons[i].replace(this.regExes.trimParens, '$1');
+ components.push(this.parse.polygon.apply(this, [polygon]).geometry);
+ }
+ return new OpenLayers.Feature.Vector(
+ new OpenLayers.Geometry.MultiPolygon(components)
+ );
+ },
+
+ /**
+ * Return an array of features given a geometrycollection WKT fragment.
+ * @param {String} str A WKT fragment representing the geometrycollection
+ * @returns {Array} An array of OpenLayers.Feature.Vector
+ * @private
+ */
+ 'geometrycollection': function(str) {
+ // separate components of the collection with |
+ str = str.replace(/,\s*([A-Za-z])/g, '|$1');
+ var wktArray = OpenLayers.String.trim(str).split('|');
+ var components = [];
+ for(var i=0, len=wktArray.length; i<len; ++i) {
+ components.push(OpenLayers.Format.WKT.prototype.read.apply(this,[wktArray[i]]));
+ }
+ return components;
+ }
+
+ },
+
+ CLASS_NAME: "OpenLayers.Format.WKT"
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/WMC.js b/misc/openlayers/lib/OpenLayers/Format/WMC.js
new file mode 100644
index 0000000..ded1b3a
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/WMC.js
@@ -0,0 +1,182 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Format/Context.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WMC
+ * Read and write Web Map Context documents.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.Context>
+ */
+OpenLayers.Format.WMC = OpenLayers.Class(OpenLayers.Format.Context, {
+
+ /**
+ * APIProperty: defaultVersion
+ * {String} Version number to assume if none found. Default is "1.1.0".
+ */
+ defaultVersion: "1.1.0",
+
+ /**
+ * Constructor: OpenLayers.Format.WMC
+ * Create a new parser for Web Map Context documents.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * Method: layerToContext
+ * Create a layer context object given a wms layer object.
+ *
+ * Parameters:
+ * layer - {<OpenLayers.Layer.WMS>} The layer.
+ *
+ * Returns:
+ * {Object} A layer context object.
+ */
+ layerToContext: function(layer) {
+ var parser = this.getParser();
+ var layerContext = {
+ queryable: layer.queryable,
+ visibility: layer.visibility,
+ name: layer.params["LAYERS"],
+ title: layer.name,
+ "abstract": layer.metadata["abstract"],
+ dataURL: layer.metadata.dataURL,
+ metadataURL: layer.metadataURL,
+ server: {
+ version: layer.params["VERSION"],
+ url: layer.url
+ },
+ maxExtent: layer.maxExtent,
+ transparent: layer.params["TRANSPARENT"],
+ numZoomLevels: layer.numZoomLevels,
+ units: layer.units,
+ isBaseLayer: layer.isBaseLayer,
+ opacity: layer.opacity == 1 ? undefined : layer.opacity,
+ displayInLayerSwitcher: layer.displayInLayerSwitcher,
+ singleTile: layer.singleTile,
+ tileSize: (layer.singleTile || !layer.tileSize) ?
+ undefined : {width: layer.tileSize.w, height: layer.tileSize.h},
+ minScale : (layer.options.resolutions ||
+ layer.options.scales ||
+ layer.options.maxResolution ||
+ layer.options.minScale) ?
+ layer.minScale : undefined,
+ maxScale : (layer.options.resolutions ||
+ layer.options.scales ||
+ layer.options.minResolution ||
+ layer.options.maxScale) ?
+ layer.maxScale : undefined,
+ formats: [],
+ styles: [],
+ srs: layer.srs,
+ dimensions: layer.dimensions
+ };
+
+
+ if (layer.metadata.servertitle) {
+ layerContext.server.title = layer.metadata.servertitle;
+ }
+
+ if (layer.metadata.formats && layer.metadata.formats.length > 0) {
+ for (var i=0, len=layer.metadata.formats.length; i<len; i++) {
+ var format = layer.metadata.formats[i];
+ layerContext.formats.push({
+ value: format.value,
+ current: (format.value == layer.params["FORMAT"])
+ });
+ }
+ } else {
+ layerContext.formats.push({
+ value: layer.params["FORMAT"],
+ current: true
+ });
+ }
+
+ if (layer.metadata.styles && layer.metadata.styles.length > 0) {
+ for (var i=0, len=layer.metadata.styles.length; i<len; i++) {
+ var style = layer.metadata.styles[i];
+ if ((style.href == layer.params["SLD"]) ||
+ (style.body == layer.params["SLD_BODY"]) ||
+ (style.name == layer.params["STYLES"])) {
+ style.current = true;
+ } else {
+ style.current = false;
+ }
+ layerContext.styles.push(style);
+ }
+ } else {
+ layerContext.styles.push({
+ href: layer.params["SLD"],
+ body: layer.params["SLD_BODY"],
+ name: layer.params["STYLES"] || parser.defaultStyleName,
+ title: parser.defaultStyleTitle,
+ current: true
+ });
+ }
+
+ return layerContext;
+ },
+
+ /**
+ * Method: toContext
+ * Create a context object free from layer given a map or a
+ * context object.
+ *
+ * Parameters:
+ * obj - {<OpenLayers.Map> | Object} The map or context.
+ *
+ * Returns:
+ * {Object} A context object.
+ */
+ toContext: function(obj) {
+ var context = {};
+ var layers = obj.layers;
+ if (obj.CLASS_NAME == "OpenLayers.Map") {
+ var metadata = obj.metadata || {};
+ context.size = obj.getSize();
+ context.bounds = obj.getExtent();
+ context.projection = obj.projection;
+ context.title = obj.title;
+ context.keywords = metadata.keywords;
+ context["abstract"] = metadata["abstract"];
+ context.logo = metadata.logo;
+ context.descriptionURL = metadata.descriptionURL;
+ context.contactInformation = metadata.contactInformation;
+ context.maxExtent = obj.maxExtent;
+ } else {
+ // copy all obj properties except the "layers" property
+ OpenLayers.Util.applyDefaults(context, obj);
+ if (context.layers != undefined) {
+ delete(context.layers);
+ }
+ }
+
+ if (context.layersContext == undefined) {
+ context.layersContext = [];
+ }
+
+ // let's convert layers into layersContext object (if any)
+ if (layers != undefined && OpenLayers.Util.isArray(layers)) {
+ for (var i=0, len=layers.length; i<len; i++) {
+ var layer = layers[i];
+ if (layer instanceof OpenLayers.Layer.WMS) {
+ context.layersContext.push(this.layerToContext(layer));
+ }
+ }
+ }
+ return context;
+ },
+
+ CLASS_NAME: "OpenLayers.Format.WMC"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/WMC/v1.js b/misc/openlayers/lib/OpenLayers/Format/WMC/v1.js
new file mode 100644
index 0000000..6c9a5c3
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/WMC/v1.js
@@ -0,0 +1,1267 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WMC.js
+ * @requires OpenLayers/Format/XML.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WMC.v1
+ * Superclass for WMC version 1 parsers.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.WMC.v1 = OpenLayers.Class(OpenLayers.Format.XML, {
+
+ /**
+ * Property: namespaces
+ * {Object} Mapping of namespace aliases to namespace URIs.
+ */
+ namespaces: {
+ ol: "http://openlayers.org/context",
+ wmc: "http://www.opengis.net/context",
+ sld: "http://www.opengis.net/sld",
+ xlink: "http://www.w3.org/1999/xlink",
+ xsi: "http://www.w3.org/2001/XMLSchema-instance"
+ },
+
+ /**
+ * Property: schemaLocation
+ * {String} Schema location for a particular minor version.
+ */
+ schemaLocation: "",
+
+ /**
+ * Method: getNamespacePrefix
+ * Get the namespace prefix for a given uri from the <namespaces> object.
+ *
+ * Returns:
+ * {String} A namespace prefix or null if none found.
+ */
+ getNamespacePrefix: function(uri) {
+ var prefix = null;
+ if(uri == null) {
+ prefix = this.namespaces[this.defaultPrefix];
+ } else {
+ for(prefix in this.namespaces) {
+ if(this.namespaces[prefix] == uri) {
+ break;
+ }
+ }
+ }
+ return prefix;
+ },
+
+ /**
+ * Property: defaultPrefix
+ */
+ defaultPrefix: "wmc",
+
+ /**
+ * Property: rootPrefix
+ * {String} Prefix on the root node that maps to the context namespace URI.
+ */
+ rootPrefix: null,
+
+ /**
+ * Property: defaultStyleName
+ * {String} Style name used if layer has no style param. Default is "".
+ */
+ defaultStyleName: "",
+
+ /**
+ * Property: defaultStyleTitle
+ * {String} Default style title. Default is "Default".
+ */
+ defaultStyleTitle: "Default",
+
+ /**
+ * Constructor: OpenLayers.Format.WMC.v1
+ * Instances of this class are not created directly. Use the
+ * <OpenLayers.Format.WMC> constructor instead.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+ initialize: function(options) {
+ OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+ },
+
+ /**
+ * Method: read
+ * Read capabilities data from a string, and return a list of layers.
+ *
+ * Parameters:
+ * data - {String} or {DOMElement} data to read/parse.
+ *
+ * Returns:
+ * {Array} List of named layers.
+ */
+ read: function(data) {
+ if(typeof data == "string") {
+ data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+ }
+ var root = data.documentElement;
+ this.rootPrefix = root.prefix;
+ var context = {
+ version: root.getAttribute("version")
+ };
+ this.runChildNodes(context, root);
+ return context;
+ },
+
+ /**
+ * Method: runChildNodes
+ */
+ runChildNodes: function(obj, node) {
+ var children = node.childNodes;
+ var childNode, processor, prefix, local;
+ for(var i=0, len=children.length; i<len; ++i) {
+ childNode = children[i];
+ if(childNode.nodeType == 1) {
+ prefix = this.getNamespacePrefix(childNode.namespaceURI);
+ local = childNode.nodeName.split(":").pop();
+ processor = this["read_" + prefix + "_" + local];
+ if(processor) {
+ processor.apply(this, [obj, childNode]);
+ }
+ }
+ }
+ },
+
+ /**
+ * Method: read_wmc_General
+ */
+ read_wmc_General: function(context, node) {
+ this.runChildNodes(context, node);
+ },
+
+ /**
+ * Method: read_wmc_BoundingBox
+ */
+ read_wmc_BoundingBox: function(context, node) {
+ context.projection = node.getAttribute("SRS");
+ context.bounds = new OpenLayers.Bounds(
+ node.getAttribute("minx"), node.getAttribute("miny"),
+ node.getAttribute("maxx"), node.getAttribute("maxy")
+ );
+ },
+
+ /**
+ * Method: read_wmc_LayerList
+ */
+ read_wmc_LayerList: function(context, node) {
+ // layersContext is an array containing info for each layer
+ context.layersContext = [];
+ this.runChildNodes(context, node);
+ },
+
+ /**
+ * Method: read_wmc_Layer
+ */
+ read_wmc_Layer: function(context, node) {
+ var layerContext = {
+ visibility: (node.getAttribute("hidden") != "1"),
+ queryable: (node.getAttribute("queryable") == "1"),
+ formats: [],
+ styles: [],
+ metadata: {}
+ };
+
+ this.runChildNodes(layerContext, node);
+ // set properties common to multiple objects on layer options/params
+ context.layersContext.push(layerContext);
+ },
+
+ /**
+ * Method: read_wmc_Extension
+ */
+ read_wmc_Extension: function(obj, node) {
+ this.runChildNodes(obj, node);
+ },
+
+ /**
+ * Method: read_ol_units
+ */
+ read_ol_units: function(layerContext, node) {
+ layerContext.units = this.getChildValue(node);
+ },
+
+ /**
+ * Method: read_ol_maxExtent
+ */
+ read_ol_maxExtent: function(obj, node) {
+ var bounds = new OpenLayers.Bounds(
+ node.getAttribute("minx"), node.getAttribute("miny"),
+ node.getAttribute("maxx"), node.getAttribute("maxy")
+ );
+ obj.maxExtent = bounds;
+ },
+
+ /**
+ * Method: read_ol_transparent
+ */
+ read_ol_transparent: function(layerContext, node) {
+ layerContext.transparent = this.getChildValue(node);
+ },
+
+ /**
+ * Method: read_ol_numZoomLevels
+ */
+ read_ol_numZoomLevels: function(layerContext, node) {
+ layerContext.numZoomLevels = parseInt(this.getChildValue(node));
+ },
+
+ /**
+ * Method: read_ol_opacity
+ */
+ read_ol_opacity: function(layerContext, node) {
+ layerContext.opacity = parseFloat(this.getChildValue(node));
+ },
+
+ /**
+ * Method: read_ol_singleTile
+ */
+ read_ol_singleTile: function(layerContext, node) {
+ layerContext.singleTile = (this.getChildValue(node) == "true");
+ },
+
+ /**
+ * Method: read_ol_tileSize
+ */
+ read_ol_tileSize: function(layerContext, node) {
+ var obj = {"width": node.getAttribute("width"), "height": node.getAttribute("height")};
+ layerContext.tileSize = obj;
+ },
+
+ /**
+ * Method: read_ol_isBaseLayer
+ */
+ read_ol_isBaseLayer: function(layerContext, node) {
+ layerContext.isBaseLayer = (this.getChildValue(node) == "true");
+ },
+
+ /**
+ * Method: read_ol_displayInLayerSwitcher
+ */
+ read_ol_displayInLayerSwitcher: function(layerContext, node) {
+ layerContext.displayInLayerSwitcher = (this.getChildValue(node) == "true");
+ },
+
+ /**
+ * Method: read_wmc_Server
+ */
+ read_wmc_Server: function(layerContext, node) {
+ layerContext.version = node.getAttribute("version");
+ layerContext.url = this.getOnlineResource_href(node);
+ layerContext.metadata.servertitle = node.getAttribute("title");
+ },
+
+ /**
+ * Method: read_wmc_FormatList
+ */
+ read_wmc_FormatList: function(layerContext, node) {
+ this.runChildNodes(layerContext, node);
+ },
+
+ /**
+ * Method: read_wmc_Format
+ */
+ read_wmc_Format: function(layerContext, node) {
+ var format = {
+ value: this.getChildValue(node)
+ };
+ if(node.getAttribute("current") == "1") {
+ format.current = true;
+ }
+ layerContext.formats.push(format);
+ },
+
+ /**
+ * Method: read_wmc_StyleList
+ */
+ read_wmc_StyleList: function(layerContext, node) {
+ this.runChildNodes(layerContext, node);
+ },
+
+ /**
+ * Method: read_wmc_Style
+ */
+ read_wmc_Style: function(layerContext, node) {
+ var style = {};
+ this.runChildNodes(style, node);
+ if(node.getAttribute("current") == "1") {
+ style.current = true;
+ }
+ layerContext.styles.push(style);
+ },
+
+ /**
+ * Method: read_wmc_SLD
+ */
+ read_wmc_SLD: function(style, node) {
+ this.runChildNodes(style, node);
+ // style either comes back with an href or a body property
+ },
+
+ /**
+ * Method: read_sld_StyledLayerDescriptor
+ */
+ read_sld_StyledLayerDescriptor: function(sld, node) {
+ var xml = OpenLayers.Format.XML.prototype.write.apply(this, [node]);
+ sld.body = xml;
+ },
+
+ /**
+ * Method: read_sld_FeatureTypeStyle
+ */
+ read_sld_FeatureTypeStyle: function(sld, node) {
+ var xml = OpenLayers.Format.XML.prototype.write.apply(this, [node]);
+ sld.body = xml;
+ },
+
+ /**
+ * Method: read_wmc_OnlineResource
+ */
+ read_wmc_OnlineResource: function(obj, node) {
+ obj.href = this.getAttributeNS(
+ node, this.namespaces.xlink, "href"
+ );
+ },
+
+ /**
+ * Method: read_wmc_Name
+ */
+ read_wmc_Name: function(obj, node) {
+ var name = this.getChildValue(node);
+ if(name) {
+ obj.name = name;
+ }
+ },
+
+ /**
+ * Method: read_wmc_Title
+ */
+ read_wmc_Title: function(obj, node) {
+ var title = this.getChildValue(node);
+ if(title) {
+ obj.title = title;
+ }
+ },
+
+ /**
+ * Method: read_wmc_MetadataURL
+ */
+ read_wmc_MetadataURL: function(layerContext, node) {
+ layerContext.metadataURL = this.getOnlineResource_href(node);
+ },
+
+ /**
+ * Method: read_wmc_KeywordList
+ */
+ read_wmc_KeywordList: function(context, node) {
+ context.keywords = [];
+ this.runChildNodes(context.keywords, node);
+ },
+
+ /**
+ * Method: read_wmc_Keyword
+ */
+ read_wmc_Keyword: function(keywords, node) {
+ keywords.push(this.getChildValue(node));
+ },
+
+ /**
+ * Method: read_wmc_Abstract
+ */
+ read_wmc_Abstract: function(obj, node) {
+ var abst = this.getChildValue(node);
+ if(abst) {
+ obj["abstract"] = abst;
+ }
+ },
+
+ /**
+ * Method: read_wmc_LogoURL
+ */
+ read_wmc_LogoURL: function(context, node) {
+ context.logo = {
+ width: node.getAttribute("width"),
+ height: node.getAttribute("height"),
+ format: node.getAttribute("format"),
+ href: this.getOnlineResource_href(node)
+ };
+ },
+
+ /**
+ * Method: read_wmc_DescriptionURL
+ */
+ read_wmc_DescriptionURL: function(context, node) {
+ context.descriptionURL = this.getOnlineResource_href(node);
+ },
+
+ /**
+ * Method: read_wmc_ContactInformation
+ */
+ read_wmc_ContactInformation: function(obj, node) {
+ var contact = {};
+ this.runChildNodes(contact, node);
+ obj.contactInformation = contact;
+ },
+
+ /**
+ * Method: read_wmc_ContactPersonPrimary
+ */
+ read_wmc_ContactPersonPrimary: function(contact, node) {
+ var personPrimary = {};
+ this.runChildNodes(personPrimary, node);
+ contact.personPrimary = personPrimary;
+ },
+
+ /**
+ * Method: read_wmc_ContactPerson
+ */
+ read_wmc_ContactPerson: function(primaryPerson, node) {
+ var person = this.getChildValue(node);
+ if (person) {
+ primaryPerson.person = person;
+ }
+ },
+
+ /**
+ * Method: read_wmc_ContactOrganization
+ */
+ read_wmc_ContactOrganization: function(primaryPerson, node) {
+ var organization = this.getChildValue(node);
+ if (organization) {
+ primaryPerson.organization = organization;
+ }
+ },
+
+ /**
+ * Method: read_wmc_ContactPosition
+ */
+ read_wmc_ContactPosition: function(contact, node) {
+ var position = this.getChildValue(node);
+ if (position) {
+ contact.position = position;
+ }
+ },
+
+ /**
+ * Method: read_wmc_ContactAddress
+ */
+ read_wmc_ContactAddress: function(contact, node) {
+ var contactAddress = {};
+ this.runChildNodes(contactAddress, node);
+ contact.contactAddress = contactAddress;
+ },
+
+ /**
+ * Method: read_wmc_AddressType
+ */
+ read_wmc_AddressType: function(contactAddress, node) {
+ var type = this.getChildValue(node);
+ if (type) {
+ contactAddress.type = type;
+ }
+ },
+
+ /**
+ * Method: read_wmc_Address
+ */
+ read_wmc_Address: function(contactAddress, node) {
+ var address = this.getChildValue(node);
+ if (address) {
+ contactAddress.address = address;
+ }
+ },
+
+ /**
+ * Method: read_wmc_City
+ */
+ read_wmc_City: function(contactAddress, node) {
+ var city = this.getChildValue(node);
+ if (city) {
+ contactAddress.city = city;
+ }
+ },
+
+ /**
+ * Method: read_wmc_StateOrProvince
+ */
+ read_wmc_StateOrProvince: function(contactAddress, node) {
+ var stateOrProvince = this.getChildValue(node);
+ if (stateOrProvince) {
+ contactAddress.stateOrProvince = stateOrProvince;
+ }
+ },
+
+ /**
+ * Method: read_wmc_PostCode
+ */
+ read_wmc_PostCode: function(contactAddress, node) {
+ var postcode = this.getChildValue(node);
+ if (postcode) {
+ contactAddress.postcode = postcode;
+ }
+ },
+
+ /**
+ * Method: read_wmc_Country
+ */
+ read_wmc_Country: function(contactAddress, node) {
+ var country = this.getChildValue(node);
+ if (country) {
+ contactAddress.country = country;
+ }
+ },
+
+ /**
+ * Method: read_wmc_ContactVoiceTelephone
+ */
+ read_wmc_ContactVoiceTelephone: function(contact, node) {
+ var phone = this.getChildValue(node);
+ if (phone) {
+ contact.phone = phone;
+ }
+ },
+
+ /**
+ * Method: read_wmc_ContactFacsimileTelephone
+ */
+ read_wmc_ContactFacsimileTelephone: function(contact, node) {
+ var fax = this.getChildValue(node);
+ if (fax) {
+ contact.fax = fax;
+ }
+ },
+
+ /**
+ * Method: read_wmc_ContactElectronicMailAddress
+ */
+ read_wmc_ContactElectronicMailAddress: function(contact, node) {
+ var email = this.getChildValue(node);
+ if (email) {
+ contact.email = email;
+ }
+ },
+
+ /**
+ * Method: read_wmc_DataURL
+ */
+ read_wmc_DataURL: function(layerContext, node) {
+ layerContext.dataURL = this.getOnlineResource_href(node);
+ },
+
+ /**
+ * Method: read_wmc_LegendURL
+ */
+ read_wmc_LegendURL: function(style, node) {
+ var legend = {
+ width: node.getAttribute('width'),
+ height: node.getAttribute('height'),
+ format: node.getAttribute('format'),
+ href: this.getOnlineResource_href(node)
+ };
+ style.legend = legend;
+ },
+
+ /**
+ * Method: read_wmc_DimensionList
+ */
+ read_wmc_DimensionList: function(layerContext, node) {
+ layerContext.dimensions = {};
+ this.runChildNodes(layerContext.dimensions, node);
+ },
+ /**
+ * Method: read_wmc_Dimension
+ */
+ read_wmc_Dimension: function(dimensions, node) {
+ var name = node.getAttribute("name").toLowerCase();
+
+ var dim = {
+ name: name,
+ units: node.getAttribute("units") || "",
+ unitSymbol: node.getAttribute("unitSymbol") || "",
+ userValue: node.getAttribute("userValue") || "",
+ nearestValue: node.getAttribute("nearestValue") === "1",
+ multipleValues: node.getAttribute("multipleValues") === "1",
+ current: node.getAttribute("current") === "1",
+ "default": node.getAttribute("default") || ""
+ };
+ var values = this.getChildValue(node);
+ dim.values = values.split(",");
+
+ dimensions[dim.name] = dim;
+ },
+
+ /**
+ * Method: write
+ *
+ * Parameters:
+ * context - {Object} An object representing the map context.
+ * options - {Object} Optional object.
+ *
+ * Returns:
+ * {String} A WMC document string.
+ */
+ write: function(context, options) {
+ var root = this.createElementDefaultNS("ViewContext");
+ this.setAttributes(root, {
+ version: this.VERSION,
+ id: (options && typeof options.id == "string") ?
+ options.id :
+ OpenLayers.Util.createUniqueID("OpenLayers_Context_")
+ });
+
+ // add schemaLocation attribute
+ this.setAttributeNS(
+ root, this.namespaces.xsi,
+ "xsi:schemaLocation", this.schemaLocation
+ );
+
+ // required General element
+ root.appendChild(this.write_wmc_General(context));
+
+ // required LayerList element
+ root.appendChild(this.write_wmc_LayerList(context));
+
+ return OpenLayers.Format.XML.prototype.write.apply(this, [root]);
+ },
+
+ /**
+ * Method: createElementDefaultNS
+ * Shorthand for createElementNS with namespace from <defaultPrefix>.
+ * Can optionally be used to set attributes and a text child value.
+ *
+ * Parameters:
+ * name - {String} The qualified node name.
+ * childValue - {String} Optional value for text child node.
+ * attributes - {Object} Optional object representing attributes.
+ *
+ * Returns:
+ * {Element} An element node.
+ */
+ createElementDefaultNS: function(name, childValue, attributes) {
+ var node = this.createElementNS(
+ this.namespaces[this.defaultPrefix],
+ name
+ );
+ if(childValue) {
+ node.appendChild(this.createTextNode(childValue));
+ }
+ if(attributes) {
+ this.setAttributes(node, attributes);
+ }
+ return node;
+ },
+
+ /**
+ * Method: setAttributes
+ * Set multiple attributes given key value pairs from an object.
+ *
+ * Parameters:
+ * node - {Element} An element node.
+ * obj - {Object} An object whose properties represent attribute names and
+ * values represent attribute values.
+ */
+ setAttributes: function(node, obj) {
+ var value;
+ for(var name in obj) {
+ value = obj[name].toString();
+ if(value.match(/[A-Z]/)) {
+ // safari lowercases attributes with setAttribute
+ this.setAttributeNS(node, null, name, value);
+ } else {
+ node.setAttribute(name, value);
+ }
+ }
+ },
+
+ /**
+ * Method: write_wmc_General
+ * Create a General node given an context object.
+ *
+ * Parameters:
+ * context - {Object} Context object.
+ *
+ * Returns:
+ * {Element} A WMC General element node.
+ */
+ write_wmc_General: function(context) {
+ var node = this.createElementDefaultNS("General");
+
+ // optional Window element
+ if(context.size) {
+ node.appendChild(this.createElementDefaultNS(
+ "Window", null,
+ {
+ width: context.size.w,
+ height: context.size.h
+ }
+ ));
+ }
+
+ // required BoundingBox element
+ var bounds = context.bounds;
+ node.appendChild(this.createElementDefaultNS(
+ "BoundingBox", null,
+ {
+ minx: bounds.left.toPrecision(18),
+ miny: bounds.bottom.toPrecision(18),
+ maxx: bounds.right.toPrecision(18),
+ maxy: bounds.top.toPrecision(18),
+ SRS: context.projection
+ }
+ ));
+
+ // required Title element
+ node.appendChild(this.createElementDefaultNS(
+ "Title", context.title
+ ));
+
+ // optional KeywordList element
+ if (context.keywords) {
+ node.appendChild(this.write_wmc_KeywordList(context.keywords));
+ }
+
+ // optional Abstract element
+ if (context["abstract"]) {
+ node.appendChild(this.createElementDefaultNS(
+ "Abstract", context["abstract"]
+ ));
+ }
+
+ // Optional LogoURL element
+ if (context.logo) {
+ node.appendChild(this.write_wmc_URLType("LogoURL", context.logo.href, context.logo));
+ }
+
+ // Optional DescriptionURL element
+ if (context.descriptionURL) {
+ node.appendChild(this.write_wmc_URLType("DescriptionURL", context.descriptionURL));
+ }
+
+ // Optional ContactInformation element
+ if (context.contactInformation) {
+ node.appendChild(this.write_wmc_ContactInformation(context.contactInformation));
+ }
+
+ // OpenLayers specific map properties
+ node.appendChild(this.write_ol_MapExtension(context));
+
+ return node;
+ },
+
+ /**
+ * Method: write_wmc_KeywordList
+ */
+ write_wmc_KeywordList: function(keywords) {
+ var node = this.createElementDefaultNS("KeywordList");
+
+ for (var i=0, len=keywords.length; i<len; i++) {
+ node.appendChild(this.createElementDefaultNS(
+ "Keyword", keywords[i]
+ ));
+ }
+ return node;
+ },
+ /**
+ * Method: write_wmc_ContactInformation
+ */
+ write_wmc_ContactInformation: function(contact) {
+ var node = this.createElementDefaultNS("ContactInformation");
+
+ if (contact.personPrimary) {
+ node.appendChild(this.write_wmc_ContactPersonPrimary(contact.personPrimary));
+ }
+ if (contact.position) {
+ node.appendChild(this.createElementDefaultNS(
+ "ContactPosition", contact.position
+ ));
+ }
+ if (contact.contactAddress) {
+ node.appendChild(this.write_wmc_ContactAddress(contact.contactAddress));
+ }
+ if (contact.phone) {
+ node.appendChild(this.createElementDefaultNS(
+ "ContactVoiceTelephone", contact.phone
+ ));
+ }
+ if (contact.fax) {
+ node.appendChild(this.createElementDefaultNS(
+ "ContactFacsimileTelephone", contact.fax
+ ));
+ }
+ if (contact.email) {
+ node.appendChild(this.createElementDefaultNS(
+ "ContactElectronicMailAddress", contact.email
+ ));
+ }
+ return node;
+ },
+
+ /**
+ * Method: write_wmc_ContactPersonPrimary
+ */
+ write_wmc_ContactPersonPrimary: function(personPrimary) {
+ var node = this.createElementDefaultNS("ContactPersonPrimary");
+ if (personPrimary.person) {
+ node.appendChild(this.createElementDefaultNS(
+ "ContactPerson", personPrimary.person
+ ));
+ }
+ if (personPrimary.organization) {
+ node.appendChild(this.createElementDefaultNS(
+ "ContactOrganization", personPrimary.organization
+ ));
+ }
+ return node;
+ },
+
+ /**
+ * Method: write_wmc_ContactAddress
+ */
+ write_wmc_ContactAddress: function(contactAddress) {
+ var node = this.createElementDefaultNS("ContactAddress");
+ if (contactAddress.type) {
+ node.appendChild(this.createElementDefaultNS(
+ "AddressType", contactAddress.type
+ ));
+ }
+ if (contactAddress.address) {
+ node.appendChild(this.createElementDefaultNS(
+ "Address", contactAddress.address
+ ));
+ }
+ if (contactAddress.city) {
+ node.appendChild(this.createElementDefaultNS(
+ "City", contactAddress.city
+ ));
+ }
+ if (contactAddress.stateOrProvince) {
+ node.appendChild(this.createElementDefaultNS(
+ "StateOrProvince", contactAddress.stateOrProvince
+ ));
+ }
+ if (contactAddress.postcode) {
+ node.appendChild(this.createElementDefaultNS(
+ "PostCode", contactAddress.postcode
+ ));
+ }
+ if (contactAddress.country) {
+ node.appendChild(this.createElementDefaultNS(
+ "Country", contactAddress.country
+ ));
+ }
+ return node;
+ },
+
+ /**
+ * Method: write_ol_MapExtension
+ */
+ write_ol_MapExtension: function(context) {
+ var node = this.createElementDefaultNS("Extension");
+
+ var bounds = context.maxExtent;
+ if(bounds) {
+ var maxExtent = this.createElementNS(
+ this.namespaces.ol, "ol:maxExtent"
+ );
+ this.setAttributes(maxExtent, {
+ minx: bounds.left.toPrecision(18),
+ miny: bounds.bottom.toPrecision(18),
+ maxx: bounds.right.toPrecision(18),
+ maxy: bounds.top.toPrecision(18)
+ });
+ node.appendChild(maxExtent);
+ }
+
+ return node;
+ },
+
+ /**
+ * Method: write_wmc_LayerList
+ * Create a LayerList node given an context object.
+ *
+ * Parameters:
+ * context - {Object} Context object.
+ *
+ * Returns:
+ * {Element} A WMC LayerList element node.
+ */
+ write_wmc_LayerList: function(context) {
+ var list = this.createElementDefaultNS("LayerList");
+
+ for(var i=0, len=context.layersContext.length; i<len; ++i) {
+ list.appendChild(this.write_wmc_Layer(context.layersContext[i]));
+ }
+
+ return list;
+ },
+
+ /**
+ * Method: write_wmc_Layer
+ * Create a Layer node given a layer context object.
+ *
+ * Parameters:
+ * context - {Object} A layer context object.}
+ *
+ * Returns:
+ * {Element} A WMC Layer element node.
+ */
+ write_wmc_Layer: function(context) {
+ var node = this.createElementDefaultNS(
+ "Layer", null, {
+ queryable: context.queryable ? "1" : "0",
+ hidden: context.visibility ? "0" : "1"
+ }
+ );
+
+ // required Server element
+ node.appendChild(this.write_wmc_Server(context));
+
+ // required Name element
+ node.appendChild(this.createElementDefaultNS(
+ "Name", context.name
+ ));
+
+ // required Title element
+ node.appendChild(this.createElementDefaultNS(
+ "Title", context.title
+ ));
+
+ // optional Abstract element
+ if (context["abstract"]) {
+ node.appendChild(this.createElementDefaultNS(
+ "Abstract", context["abstract"]
+ ));
+ }
+
+ // optional DataURL element
+ if (context.dataURL) {
+ node.appendChild(this.write_wmc_URLType("DataURL", context.dataURL));
+ }
+
+ // optional MetadataURL element
+ if (context.metadataURL) {
+ node.appendChild(this.write_wmc_URLType("MetadataURL", context.metadataURL));
+ }
+
+ return node;
+ },
+
+ /**
+ * Method: write_wmc_LayerExtension
+ * Add OpenLayers specific layer parameters to an Extension element.
+ *
+ * Parameters:
+ * context - {Object} A layer context object.
+ *
+ * Returns:
+ * {Element} A WMC Extension element (for a layer).
+ */
+ write_wmc_LayerExtension: function(context) {
+ var node = this.createElementDefaultNS("Extension");
+
+ var bounds = context.maxExtent;
+ var maxExtent = this.createElementNS(
+ this.namespaces.ol, "ol:maxExtent"
+ );
+ this.setAttributes(maxExtent, {
+ minx: bounds.left.toPrecision(18),
+ miny: bounds.bottom.toPrecision(18),
+ maxx: bounds.right.toPrecision(18),
+ maxy: bounds.top.toPrecision(18)
+ });
+ node.appendChild(maxExtent);
+
+ if (context.tileSize && !context.singleTile) {
+ var size = this.createElementNS(
+ this.namespaces.ol, "ol:tileSize"
+ );
+ this.setAttributes(size, context.tileSize);
+ node.appendChild(size);
+ }
+
+ var properties = [
+ "transparent", "numZoomLevels", "units", "isBaseLayer",
+ "opacity", "displayInLayerSwitcher", "singleTile"
+ ];
+ var child;
+ for(var i=0, len=properties.length; i<len; ++i) {
+ child = this.createOLPropertyNode(context, properties[i]);
+ if(child) {
+ node.appendChild(child);
+ }
+ }
+
+ return node;
+ },
+
+ /**
+ * Method: createOLPropertyNode
+ * Create a node representing an OpenLayers property. If the property is
+ * null or undefined, null will be returned.
+ *
+ * Parameters:
+ * obj - {Object} An object.
+ * prop - {String} A property.
+ *
+ * Returns:
+ * {Element} A property node.
+ */
+ createOLPropertyNode: function(obj, prop) {
+ var node = null;
+ if(obj[prop] != null) {
+ node = this.createElementNS(this.namespaces.ol, "ol:" + prop);
+ node.appendChild(this.createTextNode(obj[prop].toString()));
+ }
+ return node;
+ },
+
+ /**
+ * Method: write_wmc_Server
+ * Create a Server node given a layer context object.
+ *
+ * Parameters:
+ * context - {Object} Layer context object.
+ *
+ * Returns:
+ * {Element} A WMC Server element node.
+ */
+ write_wmc_Server: function(context) {
+ var server = context.server;
+ var node = this.createElementDefaultNS("Server");
+ var attributes = {
+ service: "OGC:WMS",
+ version: server.version
+ };
+ if (server.title) {
+ attributes.title = server.title;
+ }
+ this.setAttributes(node, attributes);
+
+ // required OnlineResource element
+ node.appendChild(this.write_wmc_OnlineResource(server.url));
+
+ return node;
+ },
+
+ /**
+ * Method: write_wmc_URLType
+ * Create a LogoURL/DescriptionURL/MetadataURL/DataURL/LegendURL node given a object and elementName.
+ *
+ * Parameters:
+ * elName - {String} Name of element (LogoURL/DescriptionURL/MetadataURL/LegendURL)
+ * url - {String} URL string value
+ * attr - {Object} Optional attributes (width, height, format)
+ *
+ * Returns:
+ * {Element} A WMC element node.
+ */
+ write_wmc_URLType: function(elName, url, attr) {
+ var node = this.createElementDefaultNS(elName);
+ node.appendChild(this.write_wmc_OnlineResource(url));
+ if (attr) {
+ var optionalAttributes = ["width", "height", "format"];
+ for (var i=0; i<optionalAttributes.length; i++) {
+ if (optionalAttributes[i] in attr) {
+ node.setAttribute(optionalAttributes[i], attr[optionalAttributes[i]]);
+ }
+ }
+ }
+ return node;
+ },
+
+ /**
+ * Method: write_wmc_DimensionList
+ */
+ write_wmc_DimensionList: function(context) {
+ var node = this.createElementDefaultNS("DimensionList");
+ var required_attributes = {
+ name: true,
+ units: true,
+ unitSymbol: true,
+ userValue: true
+ };
+ for (var dim in context.dimensions) {
+ var attributes = {};
+ var dimension = context.dimensions[dim];
+ for (var name in dimension) {
+ if (typeof dimension[name] == "boolean") {
+ attributes[name] = Number(dimension[name]);
+ } else {
+ attributes[name] = dimension[name];
+ }
+ }
+ var values = "";
+ if (attributes.values) {
+ values = attributes.values.join(",");
+ delete attributes.values;
+ }
+
+ node.appendChild(this.createElementDefaultNS(
+ "Dimension", values, attributes
+ ));
+ }
+ return node;
+ },
+
+ /**
+ * Method: write_wmc_FormatList
+ * Create a FormatList node given a layer context.
+ *
+ * Parameters:
+ * context - {Object} Layer context object.
+ *
+ * Returns:
+ * {Element} A WMC FormatList element node.
+ */
+ write_wmc_FormatList: function(context) {
+ var node = this.createElementDefaultNS("FormatList");
+ for (var i=0, len=context.formats.length; i<len; i++) {
+ var format = context.formats[i];
+ node.appendChild(this.createElementDefaultNS(
+ "Format",
+ format.value,
+ (format.current && format.current == true) ?
+ {current: "1"} : null
+ ));
+ }
+
+ return node;
+ },
+
+ /**
+ * Method: write_wmc_StyleList
+ * Create a StyleList node given a layer context.
+ *
+ * Parameters:
+ * layer - {Object} Layer context object.
+ *
+ * Returns:
+ * {Element} A WMC StyleList element node.
+ */
+ write_wmc_StyleList: function(layer) {
+ var node = this.createElementDefaultNS("StyleList");
+
+ var styles = layer.styles;
+ if (styles && OpenLayers.Util.isArray(styles)) {
+ var sld;
+ for (var i=0, len=styles.length; i<len; i++) {
+ var s = styles[i];
+ // three style types to consider
+ // [1] linked SLD
+ // [2] inline SLD
+ // [3] named style
+ // running child nodes always gets name, optionally gets href or body
+ var style = this.createElementDefaultNS(
+ "Style",
+ null,
+ (s.current && s.current == true) ?
+ {current: "1"} : null
+ );
+ if(s.href) { // [1]
+ sld = this.createElementDefaultNS("SLD");
+ // Name is optional.
+ if (s.name) {
+ sld.appendChild(this.createElementDefaultNS("Name", s.name));
+ }
+ // Title is optional.
+ if (s.title) {
+ sld.appendChild(this.createElementDefaultNS("Title", s.title));
+ }
+ // LegendURL is optional
+ if (s.legend) {
+ sld.appendChild(this.write_wmc_URLType("LegendURL", s.legend.href, s.legend));
+ }
+
+ var link = this.write_wmc_OnlineResource(s.href);
+ sld.appendChild(link);
+ style.appendChild(sld);
+ } else if(s.body) { // [2]
+ sld = this.createElementDefaultNS("SLD");
+ // Name is optional.
+ if (s.name) {
+ sld.appendChild(this.createElementDefaultNS("Name", s.name));
+ }
+ // Title is optional.
+ if (s.title) {
+ sld.appendChild(this.createElementDefaultNS("Title", s.title));
+ }
+ // LegendURL is optional
+ if (s.legend) {
+ sld.appendChild(this.write_wmc_URLType("LegendURL", s.legend.href, s.legend));
+ }
+
+ // read in body as xml doc - assume proper namespace declarations
+ var doc = OpenLayers.Format.XML.prototype.read.apply(this, [s.body]);
+ // append to StyledLayerDescriptor node
+ var imported = doc.documentElement;
+ if(sld.ownerDocument && sld.ownerDocument.importNode) {
+ imported = sld.ownerDocument.importNode(imported, true);
+ }
+ sld.appendChild(imported);
+ style.appendChild(sld);
+ } else { // [3]
+ // both Name and Title are required.
+ style.appendChild(this.createElementDefaultNS("Name", s.name));
+ style.appendChild(this.createElementDefaultNS("Title", s.title));
+ // Abstract is optional
+ if (s['abstract']) { // abstract is a js keyword
+ style.appendChild(this.createElementDefaultNS(
+ "Abstract", s['abstract']
+ ));
+ }
+ // LegendURL is optional
+ if (s.legend) {
+ style.appendChild(this.write_wmc_URLType("LegendURL", s.legend.href, s.legend));
+ }
+ }
+ node.appendChild(style);
+ }
+ }
+
+ return node;
+ },
+
+ /**
+ * Method: write_wmc_OnlineResource
+ * Create an OnlineResource node given a URL.
+ *
+ * Parameters:
+ * href - {String} URL for the resource.
+ *
+ * Returns:
+ * {Element} A WMC OnlineResource element node.
+ */
+ write_wmc_OnlineResource: function(href) {
+ var node = this.createElementDefaultNS("OnlineResource");
+ this.setAttributeNS(node, this.namespaces.xlink, "xlink:type", "simple");
+ this.setAttributeNS(node, this.namespaces.xlink, "xlink:href", href);
+ return node;
+ },
+
+ /**
+ * Method: getOnlineResource_href
+ */
+ getOnlineResource_href: function(node) {
+ var object = {};
+ var links = node.getElementsByTagName("OnlineResource");
+ if(links.length > 0) {
+ this.read_wmc_OnlineResource(object, links[0]);
+ }
+ return object.href;
+ },
+
+
+ CLASS_NAME: "OpenLayers.Format.WMC.v1"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/WMC/v1_0_0.js b/misc/openlayers/lib/OpenLayers/Format/WMC/v1_0_0.js
new file mode 100644
index 0000000..ace0d95
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/WMC/v1_0_0.js
@@ -0,0 +1,104 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WMC/v1.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WMC.v1_0_0
+ * Read and write WMC version 1.0.0.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.WMC.v1>
+ */
+OpenLayers.Format.WMC.v1_0_0 = OpenLayers.Class(
+ OpenLayers.Format.WMC.v1, {
+
+ /**
+ * Constant: VERSION
+ * {String} 1.0.0
+ */
+ VERSION: "1.0.0",
+
+ /**
+ * Property: schemaLocation
+ * {String} http://www.opengis.net/context
+ * http://schemas.opengis.net/context/1.0.0/context.xsd
+ */
+ schemaLocation: "http://www.opengis.net/context http://schemas.opengis.net/context/1.0.0/context.xsd",
+
+ /**
+ * Constructor: OpenLayers.Format.WMC.v1_0_0
+ * Instances of this class are not created directly. Use the
+ * <OpenLayers.Format.WMC> constructor instead.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+ initialize: function(options) {
+ OpenLayers.Format.WMC.v1.prototype.initialize.apply(
+ this, [options]
+ );
+ },
+
+ /**
+ * Method: read_wmc_SRS
+ */
+ read_wmc_SRS: function(layerContext, node) {
+ var srs = this.getChildValue(node);
+ if (typeof layerContext.projections != "object") {
+ layerContext.projections = {};
+ }
+ var values = srs.split(/ +/);
+ for (var i=0, len=values.length; i<len; i++) {
+ layerContext.projections[values[i]] = true;
+ }
+ },
+
+ /**
+ * Method: write_wmc_Layer
+ * Create a Layer node given a layer context object. This method adds
+ * elements specific to version 1.0.0.
+ *
+ * Parameters:
+ * context - {Object} A layer context object.}
+ *
+ * Returns:
+ * {Element} A WMC Layer element node.
+ */
+ write_wmc_Layer: function(context) {
+ var node = OpenLayers.Format.WMC.v1.prototype.write_wmc_Layer.apply(
+ this, [context]
+ );
+
+ // optional SRS element(s)
+ if (context.srs) {
+ var projections = [];
+ for(var name in context.srs) {
+ projections.push(name);
+ }
+ node.appendChild(this.createElementDefaultNS("SRS", projections.join(" ")));
+ }
+
+ // optional FormatList element
+ node.appendChild(this.write_wmc_FormatList(context));
+
+ // optional StyleList element
+ node.appendChild(this.write_wmc_StyleList(context));
+
+ // optional DimensionList element
+ if (context.dimensions) {
+ node.appendChild(this.write_wmc_DimensionList(context));
+ }
+
+ // OpenLayers specific properties go in an Extension element
+ node.appendChild(this.write_wmc_LayerExtension(context));
+ },
+
+ CLASS_NAME: "OpenLayers.Format.WMC.v1_0_0"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/WMC/v1_1_0.js b/misc/openlayers/lib/OpenLayers/Format/WMC/v1_1_0.js
new file mode 100644
index 0000000..e5efc3e
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/WMC/v1_1_0.js
@@ -0,0 +1,149 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WMC/v1.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WMC.v1_1_0
+ * Read and write WMC version 1.1.0.
+ *
+ * Differences between 1.1.0 and 1.0.0:
+ * - 1.1.0 Layers have optional sld:MinScaleDenominator and
+ * sld:MaxScaleDenominator
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.WMC.v1>
+ */
+OpenLayers.Format.WMC.v1_1_0 = OpenLayers.Class(
+ OpenLayers.Format.WMC.v1, {
+
+ /**
+ * Constant: VERSION
+ * {String} 1.1.0
+ */
+ VERSION: "1.1.0",
+
+ /**
+ * Property: schemaLocation
+ * {String} http://www.opengis.net/context
+ * http://schemas.opengis.net/context/1.1.0/context.xsd
+ */
+ schemaLocation: "http://www.opengis.net/context http://schemas.opengis.net/context/1.1.0/context.xsd",
+
+ /**
+ * Constructor: OpenLayers.Format.WMC.v1_1_0
+ * Instances of this class are not created directly. Use the
+ * <OpenLayers.Format.WMC> constructor instead.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+ initialize: function(options) {
+ OpenLayers.Format.WMC.v1.prototype.initialize.apply(
+ this, [options]
+ );
+ },
+
+ /**
+ * Method: read_sld_MinScaleDenominator
+ * Read a sld:MinScaleDenominator node.
+ *
+ * Parameters:
+ * layerContext - {Object} An object representing a layer.
+ * node - {Element} An element node.
+ */
+ read_sld_MinScaleDenominator: function(layerContext, node) {
+ var minScaleDenominator = parseFloat(this.getChildValue(node));
+ if (minScaleDenominator > 0) {
+ layerContext.maxScale = minScaleDenominator;
+ }
+ },
+
+ /**
+ * Method: read_sld_MaxScaleDenominator
+ * Read a sld:MaxScaleDenominator node.
+ *
+ * Parameters:
+ * layerContext - {Object} An object representing a layer.
+ * node - {Element} An element node.
+ */
+ read_sld_MaxScaleDenominator: function(layerContext, node) {
+ layerContext.minScale = parseFloat(this.getChildValue(node));
+ },
+
+ /**
+ * Method: read_wmc_SRS
+ */
+ read_wmc_SRS: function(layerContext, node) {
+ if (! ("srs" in layerContext)) {
+ layerContext.srs = {};
+ }
+ layerContext.srs[this.getChildValue(node)] = true;
+ },
+
+ /**
+ * Method: write_wmc_Layer
+ * Create a Layer node given a layer context object. This method adds
+ * elements specific to version 1.1.0.
+ *
+ * Parameters:
+ * context - {Object} A layer context object.}
+ *
+ * Returns:
+ * {Element} A WMC Layer element node.
+ */
+ write_wmc_Layer: function(context) {
+ var node = OpenLayers.Format.WMC.v1.prototype.write_wmc_Layer.apply(
+ this, [context]
+ );
+
+ // min/max scale denominator elements go before the 4th element in v1
+ if(context.maxScale) {
+ var minSD = this.createElementNS(
+ this.namespaces.sld, "sld:MinScaleDenominator"
+ );
+ minSD.appendChild(this.createTextNode(context.maxScale.toPrecision(16)));
+ node.appendChild(minSD);
+ }
+
+ if(context.minScale) {
+ var maxSD = this.createElementNS(
+ this.namespaces.sld, "sld:MaxScaleDenominator"
+ );
+ maxSD.appendChild(this.createTextNode(context.minScale.toPrecision(16)));
+ node.appendChild(maxSD);
+ }
+
+ // optional SRS element(s)
+ if (context.srs) {
+ for(var name in context.srs) {
+ node.appendChild(this.createElementDefaultNS("SRS", name));
+ }
+ }
+
+ // optional FormatList element
+ node.appendChild(this.write_wmc_FormatList(context));
+
+ // optional StyleList element
+ node.appendChild(this.write_wmc_StyleList(context));
+
+ // optional DimensionList element
+ if (context.dimensions) {
+ node.appendChild(this.write_wmc_DimensionList(context));
+ }
+
+ // OpenLayers specific properties go in an Extension element
+ node.appendChild(this.write_wmc_LayerExtension(context));
+
+ return node;
+
+ },
+
+ CLASS_NAME: "OpenLayers.Format.WMC.v1_1_0"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/WMSCapabilities.js b/misc/openlayers/lib/OpenLayers/Format/WMSCapabilities.js
new file mode 100644
index 0000000..2bf3cef
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/WMSCapabilities.js
@@ -0,0 +1,56 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML/VersionedOGC.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WMSCapabilities
+ * Read WMS Capabilities.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML.VersionedOGC>
+ */
+OpenLayers.Format.WMSCapabilities = OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC, {
+
+ /**
+ * APIProperty: defaultVersion
+ * {String} Version number to assume if none found. Default is "1.1.1".
+ */
+ defaultVersion: "1.1.1",
+
+ /**
+ * APIProperty: profile
+ * {String} If provided, use a custom profile.
+ *
+ * Currently supported profiles:
+ * - WMSC - parses vendor specific capabilities for WMS-C.
+ */
+ profile: null,
+
+ /**
+ * Constructor: OpenLayers.Format.WMSCapabilities
+ * Create a new parser for WMS capabilities.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * APIMethod: read
+ * Read capabilities data from a string, and return a list of layers.
+ *
+ * Parameters:
+ * data - {String} or {DOMElement} data to read/parse.
+ *
+ * Returns:
+ * {Array} List of named layers.
+ */
+
+ CLASS_NAME: "OpenLayers.Format.WMSCapabilities"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1.js b/misc/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1.js
new file mode 100644
index 0000000..ef5c133
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1.js
@@ -0,0 +1,368 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WMSCapabilities.js
+ * @requires OpenLayers/Format/OGCExceptionReport.js
+ * @requires OpenLayers/Format/XML.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WMSCapabilities.v1
+ * Abstract class not to be instantiated directly. Creates
+ * the common parts for both WMS 1.1.X and WMS 1.3.X.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.WMSCapabilities.v1 = OpenLayers.Class(
+ OpenLayers.Format.XML, {
+
+ /**
+ * Property: namespaces
+ * {Object} Mapping of namespace aliases to namespace URIs.
+ */
+ namespaces: {
+ wms: "http://www.opengis.net/wms",
+ xlink: "http://www.w3.org/1999/xlink",
+ xsi: "http://www.w3.org/2001/XMLSchema-instance"
+ },
+
+ /**
+ * Property: defaultPrefix
+ */
+ defaultPrefix: "wms",
+
+ /**
+ * Constructor: OpenLayers.Format.WMSCapabilities.v1
+ * Create an instance of one of the subclasses.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * APIMethod: read
+ * Read capabilities data from a string, and return a list of layers.
+ *
+ * Parameters:
+ * data - {String} or {DOMElement} data to read/parse.
+ *
+ * Returns:
+ * {Array} List of named layers.
+ */
+ read: function(data) {
+ if(typeof data == "string") {
+ data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+ }
+ var raw = data;
+ if(data && data.nodeType == 9) {
+ data = data.documentElement;
+ }
+ var capabilities = {};
+ this.readNode(data, capabilities);
+ if (capabilities.service === undefined) {
+ // an exception must have occurred, so parse it
+ var parser = new OpenLayers.Format.OGCExceptionReport();
+ capabilities.error = parser.read(raw);
+ }
+ return capabilities;
+ },
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "wms": {
+ "Service": function(node, obj) {
+ obj.service = {};
+ this.readChildNodes(node, obj.service);
+ },
+ "Name": function(node, obj) {
+ obj.name = this.getChildValue(node);
+ },
+ "Title": function(node, obj) {
+ obj.title = this.getChildValue(node);
+ },
+ "Abstract": function(node, obj) {
+ obj["abstract"] = this.getChildValue(node);
+ },
+ "BoundingBox": function(node, obj) {
+ var bbox = {};
+ bbox.bbox = [
+ parseFloat(node.getAttribute("minx")),
+ parseFloat(node.getAttribute("miny")),
+ parseFloat(node.getAttribute("maxx")),
+ parseFloat(node.getAttribute("maxy"))
+ ];
+ var res = {
+ x: parseFloat(node.getAttribute("resx")),
+ y: parseFloat(node.getAttribute("resy"))
+ };
+
+ if (! (isNaN(res.x) && isNaN(res.y))) {
+ bbox.res = res;
+ }
+ // return the bbox so that descendant classes can set the
+ // CRS and SRS and add it to the obj
+ return bbox;
+ },
+ "OnlineResource": function(node, obj) {
+ obj.href = this.getAttributeNS(node, this.namespaces.xlink,
+ "href");
+ },
+ "ContactInformation": function(node, obj) {
+ obj.contactInformation = {};
+ this.readChildNodes(node, obj.contactInformation);
+ },
+ "ContactPersonPrimary": function(node, obj) {
+ obj.personPrimary = {};
+ this.readChildNodes(node, obj.personPrimary);
+ },
+ "ContactPerson": function(node, obj) {
+ obj.person = this.getChildValue(node);
+ },
+ "ContactOrganization": function(node, obj) {
+ obj.organization = this.getChildValue(node);
+ },
+ "ContactPosition": function(node, obj) {
+ obj.position = this.getChildValue(node);
+ },
+ "ContactAddress": function(node, obj) {
+ obj.contactAddress = {};
+ this.readChildNodes(node, obj.contactAddress);
+ },
+ "AddressType": function(node, obj) {
+ obj.type = this.getChildValue(node);
+ },
+ "Address": function(node, obj) {
+ obj.address = this.getChildValue(node);
+ },
+ "City": function(node, obj) {
+ obj.city = this.getChildValue(node);
+ },
+ "StateOrProvince": function(node, obj) {
+ obj.stateOrProvince = this.getChildValue(node);
+ },
+ "PostCode": function(node, obj) {
+ obj.postcode = this.getChildValue(node);
+ },
+ "Country": function(node, obj) {
+ obj.country = this.getChildValue(node);
+ },
+ "ContactVoiceTelephone": function(node, obj) {
+ obj.phone = this.getChildValue(node);
+ },
+ "ContactFacsimileTelephone": function(node, obj) {
+ obj.fax = this.getChildValue(node);
+ },
+ "ContactElectronicMailAddress": function(node, obj) {
+ obj.email = this.getChildValue(node);
+ },
+ "Fees": function(node, obj) {
+ var fees = this.getChildValue(node);
+ if (fees && fees.toLowerCase() != "none") {
+ obj.fees = fees;
+ }
+ },
+ "AccessConstraints": function(node, obj) {
+ var constraints = this.getChildValue(node);
+ if (constraints && constraints.toLowerCase() != "none") {
+ obj.accessConstraints = constraints;
+ }
+ },
+ "Capability": function(node, obj) {
+ obj.capability = {
+ nestedLayers: [],
+ layers: []
+ };
+ this.readChildNodes(node, obj.capability);
+ },
+ "Request": function(node, obj) {
+ obj.request = {};
+ this.readChildNodes(node, obj.request);
+ },
+ "GetCapabilities": function(node, obj) {
+ obj.getcapabilities = {formats: []};
+ this.readChildNodes(node, obj.getcapabilities);
+ },
+ "Format": function(node, obj) {
+ if (OpenLayers.Util.isArray(obj.formats)) {
+ obj.formats.push(this.getChildValue(node));
+ } else {
+ obj.format = this.getChildValue(node);
+ }
+ },
+ "DCPType": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "HTTP": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "Get": function(node, obj) {
+ obj.get = {};
+ this.readChildNodes(node, obj.get);
+ // backwards compatibility
+ if (!obj.href) {
+ obj.href = obj.get.href;
+ }
+ },
+ "Post": function(node, obj) {
+ obj.post = {};
+ this.readChildNodes(node, obj.post);
+ // backwards compatibility
+ if (!obj.href) {
+ obj.href = obj.get.href;
+ }
+ },
+ "GetMap": function(node, obj) {
+ obj.getmap = {formats: []};
+ this.readChildNodes(node, obj.getmap);
+ },
+ "GetFeatureInfo": function(node, obj) {
+ obj.getfeatureinfo = {formats: []};
+ this.readChildNodes(node, obj.getfeatureinfo);
+ },
+ "Exception": function(node, obj) {
+ obj.exception = {formats: []};
+ this.readChildNodes(node, obj.exception);
+ },
+ "Layer": function(node, obj) {
+ var parentLayer, capability;
+ if (obj.capability) {
+ capability = obj.capability;
+ parentLayer = obj;
+ } else {
+ capability = obj;
+ }
+ var attrNode = node.getAttributeNode("queryable");
+ var queryable = (attrNode && attrNode.specified) ?
+ node.getAttribute("queryable") : null;
+ attrNode = node.getAttributeNode("cascaded");
+ var cascaded = (attrNode && attrNode.specified) ?
+ node.getAttribute("cascaded") : null;
+ attrNode = node.getAttributeNode("opaque");
+ var opaque = (attrNode && attrNode.specified) ?
+ node.getAttribute('opaque') : null;
+ var noSubsets = node.getAttribute('noSubsets');
+ var fixedWidth = node.getAttribute('fixedWidth');
+ var fixedHeight = node.getAttribute('fixedHeight');
+ var parent = parentLayer || {},
+ extend = OpenLayers.Util.extend;
+ var layer = {
+ nestedLayers: [],
+ styles: parentLayer ? [].concat(parentLayer.styles) : [],
+ srs: parentLayer ? extend({}, parent.srs) : {},
+ metadataURLs: [],
+ bbox: parentLayer ? extend({}, parent.bbox) : {},
+ llbbox: parent.llbbox,
+ dimensions: parentLayer ? extend({}, parent.dimensions) : {},
+ authorityURLs: parentLayer ? extend({}, parent.authorityURLs) : {},
+ identifiers: {},
+ keywords: [],
+ queryable: (queryable && queryable !== "") ?
+ (queryable === "1" || queryable === "true" ) :
+ (parent.queryable || false),
+ cascaded: (cascaded !== null) ? parseInt(cascaded) :
+ (parent.cascaded || 0),
+ opaque: opaque ?
+ (opaque === "1" || opaque === "true" ) :
+ (parent.opaque || false),
+ noSubsets: (noSubsets !== null) ?
+ (noSubsets === "1" || noSubsets === "true" ) :
+ (parent.noSubsets || false),
+ fixedWidth: (fixedWidth != null) ?
+ parseInt(fixedWidth) : (parent.fixedWidth || 0),
+ fixedHeight: (fixedHeight != null) ?
+ parseInt(fixedHeight) : (parent.fixedHeight || 0),
+ minScale: parent.minScale,
+ maxScale: parent.maxScale,
+ attribution: parent.attribution
+ };
+ obj.nestedLayers.push(layer);
+ layer.capability = capability;
+ this.readChildNodes(node, layer);
+ delete layer.capability;
+ if(layer.name) {
+ var parts = layer.name.split(":"),
+ request = capability.request,
+ gfi = request.getfeatureinfo;
+ if(parts.length > 0) {
+ layer.prefix = parts[0];
+ }
+ capability.layers.push(layer);
+ if (layer.formats === undefined) {
+ layer.formats = request.getmap.formats;
+ }
+ if (layer.infoFormats === undefined && gfi) {
+ layer.infoFormats = gfi.formats;
+ }
+ }
+ },
+ "Attribution": function(node, obj) {
+ obj.attribution = {};
+ this.readChildNodes(node, obj.attribution);
+ },
+ "LogoURL": function(node, obj) {
+ obj.logo = {
+ width: node.getAttribute("width"),
+ height: node.getAttribute("height")
+ };
+ this.readChildNodes(node, obj.logo);
+ },
+ "Style": function(node, obj) {
+ var style = {};
+ obj.styles.push(style);
+ this.readChildNodes(node, style);
+ },
+ "LegendURL": function(node, obj) {
+ var legend = {
+ width: node.getAttribute("width"),
+ height: node.getAttribute("height")
+ };
+ obj.legend = legend;
+ this.readChildNodes(node, legend);
+ },
+ "MetadataURL": function(node, obj) {
+ var metadataURL = {type: node.getAttribute("type")};
+ obj.metadataURLs.push(metadataURL);
+ this.readChildNodes(node, metadataURL);
+ },
+ "DataURL": function(node, obj) {
+ obj.dataURL = {};
+ this.readChildNodes(node, obj.dataURL);
+ },
+ "FeatureListURL": function(node, obj) {
+ obj.featureListURL = {};
+ this.readChildNodes(node, obj.featureListURL);
+ },
+ "AuthorityURL": function(node, obj) {
+ var name = node.getAttribute("name");
+ var authority = {};
+ this.readChildNodes(node, authority);
+ obj.authorityURLs[name] = authority.href;
+ },
+ "Identifier": function(node, obj) {
+ var authority = node.getAttribute("authority");
+ obj.identifiers[authority] = this.getChildValue(node);
+ },
+ "KeywordList": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "SRS": function(node, obj) {
+ obj.srs[this.getChildValue(node)] = true;
+ }
+ }
+ },
+
+ CLASS_NAME: "OpenLayers.Format.WMSCapabilities.v1"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1_1.js b/misc/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1_1.js
new file mode 100644
index 0000000..0e15d38
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1_1.js
@@ -0,0 +1,122 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WMSCapabilities/v1.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WMSCapabilities.v1_1
+ * Abstract class not to be instantiated directly.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.WMSCapabilities.v1>
+ */
+OpenLayers.Format.WMSCapabilities.v1_1 = OpenLayers.Class(
+ OpenLayers.Format.WMSCapabilities.v1, {
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "wms": OpenLayers.Util.applyDefaults({
+ "WMT_MS_Capabilities": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "Keyword": function(node, obj) {
+ if (obj.keywords) {
+ obj.keywords.push(this.getChildValue(node));
+ }
+ },
+ "DescribeLayer": function(node, obj) {
+ obj.describelayer = {formats: []};
+ this.readChildNodes(node, obj.describelayer);
+ },
+ "GetLegendGraphic": function(node, obj) {
+ obj.getlegendgraphic = {formats: []};
+ this.readChildNodes(node, obj.getlegendgraphic);
+ },
+ "GetStyles": function(node, obj) {
+ obj.getstyles = {formats: []};
+ this.readChildNodes(node, obj.getstyles);
+ },
+ "PutStyles": function(node, obj) {
+ obj.putstyles = {formats: []};
+ this.readChildNodes(node, obj.putstyles);
+ },
+ "UserDefinedSymbolization": function(node, obj) {
+ var userSymbols = {
+ supportSLD: parseInt(node.getAttribute("SupportSLD")) == 1,
+ userLayer: parseInt(node.getAttribute("UserLayer")) == 1,
+ userStyle: parseInt(node.getAttribute("UserStyle")) == 1,
+ remoteWFS: parseInt(node.getAttribute("RemoteWFS")) == 1
+ };
+ obj.userSymbols = userSymbols;
+ },
+ "LatLonBoundingBox": function(node, obj) {
+ obj.llbbox = [
+ parseFloat(node.getAttribute("minx")),
+ parseFloat(node.getAttribute("miny")),
+ parseFloat(node.getAttribute("maxx")),
+ parseFloat(node.getAttribute("maxy"))
+ ];
+ },
+ "BoundingBox": function(node, obj) {
+ var bbox = OpenLayers.Format.WMSCapabilities.v1.prototype.readers["wms"].BoundingBox.apply(this, [node, obj]);
+ bbox.srs = node.getAttribute("SRS");
+ obj.bbox[bbox.srs] = bbox;
+ },
+ "ScaleHint": function(node, obj) {
+ var min = node.getAttribute("min");
+ var max = node.getAttribute("max");
+ var rad2 = Math.pow(2, 0.5);
+ var ipm = OpenLayers.INCHES_PER_UNIT["m"];
+ if (min != 0) {
+ obj.maxScale = parseFloat(
+ ((min / rad2) * ipm *
+ OpenLayers.DOTS_PER_INCH).toPrecision(13)
+ );
+ }
+ if (max != Number.POSITIVE_INFINITY) {
+ obj.minScale = parseFloat(
+ ((max / rad2) * ipm *
+ OpenLayers.DOTS_PER_INCH).toPrecision(13)
+ );
+ }
+ },
+ "Dimension": function(node, obj) {
+ var name = node.getAttribute("name").toLowerCase();
+ var dim = {
+ name: name,
+ units: node.getAttribute("units"),
+ unitsymbol: node.getAttribute("unitSymbol")
+ };
+ obj.dimensions[dim.name] = dim;
+ },
+ "Extent": function(node, obj) {
+ var name = node.getAttribute("name").toLowerCase();
+ if (name in obj["dimensions"]) {
+ var extent = obj.dimensions[name];
+ extent.nearestVal =
+ node.getAttribute("nearestValue") === "1";
+ extent.multipleVal =
+ node.getAttribute("multipleValues") === "1";
+ extent.current = node.getAttribute("current") === "1";
+ extent["default"] = node.getAttribute("default") || "";
+ var values = this.getChildValue(node);
+ extent.values = values.split(",");
+ }
+ }
+ }, OpenLayers.Format.WMSCapabilities.v1.prototype.readers["wms"])
+ },
+
+ CLASS_NAME: "OpenLayers.Format.WMSCapabilities.v1_1"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1_1_0.js b/misc/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1_1_0.js
new file mode 100644
index 0000000..a1c6279
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1_1_0.js
@@ -0,0 +1,57 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WMSCapabilities/v1_1.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WMSCapabilities/v1_1_0
+ * Read WMS Capabilities version 1.1.0.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.WMSCapabilities.v1_1>
+ */
+OpenLayers.Format.WMSCapabilities.v1_1_0 = OpenLayers.Class(
+ OpenLayers.Format.WMSCapabilities.v1_1, {
+
+ /**
+ * Property: version
+ * {String} The specific parser version.
+ */
+ version: "1.1.0",
+
+ /**
+ * Constructor: OpenLayers.Format.WMSCapabilities.v1_1_0
+ * Create a new parser for WMS capabilities version 1.1.0.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "wms": OpenLayers.Util.applyDefaults({
+ "SRS": function(node, obj) {
+ var srs = this.getChildValue(node);
+ var values = srs.split(/ +/);
+ for (var i=0, len=values.length; i<len; i++) {
+ obj.srs[values[i]] = true;
+ }
+ }
+ }, OpenLayers.Format.WMSCapabilities.v1_1.prototype.readers["wms"])
+ },
+
+ CLASS_NAME: "OpenLayers.Format.WMSCapabilities.v1_1_0"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1_1_1.js b/misc/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1_1_1.js
new file mode 100644
index 0000000..459572b
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1_1_1.js
@@ -0,0 +1,60 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WMSCapabilities/v1_1.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WMSCapabilities/v1_1_1
+ * Read WMS Capabilities version 1.1.1.
+ *
+ * Note on <ScaleHint> parsing: If the 'min' attribute is set to "0", no
+ * maxScale will be set on the layer object. If the 'max' attribute is set to
+ * "Infinity", no minScale will be set. This makes it easy to create proper
+ * {<OpenLayers.Layer.WMS>} configurations directly from the layer object
+ * literals returned by this format, because no minScale/maxScale modifications
+ * need to be made.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.WMSCapabilities.v1_1>
+ */
+OpenLayers.Format.WMSCapabilities.v1_1_1 = OpenLayers.Class(
+ OpenLayers.Format.WMSCapabilities.v1_1, {
+
+ /**
+ * Property: version
+ * {String} The specific parser version.
+ */
+ version: "1.1.1",
+
+ /**
+ * Constructor: OpenLayers.Format.WMSCapabilities.v1_1_1
+ * Create a new parser for WMS capabilities version 1.1.1.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "wms": OpenLayers.Util.applyDefaults({
+ "SRS": function(node, obj) {
+ obj.srs[this.getChildValue(node)] = true;
+ }
+ }, OpenLayers.Format.WMSCapabilities.v1_1.prototype.readers["wms"])
+ },
+
+ CLASS_NAME: "OpenLayers.Format.WMSCapabilities.v1_1_1"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1_1_1_WMSC.js b/misc/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1_1_1_WMSC.js
new file mode 100644
index 0000000..e58e4f7
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1_1_1_WMSC.js
@@ -0,0 +1,85 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WMSCapabilities/v1_1_1.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WMSCapabilities/v1_1_1_WMSC
+ * Read WMS-C Capabilities version 1.1.1.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.WMSCapabilities.v1_1_1>
+ */
+OpenLayers.Format.WMSCapabilities.v1_1_1_WMSC = OpenLayers.Class(
+ OpenLayers.Format.WMSCapabilities.v1_1_1, {
+
+ /**
+ * Property: version
+ * {String} The specific parser version.
+ */
+ version: "1.1.1",
+
+ /**
+ * Property: profile
+ * {String} The specific profile
+ */
+ profile: "WMSC",
+
+ /**
+ * Constructor: OpenLayers.Format.WMSCapabilities.v1_1_1
+ * Create a new parser for WMS-C capabilities version 1.1.1.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "wms": OpenLayers.Util.applyDefaults({
+ "VendorSpecificCapabilities": function(node, obj) {
+ obj.vendorSpecific = {tileSets: []};
+ this.readChildNodes(node, obj.vendorSpecific);
+ },
+ "TileSet": function(node, vendorSpecific) {
+ var tileset = {srs: {}, bbox: {}, resolutions: []};
+ this.readChildNodes(node, tileset);
+ vendorSpecific.tileSets.push(tileset);
+ },
+ "Resolutions": function(node, tileset) {
+ var res = this.getChildValue(node).split(" ");
+ for (var i=0, len=res.length; i<len; i++) {
+ if (res[i] != "") {
+ tileset.resolutions.push(parseFloat(res[i]));
+ }
+ }
+ },
+ "Width": function(node, tileset) {
+ tileset.width = parseInt(this.getChildValue(node));
+ },
+ "Height": function(node, tileset) {
+ tileset.height = parseInt(this.getChildValue(node));
+ },
+ "Layers": function(node, tileset) {
+ tileset.layers = this.getChildValue(node);
+ },
+ "Styles": function(node, tileset) {
+ tileset.styles = this.getChildValue(node);
+ }
+ }, OpenLayers.Format.WMSCapabilities.v1_1_1.prototype.readers["wms"])
+ },
+
+ CLASS_NAME: "OpenLayers.Format.WMSCapabilities.v1_1_1_WMSC"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1_3.js b/misc/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1_3.js
new file mode 100644
index 0000000..57aee1a
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1_3.js
@@ -0,0 +1,128 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WMSCapabilities/v1.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WMSCapabilities/v1_3
+ * Abstract base class for WMS Capabilities version 1.3.X.
+ * SLD 1.1.0 adds in the extra operations DescribeLayer and GetLegendGraphic,
+ * see: http://schemas.opengis.net/sld/1.1.0/sld_capabilities.xsd
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.WMSCapabilities.v1>
+ */
+OpenLayers.Format.WMSCapabilities.v1_3 = OpenLayers.Class(
+ OpenLayers.Format.WMSCapabilities.v1, {
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "wms": OpenLayers.Util.applyDefaults({
+ "WMS_Capabilities": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "LayerLimit": function(node, obj) {
+ obj.layerLimit = parseInt(this.getChildValue(node));
+ },
+ "MaxWidth": function(node, obj) {
+ obj.maxWidth = parseInt(this.getChildValue(node));
+ },
+ "MaxHeight": function(node, obj) {
+ obj.maxHeight = parseInt(this.getChildValue(node));
+ },
+ "BoundingBox": function(node, obj) {
+ var bbox = OpenLayers.Format.WMSCapabilities.v1.prototype.readers["wms"].BoundingBox.apply(this, [node, obj]);
+ bbox.srs = node.getAttribute("CRS");
+ obj.bbox[bbox.srs] = bbox;
+ },
+ "CRS": function(node, obj) {
+ // CRS is the synonym of SRS
+ this.readers.wms.SRS.apply(this, [node, obj]);
+ },
+ "EX_GeographicBoundingBox": function(node, obj) {
+ // replacement of LatLonBoundingBox
+ obj.llbbox = [];
+ this.readChildNodes(node, obj.llbbox);
+
+ },
+ "westBoundLongitude": function(node, obj) {
+ obj[0] = this.getChildValue(node);
+ },
+ "eastBoundLongitude": function(node, obj) {
+ obj[2] = this.getChildValue(node);
+ },
+ "southBoundLatitude": function(node, obj) {
+ obj[1] = this.getChildValue(node);
+ },
+ "northBoundLatitude": function(node, obj) {
+ obj[3] = this.getChildValue(node);
+ },
+ "MinScaleDenominator": function(node, obj) {
+ obj.maxScale = parseFloat(this.getChildValue(node)).toPrecision(16);
+ },
+ "MaxScaleDenominator": function(node, obj) {
+ obj.minScale = parseFloat(this.getChildValue(node)).toPrecision(16);
+ },
+ "Dimension": function(node, obj) {
+ // dimension has extra attributes: default, multipleValues,
+ // nearestValue, current which used to be part of Extent. It now
+ // also contains the values.
+ var name = node.getAttribute("name").toLowerCase();
+ var dim = {
+ name: name,
+ units: node.getAttribute("units"),
+ unitsymbol: node.getAttribute("unitSymbol"),
+ nearestVal: node.getAttribute("nearestValue") === "1",
+ multipleVal: node.getAttribute("multipleValues") === "1",
+ "default": node.getAttribute("default") || "",
+ current: node.getAttribute("current") === "1",
+ values: this.getChildValue(node).split(",")
+
+ };
+ // Theoretically there can be more dimensions with the same
+ // name, but with a different unit. Until we meet such a case,
+ // let's just keep the same structure as the WMS 1.1
+ // GetCapabilities parser uses. We will store the last
+ // one encountered.
+ obj.dimensions[dim.name] = dim;
+ },
+ "Keyword": function(node, obj) {
+ // TODO: should we change the structure of keyword in v1.js?
+ // Make it an object with a value instead of a string?
+ var keyword = {value: this.getChildValue(node),
+ vocabulary: node.getAttribute("vocabulary")};
+ if (obj.keywords) {
+ obj.keywords.push(keyword);
+ }
+ }
+ }, OpenLayers.Format.WMSCapabilities.v1.prototype.readers["wms"]),
+ "sld": {
+ "UserDefinedSymbolization": function(node, obj) {
+ this.readers.wms.UserDefinedSymbolization.apply(this, [node, obj]);
+ // add the two extra attributes
+ obj.userSymbols.inlineFeature = parseInt(node.getAttribute("InlineFeature")) == 1;
+ obj.userSymbols.remoteWCS = parseInt(node.getAttribute("RemoteWCS")) == 1;
+ },
+ "DescribeLayer": function(node, obj) {
+ this.readers.wms.DescribeLayer.apply(this, [node, obj]);
+ },
+ "GetLegendGraphic": function(node, obj) {
+ this.readers.wms.GetLegendGraphic.apply(this, [node, obj]);
+ }
+ }
+ },
+
+ CLASS_NAME: "OpenLayers.Format.WMSCapabilities.v1_3"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1_3_0.js b/misc/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1_3_0.js
new file mode 100644
index 0000000..c2c4ca4
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/WMSCapabilities/v1_3_0.js
@@ -0,0 +1,30 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WMSCapabilities/v1_3.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WMSCapabilities/v1_3_0
+ * Read WMS Capabilities version 1.3.0.
+ * SLD 1.1.0 adds in the extra operations DescribeLayer and GetLegendGraphic,
+ * see: http://schemas.opengis.net/sld/1.1.0/sld_capabilities.xsd
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.WMSCapabilities.v1_3>
+ */
+OpenLayers.Format.WMSCapabilities.v1_3_0 = OpenLayers.Class(
+ OpenLayers.Format.WMSCapabilities.v1_3, {
+
+ /**
+ * Property: version
+ * {String} The specific parser version.
+ */
+ version: "1.3.0",
+
+ CLASS_NAME: "OpenLayers.Format.WMSCapabilities.v1_3_0"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/WMSDescribeLayer.js b/misc/openlayers/lib/OpenLayers/Format/WMSDescribeLayer.js
new file mode 100644
index 0000000..296262c
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/WMSDescribeLayer.js
@@ -0,0 +1,53 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML/VersionedOGC.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WMSDescribeLayer
+ * Read SLD WMS DescribeLayer response
+ * DescribeLayer is meant to couple WMS to WFS and WCS
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML.VersionedOGC>
+ */
+OpenLayers.Format.WMSDescribeLayer = OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC, {
+
+ /**
+ * APIProperty: defaultVersion
+ * {String} Version number to assume if none found. Default is "1.1.1".
+ */
+ defaultVersion: "1.1.1",
+
+ /**
+ * Constructor: OpenLayers.Format.WMSDescribeLayer
+ * Create a new parser for WMS DescribeLayer responses.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * APIMethod: read
+ * Read DescribeLayer data from a string, and return the response.
+ * The OGC currently defines 2 formats which are allowed for output,
+ * so we need to parse these 2 types
+ *
+ * Parameters:
+ * data - {String} or {DOMElement} data to read/parse.
+ *
+ * Returns:
+ * {Array} Array of {<LayerDescription>} objects which have:
+ * - {String} owsType: WFS/WCS
+ * - {String} owsURL: the online resource
+ * - {String} typeName: the name of the typename on the service
+ */
+
+ CLASS_NAME: "OpenLayers.Format.WMSDescribeLayer"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/WMSDescribeLayer/v1_1.js b/misc/openlayers/lib/OpenLayers/Format/WMSDescribeLayer/v1_1.js
new file mode 100644
index 0000000..3929d4b
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/WMSDescribeLayer/v1_1.js
@@ -0,0 +1,122 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WMSDescribeLayer.js
+ * @requires OpenLayers/Format/OGCExceptionReport.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WMSDescribeLayer.v1_1_1
+ * Read SLD WMS DescribeLayer response for WMS 1.1.X
+ * WMS 1.1.X is tightly coupled to SLD 1.0.0
+ *
+ * Example DescribeLayer request:
+ * http://demo.opengeo.org/geoserver/wms?request=DescribeLayer&version=1.1.1&layers=topp:states
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.WMSDescribeLayer>
+ */
+OpenLayers.Format.WMSDescribeLayer.v1_1_1 = OpenLayers.Class(
+ OpenLayers.Format.WMSDescribeLayer, {
+
+ /**
+ * Constructor: OpenLayers.Format.WMSDescribeLayer
+ * Create a new parser for WMS DescribeLayer responses.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+ initialize: function(options) {
+ OpenLayers.Format.WMSDescribeLayer.prototype.initialize.apply(this,
+ [options]);
+ },
+
+ /**
+ * APIMethod: read
+ * Read DescribeLayer data from a string, and return the response.
+ * The OGC defines 2 formats which are allowed for output,
+ * so we need to parse these 2 types for version 1.1.X
+ *
+ * Parameters:
+ * data - {String} or {DOMElement} data to read/parse.
+ *
+ * Returns:
+ * {Object} Object with a layerDescriptions property, which holds an Array
+ * of {<LayerDescription>} objects which have:
+ * - {String} owsType: WFS/WCS
+ * - {String} owsURL: the online resource
+ * - {String} typeName: the name of the typename on the owsType service
+ * - {String} layerName: the name of the WMS layer we did a lookup for
+ */
+ read: function(data) {
+ if(typeof data == "string") {
+ data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+ }
+ var root = data.documentElement;
+ var children = root.childNodes;
+ var describelayer = {layerDescriptions: []};
+ var childNode, nodeName;
+ for(var i=0; i<children.length; ++i) {
+ childNode = children[i];
+ nodeName = childNode.nodeName;
+ if (nodeName == 'LayerDescription') {
+ var layerName = childNode.getAttribute('name');
+ var owsType = '';
+ var owsURL = '';
+ var typeName = '';
+ // check for owsType and owsURL attributes
+ if (childNode.getAttribute('owsType')) {
+ owsType = childNode.getAttribute('owsType');
+ owsURL = childNode.getAttribute('owsURL');
+ } else {
+ // look for wfs or wcs attribute
+ if (childNode.getAttribute('wfs') != '') {
+ owsType = 'WFS';
+ owsURL = childNode.getAttribute('wfs');
+ } else if (childNode.getAttribute('wcs') != '') {
+ owsType = 'WCS';
+ owsURL = childNode.getAttribute('wcs');
+ }
+ }
+ // look for Query child
+ var query = childNode.getElementsByTagName('Query');
+ if(query.length > 0) {
+ typeName = query[0].getAttribute('typeName');
+ if (!typeName) {
+ // because of Ionic bug
+ typeName = query[0].getAttribute('typename');
+ }
+ }
+ var layerDescription = {
+ layerName: layerName, owsType: owsType,
+ owsURL: owsURL, typeName: typeName
+ };
+ describelayer.layerDescriptions.push(layerDescription);
+
+ //TODO do this in deprecated.js instead:
+ // array style index for backwards compatibility
+ describelayer.length = describelayer.layerDescriptions.length;
+ describelayer[describelayer.length - 1] = layerDescription;
+
+ } else if (nodeName == 'ServiceException') {
+ // an exception must have occurred, so parse it
+ var parser = new OpenLayers.Format.OGCExceptionReport();
+ return {
+ error: parser.read(data)
+ };
+ }
+ }
+ return describelayer;
+ },
+
+ CLASS_NAME: "OpenLayers.Format.WMSDescribeLayer.v1_1_1"
+
+});
+
+// Version alias - workaround for http://trac.osgeo.org/mapserver/ticket/2257
+OpenLayers.Format.WMSDescribeLayer.v1_1_0 =
+ OpenLayers.Format.WMSDescribeLayer.v1_1_1;
diff --git a/misc/openlayers/lib/OpenLayers/Format/WMSGetFeatureInfo.js b/misc/openlayers/lib/OpenLayers/Format/WMSGetFeatureInfo.js
new file mode 100644
index 0000000..57eb219
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/WMSGetFeatureInfo.js
@@ -0,0 +1,296 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WMSGetFeatureInfo
+ * Class to read GetFeatureInfo responses from Web Mapping Services
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.WMSGetFeatureInfo = OpenLayers.Class(OpenLayers.Format.XML, {
+
+ /**
+ * APIProperty: layerIdentifier
+ * {String} All xml nodes containing this search criteria will populate an
+ * internal array of layer nodes.
+ */
+ layerIdentifier: '_layer',
+
+ /**
+ * APIProperty: featureIdentifier
+ * {String} All xml nodes containing this search criteria will populate an
+ * internal array of feature nodes for each layer node found.
+ */
+ featureIdentifier: '_feature',
+
+ /**
+ * Property: regExes
+ * Compiled regular expressions for manipulating strings.
+ */
+ regExes: {
+ trimSpace: (/^\s*|\s*$/g),
+ removeSpace: (/\s*/g),
+ splitSpace: (/\s+/),
+ trimComma: (/\s*,\s*/g)
+ },
+
+ /**
+ * Property: gmlFormat
+ * {<OpenLayers.Format.GML>} internal GML format for parsing geometries
+ * in msGMLOutput
+ */
+ gmlFormat: null,
+
+ /**
+ * Constructor: OpenLayers.Format.WMSGetFeatureInfo
+ * Create a new parser for WMS GetFeatureInfo responses
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * APIMethod: read
+ * Read WMS GetFeatureInfo data from a string, and return an array of features
+ *
+ * Parameters:
+ * data - {String} or {DOMElement} data to read/parse.
+ *
+ * Returns:
+ * {Array(<OpenLayers.Feature.Vector>)} An array of features.
+ */
+ read: function(data) {
+ var result;
+ if(typeof data == "string") {
+ data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+ }
+ var root = data.documentElement;
+ if(root) {
+ var scope = this;
+ var read = this["read_" + root.nodeName];
+ if(read) {
+ result = read.call(this, root);
+ } else {
+ // fall-back to GML since this is a common output format for WMS
+ // GetFeatureInfo responses
+ result = new OpenLayers.Format.GML((this.options ? this.options : {})).read(data);
+ }
+ } else {
+ result = data;
+ }
+ return result;
+ },
+
+
+ /**
+ * Method: read_msGMLOutput
+ * Parse msGMLOutput nodes.
+ *
+ * Parameters:
+ * data - {DOMElement}
+ *
+ * Returns:
+ * {Array}
+ */
+ read_msGMLOutput: function(data) {
+ var response = [];
+ var layerNodes = this.getSiblingNodesByTagCriteria(data,
+ this.layerIdentifier);
+ if (layerNodes) {
+ for (var i=0, len=layerNodes.length; i<len; ++i) {
+ var node = layerNodes[i];
+ var layerName = node.nodeName;
+ if (node.prefix) {
+ layerName = layerName.split(':')[1];
+ }
+ var layerName = layerName.replace(this.layerIdentifier, '');
+ var featureNodes = this.getSiblingNodesByTagCriteria(node,
+ this.featureIdentifier);
+ if (featureNodes) {
+ for (var j = 0; j < featureNodes.length; j++) {
+ var featureNode = featureNodes[j];
+ var geomInfo = this.parseGeometry(featureNode);
+ var attributes = this.parseAttributes(featureNode);
+ var feature = new OpenLayers.Feature.Vector(geomInfo.geometry,
+ attributes, null);
+ feature.bounds = geomInfo.bounds;
+ feature.type = layerName;
+ response.push(feature);
+ }
+ }
+ }
+ }
+ return response;
+ },
+
+ /**
+ * Method: read_FeatureInfoResponse
+ * Parse FeatureInfoResponse nodes.
+ *
+ * Parameters:
+ * data - {DOMElement}
+ *
+ * Returns:
+ * {Array}
+ */
+ read_FeatureInfoResponse: function(data) {
+ var response = [];
+ var featureNodes = this.getElementsByTagNameNS(data, '*',
+ 'FIELDS');
+
+ for(var i=0, len=featureNodes.length;i<len;i++) {
+ var featureNode = featureNodes[i];
+ var geom = null;
+
+ // attributes can be actual attributes on the FIELDS tag,
+ // or FIELD children
+ var attributes = {};
+ var j;
+ var jlen = featureNode.attributes.length;
+ if (jlen > 0) {
+ for(j=0; j<jlen; j++) {
+ var attribute = featureNode.attributes[j];
+ attributes[attribute.nodeName] = attribute.nodeValue;
+ }
+ } else {
+ var nodes = featureNode.childNodes;
+ for (j=0, jlen=nodes.length; j<jlen; ++j) {
+ var node = nodes[j];
+ if (node.nodeType != 3) {
+ attributes[node.getAttribute("name")] =
+ node.getAttribute("value");
+ }
+ }
+ }
+
+ response.push(
+ new OpenLayers.Feature.Vector(geom, attributes, null)
+ );
+ }
+ return response;
+ },
+
+ /**
+ * Method: getSiblingNodesByTagCriteria
+ * Recursively searches passed xml node and all it's descendant levels for
+ * nodes whose tagName contains the passed search string. This returns an
+ * array of all sibling nodes which match the criteria from the highest
+ * hierarchial level from which a match is found.
+ *
+ * Parameters:
+ * node - {DOMElement} An xml node
+ * criteria - {String} Search string which will match some part of a tagName
+ *
+ * Returns:
+ * Array({DOMElement}) An array of sibling xml nodes
+ */
+ getSiblingNodesByTagCriteria: function(node, criteria){
+ var nodes = [];
+ var children, tagName, n, matchNodes, child;
+ if (node && node.hasChildNodes()) {
+ children = node.childNodes;
+ n = children.length;
+
+ for(var k=0; k<n; k++){
+ child = children[k];
+ while (child && child.nodeType != 1) {
+ child = child.nextSibling;
+ k++;
+ }
+ tagName = (child ? child.nodeName : '');
+ if (tagName.length > 0 && tagName.indexOf(criteria) > -1) {
+ nodes.push(child);
+ } else {
+ matchNodes = this.getSiblingNodesByTagCriteria(
+ child, criteria);
+
+ if(matchNodes.length > 0){
+ (nodes.length == 0) ?
+ nodes = matchNodes : nodes.push(matchNodes);
+ }
+ }
+ }
+
+ }
+ return nodes;
+ },
+
+ /**
+ * Method: parseAttributes
+ *
+ * Parameters:
+ * node - {<DOMElement>}
+ *
+ * Returns:
+ * {Object} An attributes object.
+ *
+ * Notes:
+ * Assumes that attributes are direct child xml nodes of the passed node
+ * and contain only a single text node.
+ */
+ parseAttributes: function(node){
+ var attributes = {};
+ if (node.nodeType == 1) {
+ var children = node.childNodes;
+ var n = children.length;
+ for (var i = 0; i < n; ++i) {
+ var child = children[i];
+ if (child.nodeType == 1) {
+ var grandchildren = child.childNodes;
+ var name = (child.prefix) ?
+ child.nodeName.split(":")[1] : child.nodeName;
+ if (grandchildren.length == 0) {
+ attributes[name] = null;
+ } else if (grandchildren.length == 1) {
+ var grandchild = grandchildren[0];
+ if (grandchild.nodeType == 3 ||
+ grandchild.nodeType == 4) {
+ var value = grandchild.nodeValue.replace(
+ this.regExes.trimSpace, "");
+ attributes[name] = value;
+ }
+ }
+ }
+ }
+ }
+ return attributes;
+ },
+
+ /**
+ * Method: parseGeometry
+ * Parse the geometry and the feature bounds out of the node using
+ * Format.GML
+ *
+ * Parameters:
+ * node - {<DOMElement>}
+ *
+ * Returns:
+ * {Object} An object containing the geometry and the feature bounds
+ */
+ parseGeometry: function(node) {
+ // we need to use the old Format.GML parser since we do not know the
+ // geometry name
+ if (!this.gmlFormat) {
+ this.gmlFormat = new OpenLayers.Format.GML();
+ }
+ var feature = this.gmlFormat.parseFeature(node);
+ var geometry, bounds = null;
+ if (feature) {
+ geometry = feature.geometry && feature.geometry.clone();
+ bounds = feature.bounds && feature.bounds.clone();
+ feature.destroy();
+ }
+ return {geometry: geometry, bounds: bounds};
+ },
+
+ CLASS_NAME: "OpenLayers.Format.WMSGetFeatureInfo"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/WMTSCapabilities.js b/misc/openlayers/lib/OpenLayers/Format/WMTSCapabilities.js
new file mode 100644
index 0000000..9cff69c
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/WMTSCapabilities.js
@@ -0,0 +1,230 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML/VersionedOGC.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WMTSCapabilities
+ * Read WMTS Capabilities.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML.VersionedOGC>
+ */
+OpenLayers.Format.WMTSCapabilities = OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC, {
+
+ /**
+ * APIProperty: defaultVersion
+ * {String} Version number to assume if none found. Default is "1.0.0".
+ */
+ defaultVersion: "1.0.0",
+
+ /**
+ * APIProperty: yx
+ * {Object} Members in the yx object are used to determine if a CRS URN
+ * corresponds to a CRS with y,x axis order. Member names are CRS URNs
+ * and values are boolean. By default, the following CRS URN are
+ * assumed to correspond to a CRS with y,x axis order:
+ *
+ * * urn:ogc:def:crs:EPSG::4326
+ */
+ yx: {
+ "urn:ogc:def:crs:EPSG::4326": true
+ },
+
+ /**
+ * Constructor: OpenLayers.Format.WMTSCapabilities
+ * Create a new parser for WMTS capabilities.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * APIMethod: read
+ * Read capabilities data from a string, and return information about
+ * the service (offering and observedProperty mostly).
+ *
+ * Parameters:
+ * data - {String} or {DOMElement} data to read/parse.
+ *
+ * Returns:
+ * {Object} Info about the WMTS Capabilities
+ */
+
+ /**
+ * APIMethod: createLayer
+ * Create a WMTS layer given a capabilities object.
+ *
+ * Parameters:
+ * capabilities - {Object} The object returned from a <read> call to this
+ * format.
+ * config - {Object} Configuration properties for the layer. Defaults for
+ * the layer will apply if not provided.
+ *
+ * Required config properties:
+ * layer - {String} The layer identifier.
+ *
+ * Optional config properties:
+ * matrixSet - {String} The matrix set identifier, required if there is
+ * more than one matrix set in the layer capabilities.
+ * style - {String} The name of the style
+ * format - {String} Image format for the layer. Default is the first
+ * format returned in the GetCapabilities response.
+ * param - {Object} The dimensions values eg: {"Year": "2012"}
+ *
+ * Returns:
+ * {<OpenLayers.Layer.WMTS>} A properly configured WMTS layer. Throws an
+ * error if an incomplete config is provided. Returns undefined if no
+ * layer could be created with the provided config.
+ */
+ createLayer: function(capabilities, config) {
+ var layer;
+
+ // confirm required properties are supplied in config
+ if (!('layer' in config)) {
+ throw new Error("Missing property 'layer' in configuration.");
+ }
+
+ var contents = capabilities.contents;
+
+ // find the layer definition with the given identifier
+ var layers = contents.layers;
+ var layerDef;
+ for (var i=0, ii=contents.layers.length; i<ii; ++i) {
+ if (contents.layers[i].identifier === config.layer) {
+ layerDef = contents.layers[i];
+ break;
+ }
+ }
+ if (!layerDef) {
+ throw new Error("Layer not found");
+ }
+
+ var format = config.format;
+ if (!format && layerDef.formats && layerDef.formats.length) {
+ format = layerDef.formats[0];
+ }
+
+ // find the matrixSet definition
+ var matrixSet;
+ if (config.matrixSet) {
+ matrixSet = contents.tileMatrixSets[config.matrixSet];
+ } else if (layerDef.tileMatrixSetLinks.length >= 1) {
+ matrixSet = contents.tileMatrixSets[
+ layerDef.tileMatrixSetLinks[0].tileMatrixSet];
+ }
+ if (!matrixSet) {
+ throw new Error("matrixSet not found");
+ }
+
+ // get the default style for the layer
+ var style;
+ for (var i=0, ii=layerDef.styles.length; i<ii; ++i) {
+ style = layerDef.styles[i];
+ if (style.isDefault) {
+ break;
+ }
+ }
+
+ var requestEncoding = config.requestEncoding;
+ if (!requestEncoding) {
+ requestEncoding = "KVP";
+ if (capabilities.operationsMetadata.GetTile.dcp.http) {
+ var http = capabilities.operationsMetadata.GetTile.dcp.http;
+ // Get first get method
+ if (http.get[0].constraints) {
+ var constraints = http.get[0].constraints;
+ var allowedValues = constraints.GetEncoding.allowedValues;
+
+ // The OGC documentation is not clear if we should use
+ // REST or RESTful, ArcGis use RESTful,
+ // and OpenLayers use REST.
+ if (!allowedValues.KVP &&
+ (allowedValues.REST || allowedValues.RESTful)) {
+ requestEncoding = "REST";
+ }
+ }
+ }
+ }
+
+ var dimensions = [];
+ var params = config.params || {};
+ // to don't overwrite the changes in the applyDefaults
+ delete config.params;
+ for (var id = 0, ld = layerDef.dimensions.length ; id < ld ; id++) {
+ var dimension = layerDef.dimensions[id];
+ dimensions.push(dimension.identifier);
+ if (!params.hasOwnProperty(dimension.identifier)) {
+ params[dimension.identifier] = dimension['default'];
+ }
+ }
+
+ var projection = config.projection || matrixSet.supportedCRS.replace(
+ /urn:ogc:def:crs:(\w+):(.*:)?(\w+)$/, "$1:$3");
+ var units = config.units ||
+ (projection === "EPSG:4326" ? "degrees" : "m");
+
+ var resolutions = [];
+ for (var mid in matrixSet.matrixIds) {
+ if (matrixSet.matrixIds.hasOwnProperty(mid)) {
+ resolutions.push(
+ matrixSet.matrixIds[mid].scaleDenominator * 0.28E-3 /
+ OpenLayers.METERS_PER_INCH /
+ OpenLayers.INCHES_PER_UNIT[units]);
+ }
+ }
+
+ var url;
+ if (requestEncoding === "REST" && layerDef.resourceUrls) {
+ url = [];
+ var resourceUrls = layerDef.resourceUrls,
+ resourceUrl;
+ for (var t = 0, tt = layerDef.resourceUrls.length; t < tt; ++t) {
+ resourceUrl = layerDef.resourceUrls[t];
+ if (resourceUrl.format === format && resourceUrl.resourceType === "tile") {
+ url.push(resourceUrl.template);
+ }
+ }
+ }
+ else {
+ var httpGet = capabilities.operationsMetadata.GetTile.dcp.http.get;
+ url = [];
+ var constraint;
+ for (var i = 0, ii = httpGet.length; i < ii; i++) {
+ constraint = httpGet[i].constraints;
+ if (!constraint || (constraint && constraint.
+ GetEncoding.allowedValues[requestEncoding])) {
+ url.push(httpGet[i].url);
+ }
+ }
+ }
+
+ return new OpenLayers.Layer.WMTS(
+ OpenLayers.Util.applyDefaults(config, {
+ url: url,
+ requestEncoding: requestEncoding,
+ name: layerDef.title,
+ style: style.identifier,
+ format: format,
+ matrixIds: matrixSet.matrixIds,
+ matrixSet: matrixSet.identifier,
+ projection: projection,
+ units: units,
+ resolutions: config.isBaseLayer === false ? undefined :
+ resolutions,
+ serverResolutions: resolutions,
+ tileFullExtent: matrixSet.bounds,
+ dimensions: dimensions,
+ params: params
+ })
+ );
+ },
+
+ CLASS_NAME: "OpenLayers.Format.WMTSCapabilities"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/WMTSCapabilities/v1_0_0.js b/misc/openlayers/lib/OpenLayers/Format/WMTSCapabilities/v1_0_0.js
new file mode 100644
index 0000000..fda2584
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/WMTSCapabilities/v1_0_0.js
@@ -0,0 +1,251 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WMTSCapabilities.js
+ * @requires OpenLayers/Format/OWSCommon/v1_1_0.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WMTSCapabilities.v1_0_0
+ * Read WMTS Capabilities version 1.0.0.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.WMTSCapabilities>
+ */
+OpenLayers.Format.WMTSCapabilities.v1_0_0 = OpenLayers.Class(
+ OpenLayers.Format.OWSCommon.v1_1_0, {
+
+ /**
+ * Property: version
+ * {String} The parser version ("1.0.0").
+ */
+ version: "1.0.0",
+
+ /**
+ * Property: namespaces
+ * {Object} Mapping of namespace aliases to namespace URIs.
+ */
+ namespaces: {
+ ows: "http://www.opengis.net/ows/1.1",
+ wmts: "http://www.opengis.net/wmts/1.0",
+ xlink: "http://www.w3.org/1999/xlink"
+ },
+
+ /**
+ * Property: yx
+ * {Object} Members in the yx object are used to determine if a CRS URN
+ * corresponds to a CRS with y,x axis order. Member names are CRS URNs
+ * and values are boolean. Defaults come from the
+ * <OpenLayers.Format.WMTSCapabilities> prototype.
+ */
+ yx: null,
+
+ /**
+ * Property: defaultPrefix
+ * {String} The default namespace alias for creating element nodes.
+ */
+ defaultPrefix: "wmts",
+
+ /**
+ * Constructor: OpenLayers.Format.WMTSCapabilities.v1_0_0
+ * Create a new parser for WMTS capabilities version 1.0.0.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+ initialize: function(options) {
+ OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+ this.options = options;
+ var yx = OpenLayers.Util.extend(
+ {}, OpenLayers.Format.WMTSCapabilities.prototype.yx
+ );
+ this.yx = OpenLayers.Util.extend(yx, this.yx);
+ },
+
+ /**
+ * APIMethod: read
+ * Read capabilities data from a string, and return info about the WMTS.
+ *
+ * Parameters:
+ * data - {String} or {DOMElement} data to read/parse.
+ *
+ * Returns:
+ * {Object} Information about the SOS service.
+ */
+ read: function(data) {
+ if(typeof data == "string") {
+ data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+ }
+ if(data && data.nodeType == 9) {
+ data = data.documentElement;
+ }
+ var capabilities = {};
+ this.readNode(data, capabilities);
+ capabilities.version = this.version;
+ return capabilities;
+ },
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "wmts": {
+ "Capabilities": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "Contents": function(node, obj) {
+ obj.contents = {};
+ obj.contents.layers = [];
+ obj.contents.tileMatrixSets = {};
+ this.readChildNodes(node, obj.contents);
+ },
+ "Layer": function(node, obj) {
+ var layer = {
+ styles: [],
+ formats: [],
+ dimensions: [],
+ tileMatrixSetLinks: []
+ };
+ layer.layers = [];
+ this.readChildNodes(node, layer);
+ obj.layers.push(layer);
+ },
+ "Style": function(node, obj) {
+ var style = {};
+ style.isDefault = (node.getAttribute("isDefault") === "true");
+ this.readChildNodes(node, style);
+ obj.styles.push(style);
+ },
+ "Format": function(node, obj) {
+ obj.formats.push(this.getChildValue(node));
+ },
+ "TileMatrixSetLink": function(node, obj) {
+ var tileMatrixSetLink = {};
+ this.readChildNodes(node, tileMatrixSetLink);
+ obj.tileMatrixSetLinks.push(tileMatrixSetLink);
+ },
+ "TileMatrixSet": function(node, obj) {
+ // node could be child of wmts:Contents or wmts:TileMatrixSetLink
+ // duck type wmts:Contents by looking for layers
+ if (obj.layers) {
+ // TileMatrixSet as object type in schema
+ var tileMatrixSet = {
+ matrixIds: []
+ };
+ this.readChildNodes(node, tileMatrixSet);
+ obj.tileMatrixSets[tileMatrixSet.identifier] = tileMatrixSet;
+ } else {
+ // TileMatrixSet as string type in schema
+ obj.tileMatrixSet = this.getChildValue(node);
+ }
+ },
+ "TileMatrix": function(node, obj) {
+ var tileMatrix = {
+ supportedCRS: obj.supportedCRS
+ };
+ this.readChildNodes(node, tileMatrix);
+ obj.matrixIds.push(tileMatrix);
+ },
+ "ScaleDenominator": function(node, obj) {
+ obj.scaleDenominator = parseFloat(this.getChildValue(node));
+ },
+ "TopLeftCorner": function(node, obj) {
+ var topLeftCorner = this.getChildValue(node);
+ var coords = topLeftCorner.split(" ");
+ // decide on axis order for the given CRS
+ var yx;
+ if (obj.supportedCRS) {
+ // extract out version from URN
+ var crs = obj.supportedCRS.replace(
+ /urn:ogc:def:crs:(\w+):.+:(\w+)$/,
+ "urn:ogc:def:crs:$1::$2"
+ );
+ yx = !!this.yx[crs];
+ }
+ if (yx) {
+ obj.topLeftCorner = new OpenLayers.LonLat(
+ coords[1], coords[0]
+ );
+ } else {
+ obj.topLeftCorner = new OpenLayers.LonLat(
+ coords[0], coords[1]
+ );
+ }
+ },
+ "TileWidth": function(node, obj) {
+ obj.tileWidth = parseInt(this.getChildValue(node));
+ },
+ "TileHeight": function(node, obj) {
+ obj.tileHeight = parseInt(this.getChildValue(node));
+ },
+ "MatrixWidth": function(node, obj) {
+ obj.matrixWidth = parseInt(this.getChildValue(node));
+ },
+ "MatrixHeight": function(node, obj) {
+ obj.matrixHeight = parseInt(this.getChildValue(node));
+ },
+ "ResourceURL": function(node, obj) {
+ obj.resourceUrl = obj.resourceUrl || {};
+ var resourceType = node.getAttribute("resourceType");
+ if (!obj.resourceUrls) {
+ obj.resourceUrls = [];
+ }
+ var resourceUrl = obj.resourceUrl[resourceType] = {
+ format: node.getAttribute("format"),
+ template: node.getAttribute("template"),
+ resourceType: resourceType
+ };
+ obj.resourceUrls.push(resourceUrl);
+ },
+ // not used for now, can be added in the future though
+ /*"Themes": function(node, obj) {
+ obj.themes = [];
+ this.readChildNodes(node, obj.themes);
+ },
+ "Theme": function(node, obj) {
+ var theme = {};
+ this.readChildNodes(node, theme);
+ obj.push(theme);
+ },*/
+ "WSDL": function(node, obj) {
+ obj.wsdl = {};
+ obj.wsdl.href = node.getAttribute("xlink:href");
+ // TODO: other attributes of <WSDL> element
+ },
+ "ServiceMetadataURL": function(node, obj) {
+ obj.serviceMetadataUrl = {};
+ obj.serviceMetadataUrl.href = node.getAttribute("xlink:href");
+ // TODO: other attributes of <ServiceMetadataURL> element
+ },
+ "LegendURL": function(node, obj) {
+ obj.legend = {};
+ obj.legend.href = node.getAttribute("xlink:href");
+ obj.legend.format = node.getAttribute("format");
+ },
+ "Dimension": function(node, obj) {
+ var dimension = {values: []};
+ this.readChildNodes(node, dimension);
+ obj.dimensions.push(dimension);
+ },
+ "Default": function(node, obj) {
+ obj["default"] = this.getChildValue(node);
+ },
+ "Value": function(node, obj) {
+ obj.values.push(this.getChildValue(node));
+ }
+ },
+ "ows": OpenLayers.Format.OWSCommon.v1_1_0.prototype.readers["ows"]
+ },
+
+ CLASS_NAME: "OpenLayers.Format.WMTSCapabilities.v1_0_0"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/WPSCapabilities.js b/misc/openlayers/lib/OpenLayers/Format/WPSCapabilities.js
new file mode 100644
index 0000000..f0d74db
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/WPSCapabilities.js
@@ -0,0 +1,48 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML/VersionedOGC.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WPSCapabilities
+ * Read WPS Capabilities.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML.VersionedOGC>
+ */
+OpenLayers.Format.WPSCapabilities = OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC, {
+
+ /**
+ * APIProperty: defaultVersion
+ * {String} Version number to assume if none found. Default is "1.0.0".
+ */
+ defaultVersion: "1.0.0",
+
+ /**
+ * Constructor: OpenLayers.Format.WPSCapabilities
+ * Create a new parser for WPS Capabilities.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * APIMethod: read
+ * Read capabilities data from a string, and return information about
+ * the service.
+ *
+ * Parameters:
+ * data - {String} or {DOMElement} data to read/parse.
+ *
+ * Returns:
+ * {Object} Info about the WPS
+ */
+
+ CLASS_NAME: "OpenLayers.Format.WPSCapabilities"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/WPSCapabilities/v1_0_0.js b/misc/openlayers/lib/OpenLayers/Format/WPSCapabilities/v1_0_0.js
new file mode 100644
index 0000000..e6762a9
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/WPSCapabilities/v1_0_0.js
@@ -0,0 +1,119 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/WPSCapabilities.js
+ * @requires OpenLayers/Format/OWSCommon/v1_1_0.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WPSCapabilities.v1_0_0
+ * Read WPS Capabilities version 1.0.0.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.WPSCapabilities.v1_0_0 = OpenLayers.Class(
+ OpenLayers.Format.XML, {
+
+ /**
+ * Property: namespaces
+ * {Object} Mapping of namespace aliases to namespace URIs.
+ */
+ namespaces: {
+ ows: "http://www.opengis.net/ows/1.1",
+ wps: "http://www.opengis.net/wps/1.0.0",
+ xlink: "http://www.w3.org/1999/xlink"
+ },
+
+ /**
+ * Property: regExes
+ * Compiled regular expressions for manipulating strings.
+ */
+ regExes: {
+ trimSpace: (/^\s*|\s*$/g),
+ removeSpace: (/\s*/g),
+ splitSpace: (/\s+/),
+ trimComma: (/\s*,\s*/g)
+ },
+
+ /**
+ * Constructor: OpenLayers.Format.WPSCapabilities.v1_0_0
+ * Create a new parser for WPS capabilities version 1.0.0.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+ initialize: function(options) {
+ OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+ },
+
+ /**
+ * APIMethod: read
+ * Read capabilities data from a string, and return info about the WPS.
+ *
+ * Parameters:
+ * data - {String} or {DOMElement} data to read/parse.
+ *
+ * Returns:
+ * {Object} Information about the WPS service.
+ */
+ read: function(data) {
+ if(typeof data == "string") {
+ data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+ }
+ if(data && data.nodeType == 9) {
+ data = data.documentElement;
+ }
+ var capabilities = {};
+ this.readNode(data, capabilities);
+ return capabilities;
+ },
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "wps": {
+ "Capabilities": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "ProcessOfferings": function(node, obj) {
+ obj.processOfferings = {};
+ this.readChildNodes(node, obj.processOfferings);
+ },
+ "Process": function(node, processOfferings) {
+ var processVersion = this.getAttributeNS(node, this.namespaces.wps, "processVersion");
+ var process = {processVersion: processVersion};
+ this.readChildNodes(node, process);
+ processOfferings[process.identifier] = process;
+ },
+ "Languages": function(node, obj) {
+ obj.languages = [];
+ this.readChildNodes(node, obj.languages);
+ },
+ "Default": function(node, languages) {
+ var language = {isDefault: true};
+ this.readChildNodes(node, language);
+ languages.push(language);
+ },
+ "Supported": function(node, languages) {
+ var language = {};
+ this.readChildNodes(node, language);
+ languages.push(language);
+ }
+ },
+ "ows": OpenLayers.Format.OWSCommon.v1_1_0.prototype.readers["ows"]
+ },
+
+ CLASS_NAME: "OpenLayers.Format.WPSCapabilities.v1_0_0"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/WPSDescribeProcess.js b/misc/openlayers/lib/OpenLayers/Format/WPSDescribeProcess.js
new file mode 100644
index 0000000..e8f96bb
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/WPSDescribeProcess.js
@@ -0,0 +1,185 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Format/OWSCommon/v1_1_0.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WPSDescribeProcess
+ * Read WPS DescribeProcess responses.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.WPSDescribeProcess = OpenLayers.Class(
+ OpenLayers.Format.XML, {
+
+ /**
+ * Constant: VERSION
+ * {String} 1.0.0
+ */
+ VERSION: "1.0.0",
+
+ /**
+ * Property: namespaces
+ * {Object} Mapping of namespace aliases to namespace URIs.
+ */
+ namespaces: {
+ wps: "http://www.opengis.net/wps/1.0.0",
+ ows: "http://www.opengis.net/ows/1.1",
+ xsi: "http://www.w3.org/2001/XMLSchema-instance"
+ },
+
+ /**
+ * Property: schemaLocation
+ * {String} Schema location
+ */
+ schemaLocation: "http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsAll.xsd",
+
+ /**
+ * Property: defaultPrefix
+ */
+ defaultPrefix: "wps",
+
+ /**
+ * Property: regExes
+ * Compiled regular expressions for manipulating strings.
+ */
+ regExes: {
+ trimSpace: (/^\s*|\s*$/g),
+ removeSpace: (/\s*/g),
+ splitSpace: (/\s+/),
+ trimComma: (/\s*,\s*/g)
+ },
+
+ /**
+ * Constructor: OpenLayers.Format.WPSDescribeProcess
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * APIMethod: read
+ * Parse a WPS DescribeProcess and return an object with its information.
+ *
+ * Parameters:
+ * data - {String} or {DOMElement} data to read/parse.
+ *
+ * Returns:
+ * {Object}
+ */
+ read: function(data) {
+ if(typeof data == "string") {
+ data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+ }
+ if(data && data.nodeType == 9) {
+ data = data.documentElement;
+ }
+ var info = {};
+ this.readNode(data, info);
+ return info;
+ },
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "wps": {
+ "ProcessDescriptions": function(node, obj) {
+ obj.processDescriptions = {};
+ this.readChildNodes(node, obj.processDescriptions);
+ },
+ "ProcessDescription": function(node, processDescriptions) {
+ var processVersion = this.getAttributeNS(node, this.namespaces.wps, "processVersion");
+ var processDescription = {
+ processVersion: processVersion,
+ statusSupported: (node.getAttribute("statusSupported") === "true"),
+ storeSupported: (node.getAttribute("storeSupported") === "true")
+ };
+ this.readChildNodes(node, processDescription);
+ processDescriptions[processDescription.identifier] = processDescription;
+ },
+ "DataInputs": function(node, processDescription) {
+ processDescription.dataInputs = [];
+ this.readChildNodes(node, processDescription.dataInputs);
+ },
+ "ProcessOutputs": function(node, processDescription) {
+ processDescription.processOutputs = [];
+ this.readChildNodes(node, processDescription.processOutputs);
+ },
+ "Output": function(node, processOutputs) {
+ var output = {};
+ this.readChildNodes(node, output);
+ processOutputs.push(output);
+ },
+ "ComplexOutput": function(node, output) {
+ output.complexOutput = {};
+ this.readChildNodes(node, output.complexOutput);
+ },
+ "LiteralOutput": function(node, output) {
+ output.literalOutput = {};
+ this.readChildNodes(node, output.literalOutput);
+ },
+ "Input": function(node, dataInputs) {
+ var input = {
+ maxOccurs: parseInt(node.getAttribute("maxOccurs")),
+ minOccurs: parseInt(node.getAttribute("minOccurs"))
+ };
+ this.readChildNodes(node, input);
+ dataInputs.push(input);
+ },
+ "BoundingBoxData": function(node, input) {
+ input.boundingBoxData = {};
+ this.readChildNodes(node, input.boundingBoxData);
+ },
+ "CRS": function(node, obj) {
+ if (!obj.CRSs) {
+ obj.CRSs = {};
+ }
+ obj.CRSs[this.getChildValue(node)] = true;
+ },
+ "LiteralData": function(node, input) {
+ input.literalData = {};
+ this.readChildNodes(node, input.literalData);
+ },
+ "ComplexData": function(node, input) {
+ input.complexData = {};
+ this.readChildNodes(node, input.complexData);
+ },
+ "Default": function(node, complexData) {
+ complexData["default"] = {};
+ this.readChildNodes(node, complexData["default"]);
+ },
+ "Supported": function(node, complexData) {
+ complexData["supported"] = {};
+ this.readChildNodes(node, complexData["supported"]);
+ },
+ "Format": function(node, obj) {
+ var format = {};
+ this.readChildNodes(node, format);
+ if (!obj.formats) {
+ obj.formats = {};
+ }
+ obj.formats[format.mimeType] = true;
+ },
+ "MimeType": function(node, format) {
+ format.mimeType = this.getChildValue(node);
+ }
+ },
+ "ows": OpenLayers.Format.OWSCommon.v1_1_0.prototype.readers["ows"]
+ },
+
+ CLASS_NAME: "OpenLayers.Format.WPSDescribeProcess"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/WPSExecute.js b/misc/openlayers/lib/OpenLayers/Format/WPSExecute.js
new file mode 100644
index 0000000..0795b0d
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/WPSExecute.js
@@ -0,0 +1,395 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Format/OWSCommon/v1_1_0.js
+ * @requires OpenLayers/Format/WCSGetCoverage.js
+ * @requires OpenLayers/Format/WFST/v1_1_0.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WPSExecute version 1.0.0
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.WPSExecute = OpenLayers.Class(OpenLayers.Format.XML,
+ OpenLayers.Format.Filter.v1_1_0, {
+
+ /**
+ * Property: namespaces
+ * {Object} Mapping of namespace aliases to namespace URIs.
+ */
+ namespaces: {
+ ows: "http://www.opengis.net/ows/1.1",
+ gml: "http://www.opengis.net/gml",
+ wps: "http://www.opengis.net/wps/1.0.0",
+ wfs: "http://www.opengis.net/wfs",
+ ogc: "http://www.opengis.net/ogc",
+ wcs: "http://www.opengis.net/wcs",
+ xlink: "http://www.w3.org/1999/xlink",
+ xsi: "http://www.w3.org/2001/XMLSchema-instance"
+ },
+
+ /**
+ * Property: regExes
+ * Compiled regular expressions for manipulating strings.
+ */
+ regExes: {
+ trimSpace: (/^\s*|\s*$/g),
+ removeSpace: (/\s*/g),
+ splitSpace: (/\s+/),
+ trimComma: (/\s*,\s*/g)
+ },
+
+ /**
+ * Constant: VERSION
+ * {String} 1.0.0
+ */
+ VERSION: "1.0.0",
+
+ /**
+ * Property: schemaLocation
+ * {String} Schema location
+ */
+ schemaLocation: "http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsAll.xsd",
+
+ schemaLocationAttr: function(options) {
+ return undefined;
+ },
+
+ /**
+ * Constructor: OpenLayers.Format.WPSExecute
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * Method: write
+ *
+ * Parameters:
+ * options - {Object} Optional object.
+ *
+ * Returns:
+ * {String} An WPS Execute request XML string.
+ */
+ write: function(options) {
+ var doc;
+ if (window.ActiveXObject) {
+ doc = new ActiveXObject("Microsoft.XMLDOM");
+ this.xmldom = doc;
+ } else {
+ doc = document.implementation.createDocument("", "", null);
+ }
+ var node = this.writeNode("wps:Execute", options, doc);
+ this.setAttributeNS(
+ node, this.namespaces.xsi,
+ "xsi:schemaLocation", this.schemaLocation
+ );
+ return OpenLayers.Format.XML.prototype.write.apply(this, [node]);
+ },
+
+ /**
+ * APIMethod: read
+ * Parse a WPS Execute and return an object with its information.
+ *
+ * Parameters:
+ * data - {String} or {DOMElement} data to read/parse.
+ *
+ * Returns:
+ * {Object}
+ */
+ read: function(data) {
+ if(typeof data == "string") {
+ data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+ }
+ if(data && data.nodeType == 9) {
+ data = data.documentElement;
+ }
+ var info = {};
+ this.readNode(data, info);
+ return info;
+ },
+
+ /**
+ * Property: writers
+ * As a compliment to the readers property, this structure contains public
+ * writing functions grouped by namespace alias and named like the
+ * node names they produce.
+ */
+ writers: {
+ "wps": {
+ "Execute": function(options) {
+ var node = this.createElementNSPlus("wps:Execute", {
+ attributes: {
+ version: this.VERSION,
+ service: 'WPS'
+ }
+ });
+ this.writeNode("ows:Identifier", options.identifier, node);
+ this.writeNode("wps:DataInputs", options.dataInputs, node);
+ this.writeNode("wps:ResponseForm", options.responseForm, node);
+ return node;
+ },
+ "ResponseForm": function(responseForm) {
+ var node = this.createElementNSPlus("wps:ResponseForm", {});
+ if (responseForm.rawDataOutput) {
+ this.writeNode("wps:RawDataOutput", responseForm.rawDataOutput, node);
+ }
+ if (responseForm.responseDocument) {
+ this.writeNode("wps:ResponseDocument", responseForm.responseDocument, node);
+ }
+ return node;
+ },
+ "ResponseDocument": function(responseDocument) {
+ var node = this.createElementNSPlus("wps:ResponseDocument", {
+ attributes: {
+ storeExecuteResponse: responseDocument.storeExecuteResponse,
+ lineage: responseDocument.lineage,
+ status: responseDocument.status
+ }
+ });
+ if (responseDocument.outputs) {
+ for (var i = 0, len = responseDocument.outputs.length; i < len; i++) {
+ this.writeNode("wps:Output", responseDocument.outputs[i], node);
+ }
+ }
+ return node;
+ },
+ "Output": function(output) {
+ var node = this.createElementNSPlus("wps:Output", {
+ attributes: {
+ asReference: output.asReference,
+ mimeType: output.mimeType,
+ encoding: output.encoding,
+ schema: output.schema
+ }
+ });
+ this.writeNode("ows:Identifier", output.identifier, node);
+ this.writeNode("ows:Title", output.title, node);
+ this.writeNode("ows:Abstract", output["abstract"], node);
+ return node;
+ },
+ "RawDataOutput": function(rawDataOutput) {
+ var node = this.createElementNSPlus("wps:RawDataOutput", {
+ attributes: {
+ mimeType: rawDataOutput.mimeType,
+ encoding: rawDataOutput.encoding,
+ schema: rawDataOutput.schema
+ }
+ });
+ this.writeNode("ows:Identifier", rawDataOutput.identifier, node);
+ return node;
+ },
+ "DataInputs": function(dataInputs) {
+ var node = this.createElementNSPlus("wps:DataInputs", {});
+ for (var i=0, ii=dataInputs.length; i<ii; ++i) {
+ this.writeNode("wps:Input", dataInputs[i], node);
+ }
+ return node;
+ },
+ "Input": function(input) {
+ var node = this.createElementNSPlus("wps:Input", {});
+ this.writeNode("ows:Identifier", input.identifier, node);
+ if (input.title) {
+ this.writeNode("ows:Title", input.title, node);
+ }
+ if (input.data) {
+ this.writeNode("wps:Data", input.data, node);
+ }
+ if (input.reference) {
+ this.writeNode("wps:Reference", input.reference, node);
+ }
+ if (input.boundingBoxData) {
+ this.writeNode("wps:BoundingBoxData", input.boundingBoxData, node);
+ }
+ return node;
+ },
+ "Data": function(data) {
+ var node = this.createElementNSPlus("wps:Data", {});
+ if (data.literalData) {
+ this.writeNode("wps:LiteralData", data.literalData, node);
+ } else if (data.complexData) {
+ this.writeNode("wps:ComplexData", data.complexData, node);
+ } else if (data.boundingBoxData) {
+ this.writeNode("ows:BoundingBox", data.boundingBoxData, node);
+ }
+ return node;
+ },
+ "LiteralData": function(literalData) {
+ var node = this.createElementNSPlus("wps:LiteralData", {
+ attributes: {
+ uom: literalData.uom
+ },
+ value: literalData.value
+ });
+ return node;
+ },
+ "ComplexData": function(complexData) {
+ var node = this.createElementNSPlus("wps:ComplexData", {
+ attributes: {
+ mimeType: complexData.mimeType,
+ encoding: complexData.encoding,
+ schema: complexData.schema
+ }
+ });
+ var data = complexData.value;
+ if (typeof data === "string") {
+ node.appendChild(
+ this.getXMLDoc().createCDATASection(complexData.value)
+ );
+ } else {
+ node.appendChild(data);
+ }
+ return node;
+ },
+ "Reference": function(reference) {
+ var node = this.createElementNSPlus("wps:Reference", {
+ attributes: {
+ mimeType: reference.mimeType,
+ "xlink:href": reference.href,
+ method: reference.method,
+ encoding: reference.encoding,
+ schema: reference.schema
+ }
+ });
+ if (reference.body) {
+ this.writeNode("wps:Body", reference.body, node);
+ }
+ return node;
+ },
+ "BoundingBoxData": function(node, obj) {
+ this.writers['ows']['BoundingBox'].apply(this, [node, obj, "wps:BoundingBoxData"]);
+ },
+ "Body": function(body) {
+ var node = this.createElementNSPlus("wps:Body", {});
+ if (body.wcs) {
+ this.writeNode("wcs:GetCoverage", body.wcs, node);
+ }
+ else if (body.wfs) {
+ // OpenLayers.Format.WFST expects these to be on the
+ // instance and not in the options
+ this.featureType = body.wfs.featureType;
+ this.version = body.wfs.version;
+ this.writeNode("wfs:GetFeature", body.wfs, node);
+ } else {
+ this.writeNode("wps:Execute", body, node);
+ }
+ return node;
+ }
+ },
+ "wcs": OpenLayers.Format.WCSGetCoverage.prototype.writers.wcs,
+ "wfs": OpenLayers.Format.WFST.v1_1_0.prototype.writers.wfs,
+ "ogc": OpenLayers.Format.Filter.v1_1_0.prototype.writers.ogc,
+ "ows": OpenLayers.Format.OWSCommon.v1_1_0.prototype.writers.ows
+ },
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "wps": {
+ "ExecuteResponse": function(node, obj) {
+ obj.executeResponse = {
+ lang: node.getAttribute("lang"),
+ statusLocation: node.getAttribute("statusLocation"),
+ serviceInstance: node.getAttribute("serviceInstance"),
+ service: node.getAttribute("service")
+ };
+ this.readChildNodes(node, obj.executeResponse);
+ },
+ "Process":function(node,obj) {
+ obj.process = {};
+ this.readChildNodes(node, obj.process);
+ },
+ "Status":function(node,obj) {
+ obj.status = {
+ creationTime: node.getAttribute("creationTime")
+ };
+ this.readChildNodes(node, obj.status);
+ },
+ "ProcessSucceeded": function(node,obj) {
+ obj.processSucceeded = true;
+ },
+ "ProcessOutputs": function(node, processDescription) {
+ processDescription.processOutputs = [];
+ this.readChildNodes(node, processDescription.processOutputs);
+ },
+ "Output": function(node, processOutputs) {
+ var output = {};
+ this.readChildNodes(node, output);
+ processOutputs.push(output);
+ },
+ "Reference": function(node, output) {
+ output.reference = {
+ href: node.getAttribute("href"),
+ mimeType: node.getAttribute("mimeType"),
+ encoding: node.getAttribute("encoding"),
+ schema: node.getAttribute("schema")
+ };
+ },
+ "Data": function(node, output) {
+ output.data = {};
+ this.readChildNodes(node, output);
+ },
+ "LiteralData": function(node, output) {
+ output.literalData = {
+ dataType: node.getAttribute("dataType"),
+ uom: node.getAttribute("uom"),
+ value: this.getChildValue(node)
+ };
+ },
+ "ComplexData": function(node, output) {
+ output.complexData = {
+ mimeType: node.getAttribute("mimeType"),
+ schema: node.getAttribute("schema"),
+ encoding: node.getAttribute("encoding"),
+ value: ""
+ };
+
+ // try to get *some* value, ignore the empty text values
+ if (this.isSimpleContent(node)) {
+ var child;
+ for(child=node.firstChild; child; child=child.nextSibling) {
+ switch(child.nodeType) {
+ case 3: // text node
+ case 4: // cdata section
+ output.complexData.value += child.nodeValue;
+ }
+ }
+ }
+ else {
+ for(child=node.firstChild; child; child=child.nextSibling) {
+ if (child.nodeType == 1) {
+ output.complexData.value = child;
+ }
+ }
+ }
+
+ },
+ "BoundingBox": function(node, output) {
+ output.boundingBoxData = {
+ dimensions: node.getAttribute("dimensions"),
+ crs: node.getAttribute("crs")
+ };
+ this.readChildNodes(node, output.boundingBoxData);
+ }
+ },
+
+ // TODO: we should add Exception parsing here
+ "ows": OpenLayers.Format.OWSCommon.v1_1_0.prototype.readers["ows"]
+ },
+
+ CLASS_NAME: "OpenLayers.Format.WPSExecute"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/XLS.js b/misc/openlayers/lib/OpenLayers/Format/XLS.js
new file mode 100644
index 0000000..76f3f10
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/XLS.js
@@ -0,0 +1,68 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML/VersionedOGC.js
+ */
+
+/**
+ * Class: OpenLayers.Format.XLS
+ * Read/Write XLS (OpenLS). Create a new instance with the <OpenLayers.Format.XLS>
+ * constructor. Currently only implemented for Location Utility Services, more
+ * specifically only for Geocoding. No support for Reverse Geocoding as yet.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML.VersionedOGC>
+ */
+OpenLayers.Format.XLS = OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC, {
+
+ /**
+ * APIProperty: defaultVersion
+ * {String} Version number to assume if none found. Default is "1.1.0".
+ */
+ defaultVersion: "1.1.0",
+
+ /**
+ * APIProperty: stringifyOutput
+ * {Boolean} If true, write will return a string otherwise a DOMElement.
+ * Default is true.
+ */
+ stringifyOutput: true,
+
+ /**
+ * Constructor: OpenLayers.Format.XLS
+ * Create a new parser for XLS.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * APIMethod: write
+ * Write out an XLS request.
+ *
+ * Parameters:
+ * request - {Object} An object representing the LUS request.
+ * options - {Object} Optional configuration object.
+ *
+ * Returns:
+ * {String} An XLS document string.
+ */
+
+ /**
+ * APIMethod: read
+ * Read an XLS doc and return an object representing the result.
+ *
+ * Parameters:
+ * data - {String | DOMElement} Data to read.
+ * options - {Object} Options for the reader.
+ *
+ * Returns:
+ * {Object} An object representing the GeocodeResponse.
+ */
+
+ CLASS_NAME: "OpenLayers.Format.XLS"
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/XLS/v1.js b/misc/openlayers/lib/OpenLayers/Format/XLS/v1.js
new file mode 100644
index 0000000..642474f
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/XLS/v1.js
@@ -0,0 +1,304 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XLS.js
+ * @requires OpenLayers/Format/GML/v3.js
+ */
+
+/**
+ * Class: OpenLayers.Format.XLS.v1
+ * Superclass for XLS version 1 parsers. Only supports GeocodeRequest for now.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.XLS.v1 = OpenLayers.Class(OpenLayers.Format.XML, {
+
+ /**
+ * Property: namespaces
+ * {Object} Mapping of namespace aliases to namespace URIs.
+ */
+ namespaces: {
+ xls: "http://www.opengis.net/xls",
+ gml: "http://www.opengis.net/gml",
+ xsi: "http://www.w3.org/2001/XMLSchema-instance"
+ },
+
+ /**
+ * Property: regExes
+ * Compiled regular expressions for manipulating strings.
+ */
+ regExes: {
+ trimSpace: (/^\s*|\s*$/g),
+ removeSpace: (/\s*/g),
+ splitSpace: (/\s+/),
+ trimComma: (/\s*,\s*/g)
+ },
+
+ /**
+ * APIProperty: xy
+ * {Boolean} Order of the GML coordinate true:(x,y) or false:(y,x)
+ * Changing is not recommended, a new Format should be instantiated.
+ */
+ xy: true,
+
+ /**
+ * Property: defaultPrefix
+ */
+ defaultPrefix: "xls",
+
+ /**
+ * Property: schemaLocation
+ * {String} Schema location for a particular minor version.
+ */
+ schemaLocation: null,
+
+ /**
+ * Constructor: OpenLayers.Format.XLS.v1
+ * Instances of this class are not created directly. Use the
+ * <OpenLayers.Format.XLS> constructor instead.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * Method: read
+ *
+ * Parameters:
+ * data - {DOMElement} An XLS document element.
+ * options - {Object} Options for the reader.
+ *
+ * Returns:
+ * {Object} An object representing the XLSResponse.
+ */
+ read: function(data, options) {
+ options = OpenLayers.Util.applyDefaults(options, this.options);
+ var xls = {};
+ this.readChildNodes(data, xls);
+ return xls;
+ },
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "xls": {
+ "XLS": function(node, xls) {
+ xls.version = node.getAttribute("version");
+ this.readChildNodes(node, xls);
+ },
+ "Response": function(node, xls) {
+ this.readChildNodes(node, xls);
+ },
+ "GeocodeResponse": function(node, xls) {
+ xls.responseLists = [];
+ this.readChildNodes(node, xls);
+ },
+ "GeocodeResponseList": function(node, xls) {
+ var responseList = {
+ features: [],
+ numberOfGeocodedAddresses:
+ parseInt(node.getAttribute("numberOfGeocodedAddresses"))
+ };
+ xls.responseLists.push(responseList);
+ this.readChildNodes(node, responseList);
+ },
+ "GeocodedAddress": function(node, responseList) {
+ var feature = new OpenLayers.Feature.Vector();
+ responseList.features.push(feature);
+ this.readChildNodes(node, feature);
+ // post-process geometry
+ feature.geometry = feature.components[0];
+ },
+ "GeocodeMatchCode": function(node, feature) {
+ feature.attributes.matchCode = {
+ accuracy: parseFloat(node.getAttribute("accuracy")),
+ matchType: node.getAttribute("matchType")
+ };
+ },
+ "Address": function(node, feature) {
+ var address = {
+ countryCode: node.getAttribute("countryCode"),
+ addressee: node.getAttribute("addressee"),
+ street: [],
+ place: []
+ };
+ feature.attributes.address = address;
+ this.readChildNodes(node, address);
+ },
+ "freeFormAddress": function(node, address) {
+ address.freeFormAddress = this.getChildValue(node);
+ },
+ "StreetAddress": function(node, address) {
+ this.readChildNodes(node, address);
+ },
+ "Building": function(node, address) {
+ address.building = {
+ 'number': node.getAttribute("number"),
+ subdivision: node.getAttribute("subdivision"),
+ buildingName: node.getAttribute("buildingName")
+ };
+ },
+ "Street": function(node, address) {
+ // only support the built-in primitive type for now
+ address.street.push(this.getChildValue(node));
+ },
+ "Place": function(node, address) {
+ // type is one of CountrySubdivision,
+ // CountrySecondarySubdivision, Municipality or
+ // MunicipalitySubdivision
+ address.place[node.getAttribute("type")] =
+ this.getChildValue(node);
+ },
+ "PostalCode": function(node, address) {
+ address.postalCode = this.getChildValue(node);
+ }
+ },
+ "gml": OpenLayers.Format.GML.v3.prototype.readers.gml
+ },
+
+ /**
+ * Method: write
+ *
+ * Parameters:
+ * request - {Object} An object representing the geocode request.
+ *
+ * Returns:
+ * {DOMElement} The root of an XLS document.
+ */
+ write: function(request) {
+ return this.writers.xls.XLS.apply(this, [request]);
+ },
+
+ /**
+ * Property: writers
+ * As a compliment to the readers property, this structure contains public
+ * writing functions grouped by namespace alias and named like the
+ * node names they produce.
+ */
+ writers: {
+ "xls": {
+ "XLS": function(request) {
+ var root = this.createElementNSPlus(
+ "xls:XLS",
+ {attributes: {
+ "version": this.VERSION,
+ "xsi:schemaLocation": this.schemaLocation
+ }}
+ );
+ this.writeNode("RequestHeader", request.header, root);
+ this.writeNode("Request", request, root);
+ return root;
+ },
+ "RequestHeader": function(header) {
+ return this.createElementNSPlus("xls:RequestHeader");
+ },
+ "Request": function(request) {
+ var node = this.createElementNSPlus("xls:Request", {
+ attributes: {
+ methodName: "GeocodeRequest",
+ requestID: request.requestID || "",
+ version: this.VERSION
+ }
+ });
+ this.writeNode("GeocodeRequest", request.addresses, node);
+ return node;
+ },
+ "GeocodeRequest": function(addresses) {
+ var node = this.createElementNSPlus("xls:GeocodeRequest");
+ for (var i=0, len=addresses.length; i<len; i++) {
+ this.writeNode("Address", addresses[i], node);
+ }
+ return node;
+ },
+ "Address": function(address) {
+ var node = this.createElementNSPlus("xls:Address", {
+ attributes: {
+ countryCode: address.countryCode
+ }
+ });
+ if (address.freeFormAddress) {
+ this.writeNode("freeFormAddress", address.freeFormAddress, node);
+ } else {
+ if (address.street) {
+ this.writeNode("StreetAddress", address, node);
+ }
+ if (address.municipality) {
+ this.writeNode("Municipality", address.municipality, node);
+ }
+ if (address.countrySubdivision) {
+ this.writeNode("CountrySubdivision", address.countrySubdivision, node);
+ }
+ if (address.postalCode) {
+ this.writeNode("PostalCode", address.postalCode, node);
+ }
+ }
+ return node;
+ },
+ "freeFormAddress": function(freeFormAddress) {
+ return this.createElementNSPlus("freeFormAddress",
+ {value: freeFormAddress});
+ },
+ "StreetAddress": function(address) {
+ var node = this.createElementNSPlus("xls:StreetAddress");
+ if (address.building) {
+ this.writeNode(node, "Building", address.building);
+ }
+ var street = address.street;
+ if (!(OpenLayers.Util.isArray(street))) {
+ street = [street];
+ }
+ for (var i=0, len=street.length; i < len; i++) {
+ this.writeNode("Street", street[i], node);
+ }
+ return node;
+ },
+ "Building": function(building) {
+ return this.createElementNSPlus("xls:Building", {
+ attributes: {
+ "number": building["number"],
+ "subdivision": building.subdivision,
+ "buildingName": building.buildingName
+ }
+ });
+ },
+ "Street": function(street) {
+ return this.createElementNSPlus("xls:Street", {value: street});
+ },
+ "Municipality": function(municipality) {
+ return this.createElementNSPlus("xls:Place", {
+ attributes: {
+ type: "Municipality"
+ },
+ value: municipality
+ });
+ },
+ "CountrySubdivision": function(countrySubdivision) {
+ return this.createElementNSPlus("xls:Place", {
+ attributes: {
+ type: "CountrySubdivision"
+ },
+ value: countrySubdivision
+ });
+ },
+ "PostalCode": function(postalCode) {
+ return this.createElementNSPlus("xls:PostalCode", {
+ value: postalCode
+ });
+ }
+ }
+ },
+
+ CLASS_NAME: "OpenLayers.Format.XLS.v1"
+
+});
diff --git a/misc/openlayers/lib/OpenLayers/Format/XLS/v1_1_0.js b/misc/openlayers/lib/OpenLayers/Format/XLS/v1_1_0.js
new file mode 100644
index 0000000..7ffca26
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/XLS/v1_1_0.js
@@ -0,0 +1,48 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XLS/v1.js
+ */
+
+/**
+ * Class: OpenLayers.Format.XLS.v1_1_0
+ * Read / write XLS version 1.1.0.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XLS.v1>
+ */
+OpenLayers.Format.XLS.v1_1_0 = OpenLayers.Class(
+ OpenLayers.Format.XLS.v1, {
+
+ /**
+ * Constant: VERSION
+ * {String} 1.1
+ */
+ VERSION: "1.1",
+
+ /**
+ * Property: schemaLocation
+ * {String} http://www.opengis.net/xls
+ * http://schemas.opengis.net/ols/1.1.0/LocationUtilityService.xsd
+ */
+ schemaLocation: "http://www.opengis.net/xls http://schemas.opengis.net/ols/1.1.0/LocationUtilityService.xsd",
+
+ /**
+ * Constructor: OpenLayers.Format.XLS.v1_1_0
+ * Instances of this class are not created directly. Use the
+ * <OpenLayers.Format.XLS> constructor instead.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ CLASS_NAME: "OpenLayers.Format.XLS.v1_1_0"
+
+});
+
+// Support non standard implementation
+OpenLayers.Format.XLS.v1_1 = OpenLayers.Format.XLS.v1_1_0;
diff --git a/misc/openlayers/lib/OpenLayers/Format/XML.js b/misc/openlayers/lib/OpenLayers/Format/XML.js
new file mode 100644
index 0000000..56f5871
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/XML.js
@@ -0,0 +1,897 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format.js
+ */
+
+/**
+ * Class: OpenLayers.Format.XML
+ * Read and write XML. For cross-browser XML generation, use methods on an
+ * instance of the XML format class instead of on <code>document<end>.
+ * The DOM creation and traversing methods exposed here all mimic the
+ * W3C XML DOM methods. Create a new parser with the
+ * <OpenLayers.Format.XML> constructor.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format>
+ */
+OpenLayers.Format.XML = OpenLayers.Class(OpenLayers.Format, {
+
+ /**
+ * Property: namespaces
+ * {Object} Mapping of namespace aliases to namespace URIs. Properties
+ * of this object should not be set individually. Read-only. All
+ * XML subclasses should have their own namespaces object. Use
+ * <setNamespace> to add or set a namespace alias after construction.
+ */
+ namespaces: null,
+
+ /**
+ * Property: namespaceAlias
+ * {Object} Mapping of namespace URI to namespace alias. This object
+ * is read-only. Use <setNamespace> to add or set a namespace alias.
+ */
+ namespaceAlias: null,
+
+ /**
+ * Property: defaultPrefix
+ * {String} The default namespace alias for creating element nodes.
+ */
+ defaultPrefix: null,
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {},
+
+ /**
+ * Property: writers
+ * As a compliment to the <readers> property, this structure contains public
+ * writing functions grouped by namespace alias and named like the
+ * node names they produce.
+ */
+ writers: {},
+
+ /**
+ * Property: xmldom
+ * {XMLDom} If this browser uses ActiveX, this will be set to a XMLDOM
+ * object. It is not intended to be a browser sniffing property.
+ * Instead, the xmldom property is used instead of <code>document<end>
+ * where namespaced node creation methods are not supported. In all
+ * other browsers, this remains null.
+ */
+ xmldom: null,
+
+ /**
+ * Constructor: OpenLayers.Format.XML
+ * Construct an XML parser. The parser is used to read and write XML.
+ * Reading XML from a string returns a DOM element. Writing XML from
+ * a DOM element returns a string.
+ *
+ * Parameters:
+ * options - {Object} Optional object whose properties will be set on
+ * the object.
+ */
+ initialize: function(options) {
+ if(window.ActiveXObject) {
+ this.xmldom = new ActiveXObject("Microsoft.XMLDOM");
+ }
+ OpenLayers.Format.prototype.initialize.apply(this, [options]);
+ // clone the namespace object and set all namespace aliases
+ this.namespaces = OpenLayers.Util.extend({}, this.namespaces);
+ this.namespaceAlias = {};
+ for(var alias in this.namespaces) {
+ this.namespaceAlias[this.namespaces[alias]] = alias;
+ }
+ },
+
+ /**
+ * APIMethod: destroy
+ * Clean up.
+ */
+ destroy: function() {
+ this.xmldom = null;
+ OpenLayers.Format.prototype.destroy.apply(this, arguments);
+ },
+
+ /**
+ * Method: setNamespace
+ * Set a namespace alias and URI for the format.
+ *
+ * Parameters:
+ * alias - {String} The namespace alias (prefix).
+ * uri - {String} The namespace URI.
+ */
+ setNamespace: function(alias, uri) {
+ this.namespaces[alias] = uri;
+ this.namespaceAlias[uri] = alias;
+ },
+
+ /**
+ * APIMethod: read
+ * Deserialize a XML string and return a DOM node.
+ *
+ * Parameters:
+ * text - {String} A XML string
+
+ * Returns:
+ * {DOMElement} A DOM node
+ */
+ read: function(text) {
+ var index = text.indexOf('<');
+ if(index > 0) {
+ text = text.substring(index);
+ }
+ var node = OpenLayers.Util.Try(
+ OpenLayers.Function.bind((
+ function() {
+ var xmldom;
+ /**
+ * Since we want to be able to call this method on the prototype
+ * itself, this.xmldom may not exist even if in IE.
+ */
+ if(window.ActiveXObject && !this.xmldom) {
+ xmldom = new ActiveXObject("Microsoft.XMLDOM");
+ } else {
+ xmldom = this.xmldom;
+
+ }
+ xmldom.loadXML(text);
+ return xmldom;
+ }
+ ), this),
+ function() {
+ return new DOMParser().parseFromString(text, 'text/xml');
+ },
+ function() {
+ var req = new XMLHttpRequest();
+ req.open("GET", "data:" + "text/xml" +
+ ";charset=utf-8," + encodeURIComponent(text), false);
+ if(req.overrideMimeType) {
+ req.overrideMimeType("text/xml");
+ }
+ req.send(null);
+ return req.responseXML;
+ }
+ );
+
+ if(this.keepData) {
+ this.data = node;
+ }
+
+ return node;
+ },
+
+ /**
+ * APIMethod: write
+ * Serialize a DOM node into a XML string.
+ *
+ * Parameters:
+ * node - {DOMElement} A DOM node.
+ *
+ * Returns:
+ * {String} The XML string representation of the input node.
+ */
+ write: function(node) {
+ var data;
+ if(this.xmldom) {
+ data = node.xml;
+ } else {
+ var serializer = new XMLSerializer();
+ if (node.nodeType == 1) {
+ // Add nodes to a document before serializing. Everything else
+ // is serialized as is. This may need more work. See #1218 .
+ var doc = document.implementation.createDocument("", "", null);
+ if (doc.importNode) {
+ node = doc.importNode(node, true);
+ }
+ doc.appendChild(node);
+ data = serializer.serializeToString(doc);
+ } else {
+ data = serializer.serializeToString(node);
+ }
+ }
+ return data;
+ },
+
+ /**
+ * APIMethod: createElementNS
+ * Create a new element with namespace. This node can be appended to
+ * another node with the standard node.appendChild method. For
+ * cross-browser support, this method must be used instead of
+ * document.createElementNS.
+ *
+ * Parameters:
+ * uri - {String} Namespace URI for the element.
+ * name - {String} The qualified name of the element (prefix:localname).
+ *
+ * Returns:
+ * {Element} A DOM element with namespace.
+ */
+ createElementNS: function(uri, name) {
+ var element;
+ if(this.xmldom) {
+ if(typeof uri == "string") {
+ element = this.xmldom.createNode(1, name, uri);
+ } else {
+ element = this.xmldom.createNode(1, name, "");
+ }
+ } else {
+ element = document.createElementNS(uri, name);
+ }
+ return element;
+ },
+
+ /**
+ * APIMethod: createDocumentFragment
+ * Create a document fragment node that can be appended to another node
+ * created by createElementNS. This will call
+ * document.createDocumentFragment outside of IE. In IE, the ActiveX
+ * object's createDocumentFragment method is used.
+ *
+ * Returns:
+ * {Element} A document fragment.
+ */
+ createDocumentFragment: function() {
+ var element;
+ if (this.xmldom) {
+ element = this.xmldom.createDocumentFragment();
+ } else {
+ element = document.createDocumentFragment();
+ }
+ return element;
+ },
+
+ /**
+ * APIMethod: createTextNode
+ * Create a text node. This node can be appended to another node with
+ * the standard node.appendChild method. For cross-browser support,
+ * this method must be used instead of document.createTextNode.
+ *
+ * Parameters:
+ * text - {String} The text of the node.
+ *
+ * Returns:
+ * {DOMElement} A DOM text node.
+ */
+ createTextNode: function(text) {
+ var node;
+ if (typeof text !== "string") {
+ text = String(text);
+ }
+ if(this.xmldom) {
+ node = this.xmldom.createTextNode(text);
+ } else {
+ node = document.createTextNode(text);
+ }
+ return node;
+ },
+
+ /**
+ * APIMethod: getElementsByTagNameNS
+ * Get a list of elements on a node given the namespace URI and local name.
+ * To return all nodes in a given namespace, use '*' for the name
+ * argument. To return all nodes of a given (local) name, regardless
+ * of namespace, use '*' for the uri argument.
+ *
+ * Parameters:
+ * node - {Element} Node on which to search for other nodes.
+ * uri - {String} Namespace URI.
+ * name - {String} Local name of the tag (without the prefix).
+ *
+ * Returns:
+ * {NodeList} A node list or array of elements.
+ */
+ getElementsByTagNameNS: function(node, uri, name) {
+ var elements = [];
+ if(node.getElementsByTagNameNS) {
+ elements = node.getElementsByTagNameNS(uri, name);
+ } else {
+ // brute force method
+ var allNodes = node.getElementsByTagName("*");
+ var potentialNode, fullName;
+ for(var i=0, len=allNodes.length; i<len; ++i) {
+ potentialNode = allNodes[i];
+ fullName = (potentialNode.prefix) ?
+ (potentialNode.prefix + ":" + name) : name;
+ if((name == "*") || (fullName == potentialNode.nodeName)) {
+ if((uri == "*") || (uri == potentialNode.namespaceURI)) {
+ elements.push(potentialNode);
+ }
+ }
+ }
+ }
+ return elements;
+ },
+
+ /**
+ * APIMethod: getAttributeNodeNS
+ * Get an attribute node given the namespace URI and local name.
+ *
+ * Parameters:
+ * node - {Element} Node on which to search for attribute nodes.
+ * uri - {String} Namespace URI.
+ * name - {String} Local name of the attribute (without the prefix).
+ *
+ * Returns:
+ * {DOMElement} An attribute node or null if none found.
+ */
+ getAttributeNodeNS: function(node, uri, name) {
+ var attributeNode = null;
+ if(node.getAttributeNodeNS) {
+ attributeNode = node.getAttributeNodeNS(uri, name);
+ } else {
+ var attributes = node.attributes;
+ var potentialNode, fullName;
+ for(var i=0, len=attributes.length; i<len; ++i) {
+ potentialNode = attributes[i];
+ if(potentialNode.namespaceURI == uri) {
+ fullName = (potentialNode.prefix) ?
+ (potentialNode.prefix + ":" + name) : name;
+ if(fullName == potentialNode.nodeName) {
+ attributeNode = potentialNode;
+ break;
+ }
+ }
+ }
+ }
+ return attributeNode;
+ },
+
+ /**
+ * APIMethod: getAttributeNS
+ * Get an attribute value given the namespace URI and local name.
+ *
+ * Parameters:
+ * node - {Element} Node on which to search for an attribute.
+ * uri - {String} Namespace URI.
+ * name - {String} Local name of the attribute (without the prefix).
+ *
+ * Returns:
+ * {String} An attribute value or and empty string if none found.
+ */
+ getAttributeNS: function(node, uri, name) {
+ var attributeValue = "";
+ if(node.getAttributeNS) {
+ attributeValue = node.getAttributeNS(uri, name) || "";
+ } else {
+ var attributeNode = this.getAttributeNodeNS(node, uri, name);
+ if(attributeNode) {
+ attributeValue = attributeNode.nodeValue;
+ }
+ }
+ return attributeValue;
+ },
+
+ /**
+ * APIMethod: getChildValue
+ * Get the textual value of the node if it exists, or return an
+ * optional default string. Returns an empty string if no first child
+ * exists and no default value is supplied.
+ *
+ * Parameters:
+ * node - {DOMElement} The element used to look for a first child value.
+ * def - {String} Optional string to return in the event that no
+ * first child value exists.
+ *
+ * Returns:
+ * {String} The value of the first child of the given node.
+ */
+ getChildValue: function(node, def) {
+ var value = def || "";
+ if(node) {
+ for(var child=node.firstChild; child; child=child.nextSibling) {
+ switch(child.nodeType) {
+ case 3: // text node
+ case 4: // cdata section
+ value += child.nodeValue;
+ }
+ }
+ }
+ return value;
+ },
+
+ /**
+ * APIMethod: isSimpleContent
+ * Test if the given node has only simple content (i.e. no child element
+ * nodes).
+ *
+ * Parameters:
+ * node - {DOMElement} An element node.
+ *
+ * Returns:
+ * {Boolean} The node has no child element nodes (nodes of type 1).
+ */
+ isSimpleContent: function(node) {
+ var simple = true;
+ for(var child=node.firstChild; child; child=child.nextSibling) {
+ if(child.nodeType === 1) {
+ simple = false;
+ break;
+ }
+ }
+ return simple;
+ },
+
+ /**
+ * APIMethod: contentType
+ * Determine the content type for a given node.
+ *
+ * Parameters:
+ * node - {DOMElement}
+ *
+ * Returns:
+ * {Integer} One of OpenLayers.Format.XML.CONTENT_TYPE.{EMPTY,SIMPLE,COMPLEX,MIXED}
+ * if the node has no, simple, complex, or mixed content.
+ */
+ contentType: function(node) {
+ var simple = false,
+ complex = false;
+
+ var type = OpenLayers.Format.XML.CONTENT_TYPE.EMPTY;
+
+ for(var child=node.firstChild; child; child=child.nextSibling) {
+ switch(child.nodeType) {
+ case 1: // element
+ complex = true;
+ break;
+ case 8: // comment
+ break;
+ default:
+ simple = true;
+ }
+ if(complex && simple) {
+ break;
+ }
+ }
+
+ if(complex && simple) {
+ type = OpenLayers.Format.XML.CONTENT_TYPE.MIXED;
+ } else if(complex) {
+ return OpenLayers.Format.XML.CONTENT_TYPE.COMPLEX;
+ } else if(simple) {
+ return OpenLayers.Format.XML.CONTENT_TYPE.SIMPLE;
+ }
+ return type;
+ },
+
+ /**
+ * APIMethod: hasAttributeNS
+ * Determine whether a node has a particular attribute matching the given
+ * name and namespace.
+ *
+ * Parameters:
+ * node - {Element} Node on which to search for an attribute.
+ * uri - {String} Namespace URI.
+ * name - {String} Local name of the attribute (without the prefix).
+ *
+ * Returns:
+ * {Boolean} The node has an attribute matching the name and namespace.
+ */
+ hasAttributeNS: function(node, uri, name) {
+ var found = false;
+ if(node.hasAttributeNS) {
+ found = node.hasAttributeNS(uri, name);
+ } else {
+ found = !!this.getAttributeNodeNS(node, uri, name);
+ }
+ return found;
+ },
+
+ /**
+ * APIMethod: setAttributeNS
+ * Adds a new attribute or changes the value of an attribute with the given
+ * namespace and name.
+ *
+ * Parameters:
+ * node - {Element} Element node on which to set the attribute.
+ * uri - {String} Namespace URI for the attribute.
+ * name - {String} Qualified name (prefix:localname) for the attribute.
+ * value - {String} Attribute value.
+ */
+ setAttributeNS: function(node, uri, name, value) {
+ if(node.setAttributeNS) {
+ node.setAttributeNS(uri, name, value);
+ } else {
+ if(this.xmldom) {
+ if(uri) {
+ var attribute = node.ownerDocument.createNode(
+ 2, name, uri
+ );
+ attribute.nodeValue = value;
+ node.setAttributeNode(attribute);
+ } else {
+ node.setAttribute(name, value);
+ }
+ } else {
+ throw "setAttributeNS not implemented";
+ }
+ }
+ },
+
+ /**
+ * Method: createElementNSPlus
+ * Shorthand for creating namespaced elements with optional attributes and
+ * child text nodes.
+ *
+ * Parameters:
+ * name - {String} The qualified node name.
+ * options - {Object} Optional object for node configuration.
+ *
+ * Valid options:
+ * uri - {String} Optional namespace uri for the element - supply a prefix
+ * instead if the namespace uri is a property of the format's namespace
+ * object.
+ * attributes - {Object} Optional attributes to be set using the
+ * <setAttributes> method.
+ * value - {String} Optional text to be appended as a text node.
+ *
+ * Returns:
+ * {Element} An element node.
+ */
+ createElementNSPlus: function(name, options) {
+ options = options || {};
+ // order of prefix preference
+ // 1. in the uri option
+ // 2. in the prefix option
+ // 3. in the qualified name
+ // 4. from the defaultPrefix
+ var uri = options.uri || this.namespaces[options.prefix];
+ if(!uri) {
+ var loc = name.indexOf(":");
+ uri = this.namespaces[name.substring(0, loc)];
+ }
+ if(!uri) {
+ uri = this.namespaces[this.defaultPrefix];
+ }
+ var node = this.createElementNS(uri, name);
+ if(options.attributes) {
+ this.setAttributes(node, options.attributes);
+ }
+ var value = options.value;
+ if(value != null) {
+ node.appendChild(this.createTextNode(value));
+ }
+ return node;
+ },
+
+ /**
+ * Method: setAttributes
+ * Set multiple attributes given key value pairs from an object.
+ *
+ * Parameters:
+ * node - {Element} An element node.
+ * obj - {Object || Array} An object whose properties represent attribute
+ * names and values represent attribute values. If an attribute name
+ * is a qualified name ("prefix:local"), the prefix will be looked up
+ * in the parsers {namespaces} object. If the prefix is found,
+ * setAttributeNS will be used instead of setAttribute.
+ */
+ setAttributes: function(node, obj) {
+ var value, uri;
+ for(var name in obj) {
+ if(obj[name] != null && obj[name].toString) {
+ value = obj[name].toString();
+ // check for qualified attribute name ("prefix:local")
+ uri = this.namespaces[name.substring(0, name.indexOf(":"))] || null;
+ this.setAttributeNS(node, uri, name, value);
+ }
+ }
+ },
+
+ /**
+ * Method: readNode
+ * Shorthand for applying one of the named readers given the node
+ * namespace and local name. Readers take two args (node, obj) and
+ * generally extend or modify the second.
+ *
+ * Parameters:
+ * node - {DOMElement} The node to be read (required).
+ * obj - {Object} The object to be modified (optional).
+ *
+ * Returns:
+ * {Object} The input object, modified (or a new one if none was provided).
+ */
+ readNode: function(node, obj) {
+ if(!obj) {
+ obj = {};
+ }
+ var group = this.readers[node.namespaceURI ? this.namespaceAlias[node.namespaceURI]: this.defaultPrefix];
+ if(group) {
+ var local = node.localName || node.nodeName.split(":").pop();
+ var reader = group[local] || group["*"];
+ if(reader) {
+ reader.apply(this, [node, obj]);
+ }
+ }
+ return obj;
+ },
+
+ /**
+ * Method: readChildNodes
+ * Shorthand for applying the named readers to all children of a node.
+ * For each child of type 1 (element), <readSelf> is called.
+ *
+ * Parameters:
+ * node - {DOMElement} The node to be read (required).
+ * obj - {Object} The object to be modified (optional).
+ *
+ * Returns:
+ * {Object} The input object, modified.
+ */
+ readChildNodes: function(node, obj) {
+ if(!obj) {
+ obj = {};
+ }
+ var children = node.childNodes;
+ var child;
+ for(var i=0, len=children.length; i<len; ++i) {
+ child = children[i];
+ if(child.nodeType == 1) {
+ this.readNode(child, obj);
+ }
+ }
+ return obj;
+ },
+
+ /**
+ * Method: writeNode
+ * Shorthand for applying one of the named writers and appending the
+ * results to a node. If a qualified name is not provided for the
+ * second argument (and a local name is used instead), the namespace
+ * of the parent node will be assumed.
+ *
+ * Parameters:
+ * name - {String} The name of a node to generate. If a qualified name
+ * (e.g. "pre:Name") is used, the namespace prefix is assumed to be
+ * in the <writers> group. If a local name is used (e.g. "Name") then
+ * the namespace of the parent is assumed. If a local name is used
+ * and no parent is supplied, then the default namespace is assumed.
+ * obj - {Object} Structure containing data for the writer.
+ * parent - {DOMElement} Result will be appended to this node. If no parent
+ * is supplied, the node will not be appended to anything.
+ *
+ * Returns:
+ * {DOMElement} The child node.
+ */
+ writeNode: function(name, obj, parent) {
+ var prefix, local;
+ var split = name.indexOf(":");
+ if(split > 0) {
+ prefix = name.substring(0, split);
+ local = name.substring(split + 1);
+ } else {
+ if(parent) {
+ prefix = this.namespaceAlias[parent.namespaceURI];
+ } else {
+ prefix = this.defaultPrefix;
+ }
+ local = name;
+ }
+ var child = this.writers[prefix][local].apply(this, [obj]);
+ if(parent) {
+ parent.appendChild(child);
+ }
+ return child;
+ },
+
+ /**
+ * APIMethod: getChildEl
+ * Get the first child element. Optionally only return the first child
+ * if it matches the given name and namespace URI.
+ *
+ * Parameters:
+ * node - {DOMElement} The parent node.
+ * name - {String} Optional node name (local) to search for.
+ * uri - {String} Optional namespace URI to search for.
+ *
+ * Returns:
+ * {DOMElement} The first child. Returns null if no element is found, if
+ * something significant besides an element is found, or if the element
+ * found does not match the optional name and uri.
+ */
+ getChildEl: function(node, name, uri) {
+ return node && this.getThisOrNextEl(node.firstChild, name, uri);
+ },
+
+ /**
+ * APIMethod: getNextEl
+ * Get the next sibling element. Optionally get the first sibling only
+ * if it matches the given local name and namespace URI.
+ *
+ * Parameters:
+ * node - {DOMElement} The node.
+ * name - {String} Optional local name of the sibling to search for.
+ * uri - {String} Optional namespace URI of the sibling to search for.
+ *
+ * Returns:
+ * {DOMElement} The next sibling element. Returns null if no element is
+ * found, something significant besides an element is found, or the
+ * found element does not match the optional name and uri.
+ */
+ getNextEl: function(node, name, uri) {
+ return node && this.getThisOrNextEl(node.nextSibling, name, uri);
+ },
+
+ /**
+ * Method: getThisOrNextEl
+ * Return this node or the next element node. Optionally get the first
+ * sibling with the given local name or namespace URI.
+ *
+ * Parameters:
+ * node - {DOMElement} The node.
+ * name - {String} Optional local name of the sibling to search for.
+ * uri - {String} Optional namespace URI of the sibling to search for.
+ *
+ * Returns:
+ * {DOMElement} The next sibling element. Returns null if no element is
+ * found, something significant besides an element is found, or the
+ * found element does not match the query.
+ */
+ getThisOrNextEl: function(node, name, uri) {
+ outer: for(var sibling=node; sibling; sibling=sibling.nextSibling) {
+ switch(sibling.nodeType) {
+ case 1: // Element
+ if((!name || name === (sibling.localName || sibling.nodeName.split(":").pop())) &&
+ (!uri || uri === sibling.namespaceURI)) {
+ // matches
+ break outer;
+ }
+ sibling = null;
+ break outer;
+ case 3: // Text
+ if(/^\s*$/.test(sibling.nodeValue)) {
+ break;
+ }
+ case 4: // CDATA
+ case 6: // ENTITY_NODE
+ case 12: // NOTATION_NODE
+ case 10: // DOCUMENT_TYPE_NODE
+ case 11: // DOCUMENT_FRAGMENT_NODE
+ sibling = null;
+ break outer;
+ } // ignore comments and processing instructions
+ }
+ return sibling || null;
+ },
+
+ /**
+ * APIMethod: lookupNamespaceURI
+ * Takes a prefix and returns the namespace URI associated with it on the given
+ * node if found (and null if not). Supplying null for the prefix will
+ * return the default namespace.
+ *
+ * For browsers that support it, this calls the native lookupNamesapceURI
+ * function. In other browsers, this is an implementation of
+ * http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-lookupNamespaceURI.
+ *
+ * For browsers that don't support the attribute.ownerElement property, this
+ * method cannot be called on attribute nodes.
+ *
+ * Parameters:
+ * node - {DOMElement} The node from which to start looking.
+ * prefix - {String} The prefix to lookup or null to lookup the default namespace.
+ *
+ * Returns:
+ * {String} The namespace URI for the given prefix. Returns null if the prefix
+ * cannot be found or the node is the wrong type.
+ */
+ lookupNamespaceURI: function(node, prefix) {
+ var uri = null;
+ if(node) {
+ if(node.lookupNamespaceURI) {
+ uri = node.lookupNamespaceURI(prefix);
+ } else {
+ outer: switch(node.nodeType) {
+ case 1: // ELEMENT_NODE
+ if(node.namespaceURI !== null && node.prefix === prefix) {
+ uri = node.namespaceURI;
+ break outer;
+ }
+ var len = node.attributes.length;
+ if(len) {
+ var attr;
+ for(var i=0; i<len; ++i) {
+ attr = node.attributes[i];
+ if(attr.prefix === "xmlns" && attr.name === "xmlns:" + prefix) {
+ uri = attr.value || null;
+ break outer;
+ } else if(attr.name === "xmlns" && prefix === null) {
+ uri = attr.value || null;
+ break outer;
+ }
+ }
+ }
+ uri = this.lookupNamespaceURI(node.parentNode, prefix);
+ break outer;
+ case 2: // ATTRIBUTE_NODE
+ uri = this.lookupNamespaceURI(node.ownerElement, prefix);
+ break outer;
+ case 9: // DOCUMENT_NODE
+ uri = this.lookupNamespaceURI(node.documentElement, prefix);
+ break outer;
+ case 6: // ENTITY_NODE
+ case 12: // NOTATION_NODE
+ case 10: // DOCUMENT_TYPE_NODE
+ case 11: // DOCUMENT_FRAGMENT_NODE
+ break outer;
+ default:
+ // TEXT_NODE (3), CDATA_SECTION_NODE (4), ENTITY_REFERENCE_NODE (5),
+ // PROCESSING_INSTRUCTION_NODE (7), COMMENT_NODE (8)
+ uri = this.lookupNamespaceURI(node.parentNode, prefix);
+ break outer;
+ }
+ }
+ }
+ return uri;
+ },
+
+ /**
+ * Method: getXMLDoc
+ * Get an XML document for nodes that are not supported in HTML (e.g.
+ * createCDATASection). On IE, this will either return an existing or
+ * create a new <xmldom> on the instance. On other browsers, this will
+ * either return an existing or create a new shared document (see
+ * <OpenLayers.Format.XML.document>).
+ *
+ * Returns:
+ * {XMLDocument}
+ */
+ getXMLDoc: function() {
+ if (!OpenLayers.Format.XML.document && !this.xmldom) {
+ if (document.implementation && document.implementation.createDocument) {
+ OpenLayers.Format.XML.document =
+ document.implementation.createDocument("", "", null);
+ } else if (!this.xmldom && window.ActiveXObject) {
+ this.xmldom = new ActiveXObject("Microsoft.XMLDOM");
+ }
+ }
+ return OpenLayers.Format.XML.document || this.xmldom;
+ },
+
+ CLASS_NAME: "OpenLayers.Format.XML"
+
+});
+
+OpenLayers.Format.XML.CONTENT_TYPE = {EMPTY: 0, SIMPLE: 1, COMPLEX: 2, MIXED: 3};
+
+/**
+ * APIFunction: OpenLayers.Format.XML.lookupNamespaceURI
+ * Takes a prefix and returns the namespace URI associated with it on the given
+ * node if found (and null if not). Supplying null for the prefix will
+ * return the default namespace.
+ *
+ * For browsers that support it, this calls the native lookupNamesapceURI
+ * function. In other browsers, this is an implementation of
+ * http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-lookupNamespaceURI.
+ *
+ * For browsers that don't support the attribute.ownerElement property, this
+ * method cannot be called on attribute nodes.
+ *
+ * Parameters:
+ * node - {DOMElement} The node from which to start looking.
+ * prefix - {String} The prefix to lookup or null to lookup the default namespace.
+ *
+ * Returns:
+ * {String} The namespace URI for the given prefix. Returns null if the prefix
+ * cannot be found or the node is the wrong type.
+ */
+OpenLayers.Format.XML.lookupNamespaceURI = OpenLayers.Function.bind(
+ OpenLayers.Format.XML.prototype.lookupNamespaceURI,
+ OpenLayers.Format.XML.prototype
+);
+
+/**
+ * Property: OpenLayers.Format.XML.document
+ * {XMLDocument} XML document to reuse for creating non-HTML compliant nodes,
+ * like document.createCDATASection.
+ */
+OpenLayers.Format.XML.document = null;
diff --git a/misc/openlayers/lib/OpenLayers/Format/XML/VersionedOGC.js b/misc/openlayers/lib/OpenLayers/Format/XML/VersionedOGC.js
new file mode 100644
index 0000000..e68d968
--- /dev/null
+++ b/misc/openlayers/lib/OpenLayers/Format/XML/VersionedOGC.js
@@ -0,0 +1,212 @@
+/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+ * full list of contributors). Published under the 2-clause BSD license.
+ * See license.txt in the OpenLayers distribution or repository for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Format/OGCExceptionReport.js
+ */
+
+/**
+ * Class: OpenLayers.Format.XML.VersionedOGC
+ * Base class for versioned formats, i.e. a format which supports multiple
+ * versions.
+ *
+ * To enable checking if parsing succeeded, you will need to define a property
+ * called errorProperty on the parser you want to check. The parser will then
+ * check the returned object to see if that property is present. If it is, it
+ * assumes the parsing was successful. If it is not present (or is null), it will
+ * pass the document through an OGCExceptionReport parser.
+ *
+ * If errorProperty is undefined for the parser, this error checking mechanism
+ * will be disabled.
+ *
+ *
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.XML.VersionedOGC = OpenLayers.Class(OpenLayers.Format.XML, {
+
+ /**
+ * APIProperty: defaultVersion
+ * {String} Version number to assume if none found.
+ */
+ defaultVersion: null,
+
+ /**
+ * APIProperty: version
+ * {String} Specify a version string if one is known.
+ */
+ version: null,
+
+ /**
+ * APIProperty: profile
+ * {String} If provided, use a custom profile.
+ */
+ profile: null,
+
+ /**
+ * APIProperty: allowFallback
+ * {Boolean} If a profiled parser cannot be found for the returned version,
+ * use a non-profiled parser as the fallback. Application code using this
+ * should take into account that the return object structure might be
+ * missing the specifics of the profile. Defaults to false.
+ */
+ allowFallback: false,
+
+ /**
+ * Property: name
+ * {String} The name of this parser, this is the part of the CLASS_NAME
+ * except for "OpenLayers.Format."
+ */
+ name: null,
+
+ /**
+ * APIProperty: stringifyOutput
+ * {Boolean} If true, write will return a string otherwise a DOMElement.
+ * Default is false.
+ */
+ stringifyOutput: false,
+
+ /**
+ * Property: parser
+ * {Object} Instance of the versioned parser. Cached for multiple read and
+ * write calls of the same version.
+ */
+ parser: null,
+
+ /**
+ * Constructor: OpenLayers.Format.XML.VersionedOGC.
+ * Constructor.
+ *
+ * Parameters:
+ * options - {Object} Optional object whose properties will be set on
+ * the object.
+ */
+ initialize: function(options) {
+ OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+ var className = this.CLASS_NAME;
+ this.name = className.substring(className.lastIndexOf(".")+1);
+ },
+
+ /**
+ * Method: getVersion
+ * Returns the version to use. Subclasses can override this function
+ * if a different version detection is needed.
+ *
+ * Parameters:
+ * root - {DOMElement}
+ * options - {Object} Optional configuration object.
+ *
+ * Returns:
+ * {String} The version to use.
+ */
+ getVersion: function(root, options) {
+ var version;
+ // read
+ if (root) {
+ version = this.version;
+ if(!version) {
+ version = root.getAttribute("version");
+ if(!version) {
+ version = this.defaultVersion;
+ }
+ }
+ } else { // write
+ version = (options && options.version) ||
+ this.version || this.defaultVersion;
+ }
+ return version;
+ },
+
+ /**
+ * Method: getParser
+ * Get an instance of the cached parser if available, otherwise create one.
+ *
+ * Parameters:
+ * version - {String}
+ *
+ * Returns:
+ * {<OpenLayers.Format>}
+ */
+ getParser: function(version) {
+ version = version || this.defaultVersion;
+ var profile = this.profile ? "_" + this.profile : "";
+ if(!this.parser || this.parser.VERSION != version) {
+ var format = OpenLayers.Format[this.name][
+ "v" + version.replace(/\./g, "_") + profile
+ ];
+ if(!format) {
+ if (profile !== "" && this.allowFallback) {
+ // fallback to the non-profiled version of the parser
+ profile = "";
+ format = OpenLayers.Format[this.name][
+ "v" + version.replace(/\./g, "_")
+ ];
+ }
+ if (!format) {
+ throw "Can't find a " + this.name + " parser for version " +
+ version + profile;
+ }
+ }
+ this.parser = new format(this.options);
+ }
+ return this.parser;
+ },
+
+ /**
+ * APIMethod: write
+ * Write a document.
+ *
+ * Parameters:
+ * obj - {Object} An object representing the document.
+ * options - {Object} Optional configuration object.
+ *
+ * Returns:
+ * {String} The document as a string
+ */
+ write: function(obj, options) {
+ var version = this.getVersion(null, options);
+ this.parser = this.getParser(version);
+ var root = this.parser.write(obj, options);
+ if (this.stringifyOutput === false) {
+ return root;
+ } else {
+ return OpenLayers.Format.XML.prototype.write.apply(this, [root]);
+ }
+ },
+
+ /**
+ * APIMethod: read
+ * Read a doc and return an object representing the document.
+ *
+ * Parameters:
+ * data - {String | DOMElement} Data to read.
+ * options - {Object} Options for the reader.
+ *
+ * Returns:
+ * {Object} An object representing the document.
+ */
+ read: function(data, options) {
+ if(typeof data == "string") {
+ data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+ }
+ var root = data.documentElement;
+ var version = this.getVersion(root);
+ this.parser = this.getParser(version); // Select the parser
+ var obj = this.parser.read(data, options); // Parse the data
+
+ var errorProperty = this.parser.errorProperty || null;
+ if (errorProperty !== null && obj[errorProperty] === undefined) {
+ // an error must have happened, so parse it and report back
+ var format = new OpenLayers.Format.OGCExceptionReport();
+ obj.error = format.read(data);
+ }
+ obj.version = version;
+ return obj;
+ },
+
+ CLASS_NAME: "OpenLayers.Format.XML.VersionedOGC"
+});