UNPKG

webgme-engine

Version:

WebGME server and Client API without a GUI

1,194 lines (1,048 loc) 222 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>JSDoc: Source: common/core/core.js</title> <script src="scripts/prettify/prettify.js"> </script> <script src="scripts/prettify/lang-css.js"> </script> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css"> </head> <body> <div id="main"> <h1 class="page-title">Source: common/core/core.js</h1> <section> <article> <pre class="prettyprint source linenums"><code>/*globals define*/ /*eslint-env node, browser*/ /** * This class defines the public API of the WebGME-Core * * @author kecso / https://github.com/kecso * @module Core */ /** * @typedef {object} Node - the object that represents the atomic element of the containment hierarchy. */ /** * @typedef {object} DataObject - Inner data of {@link module:Core~Node} that can be serialized * and saved in the storage. */ /** * @typedef {object} GmePersisted - the result object of a persist which contains information about the newly * created data objects. * @prop {module:Core~ObjectHash} rootHash - Hash of the root node. * @prop {object.&lt;module:Core~ObjectHash, module:Core~DataObject>} objects - Hash of the root node. */ /** * @typedef {string} ObjectHash - Unique SHA-1 hash for the node object. * @example * '#5496cf226542fcceccf89056f0d27564abc88c99' */ /** * @typedef {string} GUID - Globally unique identifier. A formatted string containing hexadecimal characters. If some * projects share some GUIDs that can only be because the node with the given identification represents the same * concept. * @example * 'cd891e7b-e2ea-e929-f6cd-9faf4f1fc045' */ /** * @typedef {object} Constraint - An object that represents some additional rule regarding some node of the project. * @prop {string} script - The script which checks if the constraint is met. * @prop {string} info - Short description of the constraint. * @prop {string} priority - Gives instructions on how to deal with violations of the constraint. */ /** * @typedef {object} DefinitionInfo - Contains the owner and the target of the meta-rule that makes the * relationship between the given node and related node a valid one. There can be multiple meta-rules that make * the relationship valid, but this is the first one that answers the question isValidChildOf, isValidTargetOf etc. * @prop {Core~Node} ownerNode - The meta-node where the meta-rule is stored. * @prop {Core~Node} targetNode - The meta-node the meta-rule is targeting. */ /** * @typedef {object} RelationRule - An object that represents a relational type rule-set (pointer/set). * @prop {integer} [min] - The minimum amount of target necessary for the relationship (if not present or '-1' * then there is no minimum rule that applies) * @prop {integer} [max] - The minimum amount of target necessary for the relationship (if not present or '-1' * then there is no minimum rule that applies) * @prop {object} [absolutePathOfTarget] - special rules regarding the given type (if the object is empty, it still * represents that the type is a valid target of the relationship) * @prop {integer} [absolutePathOfTarget.min] - The minimum amount of target necessary for the relationship * from the given type (if not present or '-1' then there is no minimum rule that applies) * @prop {integer} [absolutePathOfTarget.max] - The minimum amount of target necessary for the relationship * from the given type (if not present or '-1' then there is no minimum rule that applies) * @example * '{ * 'min': 1, * 'max': -1, * 'any/path/of/node':{ * 'min':-1, * 'max':2 * }, * 'any/other/valid/path':{ * } * }' */ /** * @typedef {object} MixinViolation - An object that has information about a mixin violation in the given node. * @prop {string} [severity] - The severity of the given error ('error','warning'). * @prop {string} [type] - 'missing', 'attribute collision', 'set collision', * 'pointer collision', 'containment collision', 'aspect collision', 'constraint collision' * @prop {string|undefined} [ruleName] - The name of the affected rule definition (if available). * @prop {string|undefined} [targetInfo] - The path of the target of the violation (if available). * @prop {module:Core~Node|undefined} [targetNode] - The target node of the violation (if available). * @prop {string[]} [collisionPaths] - The list of paths of colliding nodes (if any). * @prop {module:Core~Node[]} [collisionNodes] - The colliding mixin nodes (if any). * @prop {string} [message] - The description of the violation. * @prop {string} [hint] - Hint on how to resolve the issue. * @example * '{ * 'severity': 'error', * 'type': 'missing', * 'targetInfo': '/E/b', * 'message': '[MyObject]: mixin node "E/b" is missing from the Meta', * 'hint': 'Remove mixin or add to the Meta' * }' * @example * '{ * 'severity': 'warning', * 'type': 'attribute collision', * 'ruleName': 'value', * 'collisionPaths': ['/E/a','/E/Z'], * 'collisionNodes': [Object,Object], * 'message':'[MyObject]: inherits attribute definition "value" from [TypeA] and [TypeB]', * 'hint': 'Remove one of the mixin relations' * }' */ define([ 'common/core/corerel', 'common/core/setcore', 'common/core/guidcore', 'common/core/nullpointercore', 'common/core/coreunwrap', 'common/core/coretype', 'common/core/constraintcore', 'common/core/coretree', 'common/core/metacore', 'common/core/coretreeloader', 'common/core/corediff', 'common/core/metacachecore', 'common/core/mixincore', 'common/core/metaquerycore', 'common/regexp', 'common/core/librarycore', 'common/core/CoreIllegalArgumentError', 'common/core/CoreIllegalOperationError', 'common/core/constants' ], function (CoreRel, Set, Guid, NullPtr, UnWrap, Type, Constraint, CoreTree, MetaCore, TreeLoader, CoreDiff, MetaCacheCore, MixinCore, MetaQueryCore, REGEXP, LibraryCore, CoreIllegalArgumentError, CoreIllegalOperationError, CONSTANTS) { 'use strict'; var isValidNode, isValidPath; function ensureType(input, nameOfInput, type, isAsync) { var error; if (typeof input !== type) { error = new CoreIllegalArgumentError('Parameter \'' + nameOfInput + '\' is not of type ' + type + '.'); if (isAsync) { return error; } else { throw error; } } } function ensureValue(input, nameOfInput, isAsync) { var error; if (input === undefined) { error = new CoreIllegalArgumentError('Parameter \'' + nameOfInput + '\' cannot be undefined.'); if (isAsync) { return error; } else { throw error; } } } function ensureInstanceOf(input, nameOfInput, type, isAsync) { var error; if (input instanceof type === false) { error = new CoreIllegalArgumentError('Parameter \'' + nameOfInput + '\' is not of type ' + type + '.'); if (isAsync) { return error; } else { throw error; } } } function ensurePath(input, nameOfInput, isAsync) { var error; if (isValidPath(input) === false) { error = new CoreIllegalArgumentError('Parameter \'' + nameOfInput + '\' is not a valid path.'); if (isAsync) { return error; } else { throw error; } } } function ensureNode(input, nameOfInput, isAsync) { var error; if (isValidNode(input) === false) { error = new CoreIllegalArgumentError('Parameter \'' + nameOfInput + '\' is not a valid node.'); if (isAsync) { return error; } else { throw error; } } } function ensureHash(input, nameOfInput, isAsync) { var error; if (REGEXP.DB_HASH.test(input) === false) { error = new CoreIllegalArgumentError('Parameter \'' + nameOfInput + '\' is not a valid hash.'); if (isAsync) { return error; } else { throw error; } } } function ensureGuid(input, nameOfInput, isAsync) { var error; if (REGEXP.GUID.test(input) === false) { error = new CoreIllegalArgumentError('Parameter \'' + nameOfInput + '\' is not a valid GUID.'); if (isAsync) { return error; } else { throw error; } } } function ensureMinMax(input, nameOfInput, isAsync) { var error; if (input === null || input === undefined) { return; } if (typeof input === 'number' &amp;&amp; Number.isSafeInteger(input) &amp;&amp; input >= -1) { return; } error = new CoreIllegalArgumentError('Parameter ' + nameOfInput + ' is not a safe integer from [-1,∞).'); if (error) { if (isAsync) { return error; } else { throw error; } } } function ensureRelationName(input, nameOfInput, isAsync) { var error, reserved = [ CONSTANTS.BASE_POINTER, CONSTANTS.OVERLAYS_PROPERTY, CONSTANTS.MEMBER_RELATION ]; if (typeof input !== 'string') { error = new CoreIllegalArgumentError('Parameter ' + nameOfInput + ' is not of type string.'); } else { if (input.indexOf('_') === 0 || reserved.indexOf(input) !== -1) { error = new CoreIllegalArgumentError('Parameter ' + nameOfInput + ' cannot start with \'_\'' + ', or be equal with any of the reserved ' + reserved + ' words.'); } } if (error) { if (isAsync) { return error; } else { throw error; } } } function ensureMongoCompatibleKey(input, nameOfInput, hiddenIsFine, isAsync) { var error = null, realInput = input; if (hiddenIsFine === true &amp;&amp; input[0] === '_') { realInput = input.substr(1); } if (REGEXP.DOCUMENT_KEY.test(realInput) === false) { error = new CoreIllegalArgumentError('Parameter ' + nameOfInput + ' is not a valid key (cannot contain "." or "$"' + (hiddenIsFine ? '' : ', or start with "_"') + ').'); } if (error) { if (isAsync) { return error; } else { throw error; } } } function getCommonAncestor(node1, node2, getter) { function getChain(node) { var ancestors = []; while (node) { ancestors.push(node); node = getter(node); } return ancestors; } var ancestors2 = getChain(node2), i; while (node1) { for (i = 0; i &lt; ancestors2.length; i += 1) { if (node1 === ancestors2[i]) { return node1; } } node1 = getter(node1); } return null; } /** * @param {ProjectInterface} project - project connected to storage * @param {object} options - contains logging information * @param {object} options.logger - gmeLogger * @param {object} options.globConf - gmeConfig * @alias Core * @description The Core defines the main API for model manipulation and traversal. It is important to note, that * all 'Path' function must be used with caution as the returned information is just an estimate and does not * guarantee that the actual node will exist (as in certain scenarios they might become invalid and need to * be removed, but said removal can only take place during their load). Try to always 'Load' every * node before depending on their paths. * @constructor */ function Core(project, options) { var core, coreLayers = []; coreLayers.push(CoreRel); coreLayers.push(NullPtr); coreLayers.push(Type); coreLayers.push(NullPtr); coreLayers.push(Set); coreLayers.push(Guid); coreLayers.push(Constraint); coreLayers.push(MetaCore); coreLayers.push(MetaCacheCore); coreLayers.push(MixinCore); coreLayers.push(MetaQueryCore); coreLayers.push(CoreDiff); coreLayers.push(TreeLoader); coreLayers.push(LibraryCore); // TODO check how we should handle the TASYNC error handling... // if (options.usertype !== 'tasync') { // coreLayers.push(UnWrap); // } coreLayers.push(UnWrap); core = coreLayers.reduce(function (inner, Class) { return new Class(inner, options); }, new CoreTree(project, options)); isValidNode = core.isValidNode; isValidPath = core.isValidPath; /** * Returns the parent of the node. * @param {module:Core~Node} node - the node in question * * @return {module:Core~Node|null} Returns the parent of the node or NULL if it has no parent. * * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. * @throws {CoreInternalError} If some internal error took place inside the core layers. */ this.getParent = function (node) { ensureNode(node, 'node'); return core.getParent(node); }; /** * Returns the common parent node of all supplied nodes. Note that if a node and its parent are passed, * the method will return the parent of the parent. * @param {...module:Core~Node} nodes - a variable number of nodes to compare * * @return {module:Core~Node|null} The common parent. Will be null whenever the root-node is passed in. * @example * core.getCommonParent(node1, node2, node3); * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. * @throws {CoreInternalError} If some internal error took place inside the core layers. */ this.getCommonParent = function () { var nodesArr = (arguments.length === 1 ? [arguments[0]] : Array.apply(null, arguments)), result, i; nodesArr.forEach(function (node, idx) { ensureNode(node, 'arguments[' + idx + ']'); }); result = nodesArr[0]; for (i = 1; i &lt; nodesArr.length; i += 1) { result = getCommonAncestor(result, nodesArr[i], core.getParent); } if (result &amp;&amp; nodesArr.indexOf(result) > -1) { result = core.getParent(result); } return result || null; }; /** * Returns the parent-relative identifier of the node. * @param {module:Core~Node} node - the node in question. * * @return {string|null} Returns the last segment of the node path. * * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. * @throws {CoreInternalError} If some internal error took place inside the core layers. */ this.getRelid = function (node) { ensureNode(node, 'node'); return core.getRelid(node); }; /** * Returns the root node of the containment tree that node is part of. * @param {module:Core~Node} node - the node in question. * * @return {module:Core~Node} Returns the root of the containment hierarchy (it can be the node itself). * * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. * @throws {CoreInternalError} If some internal error took place inside the core layers. */ this.getRoot = function (node) { ensureNode(node, 'node'); return core.getRoot(node); }; /** * Returns the complete path of the node in the containment hierarchy. * @param {module:Core~Node} node - the node in question. * * @return {string} Returns a path string where each portion is a relative id and they are separated by '/'. * The path can be empty as well if the node in question is the root itself, otherwise it should be a chain * of relative ids from the root of the containment hierarchy. * * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. * @throws {CoreInternalError} If some internal error took place inside the core layers. */ this.getPath = function (node) { ensureNode(node, 'node'); return core.getPath(node); }; /** * Retrieves the child of the input node at the given relative id. It is not an asynchronous load * and it automatically creates the child under the given relative id if no child was there beforehand. * @param {module:Core~Node} node - the node in question. * @param {string} relativeId - the relative id which our child in question has. * * @return {module:Core~Node} Return an empty node if it was created as a result of the function or * return the already existing and loaded node if it found. * * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. * @throws {CoreInternalError} If some internal error took place inside the core layers. */ this.getChild = function (node, relativeId) { ensureNode(node, 'node'); ensureType(relativeId, 'relativeId', 'string'); return core.getChild(node, relativeId); }; /** * Checks if the node in question has some actual data. * @param {module:Core~Node} node - the node in question. * * @return {bool} Returns true if the node is 'empty' meaning that it is not reserved by real data. * Returns false if the node is exists and have some meaningful value. * * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. * @throws {CoreInternalError} If some internal error took place inside the core layers. */ this.isEmpty = function (node) { ensureNode(node, 'node'); return core.isEmpty(node); }; /** * Returns the calculated hash and database id of the data for the node. * @param {module:Core~Node} node - the node in question. * * @return {module:Core~ObjectHash} Returns the hash value of the data for the given node. * An empty string is returned when the node was mutated and not persisted. * * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. * @throws {CoreInternalError} If some internal error took place inside the core layers. */ this.getHash = function (node) { ensureNode(node, 'node'); return core.getHash(node); }; /** * Persists the changes made in memory and computed the data blobs that needs to be saved into the database * to make the change and allow other users to see the new state of the project. * @param {module:Core~Node} node - some node element of the modified containment hierarchy (usually the root). * * @return {module:Core~GmePersisted} The function returns an object which collects all the changes * on data level and necessary to update the database on server side. Keys of the returned object are 'rootHash' * and 'objects'. The values of these should be passed to project.makeCommit. * * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. * @throws {CoreInternalError} If some internal error took place inside the core layers. */ this.persist = function (node) { ensureNode(node, 'node'); return core.persist(node); }; /** * Loads the data object with the given hash and makes it a root of a containment hierarchy. * @param {module:Core~ObjectHash} hash - the hash of the data object we like to load as root. * @param {function} [callback] * @param {Error|CoreIllegalArgumentError|CoreInternalError|null} callback.error - the result of the execution * @param {module:Core~Node} callback.node - the resulting root node * * @return {external:Promise} If no callback is given, the result will be provided in * a promiselike manner. * * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. */ this.loadRoot = function (hash, callback) { var error = null; ensureType(callback, 'callback', 'function'); error = ensureHash(hash, 'hash', true); if (error) { callback(error); } else { core.loadRoot(hash, callback); } }; /** * Loads the child of the given parent pointed by the relative id. Behind the scenes, it means * that it actually loads the data pointed by a hash stored inside the parent under the given id * and wraps it in a node object which will be connected to the parent as a child in the containment * hierarchy. If there is no such relative id reserved, the call will return with null. * @param {module:Core~Node} parent - the container node in question. * @param {string} relativeId - the relative id of the child in question. * @param {function} [callback] * @param {Error|CoreIllegalArgumentError|CoreInternalError|null} callback.error - the result of the execution * @param {module:Core~Node} callback.node - the resulting child * * @return {external:Promise} If no callback is given, the result will be provided in a promise. * * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. */ this.loadChild = function (node, relativeId, callback) { var error = null; ensureType(callback, 'callback', 'function'); error = ensureNode(node, 'node', true); error = error || ensureType(relativeId, 'relativeId', 'string', true); if (error) { callback(error); } else { core.loadChild(node, relativeId, callback); } }; /** * From the given starting node, it loads the path given as a series of relative ids (separated by '/') * and returns the node it finds at the ends of the path. If there is no node, the function will return null. * @param {module:Core~Node} node - the starting node of our search. * @param {string} relativePath - the relative path - built by relative ids - of the node in question. * @param {function} [callback] * @param {Error|CoreIllegalArgumentError|CoreInternalError|null} callback.error - the result of the execution * @param {module:Core~Node} callback.node - the resulting node * * @return {external:Promise} If no callback is given, the result will be provided in a promise. * * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. */ this.loadByPath = function (node, relativePath, callback) { var error = null; ensureType(callback, 'callback', 'function'); error = ensureNode(node, 'node', true); error = error || ensurePath(relativePath, 'relativePath', true); if (error) { callback(error); } else { core.loadByPath(node, relativePath, callback); } }; /** * Loads all the children of the given parent. As it first checks the already reserved relative ids of * the parent, it only loads the already existing children (so no on-demand empty node creation). * @param {module:Core~Node} node - the container node in question. * @param {function} [callback] * @param {Error|CoreIllegalArgumentError|CoreInternalError|null} callback.error - the result of the execution * @param {module:Core~Node[]} callback.children - the resulting children * * @return {external:Promise} If no callback is given, the result will be provided in a promise. * * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. */ this.loadChildren = function (node, callback) { var error = null; ensureType(callback, 'callback', 'function'); error = ensureNode(node, 'node', true); if (error) { callback(error); } else { core.loadChildren(node, callback); } }; /** * Loads all the children of the given parent that has some data and not just inherited. As it first checks * the already reserved relative ids of the parent, it only loads the already existing children * (so no on-demand empty node creation). * @param {module:Core~Node} node - the container node in question. * @param {function} [callback] * @param {Error|CoreIllegalArgumentError|CoreInternalError|null} callback.error - the result of the execution * @param {module:Core~Node[]} callback.node - the resulting children * * @return {external:Promise} If no callback is given, the result will be provided in a promise. * * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. */ this.loadOwnChildren = function (node, callback) { var error = null; ensureType(callback, 'callback', 'function'); error = ensureNode(node, 'node', true); if (error) { callback(error); } else { core.loadOwnChildren(node, callback); } }; /** * Loads the target of the given pointer of the given node. In the callback the node can have three values: * if the node is valid, then it is the defined target of a valid pointer, * if the returned value is null, then it means that the pointer is defined, but has no real target, * finally if the returned value is undefined than there is no such pointer defined for the given node. * @param {module:Core~Node} node - the source node in question. * @param {string} pointerName - the name of the pointer. * @param {function} [callback] * @param {Error|CoreIllegalArgumentError|CoreInternalError|null} callback.error - the result of the execution * @param {module:Core~Node} callback.node - the resulting target * * @return {external:Promise} If no callback is given, the result will be provided in a promise. * * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. */ this.loadPointer = function (node, pointerName, callback) { var error = null; ensureType(callback, 'callback', 'function'); error = ensureNode(node, 'node', true); error = error || ensureType(pointerName, 'pointerName', 'string', true); if (error) { callback(error); } else { core.loadPointer(node, pointerName, callback); } }; /** * Loads all the source nodes that has such a pointer and its target is the given node. * @param {module:Core~Node} node - the target node in question. * @param {string} pointerName - the name of the pointer of the sources. * @param {function} [callback] * @param {Error|CoreIllegalArgumentError|CoreInternalError|null} callback.error - the result of the execution * @param {module:Core~Node[]} callback.node - the resulting sources * * @return {external:Promise} If no callback is given, the result will be provided in a promise. * * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. */ this.loadCollection = function (node, pointerName, callback) { var error = null; ensureType(callback, 'callback', 'function'); error = ensureNode(node, 'node', true); error = error || ensureType(pointerName, 'pointerName', 'string', true); if (error) { callback(error); } else { core.loadCollection(node, pointerName, callback); } }; /** * Loads a complete sub-tree of the containment hierarchy starting from the given node. * @param {module:Core~Node} node - the node that is the root of the sub-tree in question. * @param {function} [callback] * @param {Error|CoreIllegalArgumentError|CoreInternalError|null} callback.error - the result of the execution * @param {module:Core~Node[]} callback.nodes - the resulting sources * * @return {external:Promise} If no callback is given, the result will be provided in a promise. * * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. */ this.loadSubTree = function (node, callback) { var error = null; ensureType(callback, 'callback', 'function'); error = ensureNode(node, 'node', true); if (error) { callback(error); } else { core.loadSubTree(node, callback); } }; /** * Loads a complete sub-tree of the containment hierarchy starting from the given node, but load only those * children that has some additional data and not purely inherited. * @param {module:Core~Node} node - the container node in question. * @param {function} [callback] * @param {Error|CoreIllegalArgumentError|CoreInternalError|null} callback.error - the result of the execution * @param {module:Core~Node[]} callback.nodes - the resulting sources * * @return {external:Promise} If no callback is given, the result will be provided in a promise. * * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. */ this.loadOwnSubTree = function (node, callback) { var error = null; ensureType(callback, 'callback', 'function'); error = ensureNode(node, 'node', true); if (error) { callback(error); } else { core.loadOwnSubTree(node, callback); } }; /** * Loads a complete containment hierarchy using the data object - pointed by the given hash - * as the root. * @param {module:Core~ObjectHash} hash - hash of the root node. * @param {function} [callback] * @param {Error|CoreIllegalArgumentError|CoreInternalError|null} callback.error - the result of the execution. * @param {module:Core~Node[]} callback.nodes - the resulting nodes. * * @return {external:Promise} If no callback is given, the result will be provided in a promise. * * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. */ this.loadTree = function (hash, callback) { var error = null; ensureType(callback, 'callback', 'function'); error = ensureHash(hash, 'hash', true); if (error) { callback(error); } else { core.loadTree(hash, callback); } }; /** * Collects the relative ids of all the children of the given node. * @param {module:Core~Node} node - the container node in question. * * @return {string[]} The function returns an array of the relative ids. */ this.getChildrenRelids = function (node) { ensureNode(node, 'node'); return core.getChildrenRelids(node); }; /** * Collects the relative ids of all the children of the given node that has some data and not just inherited. * N.B. Do not mutate the returned array! * @param {module:Core~Node} node - the container node in question. * * @return {string[]} The function returns an array of the relative ids. * * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. * @throws {CoreInternalError} If some internal error took place inside the core layers. */ this.getOwnChildrenRelids = function (node) { ensureNode(node, 'node'); return core.getOwnChildrenRelids(node); }; /** * Collects the paths of all the children of the given node. * @param {module:Core~Node} node - the container node in question. * *@return {string[]} The function returns an array of the absolute paths of the children. * * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. * @throws {CoreInternalError} If some internal error took place inside the core layers. */ this.getChildrenPaths = function (node) { ensureNode(node, 'node'); return core.getChildrenPaths(node); }; /** * Collects the paths of all the children of the given node that has some data as well and not just inherited. * @param {module:Core~Node} parent - the container node in question. * *@return {string[]} The function returns an array of the absolute paths of the children. * * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. * @throws {CoreInternalError} If some internal error took place inside the core layers. */ this.getOwnChildrenPaths = function (node) { ensureNode(node, 'node'); return core.getOwnChildrenPaths(node); }; /** * Creates a node according to the given parameters. * @param {object} [parameters] - the details of the creation. * @param {module:Core~Node|null} [parameters.parent] - the parent of the node to be created. * @param {module:Core~Node|null} [parameters.base] - the base of the node to be created. * @param {string} [parameters.relid] - the relative id of the node to be created (if reserved, the function * returns the node behind the relative id) * @param {module:Core~GUID} [parameters.guid] - the GUID of the node to be created * * * @return {module:Core~Node} The function returns the created node. * * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. * @throws {CoreIllegalOperationError} If the context of the operation is not allowed. * @throws {CoreInternalError} If some internal error took place inside the core layers. */ this.createNode = function (parameters) { if (parameters) { ensureType(parameters, 'parameters', 'object'); if (Object.hasOwn(parameters, 'parent') &amp;&amp; parameters.parent !== null &amp;&amp; parameters.parent !== undefined) { ensureNode(parameters.parent, 'parameters.parent'); } if (Object.hasOwn(parameters, 'base') &amp;&amp; parameters.base !== null &amp;&amp; parameters.base !== undefined) { ensureNode(parameters.base, 'parameters.base'); } if (Object.hasOwn(parameters, 'guid') &amp;&amp; parameters.guid !== undefined) { ensureGuid(parameters.guid, 'parameters.guid'); } } return core.createNode(parameters); }; /** * Creates a child, with base as provided, inside the provided node. * @param {module:Core~Node} node - the parent of the node to be created. * @param {module:Core~Node} base - the base of the node to be created. * * @return {module:Core~Node} The function returns the created child node. * * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. * @throws {CoreIllegalOperationError} If the context of the operation is not allowed. * @throws {CoreInternalError} If some internal error took place inside the core layers. */ this.createChild = function (node, base) { ensureNode(node, 'node'); ensureNode(base, 'base'); return core.createNode({parent: node, base: base}); }; /** * Removes a node from the containment hierarchy. * @param {module:Core~Node} node - the node to be removed. * * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. * @throws {CoreIllegalOperationError} If the context of the operation is not allowed. * @throws {CoreInternalError} If some internal error took place inside the core layers. */ this.deleteNode = function (node) { ensureNode(node, 'node'); if (core.getParent(node) === null) { throw new CoreIllegalOperationError('Not allowed to delete node without a parent.'); } return core.deleteNode(node, false); }; /** * Copies the given node into parent. * @param {module:Core~Node} node - the node to be copied. * @param {module:Core~Node} parent - the parent node of the copy. * * @return {module:Core~Node} The function returns the copied node. * * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. * @throws {CoreIllegalOperationError} If the context of the operation is not allowed. * @throws {CoreInternalError} If some internal error took place inside the core layers. */ this.copyNode = function (node, parent) { ensureNode(node, 'node'); ensureNode(parent, 'parent'); return core.copyNode(node, parent); }; /** * Copies the given nodes into parent. * @param {module:Core~Node[]} nodes - the nodes to be copied. * @param {module:Core~Node} parent - the parent node of the copy. * * @return {module:Core~Node[]} The function returns an array of the copied nodes. The order follows * the order of originals. * * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. * @throws {CoreIllegalOperationError} If the context of the operation is not allowed. * @throws {CoreInternalError} If some internal error took place inside the core layers. */ this.copyNodes = function (nodes, parent) { var i; ensureInstanceOf(nodes, 'nodes', Array); for (i = 0; i &lt; nodes.length; i += 1) { ensureNode(nodes[i], 'nodes[' + i + ']'); } ensureNode(parent, 'parent'); return core.copyNodes(nodes, parent); }; /** * Checks if parent can be the new parent of node. * @param {module:Core~Node} node - the node in question. * @param {module:Core~Node} parent - the new parent. * * @return {boolean} True if the supplied parent is a valid parent for the node. * * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. * @throws {CoreInternalError} If some internal error took place inside the core layers. */ this.isValidNewParent = function (node, parent) { ensureNode(node, 'node'); ensureNode(parent, 'parent'); return core.isValidNewParent(node, parent); }; /** * Moves the given node under the given parent. * @param {module:Core~Node} node - the node to be moved. * @param {module:Core~Node} parent - the parent node of the copy. * * @return {module:Core~Node} The function returns the node after the move. * * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. * @throws {CoreIllegalOperationError} If the context of the operation is not allowed. * @throws {CoreInternalError} If some internal error took place inside the core layers. */ this.moveNode = function (node, parent) { ensureNode(node, 'node'); ensureNode(parent, 'parent'); return core.moveNode(node, parent); }; /** * Returns the names of the defined attributes of the node. * @param {module:Core~Node} node - the node in question. * * @return {string[]} The function returns an array of the names of the attributes of the node. * * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. * @throws {CoreInternalError} If some internal error took place inside the core layers. */ this.getAttributeNames = function (node) { ensureNode(node, 'node'); return core.getAttributeNames(node); }; /** * Retrieves the value of the given attribute of the given node. * @param {module:Core~Node} node - the node in question. * @param {string} name - the name of the attribute. * * @return {string|number|bool|object|undefined} The function returns the value of the attribute of the node. * If the value is undefined that means the node do not have * such attribute defined. * * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. * @throws {CoreInternalError} If some internal error took place inside the core layers. */ this.getAttribute = function (node, name) { ensureNode(node, 'node'); ensureType(name, 'name', 'string'); return core.copyIfObject(core.getAttribute(node, name)); }; /** * Sets the value of the given attribute of the given node. It defines the attribute on demand, means that it * will set the given attribute even if was ot defined for the node beforehand. * @param {module:Core~Node} node - the node in question. * @param {string} name - the name of the attribute. * @param {string|number|bool|object} value - the new of the attribute, undefined is not allowed. * * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. * @throws {CoreIllegalOperationError} If the context of the operation is not allowed. * @throws {CoreInternalError} If some internal error took place inside the core layers. */ this.setAttribute = function (node, name, value) { ensureNode(node, 'node'); ensureType(name, 'name', 'string'); ensureMongoCompatibleKey(name, 'name', true); ensureValue(value, 'value'); return core.setAttribute(node, name, value); }; /** * Removes the given attributes from the given node. * @param {module:Core~Node} node - the node in question. * @param {string} name - the name of the attribute. * * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. * @throws {CoreIllegalOperationError} If the context of the operation is not allowed. * @throws {CoreInternalError} If some internal error took place inside the core layers. */ this.delAttribute = function (node, name) { ensureNode(node, 'node'); ensureType(name, 'name', 'string'); return core.delAttribute(node, name); }; /** * Returns the names of the defined registry entries of the node. * @param {module:Core~Node} node - the node in question. * * @return {string[]} The function returns an array of the names of the registry entries of the node. * * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. * @throws {CoreInternalError} If some internal error took place inside the core layers. */ this.getRegistryNames = function (node) { ensureNode(node, 'node'); return core.getRegistryNames(node); }; /** * Retrieves the value of the given registry entry of the given node. * @param {module:Core~Node} node - the node in question. * @param {string} name - the name of the registry entry. * * @return {string|number|bool|object|undefined} The function returns the value of the registry entry * of the node. The value can be an object or any primitive type. If the value is undefined that means * the node do not have such attribute defined. * * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. * @throws {CoreInternalError} If some internal error took place inside the core layers. */ this.getRegistry = function (node, name) { ensureNode(node, 'node'); ensureType(name, 'name', 'string'); return core.copyIfObject(core.getRegistry(node, name)); }; /** * Sets the value of the given registry entry of the given node. It defines the registry entry on demand, * means that it will set the given registry entry even if was ot defined for the node beforehand. * @param {module:Core~Node} node - the node in question. * @param {string} name - the name of the registry entry. * @param {string|number|bool|object} value - the new of the registry entry. Can be any primitive * type or object. Undefined is not allowed. * * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. * @throws {CoreIllegalOperationError} If the context of the operation is not allowed. * @throws {CoreInternalError} If some internal error took place inside the core layers. */ this.setRegistry = function (node, name, value) { ensureNode(node, 'node'); ensureType(name, 'name', 'string'); ensureMongoCompatibleKey(name, 'name', true); ensureValue(value, 'value'); return core.setRegistry(node, name, value); }; /** * Removes the given registry entry from the given node. * @param {module:Core~Node} node - the node in question. * @param {string} name - the name of the registry entry. * * * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. * @throws {CoreIllegalOperationError} If the context of the operation is not allowed. * @throws {CoreInternalError} If some internal error took place inside the core layers. */ this.delRegistry = function (node, name) { ensureNode(node, 'node'); ensureType(name, 'name', 'string'); return core.delRegistry(node, name); }; /** * Retrieves a list of the defined pointer names of the node. * @param {module:Core~Node} node - the node in question. * * @return {string[]} The function returns an array of the names of the pointers of the node. * * @throws {CoreIllegalArgumentError} If some of the parameters don't match the input criteria. * @throws {CoreInternalError} If some intern