Home Reference Source

lib6/graph-types.js

import { stringify } from './json';
const IDENTIFIER_PROPERTY_ATTRIBUTES = {
    value: true,
    enumerable: false,
    configurable: false,
    writable: false
};
const NODE_IDENTIFIER_PROPERTY = '__isNode__';
const RELATIONSHIP_IDENTIFIER_PROPERTY = '__isRelationship__';
const UNBOUND_RELATIONSHIP_IDENTIFIER_PROPERTY = '__isUnboundRelationship__';
const PATH_IDENTIFIER_PROPERTY = '__isPath__';
const PATH_SEGMENT_IDENTIFIER_PROPERTY = '__isPathSegment__';
function hasIdentifierProperty(obj, property) {
    return obj != null && obj[property] === true;
}
/**
 * Class for Node Type.
 */
class Node {
    /**
     * @constructor
     * @protected
     * @param {NumberOrInteger} identity - Unique identity
     * @param {Array<string>} labels - Array for all labels
     * @param {Properties} properties - Map with node properties
     * @param {string} elementId - Node element identifier
     */
    constructor(identity, labels, properties, elementId) {
        /**
         * Identity of the node.
         * @type {NumberOrInteger}
         * @deprecated use {@link Node#elementId} instead
         */
        this.identity = identity;
        /**
         * Labels of the node.
         * @type {string[]}
         */
        this.labels = labels;
        /**
         * Properties of the node.
         * @type {Properties}
         */
        this.properties = properties;
        /**
         * The Node element identifier.
         * @type {string}
         */
        this.elementId = _valueOrGetDefault(elementId, () => identity.toString());
    }
    /**
     * @ignore
     */
    toString() {
        let s = '(' + this.elementId;
        for (let i = 0; i < this.labels.length; i++) {
            s += ':' + this.labels[i];
        }
        const keys = Object.keys(this.properties);
        if (keys.length > 0) {
            s += ' {';
            for (let i = 0; i < keys.length; i++) {
                if (i > 0)
                    s += ',';
                s += keys[i] + ':' + stringify(this.properties[keys[i]]);
            }
            s += '}';
        }
        s += ')';
        return s;
    }
}
Object.defineProperty(Node.prototype, NODE_IDENTIFIER_PROPERTY, IDENTIFIER_PROPERTY_ATTRIBUTES);
/**
 * Test if given object is an instance of {@link Node} class.
 * @param {Object} obj the object to test.
 * @return {boolean} `true` if given object is a {@link Node}, `false` otherwise.
 */
function isNode(obj) {
    return hasIdentifierProperty(obj, NODE_IDENTIFIER_PROPERTY);
}
/**
 * Class for Relationship Type.
 */
class Relationship {
    /**
     * @constructor
     * @protected
     * @param {NumberOrInteger} identity - Unique identity
     * @param {NumberOrInteger} start - Identity of start Node
     * @param {NumberOrInteger} end - Identity of end Node
     * @param {string} type - Relationship type
     * @param {Properties} properties - Map with relationship properties
     * @param {string} elementId - Relationship element identifier
     * @param {string} startNodeElementId - Start Node element identifier
     * @param {string} endNodeElementId - End Node element identifier
     */
    constructor(identity, start, end, type, properties, elementId, startNodeElementId, endNodeElementId) {
        /**
         * Identity of the relationship.
         * @type {NumberOrInteger}
         * @deprecated use {@link Relationship#elementId} instead
         */
        this.identity = identity;
        /**
         * Identity of the start node.
         * @type {NumberOrInteger}
         * @deprecated use {@link Relationship#startNodeElementId} instead
         */
        this.start = start;
        /**
         * Identity of the end node.
         * @type {NumberOrInteger}
         * @deprecated use {@link Relationship#endNodeElementId} instead
         */
        this.end = end;
        /**
         * Type of the relationship.
         * @type {string}
         */
        this.type = type;
        /**
         * Properties of the relationship.
         * @type {Properties}
         */
        this.properties = properties;
        /**
         * The Relationship element identifier.
         * @type {string}
         */
        this.elementId = _valueOrGetDefault(elementId, () => identity.toString());
        /**
         * The Start Node element identifier.
         * @type {string}
         */
        this.startNodeElementId = _valueOrGetDefault(startNodeElementId, () => start.toString());
        /**
         * The End Node element identifier.
         * @type {string}
         */
        this.endNodeElementId = _valueOrGetDefault(endNodeElementId, () => end.toString());
    }
    /**
     * @ignore
     */
    toString() {
        let s = '(' + this.startNodeElementId + ')-[:' + this.type;
        const keys = Object.keys(this.properties);
        if (keys.length > 0) {
            s += ' {';
            for (let i = 0; i < keys.length; i++) {
                if (i > 0)
                    s += ',';
                s += keys[i] + ':' + stringify(this.properties[keys[i]]);
            }
            s += '}';
        }
        s += ']->(' + this.endNodeElementId + ')';
        return s;
    }
}
Object.defineProperty(Relationship.prototype, RELATIONSHIP_IDENTIFIER_PROPERTY, IDENTIFIER_PROPERTY_ATTRIBUTES);
/**
 * Test if given object is an instance of {@link Relationship} class.
 * @param {Object} obj the object to test.
 * @return {boolean} `true` if given object is a {@link Relationship}, `false` otherwise.
 */
