UNPKG

postchain-client

Version:

Client library for accessing a Postchain node through REST.

306 lines 8.61 kB
"use strict"; var util = require('../formatter'); function PathElement(previous) { this.previous = previous; } PathElement.prototype.getSearchKey = function () { }; function PathLeafElement(previous) { PathElement.call(this, previous); } PathLeafElement.prototype = Object.create(PathElement.prototype); PathLeafElement.prototype.constructor = PathLeafElement; PathLeafElement.prototype.equals = function (other) { if (this === other) return true; if (typeof this !== typeof other) return false; return true; }; function SearchablePathElement(previous) { PathElement.call(this, previous); } SearchablePathElement.prototype = Object.create(PathElement.prototype); SearchablePathElement.prototype.constructor = SearchablePathElement; SearchablePathElement.prototype.getSearchKey = function () { }; /** * * @param {SearchablePathElement} previous * @param {number} index */ function ArrayPathElement(previous, index) { SearchablePathElement.call(this, previous); this.index = index; } ArrayPathElement.prototype = Object.create(SearchablePathElement.prototype); ArrayPathElement.prototype.constructor = ArrayPathElement; ArrayPathElement.prototype.getSearchKey = function () { return this.index; }; /** * @param {ArrayPathElement} other */ ArrayPathElement.prototype.equals = function (other) { if (this === other) return true; if (typeof this !== typeof other) return false; if (this.index != other.index) return false; return true; }; /** * * @param {SearchablePathElement} previous * @param {string} key */ function DictPathElement(previous, key) { SearchablePathElement.call(this, previous); this.key = key; } DictPathElement.prototype = Object.create(SearchablePathElement.prototype); DictPathElement.prototype.constructor = DictPathElement; DictPathElement.prototype.getSearchKey = function () { return this.key; }; /** * @param {DictPathElement} other */ DictPathElement.prototype.equals = function (other) { if (this === other) return true; if (typeof this !== typeof other) return false; if (this.key != other.key) return false; return true; }; /** * * @param {Array} pathElements */ function Path(pathElements) { this.pathElements = pathElements; } /** * */ Path.prototype.getCurrentPathElement = function () { return this.pathElements[0]; }; /** * */ Path.prototype.size = function () { return this.pathElements.length; }; /** * */ Path.prototype.tail = function () { if (this.pathElements.length == 0) { throw new Error("Impossible to tail this array"); } else { var tail = this.pathElements.slice(1); return new Path(tail); } }; Path.prototype.debugString = function () { var sb = ""; this.pathElements.forEach(elem => { if (elem instanceof SearchablePathElement) { sb = sb + "-> " + elem.getSearchKey(); } else if (elem instanceof PathLeafElement) { sb = sb + "-> Leaf"; } }); return sb; }; /** * @param {Path} other */ Path.prototype.equals = function (other) { if (this === other) return true; if (typeof this != typeof other) return false; return this.pathElements == other.pathElements; }; /** * @param {number} index * @param {Path} path */ var getTailIfFirstElementIsArrayOfThisIndex = function (index, path) { return getTail(index, path); }; /** * * @param {string} key * @param {Path} path */ var getTailIfFirstElementIsDictOfThisKey = function (key, path) { return getTail(key, path); }; /** * * @param {string|number} searchKey * @param {Path} path */ var getTail = function (searchKey, path) { if (searchKey === null) { throw new Error("Have to provide a search key"); } try { var firstElement = path.pathElements[0]; if (firstElement instanceof SearchablePathElement) { if (firstElement.getSearchKey() == searchKey) { return path.tail(); } } } catch (err) { util.logError("Why are we dropping first element of an empty path? " + err); return null; } return null; }; /** * * @param {Array} paths */ function PathSet(paths) { this.paths = paths; } /** * */ PathSet.prototype.isEmpty = function () { return this.paths.length == 0; }; /** * */ PathSet.prototype.getPathLeafOrElseAnyCurrentPathElement = function () { var leafElem = null; var currElem = null; var prev = { "path": null, "elem": null, }; this.paths.forEach(path => { currElem = path.getCurrentPathElement(); if (currElem instanceof PathLeafElement) { leafElem = currElem; } prev = this.errorCheckUnequalParent(path, currElem, prev.path, prev.elem); }); if (leafElem != null) { return leafElem; } else { return currElem; // It doesn't matter which one we return (Next step we will get the "previous" from this one) } }; /** * Yeah, this might be a completely un-needed check (but it MIGHT save us later on if we forget this rule). * What we are looking for here is an impossible state where two paths in the same set don't have the same parent. * (Since we usually only have one path in a path set, this check should be cheap) * * @param {Path} currPath * @param {PathElement} currElem * @param {Path} prevPath * @param {PathElement} prevElem */ PathSet.prototype.errorCheckUnequalParent = function (currPath, currElem, prevPath, prevElem) { if (prevElem != null) { // weird: javascript cannot compare null == null then we have to compare each with null separately :( if (currElem.previous == null && prevElem.previous == null) { return { "path": currPath, "elem": currElem }; } else if ((currElem.previous == null && prevElem.previous != null) || (currElem.previous != null && prevElem.previous == null)) { throw new Error("Something is wrong, these paths do not have the same parent. (" + currPath + ") (" + prevPath + ")"); } else if (!currElem.previous.equals(prevElem.previous)) { throw new Error("Something is wrong, these paths do not have the same parent. (" + currPath + ") (" + prevPath + ")"); } } return { "path": currPath, "elem": currElem }; }; /** * */ PathSet.prototype.keepOnlyArrayPaths = function () { var filteredPaths = this.paths.filter(path => { return path.pathElements[0] instanceof ArrayPathElement; }); return new PathSet(filteredPaths); }; /** * */ PathSet.prototype.keepOnlyDictPaths = function () { var filteredPaths = this.paths.filter(path => { return path.pathElements[0] instanceof DictPathElement; }); return new PathSet(filteredPaths); }; /** * */ PathSet.prototype.getTailIfFirstElementIsArrayOfThisIndexFromList = function (index) { return this.getTailFromList(index, getTailIfFirstElementIsArrayOfThisIndex); }; /** * */ PathSet.prototype.getTailIfFirstElementIsDictOfThisKeyFromList = function (key) { return this.getTailFromList(key, getTailIfFirstElementIsDictOfThisKey); }; /** * */ PathSet.prototype.getTailFromList = function (searchKey, filterFunc) { var retPaths = new Array(); this.paths.forEach(path => { var newPath = filterFunc(searchKey, path); if (newPath != null) { retPaths.push(newPath); } }); return new PathSet(retPaths); }; /** * * @param {Array} arr */ var buildPathFromArray = function (arr) { var pathElements = new Array(); var lastPathElem = null; arr.forEach(item => { var newElem = null; if (typeof item === 'number') { newElem = new ArrayPathElement(lastPathElem, item); } else if (typeof item === 'string') { newElem = new DictPathElement(lastPathElem, item); } else { throw new Error("A path structure must only consist of Ints and Strings, not " + item); } pathElements.push(newElem); lastPathElem = newElem; }); var lastOne = lastPathElem; pathElements.push(new PathLeafElement(lastOne)); return new Path(pathElements); }; module.exports = { Path, PathElement, PathLeafElement, ArrayPathElement, SearchablePathElement, DictPathElement, PathSet, getTailIfFirstElementIsArrayOfThisIndex, buildPathFromArray }; //# sourceMappingURL=path.js.map