semantic-network
Version:
A utility library for manipulating a list of links that form a semantic interface to a network of resources.
232 lines • 10.3 kB
JavaScript
;
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __values = (this && this.__values) || function(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CollectionMerger = void 0;
var anylogger_1 = __importDefault(require("anylogger"));
var canonicalOrSelf_1 = require("../utils/comparators/canonicalOrSelf");
var equalityUtil_1 = require("../utils/equalityUtil");
var trackedRepresentationUtil_1 = require("../utils/trackedRepresentationUtil");
var instanceOfTrackedRepresentation_1 = require("../utils/instanceOf/instanceOfTrackedRepresentation");
var singletonMerger_1 = require("./singletonMerger");
var log = (0, anylogger_1.default)('CollectionMerger');
/**
* A helper class for manipulating items in a {@link CollectionRepresentation.items}.
*/
var CollectionMerger = /** @class */ (function () {
function CollectionMerger() {
}
/**
* Update existing items in the lvalue that are in the rvalue.
* Returns the lvalue (mutated).
*
* The equality operator is {@link CanonicalOrSelf}.
*/
CollectionMerger.updateItems = function (lvalue, rvalue, options) {
var e_1, _a;
var _b;
var _c = __assign({}, options), _d = _c.equalityOperator, equalityOperator = _d === void 0 ? canonicalOrSelf_1.CanonicalOrSelf : _d, _e = _c.equalityMatcher, equalityMatcher = _e === void 0 ? equalityUtil_1.defaultEqualityMatcher : _e;
var items = lvalue.items;
if (items && ((_b = rvalue.items) === null || _b === void 0 ? void 0 : _b.length) > 0) {
var _loop_1 = function (item) {
// TODO: implement eTag aware singletons
var found = rvalue.items.find(function (r) { return equalityMatcher(item, r, equalityOperator); });
if (found) {
singletonMerger_1.SingletonMerger.merge(item, found, options);
}
};
try {
// find existing and update
for (var items_1 = __values(items), items_1_1 = items_1.next(); !items_1_1.done; items_1_1 = items_1.next()) {
var item = items_1_1.value;
_loop_1(item);
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (items_1_1 && !items_1_1.done && (_a = items_1.return)) _a.call(items_1);
}
finally { if (e_1) throw e_1.error; }
}
}
return lvalue;
};
/**
* Omit items in the lvalue that are not in the rvalue.
* Returns the lvalue (mutated).
*
* This method splices (mutates) the {@link CollectionRepresentation.items} in order to retain bindings if they exist.
*
* The equality operator is {@link CanonicalOrSelf}.
*/
CollectionMerger.omitItems = function (lvalue, rvalue, options) {
var e_2, _a;
var _b;
var _c = __assign({}, options), _d = _c.equalityOperator, equalityOperator = _d === void 0 ? canonicalOrSelf_1.CanonicalOrSelf : _d, _e = _c.equalityMatcher, equalityMatcher = _e === void 0 ? equalityUtil_1.defaultEqualityMatcher : _e;
var items = lvalue.items;
if (!items) {
log.debug('initialised collection items');
var set = __assign({}, options).set;
if (set) {
set(lvalue, 'items', []);
}
else {
lvalue.items = [];
}
}
else {
if (((_b = rvalue.items) === null || _b === void 0 ? void 0 : _b.length) > 0) {
var indexes = items
.map(function (item, index) {
var found = rvalue.items.findIndex(function (r) {
return equalityMatcher(item, r, equalityOperator);
});
// when found in rvalue retain the corresponding lvalue index for removal
// mark -1 to those that are not to bbe removed
return found >= 0 ? -1 : index;
})
// keep just the indexes to remove
.filter(function (x) { return x >= 0; })
// sorted tail --> head (descending)
.sort(function (a, b) { return b - a; });
try {
// removed starting from the tail each item so that indexes remain correct
for (var indexes_1 = __values(indexes), indexes_1_1 = indexes_1.next(); !indexes_1_1.done; indexes_1_1 = indexes_1.next()) {
var index = indexes_1_1.value;
lvalue.items.splice(index, 1);
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (indexes_1_1 && !indexes_1_1.done && (_a = indexes_1.return)) _a.call(indexes_1);
}
finally { if (e_2) throw e_2.error; }
}
}
else {
// clear out the list because rvalue is empty
lvalue.items.splice(0, lvalue.items.length);
}
}
return lvalue;
};
/**
* Extract items in the rvalue that are not in the lvalue to extend the lvalue.
* Returns the lvalue (mutated).
*
* This method splices (mutates) the {@link CollectionRepresentation.items} in order to retain bindings if they exist.
*
* The equality operator is {@link canonicalOrSelf}.
*/
CollectionMerger.extractItems = function (lvalue, rvalue, options) {
var _a;
var _b = __assign({}, options), _c = _b.equalityOperator, equalityOperator = _c === void 0 ? canonicalOrSelf_1.CanonicalOrSelf : _c, _d = _b.equalityMatcher, equalityMatcher = _d === void 0 ? equalityUtil_1.defaultEqualityMatcher : _d;
var items = lvalue.items;
if (!items) {
log.debug('initialised collection items');
var set = __assign({}, options).set;
if (set) {
set(lvalue, 'items', []);
}
else {
lvalue.items = [];
}
}
else if (rvalue.items) {
// create a set of items in rvalue that don't exist
var include = rvalue
.items
.filter(function (item) { return items.findIndex(function (r) { return equalityMatcher(item, r, equalityOperator); }) < 0; });
// add into the set at the tail
(_a = lvalue.items).splice.apply(_a, __spreadArray([lvalue.items.length, 0], __read(include), false));
}
return lvalue;
};
/**
* Return a lvalue
* 1. items that
* - only has items found in rvalue
* - where the lvalue already had a value leave the original lvalue item in place.
* 2. links in the lvalue with any new rvalue links [optional]
*
* The equality operator is {@link canonicalOrSelf}.
*
* Note: the identity operator does not need to know about state
*/
CollectionMerger.merge = function (lvalue, rvalue, options) {
var _a = __assign({}, options), set = _a.set, _b = _a.mergeLinks, mergeLinks = _b === void 0 ? true : _b, _c = _a.mergeHeaders, mergeHeaders = _c === void 0 ? true : _c;
if (mergeLinks) {
if (set) {
// update the links
// Note: currently does not update other fields from incoming representation
// TODO: in the odd the case that a collection has attributes
set(lvalue, 'links', rvalue.links);
}
else {
Object.assign(lvalue.links, rvalue.links);
}
}
if (mergeHeaders) {
if ((0, instanceOfTrackedRepresentation_1.instanceOfTrackedRepresentation)(lvalue) && (0, instanceOfTrackedRepresentation_1.instanceOfTrackedRepresentation)(rvalue)) {
var headers = trackedRepresentationUtil_1.TrackedRepresentationUtil.getState(rvalue).headers;
trackedRepresentationUtil_1.TrackedRepresentationUtil.setHeaders(lvalue, headers);
}
}
var omitted = this.omitItems(lvalue, rvalue, options);
var updated = this.updateItems(omitted, rvalue);
return this.extractItems(updated, rvalue, options);
};
return CollectionMerger;
}());
exports.CollectionMerger = CollectionMerger;
//# sourceMappingURL=collectionMerger.js.map