function isRelationship(obj) {
    return hasIdentifierProperty(obj, RELATIONSHIP_IDENTIFIER_PROPERTY);
}
/**
 * Class for UnboundRelationship Type.
 * @access private
 */
class UnboundRelationship {
    /**
     * @constructor
     * @protected
     * @param {NumberOrInteger} identity - Unique identity
     * @param {string} type - Relationship type
     * @param {Properties} properties - Map with relationship properties
     * @param {string} elementId - Relationship element identifier
     */
    constructor(identity, type, properties, elementId) {
        /**
         * Identity of the relationship.
         * @type {NumberOrInteger}
         * @deprecated use {@link UnboundRelationship#elementId} instead
         */
        this.identity = identity;
        /**
         * Type of the relationship.
         * @type {string}
         */
        this.type = type;
        /**
         * Properties of the relationship.
         * @type {Properties}
         */
        this.properties = properties;
        /**
         * The Relationship element identifier.
         * @type {string}
         */
        this.elementId = _valueOrGetDefault(elementId, () => identity.toString());
    }
    /**
     * Bind relationship
     *
     * @protected
     * @deprecated use {@link UnboundRelationship#bindTo} instead
     * @param {Integer} start - Identity of start node
     * @param {Integer} end - Identity of end node
     * @return {Relationship} - Created relationship
     */
    bind(start, end) {
        return new Relationship(this.identity, start, end, this.type, this.properties, this.elementId);
    }
    /**
     * Bind relationship
     *
     * @protected
     * @param {Node} start - Start Node
     * @param {Node} end - End Node
     * @return {Relationship} - Created relationship
     */
    bindTo(start, end) {
        return new Relationship(this.identity, start.identity, end.identity, this.type, this.properties, this.elementId, start.elementId, end.elementId);
    }
    /**
     * @ignore
     */
    toString() {
        let s = '-[:' + this.type;
        const keys = Object.keys(this.properties);
        if (keys.length > 0) {
            s += ' {';
            for (let i = 0; i < keys.length; i++) {
                if (i > 0)
                    s += ',';
                s += keys[i] + ':' + stringify(this.properties[keys[i]]);
            }
            s += '}';
        }
        s += ']->';
        return s;
    }
}
Object.defineProperty(UnboundRelationship.prototype, UNBOUND_RELATIONSHIP_IDENTIFIER_PROPERTY, IDENTIFIER_PROPERTY_ATTRIBUTES);
/**
 * Test if given object is an instance of {@link UnboundRelationship} class.
 * @param {Object} obj the object to test.
 * @return {boolean} `true` if given object is a {@link UnboundRelationship}, `false` otherwise.
 * @access private
 */
function isUnboundRelationship(obj) {
    return hasIdentifierProperty(obj, UNBOUND_RELATIONSHIP_IDENTIFIER_PROPERTY);
}
/**
 * Class for PathSegment Type.
 */
class PathSegment {
    /**
     * @constructor
     * @protected
     * @param {Node} start - start node
     * @param {Relationship} rel - relationship that connects start and end node
     * @param {Node} end - end node
     */
    constructor(start, rel, end) {
        /**
         * Start node.
         * @type {Node}
         */
        this.start = start;
        /**
         * Relationship.
         * @type {Relationship}
         */
        this.relationship = rel;
        /**
         * End node.
         * @type {Node}
         */
        this.end = end;
    }
}
Object.defineProperty(PathSegment.prototype, PATH_SEGMENT_IDENTIFIER_PROPERTY, IDENTIFIER_PROPERTY_ATTRIBUTES);
/**
 * Test if given object is an instance of {@link PathSegment} class.
 * @param {Object} obj the object to test.
 * @return {boolean} `true` if given object is a {@link PathSegment}, `false` otherwise.
 */
function isPathSegment(obj) {
    return hasIdentifierProperty(obj, PATH_SEGMENT_IDENTIFIER_PROPERTY);
}
/**
 * Class for Path Type.
 */
class Path {
    /**
     * @constructor
     * @protected
     * @param {Node} start  - start node
     * @param {Node} end - end node
     * @param {Array<PathSegment>} segments - Array of Segments
     */
    constructor(start, end, segments) {
        /**
         * Start node.
         * @type {Node}
         */
        this.start = start;
        /**
         * End node.
         * @type {Node}
         */
        this.end = end;
        /**
         * Segments.
         * @type {Array<PathSegment>}
         */
        this.segments = segments;
        /**
         * Length of the segments.
         * @type {Number}
         */
        this.length = segments.length;
    }
}
Object.defineProperty(Path.prototype, PATH_IDENTIFIER_PROPERTY, IDENTIFIER_PROPERTY_ATTRIBUTES);
/**
 * Test if given object is an instance of {@link Path} class.
 * @param {Object} obj the object to test.
 * @return {boolean} `true` if given object is a {@link Path}, `false` otherwise.
 */
function isPath(obj) {
    return hasIdentifierProperty(obj, PATH_IDENTIFIER_PROPERTY);
}
function _valueOrGetDefault(value, getDefault) {
    return value === undefined || value === null ? getDefault() : value;
}
export { Node, isNode, Relationship, isRelationship, UnboundRelationship, isUnboundRelationship, Path, isPath, PathSegment, isPathSegment };