From b4043398ebe24379483e4a6f812bec9008ef2644 Mon Sep 17 00:00:00 2001 From: ahocevar Date: Fri, 21 Feb 2014 07:18:42 +0100 Subject: [PATCH] Added wpt serialization for ol.format.GPX --- src/ol/format/gpxformat.js | 214 ++++++++++++++++++++++++++ test/spec/ol/format/gpxformat.test.js | 25 ++- 2 files changed, 234 insertions(+), 5 deletions(-) diff --git a/src/ol/format/gpxformat.js b/src/ol/format/gpxformat.js index ded218bcaa..b649df728b 100644 --- a/src/ol/format/gpxformat.js +++ b/src/ol/format/gpxformat.js @@ -1,4 +1,5 @@ goog.provide('ol.format.GPX'); +goog.provide('ol.format.GPX.v1_1'); goog.require('goog.array'); goog.require('goog.asserts'); @@ -420,3 +421,216 @@ ol.format.GPX.prototype.readProjectionFromDocument = function(doc) { ol.format.GPX.prototype.readProjectionFromNode = function(node) { return ol.proj.get('EPSG:4326'); }; + + +/** + * @const + * @type {Array.} + * @private + */ +ol.format.GPX.LINK_SEQUENCE_ = ['text', 'type']; + + +/** + * @type {Object.>} + * @private + */ +ol.format.GPX.LINK_SERIALIZERS_ = ol.xml.makeStructureNS( + ol.format.GPX.NAMESPACE_URIS_, { + 'text': ol.xml.makeChildAppender(ol.xml.makeSimpleTypeWriter( + ol.format.XSD.writeStringTextNode)), + 'type': ol.xml.makeChildAppender(ol.xml.makeSimpleTypeWriter( + ol.format.XSD.writeStringTextNode)) + }); + + +/** + * @param {Node} node Node. + * @param {string} value Value for the link's `href` attribute. + * @param {Array.<*>} objectStack Node stack. + * @private + */ +ol.format.GPX.writeLink_ = function(node, value, objectStack) { + node.setAttribute('href', value); + var properties = objectStack[objectStack.length - 1].context; + var link = [ + goog.object.get(properties, 'linkText'), + goog.object.get(properties, 'linkType') + ]; + ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */ ({node: node}), + ol.format.GPX.LINK_SERIALIZERS_, + ol.xml.makeChildNodeFactory(node.namespaceURI), link, objectStack, + ol.format.GPX.LINK_SEQUENCE_); +}; + + +/** + * @const + * @type {Object.>} + * @private + */ +ol.format.GPX.WPT_SEQUENCE_ = ol.xml.makeStructureNS( + ol.format.GPX.NAMESPACE_URIS_, [ + 'ele', 'time', 'magvar', 'geoidheight', 'name', 'cmt', 'desc', 'src', + 'link', 'sym', 'type', 'fix', 'sat', 'hdop', 'vdop', 'pdop', + 'ageofdgpsdata', 'dgpsid' + ]); + + +/** + * @type {Object.>} + * @private + */ +ol.format.GPX.WPT_SERIALIZERS_ = ol.xml.makeStructureNS( + ol.format.GPX.NAMESPACE_URIS_, { + 'ele': ol.xml.makeChildAppender(ol.xml.makeSimpleTypeWriter( + ol.format.XSD.writeDecimalTextNode)), + 'time': ol.xml.makeChildAppender(ol.xml.makeSimpleTypeWriter( + ol.format.XSD.writeDateTimeTextNode)), + 'magvar': ol.xml.makeChildAppender(ol.xml.makeSimpleTypeWriter( + ol.format.XSD.writeDecimalTextNode)), + 'geoidheight': ol.xml.makeChildAppender(ol.xml.makeSimpleTypeWriter( + ol.format.XSD.writeDecimalTextNode)), + 'name': ol.xml.makeChildAppender(ol.xml.makeSimpleTypeWriter( + ol.format.XSD.writeStringTextNode)), + 'cmt': ol.xml.makeChildAppender(ol.xml.makeSimpleTypeWriter( + ol.format.XSD.writeStringTextNode)), + 'desc': ol.xml.makeChildAppender(ol.xml.makeSimpleTypeWriter( + ol.format.XSD.writeStringTextNode)), + 'src': ol.xml.makeChildAppender(ol.xml.makeSimpleTypeWriter( + ol.format.XSD.writeStringTextNode)), + 'link': ol.xml.makeChildAppender(ol.format.GPX.writeLink_), + 'sym': ol.xml.makeChildAppender(ol.xml.makeSimpleTypeWriter( + ol.format.XSD.writeStringTextNode)), + 'type': ol.xml.makeChildAppender(ol.xml.makeSimpleTypeWriter( + ol.format.XSD.writeStringTextNode)), + 'fix': ol.xml.makeChildAppender(ol.xml.makeSimpleTypeWriter( + ol.format.XSD.writeStringTextNode)), + 'sat': ol.xml.makeChildAppender(ol.xml.makeSimpleTypeWriter( + ol.format.XSD.writeNonNegativeIntegerTextNode)), + 'hdop': ol.xml.makeChildAppender(ol.xml.makeSimpleTypeWriter( + ol.format.XSD.writeDecimalTextNode)), + 'vdop': ol.xml.makeChildAppender(ol.xml.makeSimpleTypeWriter( + ol.format.XSD.writeDecimalTextNode)), + 'pdop': ol.xml.makeChildAppender(ol.xml.makeSimpleTypeWriter( + ol.format.XSD.writeDecimalTextNode)), + 'ageofdgpsdata': ol.xml.makeChildAppender(ol.xml.makeSimpleTypeWriter( + ol.format.XSD.writeDecimalTextNode)), + 'dgpsid': ol.xml.makeChildAppender(ol.xml.makeSimpleTypeWriter( + ol.format.XSD.writeNonNegativeIntegerTextNode)) + }); + + +/** + * @const + * @type {Object.} + * @private + */ +ol.format.GPX.GEOMETRY_TYPE_TO_NODENAME_ = { + 'Point': 'wpt', + 'LineString': 'rte', + 'MultiLineString': 'trk' +}; + + +/** + * @const + * @param {*} feature Feature. + * @param {Array.<*>} objectStack Object stack. + * @param {string=} opt_nodeName Node name. + * @return {Node} Node. + * @private + */ +ol.format.GPX.GPX_NODE_FACTORY_ = function(feature, objectStack, opt_nodeName) { + goog.asserts.assertInstanceof(feature, ol.Feature); + var geometry = feature.getGeometry(); + if (goog.isDef(geometry)) { + var parentNode = objectStack[objectStack.length - 1].node; + goog.asserts.assert(ol.xml.isNode(parentNode)); + return ol.xml.createElementNS(parentNode.namespaceURI, + ol.format.GPX.GEOMETRY_TYPE_TO_NODENAME_[geometry.getType()]); + } +}; + + +/** + * @param {Node} node Node. + * @param {ol.Feature} feature Feature. + * @param {Array.<*>} objectStack Object stack. + * @private + * @template T + */ +ol.format.GPX.writeWpt_ = function(node, feature, objectStack) { + var parentNode = objectStack[objectStack.length - 1].node; + goog.asserts.assert(ol.xml.isNode(parentNode)); + var namespaceURI = parentNode.namespaceURI; + var properties = feature.getProperties(); + var geometry = feature.getGeometry(); + if (goog.isDef(geometry)) { + goog.asserts.assert(geometry instanceof ol.geom.Point); + var coordinates = geometry.getCoordinates(); + //FIXME Projection handling + ol.xml.setAttributeNS(node, null, 'lat', coordinates[1]); + ol.xml.setAttributeNS(node, null, 'lon', coordinates[0]); + var geometryLayout = geometry.getLayout(); + switch (geometryLayout) { + case ol.geom.GeometryLayout.XYZM: + if (coordinates[3] !== 0) { + goog.object.set(properties, 'time', coordinates[3]); + } + case ol.geom.GeometryLayout.XYZ: + if (coordinates[2] !== 0) { + goog.object.set(properties, 'ele', coordinates[2]); + } + break; + case ol.geom.GeometryLayout.XYM: + if (coordinates[2] !== 0) { + goog.object.set(properties, 'time', coordinates[2]); + } + } + } + var orderedKeys = ol.format.GPX.WPT_SEQUENCE_[namespaceURI]; + var values = ol.xml.makeSequence(properties, orderedKeys); + ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */ + ({node: node, context: properties}), ol.format.GPX.WPT_SERIALIZERS_, + ol.xml.makeChildNodeFactory(namespaceURI), values, objectStack, + orderedKeys); +}; + + +/** + * @const + * @type {Object.>} + * @private + */ +ol.format.GPX.GPX_SERIALIZERS_ = ol.xml.makeStructureNS( + ol.format.GPX.NAMESPACE_URIS_, { + //'LineString': ol.xml.makeChildAppender(ol.format.GPX.writeRte_), + //'MultiLineString': ol.xml.makeChildAppender(ol.format.GPX.writeTrk_), + 'wpt': ol.xml.makeChildAppender(ol.format.GPX.writeWpt_) + }); + + + +/** + * @constructor + * @extends {ol.format.GPX} + * @todo stability experimental + */ +ol.format.GPX.V1_1 = function() { + goog.base(this); +}; +goog.inherits(ol.format.GPX.V1_1, ol.format.GPX); + + +/** + * @inheritDoc + */ +ol.format.GPX.V1_1.prototype.writeFeaturesNode = function(features) { + //FIXME Serialize metadata + var gpx = ol.xml.createElementNS(ol.format.GPX.NAMESPACE_URIS_[2], 'gpx'); + ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */ + ({node: gpx}), ol.format.GPX.GPX_SERIALIZERS_, + ol.format.GPX.GPX_NODE_FACTORY_, features, []); + return gpx; +}; diff --git a/test/spec/ol/format/gpxformat.test.js b/test/spec/ol/format/gpxformat.test.js index b146289a61..4da5a8d58c 100644 --- a/test/spec/ol/format/gpxformat.test.js +++ b/test/spec/ol/format/gpxformat.test.js @@ -214,7 +214,11 @@ describe('ol.format.GPX', function() { describe('wpt', function() { - it('can read a wpt', function() { + beforeEach(function() { + format = new ol.format.GPX.V1_1(); + }); + + it('can read and write a wpt', function() { var text = '' + ' ' + @@ -227,9 +231,11 @@ describe('ol.format.GPX', function() { expect(g).to.be.an(ol.geom.Point); expect(g.getCoordinates()).to.eql([2, 1, 0, 0]); expect(g.getLayout()).to.be(ol.geom.GeometryLayout.XYZM); + var serialized = format.writeFeatures(fs); + expect(serialized).to.xmleql(ol.xml.load(text)); }); - it('can read a wpt with ele', function() { + it('can read and write a wpt with ele', function() { var text = '' + ' ' + @@ -244,9 +250,11 @@ describe('ol.format.GPX', function() { expect(g).to.be.an(ol.geom.Point); expect(g.getCoordinates()).to.eql([2, 1, 3, 0]); expect(g.getLayout()).to.be(ol.geom.GeometryLayout.XYZM); + var serialized = format.writeFeatures(fs); + expect(serialized).to.xmleql(ol.xml.load(text)); }); - it('can read a wpt with time', function() { + it('can read and write a wpt with time', function() { var text = '' + ' ' + @@ -261,9 +269,11 @@ describe('ol.format.GPX', function() { expect(g).to.be.an(ol.geom.Point); expect(g.getCoordinates()).to.eql([2, 1, 0, 1263115752]); expect(g.getLayout()).to.be(ol.geom.GeometryLayout.XYZM); + var serialized = format.writeFeatures(fs); + expect(serialized).to.xmleql(ol.xml.load(text)); }); - it('can read a wpt with ele and time', function() { + it('can read and write a wpt with ele and time', function() { var text = '' + ' ' + @@ -279,9 +289,11 @@ describe('ol.format.GPX', function() { expect(g).to.be.an(ol.geom.Point); expect(g.getCoordinates()).to.eql([2, 1, 3, 1263115752]); expect(g.getLayout()).to.be(ol.geom.GeometryLayout.XYZM); + var serialized = format.writeFeatures(fs); + expect(serialized).to.xmleql(ol.xml.load(text)); }); - it('can read various wpt attributes', function() { + it('can read and write various wpt attributes', function() { var text = '' + ' ' + @@ -327,6 +339,8 @@ describe('ol.format.GPX', function() { expect(f.get('pdop')).to.be(8); expect(f.get('ageofdgpsdata')).to.be(9); expect(f.get('dgpsid')).to.be(10); + var serialized = format.writeFeatures(fs); + expect(serialized).to.xmleql(ol.xml.load(text)); }); }); @@ -378,3 +392,4 @@ goog.require('ol.format.GPX'); goog.require('ol.geom.LineString'); goog.require('ol.geom.MultiLineString'); goog.require('ol.geom.Point'); +goog.require('ol.xml');