var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); /** * @module ol/format/GMLBase */ // FIXME Envelopes should not be treated as geometries! readEnvelope_ is part // of GEOMETRY_PARSERS_ and methods using GEOMETRY_PARSERS_ do not expect // envelopes/extents, only geometries! import Feature from '../Feature.js'; import GeometryLayout from '../geom/GeometryLayout.js'; import LineString from '../geom/LineString.js'; import LinearRing from '../geom/LinearRing.js'; import MultiLineString from '../geom/MultiLineString.js'; import MultiPoint from '../geom/MultiPoint.js'; import MultiPolygon from '../geom/MultiPolygon.js'; import Point from '../geom/Point.js'; import Polygon from '../geom/Polygon.js'; import XMLFeature from './XMLFeature.js'; import { assign } from '../obj.js'; import { extend } from '../array.js'; import { getAllTextContent, getAttributeNS, makeArrayPusher, makeReplacer, parseNode, pushParseAndPop, } from '../xml.js'; import { get as getProjection } from '../proj.js'; import { transformExtentWithOptions, transformGeometryWithOptions, } from './Feature.js'; /** * @const * @type {string} */ export var GMLNS = 'http://www.opengis.net/gml'; /** * A regular expression that matches if a string only contains whitespace * characters. It will e.g. match `''`, `' '`, `'\n'` etc. The non-breaking * space (0xa0) is explicitly included as IE doesn't include it in its * definition of `\s`. * * Information from `goog.string.isEmptyOrWhitespace`: https://github.com/google/closure-library/blob/e877b1e/closure/goog/string/string.js#L156-L160 * * @const * @type {RegExp} */ var ONLY_WHITESPACE_RE = /^[\s\xa0]*$/; /** * @typedef {Object} Options * @property {Object|string} [featureNS] Feature * namespace. If not defined will be derived from GML. If multiple * feature types have been configured which come from different feature * namespaces, this will be an object with the keys being the prefixes used * in the entries of featureType array. The values of the object will be the * feature namespaces themselves. So for instance there might be a featureType * item `topp:states` in the `featureType` array and then there will be a key * `topp` in the featureNS object with value `http://www.openplans.org/topp`. * @property {Array|string} [featureType] Feature type(s) to parse. * If multiple feature types need to be configured * which come from different feature namespaces, `featureNS` will be an object * with the keys being the prefixes used in the entries of featureType array. * The values of the object will be the feature namespaces themselves. * So for instance there might be a featureType item `topp:states` and then * there will be a key named `topp` in the featureNS object with value * `http://www.openplans.org/topp`. * @property {string} srsName srsName to use when writing geometries. * @property {boolean} [surface=false] Write gml:Surface instead of gml:Polygon * elements. This also affects the elements in multi-part geometries. * @property {boolean} [curve=false] Write gml:Curve instead of gml:LineString * elements. This also affects the elements in multi-part geometries. * @property {boolean} [multiCurve=true] Write gml:MultiCurve instead of gml:MultiLineString. * Since the latter is deprecated in GML 3. * @property {boolean} [multiSurface=true] Write gml:multiSurface instead of * gml:MultiPolygon. Since the latter is deprecated in GML 3. * @property {string} [schemaLocation] Optional schemaLocation to use when * writing out the GML, this will override the default provided. * @property {boolean} [hasZ=false] If coordinates have a Z value. */ /** * @classdesc * Abstract base class; normally only used for creating subclasses and not * instantiated in apps. * Feature base format for reading and writing data in the GML format. * This class cannot be instantiated, it contains only base content that * is shared with versioned format classes GML2 and GML3. * * @abstract * @api */ var GMLBase = /** @class */ (function (_super) { __extends(GMLBase, _super); /** * @param {Options} [opt_options] Optional configuration object. */ function GMLBase(opt_options) { var _this = _super.call(this) || this; var options = /** @type {Options} */ (opt_options ? opt_options : {}); /** * @protected * @type {Array|string|undefined} */ _this.featureType = options.featureType; /** * @protected * @type {Object|string|undefined} */ _this.featureNS = options.featureNS; /** * @protected * @type {string} */ _this.srsName = options.srsName; /** * @protected * @type {string} */ _this.schemaLocation = ''; /** * @type {Object>} */ _this.FEATURE_COLLECTION_PARSERS = {}; _this.FEATURE_COLLECTION_PARSERS[_this.namespace] = { 'featureMember': makeArrayPusher(_this.readFeaturesInternal), 'featureMembers': makeReplacer(_this.readFeaturesInternal), }; _this.supportedMediaTypes = ['application/gml+xml']; return _this; } /** * @param {Element} node Node. * @param {Array<*>} objectStack Object stack. * @return {Array | undefined} Features. */ GMLBase.prototype.readFeaturesInternal = function (node, objectStack) { var localName = node.localName; var features = null; if (localName == 'FeatureCollection') { features = pushParseAndPop([], this.FEATURE_COLLECTION_PARSERS, node, objectStack, this); } else if (localName == 'featureMembers' || localName == 'featureMember' || localName == 'member') { var context = objectStack[0]; var featureType = context['featureType']; var featureNS = context['featureNS']; var prefix = 'p'; var defaultPrefix = 'p0'; if (!featureType && node.childNodes) { (featureType = []), (featureNS = {}); for (var i = 0, ii = node.childNodes.length; i < ii; ++i) { var child = /** @type {Element} */ (node.childNodes[i]); if (child.nodeType === 1) { var ft = child.nodeName.split(':').pop(); if (featureType.indexOf(ft) === -1) { var key = ''; var count = 0; var uri = child.namespaceURI; for (var candidate in featureNS) { if (featureNS[candidate] === uri) { key = candidate; break; } ++count; } if (!key) { key = prefix + count; featureNS[key] = uri; } featureType.push(key + ':' + ft); } } } if (localName != 'featureMember') { // recheck featureType for each featureMember context['featureType'] = featureType; context['featureNS'] = featureNS; } } if (typeof featureNS === 'string') { var ns = featureNS; featureNS = {}; featureNS[defaultPrefix] = ns; } /** @type {Object>} */ var parsersNS = {}; var featureTypes = Array.isArray(featureType) ? featureType : [featureType]; for (var p in featureNS) { /** @type {Object} */ var parsers = {}; for (var i = 0, ii = featureTypes.length; i < ii; ++i) { var featurePrefix = featureTypes[i].indexOf(':') === -1 ? defaultPrefix : featureTypes[i].split(':')[0]; if (featurePrefix === p) { parsers[featureTypes[i].split(':').pop()] = localName == 'featureMembers' ? makeArrayPusher(this.readFeatureElement, this) : makeReplacer(this.readFeatureElement, this); } } parsersNS[featureNS[p]] = parsers; } if (localName == 'featureMember' || localName == 'member') { features = pushParseAndPop(undefined, parsersNS, node, objectStack); } else { features = pushParseAndPop([], parsersNS, node, objectStack); } } if (features === null) { features = []; } return features; }; /** * @param {Element} node Node. * @param {Array<*>} objectStack Object stack. * @return {import("../geom/Geometry.js").default|import("../extent.js").Extent|undefined} Geometry. */ GMLBase.prototype.readGeometryOrExtent = function (node, objectStack) { var context = /** @type {Object} */ (objectStack[0]); context['srsName'] = node.firstElementChild.getAttribute('srsName'); context['srsDimension'] = node.firstElementChild.getAttribute('srsDimension'); return pushParseAndPop(null, this.GEOMETRY_PARSERS, node, objectStack, this); }; /** * @param {Element} node Node. * @param {Array<*>} objectStack Object stack. * @return {import("../extent.js").Extent|undefined} Geometry. */ GMLBase.prototype.readExtentElement = function (node, objectStack) { var context = /** @type {Object} */ (objectStack[0]); var extent = /** @type {import("../extent.js").Extent} */ (this.readGeometryOrExtent(node, objectStack)); return extent ? transformExtentWithOptions(extent, context) : undefined; }; /** * @param {Element} node Node. * @param {Array<*>} objectStack Object stack. * @return {import("../geom/Geometry.js").default|undefined} Geometry. */ GMLBase.prototype.readGeometryElement = function (node, objectStack) { var context = /** @type {Object} */ (objectStack[0]); var geometry = /** @type {import("../geom/Geometry.js").default} */ (this.readGeometryOrExtent(node, objectStack)); return geometry ? transformGeometryWithOptions(geometry, false, context) : undefined; }; /** * @param {Element} node Node. * @param {Array<*>} objectStack Object stack. * @param {boolean} asFeature whether result should be wrapped as a feature. * @return {Feature|Object} Feature */ GMLBase.prototype.readFeatureElementInternal = function (node, objectStack, asFeature) { var geometryName; var values = {}; for (var n = node.firstElementChild; n; n = n.nextElementSibling) { var value = void 0; var localName = n.localName; // first, check if it is simple attribute if (n.childNodes.length === 0 || (n.childNodes.length === 1 && (n.firstChild.nodeType === 3 || n.firstChild.nodeType === 4))) { value = getAllTextContent(n, false); if (ONLY_WHITESPACE_RE.test(value)) { value = undefined; } } else { if (asFeature) { //if feature, try it as a geometry or extent value = localName === 'boundedBy' ? this.readExtentElement(n, objectStack) : this.readGeometryElement(n, objectStack); } if (!value) { //if not a geometry or not a feature, treat it as a complex attribute value = this.readFeatureElementInternal(n, objectStack, false); } else if (localName !== 'boundedBy') { // boundedBy is an extent and must not be considered as a geometry geometryName = localName; } } var len = n.attributes.length; if (len > 0) { value = { _content_: value }; for (var i = 0; i < len; i++) { var attName = n.attributes[i].name; value[attName] = n.attributes[i].value; } } if (values[localName]) { if (!(values[localName] instanceof Array)) { values[localName] = [values[localName]]; } values[localName].push(value); } else { values[localName] = value; } } if (!asFeature) { return values; } else { var feature = new Feature(values); if (geometryName) { feature.setGeometryName(geometryName); } var fid = node.getAttribute('fid') || getAttributeNS(node, this.namespace, 'id'); if (fid) { feature.setId(fid); } return feature; } }; /** * @param {Element} node Node. * @param {Array<*>} objectStack Object stack. * @return {Feature} Feature. */ GMLBase.prototype.readFeatureElement = function (node, objectStack) { return this.readFeatureElementInternal(node, objectStack, true); }; /** * @param {Element} node Node. * @param {Array<*>} objectStack Object stack. * @return {Point|undefined} Point. */ GMLBase.prototype.readPoint = function (node, objectStack) { var flatCoordinates = this.readFlatCoordinatesFromNode(node, objectStack); if (flatCoordinates) { return new Point(flatCoordinates, GeometryLayout.XYZ); } }; /** * @param {Element} node Node. * @param {Array<*>} objectStack Object stack. * @return {MultiPoint|undefined} MultiPoint. */ GMLBase.prototype.readMultiPoint = function (node, objectStack) { /** @type {Array>} */ var coordinates = pushParseAndPop([], this.MULTIPOINT_PARSERS, node, objectStack, this); if (coordinates) { return new MultiPoint(coordinates); } else { return undefined; } }; /** * @param {Element} node Node. * @param {Array<*>} objectStack Object stack. * @return {MultiLineString|undefined} MultiLineString. */ GMLBase.prototype.readMultiLineString = function (node, objectStack) { /** @type {Array} */ var lineStrings = pushParseAndPop([], this.MULTILINESTRING_PARSERS, node, objectStack, this); if (lineStrings) { return new MultiLineString(lineStrings); } }; /** * @param {Element} node Node. * @param {Array<*>} objectStack Object stack. * @return {MultiPolygon|undefined} MultiPolygon. */ GMLBase.prototype.readMultiPolygon = function (node, objectStack) { /** @type {Array} */ var polygons = pushParseAndPop([], this.MULTIPOLYGON_PARSERS, node, objectStack, this); if (polygons) { return new MultiPolygon(polygons); } }; /** * @param {Element} node Node. * @param {Array<*>} objectStack Object stack. */ GMLBase.prototype.pointMemberParser = function (node, objectStack) { parseNode(this.POINTMEMBER_PARSERS, node, objectStack, this); }; /** * @param {Element} node Node. * @param {Array<*>} objectStack Object stack. */ GMLBase.prototype.lineStringMemberParser = function (node, objectStack) { parseNode(this.LINESTRINGMEMBER_PARSERS, node, objectStack, this); }; /** * @param {Element} node Node. * @param {Array<*>} objectStack Object stack. */ GMLBase.prototype.polygonMemberParser = function (node, objectStack) { parseNode(this.POLYGONMEMBER_PARSERS, node, objectStack, this); }; /** * @param {Element} node Node. * @param {Array<*>} objectStack Object stack. * @return {LineString|undefined} LineString. */ GMLBase.prototype.readLineString = function (node, objectStack) { var flatCoordinates = this.readFlatCoordinatesFromNode(node, objectStack); if (flatCoordinates) { var lineString = new LineString(flatCoordinates, GeometryLayout.XYZ); return lineString; } else { return undefined; } }; /** * @param {Element} node Node. * @param {Array<*>} objectStack Object stack. * @return {Array|undefined} LinearRing flat coordinates. */ GMLBase.prototype.readFlatLinearRing = function (node, objectStack) { var ring = pushParseAndPop(null, this.GEOMETRY_FLAT_COORDINATES_PARSERS, node, objectStack, this); if (ring) { return ring; } else { return undefined; } }; /** * @param {Element} node Node. * @param {Array<*>} objectStack Object stack. * @return {LinearRing|undefined} LinearRing. */ GMLBase.prototype.readLinearRing = function (node, objectStack) { var flatCoordinates = this.readFlatCoordinatesFromNode(node, objectStack); if (flatCoordinates) { return new LinearRing(flatCoordinates, GeometryLayout.XYZ); } }; /** * @param {Element} node Node. * @param {Array<*>} objectStack Object stack. * @return {Polygon|undefined} Polygon. */ GMLBase.prototype.readPolygon = function (node, objectStack) { /** @type {Array>} */ var flatLinearRings = pushParseAndPop([null], this.FLAT_LINEAR_RINGS_PARSERS, node, objectStack, this); if (flatLinearRings && flatLinearRings[0]) { var flatCoordinates = flatLinearRings[0]; var ends = [flatCoordinates.length]; var i = void 0, ii = void 0; for (i = 1, ii = flatLinearRings.length; i < ii; ++i) { extend(flatCoordinates, flatLinearRings[i]); ends.push(flatCoordinates.length); } return new Polygon(flatCoordinates, GeometryLayout.XYZ, ends); } else { return undefined; } }; /** * @param {Element} node Node. * @param {Array<*>} objectStack Object stack. * @return {Array} Flat coordinates. */ GMLBase.prototype.readFlatCoordinatesFromNode = function (node, objectStack) { return pushParseAndPop(null, this.GEOMETRY_FLAT_COORDINATES_PARSERS, node, objectStack, this); }; /** * @param {Element} node Node. * @param {import("./Feature.js").ReadOptions} [opt_options] Options. * @protected * @return {import("../geom/Geometry.js").default} Geometry. */ GMLBase.prototype.readGeometryFromNode = function (node, opt_options) { var geometry = this.readGeometryElement(node, [ this.getReadOptions(node, opt_options ? opt_options : {}), ]); return geometry ? geometry : null; }; /** * @param {Element} node Node. * @param {import("./Feature.js").ReadOptions} [opt_options] Options. * @return {Array} Features. */ GMLBase.prototype.readFeaturesFromNode = function (node, opt_options) { var options = { featureType: this.featureType, featureNS: this.featureNS, }; if (opt_options) { assign(options, this.getReadOptions(node, opt_options)); } var features = this.readFeaturesInternal(node, [options]); return features || []; }; /** * @param {Element} node Node. * @return {import("../proj/Projection.js").default} Projection. */ GMLBase.prototype.readProjectionFromNode = function (node) { return getProjection(this.srsName ? this.srsName : node.firstElementChild.getAttribute('srsName')); }; return GMLBase; }(XMLFeature)); GMLBase.prototype.namespace = GMLNS; /** * @const * @type {Object>} */ GMLBase.prototype.FLAT_LINEAR_RINGS_PARSERS = { 'http://www.opengis.net/gml': {}, }; /** * @const * @type {Object>} */ GMLBase.prototype.GEOMETRY_FLAT_COORDINATES_PARSERS = { 'http://www.opengis.net/gml': {}, }; /** * @const * @type {Object>} */ GMLBase.prototype.GEOMETRY_PARSERS = { 'http://www.opengis.net/gml': {}, }; /** * @const * @type {Object>} */ GMLBase.prototype.MULTIPOINT_PARSERS = { 'http://www.opengis.net/gml': { 'pointMember': makeArrayPusher(GMLBase.prototype.pointMemberParser), 'pointMembers': makeArrayPusher(GMLBase.prototype.pointMemberParser), }, }; /** * @const * @type {Object>} */ GMLBase.prototype.MULTILINESTRING_PARSERS = { 'http://www.opengis.net/gml': { 'lineStringMember': makeArrayPusher(GMLBase.prototype.lineStringMemberParser), 'lineStringMembers': makeArrayPusher(GMLBase.prototype.lineStringMemberParser), }, }; /** * @const * @type {Object>} */ GMLBase.prototype.MULTIPOLYGON_PARSERS = { 'http://www.opengis.net/gml': { 'polygonMember': makeArrayPusher(GMLBase.prototype.polygonMemberParser), 'polygonMembers': makeArrayPusher(GMLBase.prototype.polygonMemberParser), }, }; /** * @const * @type {Object>} */ GMLBase.prototype.POINTMEMBER_PARSERS = { 'http://www.opengis.net/gml': { 'Point': makeArrayPusher(GMLBase.prototype.readFlatCoordinatesFromNode), }, }; /** * @const * @type {Object>} */ GMLBase.prototype.LINESTRINGMEMBER_PARSERS = { 'http://www.opengis.net/gml': { 'LineString': makeArrayPusher(GMLBase.prototype.readLineString), }, }; /** * @const * @type {Object>} */ GMLBase.prototype.POLYGONMEMBER_PARSERS = { 'http://www.opengis.net/gml': { 'Polygon': makeArrayPusher(GMLBase.prototype.readPolygon), }, }; /** * @const * @type {Object>} */ GMLBase.prototype.RING_PARSERS = { 'http://www.opengis.net/gml': { 'LinearRing': makeReplacer(GMLBase.prototype.readFlatLinearRing), }, }; export default GMLBase; //# sourceMappingURL=GMLBase.js.map