nope/modules/mod-Memory-Interface/helpers/references.ts
2020-09-10 18:21:19 +02:00

142 lines
4.3 KiB
TypeScript

/**
* @author Martin Karkowski
* @email m.karkowski@zema.de
* @create date 2019-01-16 23:10:38
* @modify date 2019-01-16 23:10:38
* @desc [description]
*/
import { IPubSubSystem, ITopic } from '../../ZISS-Publish-And-Subscribe-System/type/interfaces';
import { rgetattr, rsetattr } from '../../ZISS-TypeScript-Library/src/Object-Methods';
export const REF_IDENTIFIER = '$ref';
/**
* Function scans the Object for Refs.
*
* @export
* @param {*} data
* @param {{[index: string] : string}} [ret={}]
* @param {string} [path='']
* @param {string} [splitchar='.']
* @returns
*/
export function extractRefs(data: any, ret: Array<{ fullpath: string, prepath: string, segment: string, src: string }> = [], path = '', segment = '', splitchar = '.') {
if (Array.isArray(data) || (typeof data === 'object')) {
if (data[REF_IDENTIFIER] !== undefined) {
ret.push({
/** Extract the Reference */
src: data[REF_IDENTIFIER],
/** Full-Path */
fullpath: path,
/** If no splitchar is in the Path => its only the Segment, otherwise remove the Segment and Splitchar */
prepath: path.includes(splitchar) ? path.slice(0, path.length - (splitchar.length + segment.length)) : '',
/** Idenfier of the current Attribute */
segment: segment
});
return ret;
} else {
/** Iterate over the Array */
for (const identifier in data) {
/** Iterate over the Elements of the Object */
ret = extractRefs(data[identifier], ret, path !== '' ? path + splitchar + identifier : identifier, identifier, splitchar);
}
}
}
return ret;
}
/**
* Function to Figure out, whether an Object has Refs
*
* @export
* @param {*} data
* @returns {boolean}
*/
export function hasRefs(data: any): boolean {
return Object.getOwnPropertyNames(extractRefs(data)).length > 0;
}
function _updateGetterAndSetter(obj, segment, topic: ITopic<any>, readonly) {
return Object.defineProperty(obj, segment, {
get: () => topic.getContent(),
set: (value) => {
if (readonly) {
throw Error('Element is Read-Only');
} else {
topic.setContent(value, undefined, undefined, 'direct')
}
}
})
}
export function integrateDataFromRefs(data: any, pubSubSystem: IPubSubSystem, mode: 'static' | 'dynamic' = 'static', readonly = true) {
const refs = extractRefs(data)
for (const ref of refs) {
if (ref.prepath == '') {
if (ref.segment == '') {
if (mode == 'dynamic') {
throw Error('Trying to return a dynamic value on a ref-Object. This is not Possible')
}
else {
return pubSubSystem.getTopic(ref.src).getContent();
}
} else {
data = _updateGetterAndSetter(data, ref.segment, pubSubSystem.getTopic(ref.src), readonly);
}
} else {
const topic = pubSubSystem.getTopic(ref.src);
switch (mode) {
case 'static':
/** Set the Attribute to a Static Value */
rsetattr(data, ref.fullpath, topic.getContent());
break;
case 'dynamic':
/** Extract the Segment and Update it */
let segment = rgetattr(data, ref.prepath);
segment = _updateGetterAndSetter(segment, ref.segment, pubSubSystem.getTopic(ref.src), readonly);
rsetattr(data, ref.prepath, segment);
break;
}
}
}
return data
}
declare const require;
declare const module;
if (require.main === module) {
console.log(extractRefs({
a: {
b: {
c: {
$ref: 'anderer.element'
}
},
c: 'Hier sind normale Daten',
d: [{
$ref: 'anderes.array.element'
}, 1, 2, {
a: {
$ref: 'anderes.array.element'
}
}]
}
}));
console.log(extractRefs({ a: { $ref: 'spast' } }));
console.log(extractRefs({ $ref: 'spast' }));
}