Commit dd61f379 authored by Matija Obreza's avatar Matija Obreza Committed by Maksym Tishchenko
Browse files

dereferenceReferences: Allow dereferencing of nested arrays[].and[].props

parent d2d5f406
......@@ -6,6 +6,7 @@ import _isArray from 'lodash/isArray';
import _isObject from 'lodash/isObject';
import { ApplicationService } from '@gringlobal-ce/client/service';
import Mustache from 'mustache';
// import { isObject } from 'util';
/**
* A very wordy comparison of two arrays
......@@ -162,6 +163,7 @@ export function dereferenceReferences3(content: any[], referenceMaps: { [key: st
return content;
}
// console.log('\n\n\n*** Here we go! ***');
const refs: any = {};
const paths = [];
const keyOfPath: any = {};
......@@ -181,48 +183,105 @@ export function dereferenceReferences3(content: any[], referenceMaps: { [key: st
});
})
});
const sortedPaths = paths.sort(); // sorted paths should ensure we access deeper properties late
console.log('Caches', refs, paths, sortedPaths, keyOfPath, cacheForPath);
const sortedPaths = paths.sort((a, b) => {
const pa = a.split('.');
const pb = b.split('.');
if (pa.length == pb.length) {
return a.localeCompare(b);
} else if (pa.length < pb.length) {
return -1;
} else {
return 1;
}
}); // sorted paths ensure we access deeper properties late
// First scan: fill caches with objects
sortedPaths.forEach((path) => {
const selfRef = '_self' === path;
const p = propertyGet(path);
content.forEach((entry, index) => {
const v = selfRef ? content[index] : p(entry);
if (v) {
if (typeof v === 'object') {
if (selfRef) {
refs._self[`${v[keyOfPath._self]}`] = v;
console.log(`Cached ${path} by prop ${keyOfPath[path]}`, v[keyOfPath[path]], v, cacheForPath[path]);
// console.log('Caches', refs, paths, sortedPaths, keyOfPath, cacheForPath);
const _handleArrayPath = (path: string, pathParts: string[], pathIndex: number, list: any[]) => {
// the array becomes the content, and we scan it for one property
// console.log(`--- Arrays at ${pathParts[pathIndex]} of ${path}`, list);
const p = propertyGet(pathParts[pathIndex]);
list.forEach((entry, index) => {
const v = path === '_self' ? entry : p(entry);
if (v && _isObject(v)) {
// console.log(`Found ${pathParts[pathIndex]}[${pathIndex}] ppl=${pathParts.length} nxt=${pathParts[pathIndex + 1]}`, v);
if (pathParts.length > pathIndex + 1 && pathParts[pathIndex + 1] !== '') {
// we have more to scan!
// console.log(`We have more to scan at ${pathParts[pathIndex + 1]}...`, v);
_handleArrayPath(path, pathParts, pathIndex + 1, v);
} else {
// console.log(`This is the final object at ${path}`, v);
if (_isArray(v)) {
v.forEach((el, index) => {
if (typeof el === 'object') {
cacheForPath[path][`${el[keyOfPath[path]]}`] = el;
// console.log(`Cached ${path}[${index}] by prop ${keyOfPath[path]}`, el); //, cacheForPath[path]);
}
});
} else {
cacheForPath[path][`${v[keyOfPath[path]]}`] = v;
console.log(`Cached ${path} by prop ${keyOfPath[path]}`, v[keyOfPath[path]], v, cacheForPath[path]);
// console.log(`Cached ${path} by prop ${keyOfPath[path]}`, v); //, cacheForPath[path]);
}
}
} else {
// console.log(`No property ${pathParts[pathIndex]} of type 'object' in`, entry);
}
});
});
}
// Second scan: convert values to objects
// First scan: fill caches with objects
sortedPaths.forEach((path) => {
const selfRef = '_self' === path;
const p = propertyGet(path);
content.forEach((entry, index) => {
const v = selfRef ? content[index] : p(entry);
if (v) {
if (typeof v !== 'object') {
const cv = cacheForPath[path][`${v}`];
if (selfRef) {
content[index] = cv || v;
console.log(`Set self from ${keyOfPath[path]}=${v}`, cv);
} else {
propertySet(entry, path, cv || v);
console.log(`Set ${path} from ${keyOfPath[path]}=${v}`, cv);
// console.log(`\n\n+++ Processing ${path}\n`);
const pathParts = path.split(/\[\]\.?/); // 'source.path.foo' splits into length=1, source[].path[].foo to length=3, source[].path[].foo[] to length = 4 + last one is empty string ""
_handleArrayPath(path, pathParts, 0, content);
});
const _processArrayPath = (path: string, pathParts: string[], pathIndex: number, list: any[]) => {
// the array becomes the content, and we scan it for one property
// console.log(`--- Arrays at ${pathParts[pathIndex]} of ${path}`, list);
const p = propertyGet(pathParts[pathIndex]);
list.forEach((entry, index) => {
const v = path === '_self' ? entry : p(entry);
if (v && _isObject(v)) {
// console.log(`Found ${pathParts[pathIndex]}[${pathIndex}] ppl=${pathParts.length} nxt=${pathParts[pathIndex + 1]}`, v);
if (pathParts.length > pathIndex + 1 && pathParts[pathIndex + 1] !== '') {
// console.log(`We have more to scan at ${pathParts[pathIndex + 1]}...`, v);
_processArrayPath(path, pathParts, pathIndex + 1, v);
} else {
// console.log(`This is the final object at ${path}`, v);
if (_isArray(v)) {
v.forEach((el, index) => {
if (el && !_isObject(el)) {
// console.log(`Handling ${pathParts[pathIndex]}[${index}] by prop ${keyOfPath[path]}`, el, cacheForPath[path]);
const cv = cacheForPath[path][`${el}`];
v[index] = cv || el;
// console.log(`Set list element ${pathParts[pathIndex]} from ${keyOfPath[path]}=${el} on`); //, v);
}
});
}
}
} else if (v && !_isObject(v)) {
// console.log(`Handling ${pathParts[pathIndex]}[${index}] by prop ${keyOfPath[path]}`, v, cacheForPath[path]);
const cv = cacheForPath[path][`${v}`];
if (path === '_self') {
list[index] = cv || v;
// console.log(`Set self from ${keyOfPath[path]}=${v} on`); //, list[index]);
} else {
propertySet(entry, pathParts[pathIndex], cv || v);
// console.log(`Set ${pathParts[pathIndex]} from ${keyOfPath[path]}=${v} on`); //, entry);
}
} else {
// console.log(`No property ${pathParts[pathIndex]} of type 'object' in`, entry);
}
});
}
// Second scan: convert values to objects
sortedPaths.forEach((path) => {
// console.log(`\n\n=== Dereferencing ${path}\n`);
const pathParts = path.split(/\[\]\.?/); // 'source.path.foo' splits into length=1, source[].path[].foo to length=3, source[].path[].foo[] to length = 4 + last one is empty string ""
_processArrayPath(path, pathParts, 0, content);
});
// console.log('End caches', refs);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment