From 0e8f0034ab4621d70e95708cc65d1cdc05817bcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ziela=C5=84ski?= Date: Mon, 15 Jun 2020 13:00:26 +0200 Subject: [PATCH] Creating an object that stores properties only when needed in BaseObject class --- src/ol/Feature.js | 4 +++- src/ol/Object.js | 29 ++++++++++++++++-------- src/ol/format/EsriJSON.js | 8 +++++-- src/ol/format/GML2.js | 45 ++++++++++++++++++++----------------- src/ol/format/GML3.js | 45 ++++++++++++++++++++----------------- src/ol/format/GeoJSON.js | 14 ++++++++---- test/spec/ol/object.test.js | 16 +++++++++++++ 7 files changed, 103 insertions(+), 58 deletions(-) diff --git a/src/ol/Feature.js b/src/ol/Feature.js index e636bb4b40..3056896278 100644 --- a/src/ol/Feature.js +++ b/src/ol/Feature.js @@ -128,7 +128,9 @@ class Feature extends BaseObject { * @api */ clone() { - const clone = new Feature(this.getProperties()); + const clone = new Feature( + this.hasProperties() ? this.getProperties() : undefined + ); clone.setGeometryName(this.getGeometryName()); const geometry = this.getGeometry(); if (geometry) { diff --git a/src/ol/Object.js b/src/ol/Object.js index a462129c10..2731dbd2a7 100644 --- a/src/ol/Object.js +++ b/src/ol/Object.js @@ -4,7 +4,7 @@ import Event from './events/Event.js'; import ObjectEventType from './ObjectEventType.js'; import Observable from './Observable.js'; -import {assign} from './obj.js'; +import {assign, isEmpty} from './obj.js'; import {getUid} from './util.js'; /** @@ -94,10 +94,10 @@ class BaseObject extends Observable { getUid(this); /** + * @name values_ * @private * @type {!Object} */ - this.values_ = {}; if (opt_values !== undefined) { this.setProperties(opt_values); @@ -112,7 +112,7 @@ class BaseObject extends Observable { */ get(key) { let value; - if (this.values_.hasOwnProperty(key)) { + if (this.values_ && this.values_.hasOwnProperty(key)) { value = this.values_[key]; } return value; @@ -124,7 +124,7 @@ class BaseObject extends Observable { * @api */ getKeys() { - return Object.keys(this.values_); + return (this.values_ && Object.keys(this.values_)) || []; } /** @@ -133,7 +133,14 @@ class BaseObject extends Observable { * @api */ getProperties() { - return assign({}, this.values_); + return (this.values_ && assign({}, this.values_)) || {}; + } + + /** + * @return {boolean} The object has properties. + */ + hasProperties() { + return !!this.values_; } /** @@ -156,11 +163,12 @@ class BaseObject extends Observable { * @api */ set(key, value, opt_silent) { + const values = this.values_ || (this.values_ = {}); if (opt_silent) { - this.values_[key] = value; + values[key] = value; } else { - const oldValue = this.values_[key]; - this.values_[key] = value; + const oldValue = values[key]; + values[key] = value; if (oldValue !== value) { this.notify(key, oldValue); } @@ -187,9 +195,12 @@ class BaseObject extends Observable { * @api */ unset(key, opt_silent) { - if (key in this.values_) { + if (this.values_ && key in this.values_) { const oldValue = this.values_[key]; delete this.values_[key]; + if (isEmpty(this.values_)) { + delete this.values_; + } if (!opt_silent) { this.notify(key, oldValue); } diff --git a/src/ol/format/EsriJSON.js b/src/ol/format/EsriJSON.js index 54294236bd..77973fdf2c 100644 --- a/src/ol/format/EsriJSON.js +++ b/src/ol/format/EsriJSON.js @@ -199,6 +199,11 @@ class EsriJSON extends JSONFeature { writeFeatureObject(feature, opt_options) { opt_options = this.adaptOptions(opt_options); const object = {}; + if (!feature.hasProperties()) { + object['attributes'] = {}; + return object; + } + const properties = feature.getProperties(); const geometry = feature.getGeometry(); if (geometry) { object['geometry'] = writeGeometry(geometry, opt_options); @@ -214,9 +219,8 @@ class EsriJSON extends JSONFeature { ), }); } + delete properties[feature.getGeometryName()]; } - const properties = feature.getProperties(); - delete properties[feature.getGeometryName()]; if (!isEmpty(properties)) { object['attributes'] = properties; } else { diff --git a/src/ol/format/GML2.js b/src/ol/format/GML2.js index cc85f92e4e..0d2cb67be8 100644 --- a/src/ol/format/GML2.js +++ b/src/ol/format/GML2.js @@ -212,29 +212,32 @@ class GML2 extends GMLBase { context.serializers = {}; context.serializers[featureNS] = {}; } - const properties = feature.getProperties(); const keys = []; const values = []; - for (const key in properties) { - const value = properties[key]; - if (value !== null) { - keys.push(key); - values.push(value); - if ( - key == geometryName || - typeof (/** @type {?} */ (value).getSimplifiedGeometry) === 'function' - ) { - if (!(key in context.serializers[featureNS])) { - context.serializers[featureNS][key] = makeChildAppender( - this.writeGeometryElement, - this - ); - } - } else { - if (!(key in context.serializers[featureNS])) { - context.serializers[featureNS][key] = makeChildAppender( - writeStringTextNode - ); + if (feature.hasProperties()) { + const properties = feature.getProperties(); + for (const key in properties) { + const value = properties[key]; + if (value !== null) { + keys.push(key); + values.push(value); + if ( + key == geometryName || + typeof (/** @type {?} */ (value).getSimplifiedGeometry) === + 'function' + ) { + if (!(key in context.serializers[featureNS])) { + context.serializers[featureNS][key] = makeChildAppender( + this.writeGeometryElement, + this + ); + } + } else { + if (!(key in context.serializers[featureNS])) { + context.serializers[featureNS][key] = makeChildAppender( + writeStringTextNode + ); + } } } } diff --git a/src/ol/format/GML3.js b/src/ol/format/GML3.js index 7692d3d23b..fb67e703ee 100644 --- a/src/ol/format/GML3.js +++ b/src/ol/format/GML3.js @@ -843,29 +843,32 @@ class GML3 extends GMLBase { context.serializers = {}; context.serializers[featureNS] = {}; } - const properties = feature.getProperties(); const keys = []; const values = []; - for (const key in properties) { - const value = properties[key]; - if (value !== null) { - keys.push(key); - values.push(value); - if ( - key == geometryName || - typeof (/** @type {?} */ (value).getSimplifiedGeometry) === 'function' - ) { - if (!(key in context.serializers[featureNS])) { - context.serializers[featureNS][key] = makeChildAppender( - this.writeGeometryElement, - this - ); - } - } else { - if (!(key in context.serializers[featureNS])) { - context.serializers[featureNS][key] = makeChildAppender( - writeStringTextNode - ); + if (feature.hasProperties()) { + const properties = feature.getProperties(); + for (const key in properties) { + const value = properties[key]; + if (value !== null) { + keys.push(key); + values.push(value); + if ( + key == geometryName || + typeof (/** @type {?} */ (value).getSimplifiedGeometry) === + 'function' + ) { + if (!(key in context.serializers[featureNS])) { + context.serializers[featureNS][key] = makeChildAppender( + this.writeGeometryElement, + this + ); + } + } else { + if (!(key in context.serializers[featureNS])) { + context.serializers[featureNS][key] = makeChildAppender( + writeStringTextNode + ); + } } } } diff --git a/src/ol/format/GeoJSON.js b/src/ol/format/GeoJSON.js index 93cc1b9a39..583215bdfc 100644 --- a/src/ol/format/GeoJSON.js +++ b/src/ol/format/GeoJSON.js @@ -207,16 +207,22 @@ class GeoJSON extends JSONFeature { object.id = id; } - const geometry = feature.getGeometry(); - if (geometry) { - object.geometry = writeGeometry(geometry, opt_options); + if (!feature.hasProperties()) { + return object; } const properties = feature.getProperties(); - delete properties[feature.getGeometryName()]; + const geometry = feature.getGeometry(); + if (geometry) { + object.geometry = writeGeometry(geometry, opt_options); + + delete properties[feature.getGeometryName()]; + } + if (!isEmpty(properties)) { object.properties = properties; } + return object; } diff --git a/test/spec/ol/object.test.js b/test/spec/ol/object.test.js index 353c367e01..b3529b27c2 100644 --- a/test/spec/ol/object.test.js +++ b/test/spec/ol/object.test.js @@ -101,6 +101,22 @@ describe('ol.Object', function () { }); }); + describe('hasProperties', function () { + it('has no properties after creation', function () { + expect(o.hasProperties()).to.eql(false); + }); + + it('has properties after set', function () { + o.set('foo', 1); + expect(o.hasProperties()).to.eql(true); + }); + + it('has no properties after unset all', function () { + o.unset('foo'); + expect(o.hasProperties()).to.eql(false); + }); + }); + describe('notify', function () { let listener1, listener2;