/* eslint-disable no-param-reassign */
+/* eslint-disable no-restricted-syntax */
+import _ from "underscore";
+
+import { RelineNodeSchema } from "../interfaces/node.relineSchema";
+
+import fastCopy from "../../utils/fastCopy";
+import Options from "../../utils/relineOptions";
+import FieldNameFlag from "../../utils/fieldNameFlag";
+
+/**
+ * Class representing an util of RelineNode
+ */
+class RelineNodeUtil {
+ /**
+ * PARAMETER INMUTABLE
+ * Create a new node with given node. If 'id' is a empty string, return undefined.
+ * and throw an exception if options.strict is true.
+ * @param {String} id The id of the given node. Invoker should the uniqueness of the id of node.
+ * @param {{strict:boolean}} options
+ * @returns {RelineNodeSchema|undefined}
+ */
+ static create(id:string, options:Options):RelineNodeSchema|undefined {
+ if (id === "") {
+ if (options.strict) {
+ throw Error("Empty string id in Creating node");
+ } else {
+ return undefined;
+ }
+ }
+ return {
+ id,
+ metadata: {
+ basic: {
+ id,
+ },
+ },
+ };
+ }
+
+ /**
+ * PARAMETER INMUTABLE
+ * Returns a copy of a given node. This function will not do checking for 'node'.
+ * Use RelineValidator to verify the parameter(s) before using it.
+ * @param {RelineNodeSchema} node
+ * @returns {RelineNodeSchema} a copy of the node
+ */
+ static copy(node : RelineNodeSchema) : RelineNodeSchema {
+ return fastCopy(node);
+ }
+
+ /**
+ * PARAMETER INMUTABLE
+ * True if node1,node2 have value equality in their metadata(without feild basic).
+ * This function will not do checking for param:node1,node2.
+ * Use RelineValidator to verify the parameter(s) before using it.
+ * @param {RelineNodeSchema} node1
+ * @param {RelineNodeSchema} node2
+ * @returns {Boolean}
+ */
+ static isEqual(node1: RelineNodeSchema, node2: RelineNodeSchema):boolean {
+ const nodesMetaData = ([node1.metadata, node2.metadata]).map(
+ (item) => {
+ const { basic, ...other } = item;
+ return { ...other };
+ },
+ );
+ return _.isEqual(nodesMetaData[0], nodesMetaData[1]);
+ }
+
+ /**
+ * PARAMETER MUTABLE
+ * Change the field of the 'node' with a given fieldName.
+ * This function will not do checking for param:node.
+ * Use RelineValidator to verify the parameter(s) before using it.
+ * This function do nothing if fieldName is an empty string.
+ * If fieldName is not founded in node.metadata,
+ * this function create a field with the given fieldName and field if
+ * options.strict is false or throw an exception.
+ * // TODO :Use a check table.
+ * @param {RelineNodeSchema} node
+ * @param {string} fieldName
+ * @param {Object} field
+ * @param {{strict:boolean}} options
+ * @returns {RelineNodeSchema} the reference of given node for cascading calls.
+ */
+ static updateField(
+ node:RelineNodeSchema,
+ fieldName:string,
+ field:Object,
+ options:Options,
+ ):RelineNodeSchema {
+ let fieldNameFlag = 0;
+ if (fieldName === "") {
+ fieldNameFlag = FieldNameFlag.emptyString;
+ } else if (!(Object.prototype.hasOwnProperty.call(node.metadata, fieldName))) {
+ fieldNameFlag = FieldNameFlag.notFounded;
+ } else {
+ fieldNameFlag = FieldNameFlag.founded;
+ }
+
+ if (fieldNameFlag === FieldNameFlag.emptyString && options.strict) {
+ throw Error("FieldName is empty and function is in strict-mode");
+ } else if (fieldNameFlag === FieldNameFlag.emptyString && !options.strict) {
+ return node;
+ } else if (fieldNameFlag === FieldNameFlag.notFounded && options.strict) {
+ throw Error("FieldName is not founded in node and function is in strict-mode");
+ } else if (fieldNameFlag === FieldNameFlag.notFounded && !options.strict) {
+ const temp = <any>(node);
+ temp.metadata[fieldName] = field;
+ return <RelineNodeSchema>temp;
+ } else if (fieldNameFlag === FieldNameFlag.founded && options.strict) {
+ const temp = <any>(node);
+ temp.metadata[fieldName] = field;
+ return <RelineNodeSchema>temp;
+ } else { // (fileNameFlag === FieldNameFlag.founded && !options.strict)
+ const temp = <any>(node);
+ temp.metadata[fieldName] = field;
+ return <RelineNodeSchema>temp;
+ }
+ }
+
+ /**
+ * PARAMETER MUTABLE
+ * Create a field in a given node.
+ * This function will not do checking for param:node.
+ * Use RelineValidator to verify the parameter(s) before using it.
+ * This function do nothing if fieldName is an empty string.
+ * If there is a field with fieldName as it's key,this function will do nothing if
+ * options.strict is false.
+ * @param {RelineNodeSchema} node
+ * @param {string} fieldName
+ * @param {{strict:boolean}} options
+ * @returns {RelineNodeSchema} the reference of given node for cascading calls.
+ */
+ static createField(node:RelineNodeSchema, fieldName:string, options:Options):RelineNodeSchema {
+ let fieldNameFlag = 0;
+ if (fieldName === "") {
+ fieldNameFlag = FieldNameFlag.emptyString;
+ } else if (!(Object.prototype.hasOwnProperty.call(node.metadata, fieldName))) {
+ fieldNameFlag = FieldNameFlag.notFounded;
+ } else {
+ fieldNameFlag = FieldNameFlag.founded;
+ }
+
+ if (fieldNameFlag === FieldNameFlag.emptyString && options.strict) {
+ throw Error("FieldName is empty and function is in strict-mode");
+ } else if (fieldNameFlag === FieldNameFlag.emptyString && !options.strict) {
+ return node;
+ } else if (fieldNameFlag === FieldNameFlag.notFounded && options.strict) {
+ const temp = <any>(node);
+ temp.metadata[fieldName] = {};
+ return <RelineNodeSchema>temp;
+ } else if (fieldNameFlag === FieldNameFlag.notFounded && !options.strict) {
+ const temp = <any>(node);
+ temp.metadata[fieldName] = {};
+ return <RelineNodeSchema>temp;
+ } else if (fieldNameFlag === FieldNameFlag.founded && options.strict) {
+ throw Error("Duplicated creating feild in strict mode");
+ } else { // (fileNameFlag === FieldNameFlag.founded && !options.strict)
+ return node;
+ }
+ }
+
+ /**
+ * PARAMETER MUTABLE
+ * Delete a field in a given node
+ * This function will not do checking for param:node.
+ * Use RelineValidator to verify the parameter(s) before using it.
+ * This function do nothing if fieldName is an empty string.
+ * If there is no feild with fieldName as its key, this function will do nothing if
+ * options.strict is false or throw an exception.
+ * @param {RelineNodeSchema} node
+ * @param {String} fieldName
+ * @param {{strict:boolean}} options
+ * @returns {RelineNodeSchema} the reference of given node for cascading calls.
+ */
+ static deleteField(
+ node:RelineNodeSchema,
+ fieldName: string,
+ options: Options,
+ ): RelineNodeSchema {
+ let fieldNameFlag = 0;
+ if (fieldName === "") {
+ fieldNameFlag = FieldNameFlag.emptyString;
+ } else if (!(Object.prototype.hasOwnProperty.call(node.metadata, fieldName))) {
+ fieldNameFlag = FieldNameFlag.notFounded;
+ } else {
+ fieldNameFlag = FieldNameFlag.founded;
+ }
+
+ if (fieldNameFlag === FieldNameFlag.emptyString && options.strict) {
+ throw Error("FieldName is empty and function is in strict-mode");
+ } else if (fieldNameFlag === FieldNameFlag.emptyString && !options.strict) {
+ return node;
+ } else if (fieldNameFlag === FieldNameFlag.notFounded && options.strict) {
+ throw Error("FieldName is not founded in node and function is in strict-mode");
+ } else if (fieldNameFlag === FieldNameFlag.notFounded && !options.strict) {
+ return node;
+ } else if (fieldNameFlag === FieldNameFlag.founded && options.strict) {
+ delete (node.metadata)[fieldName];
+ return node;
+ } else { // (fileNameFlag === FieldNameFlag.founded && !options.strict)
+ delete (node.metadata)[fieldName];
+ return node;
+ }
+ }
+
+ /**
+ * PARAMETER INMUTABLE
+ * True if field1,field2 have value equality.
+ * @param {Object} field1
+ * @param {Object} field2
+ * @return {Boolean}
+ */
+ static isEqualField(field1:object, field2: object): boolean {
+ return _.isEqual(field1, field2);
+ }
+
+ /**
+ * PARAMETER MUTABLE
+ * Update the id of a given node.
+ * This function will not do checking for param:node.
+ * Use RelineValidator to verify the parameter(s) before using it.
+ * If newId is an empty string, throw an error
+ * @param {RelineNodeSchema} node
+ * @param {string} newId The newid of the given node. Invoker should the
+ * uniqueness of the id of node.
+ * @returns {RelineNodeSchema} the reference of given node for cascading calls.
+ */
+ static updateId(node:RelineNodeSchema, newId:string):RelineNodeSchema {
+ if (newId !== "") {
+ node.id = newId;
+ node.metadata.basic.id = newId;
+ return node;
+ }
+ throw Error("Updating node id with empty string");
+ }
+}
+
+export default RelineNodeUtil;
+ |