/**
|
* Row data are defined as name and (immediate) parent only.
|
* DataHierarchyProvider class is able to query recursively to infer all ancestors.
|
*/
|
export interface DataHierarchy {
|
Name: string;
|
ParentKey: string;
|
NameKey: string;
|
OndrawImageName?: string;
|
}
|
|
/**
|
* Provider class to get all ancestor row names by passing in the target child row.
|
*/
|
export class DataHierarchyProvider {
|
private readonly store: Map<string, DataHierarchy> = new Map();
|
|
public constructor(data: Record<string, DataHierarchy>) {
|
for (const t of Object.keys(data)) {
|
const a = data[t];
|
this.store.set(a.NameKey, a); // Stores row data and its immediate parent
|
}
|
}
|
|
/**
|
* Given a row name, infer the ancestor rows.
|
*
|
* @param key Row name.
|
* @returns Tuple containing row name and all ancestors.
|
*/
|
public getHierarchy(key: DataHierarchy): [DataHierarchy, DataHierarchy[]] {
|
// Recursive get all ancestor rows
|
const ancestor = this.store.get(key.NameKey);
|
let ancestorArr: DataHierarchy[] = [];
|
ancestorArr = this.recursiveGetAncestor(ancestor!, ancestorArr);
|
return [key, ancestorArr];
|
}
|
|
private recursiveGetAncestor(ancestor: DataHierarchy, ancestorArr: DataHierarchy[]): DataHierarchy[] {
|
const hasParent = ancestor !== undefined && ancestor.ParentKey !== '';
|
if (hasParent) {
|
const ancestorName = this.store.get(ancestor.ParentKey);
|
if (ancestorName) {
|
ancestorArr = [ancestorName].concat(ancestorArr); // Put ancestor to the front of array
|
ancestorArr = this.recursiveGetAncestor(ancestorName, ancestorArr);
|
} else {
|
throw(TypeError(`No Ancestor: ${ancestor.ParentKey} to be found.`));
|
}
|
}
|
return ancestorArr;
|
}
|
}
|