Support for unique collections

This commit is contained in:
Tim Schaub
2017-04-11 21:29:30 -06:00
parent 8b0e1b638b
commit d28f50465b
3 changed files with 117 additions and 1 deletions

View File

@@ -8,6 +8,21 @@ var olx;
/* typedefs for object literals provided by applications */
/**
* @typedef {{unique: (boolean|undefined)}}
*/
olx.CollectionOptions;
/**
* Disallow the same item from being added to the collection twice. Default is
* false.
* @type {boolean|undefined}
* @api
*/
olx.CollectionOptions.prototype.unique;
/**
* @typedef {{html: string,
* tileRanges: (Object.<string, Array.<ol.TileRange>>|undefined)}}

View File

@@ -23,19 +23,34 @@ goog.require('ol.events.Event');
* @extends {ol.Object}
* @fires ol.Collection.Event
* @param {!Array.<T>=} opt_array Array.
* @param {olx.CollectionOptions=} opt_options Collection options.
* @template T
* @api
*/
ol.Collection = function(opt_array) {
ol.Collection = function(opt_array, opt_options) {
ol.Object.call(this);
var options = opt_options || {};
/**
* @private
* @type {boolean}
*/
this.unique_ = !!options.unique;
/**
* @private
* @type {!Array.<T>}
*/
this.array_ = opt_array ? opt_array : [];
if (this.unique_) {
for (var i = 0, ii = this.array_.length; i < ii; ++i) {
this.assertUnique_(this.array_[i], i);
}
}
this.updateLength_();
};
@@ -125,6 +140,9 @@ ol.Collection.prototype.getLength = function() {
* @api
*/
ol.Collection.prototype.insertAt = function(index, elem) {
if (this.unique_) {
this.assertUnique_(elem);
}
this.array_.splice(index, 0, elem);
this.updateLength_();
this.dispatchEvent(
@@ -150,6 +168,9 @@ ol.Collection.prototype.pop = function() {
* @api
*/
ol.Collection.prototype.push = function(elem) {
if (this.unique_) {
this.assertUnique_(elem);
}
var n = this.getLength();
this.insertAt(n, elem);
return this.getLength();
@@ -200,6 +221,9 @@ ol.Collection.prototype.removeAt = function(index) {
ol.Collection.prototype.setAt = function(index, elem) {
var n = this.getLength();
if (index < n) {
if (this.unique_) {
this.assertUnique_(elem, index);
}
var prev = this.array_[index];
this.array_[index] = elem;
this.dispatchEvent(
@@ -224,6 +248,20 @@ ol.Collection.prototype.updateLength_ = function() {
};
/**
* @private
* @param {T} elem Element.
* @param {number=} opt_except Optional index to ignore.
*/
ol.Collection.prototype.assertUnique_ = function(elem, opt_except) {
for (var i = 0, ii = this.array_.length; i < ii; ++i) {
if (this.array_[i] === elem && i !== opt_except) {
throw new Error('Duplicate item added to a unique collection');
}
}
};
/**
* @enum {string}
* @private

View File

@@ -298,4 +298,67 @@ describe('ol.collection', function() {
});
});
describe('unique collection', function() {
it('allows unique items in the constructor', function() {
new ol.Collection([{}, {}, {}], {unique: true});
});
it('throws if duplicate items are passed to the contructor', function() {
var item = {};
var call = function() {
new ol.Collection([item, item], {unique: true});
};
expect(call).to.throwException();
});
it('allows unique items to be added via push', function() {
var unique = new ol.Collection(undefined, {unique: true});
unique.push({});
unique.push({});
});
it('throws if duplicate items are added via push', function() {
var unique = new ol.Collection(undefined, {unique: true});
var item = {};
unique.push(item);
var call = function() {
unique.push(item);
};
expect(call).to.throwException();
});
it('allows unique items to be added via insertAt', function() {
var unique = new ol.Collection(undefined, {unique: true});
unique.insertAt(0, {});
unique.insertAt(0, {});
});
it('throws if duplicate items are added via insertAt', function() {
var unique = new ol.Collection(undefined, {unique: true});
var item = {};
unique.insertAt(0, item);
var call = function() {
unique.insertAt(0, item);
};
expect(call).to.throwException();
});
it('allows unique items to be added via setAt', function() {
var unique = new ol.Collection(undefined, {unique: true});
unique.setAt(0, {});
unique.setAt(1, {});
});
it('throws if duplicate items are added via setAt', function() {
var unique = new ol.Collection(undefined, {unique: true});
var item = {};
unique.setAt(0, item);
var call = function() {
unique.setAt(1, item);
};
expect(call).to.throwException();
});
});
});