diff options
Diffstat (limited to 'misc/openlayers/lib/OpenLayers/Format/OWSContext/v0_3_1.js')
-rw-r--r-- | misc/openlayers/lib/OpenLayers/Format/OWSContext/v0_3_1.js | 595 |
1 files changed, 595 insertions, 0 deletions
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" + +}); |