postchain-client
Version:
Client library for accessing a Postchain node through REST.
306 lines • 8.61 kB
JavaScript
"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