nope/lib/helpers/mergedData.ts

135 lines
3.3 KiB
TypeScript

/**
* @author Martin Karkowski
* @email m.karkowski@zema.de
* @create date 2021-11-23 11:04:49
* @modify date 2021-11-23 11:04:49
* @desc [description]
*/
import { NopeEventEmitter } from "../eventEmitter/nopeEventEmitter";
import { determineDifference } from "../helpers/setMethods";
import { NopeObservable } from "../observables/nopeObservable";
import { INopeEventEmitter, INopeObservable } from "../types/nope";
import { IMergeData } from "../types/nope/nopeHelpers.interface";
import { countElements } from "./arrayMethods";
import {
extractUniqueValues,
extractValues,
reverse,
transformValues,
} from "./mapMethods";
export class MergeData<T, D = any> implements IMergeData<T, D> {
/**
* Element which will trig implements IMergeDatager an event containing the changes
*
* @author M.Karkowski
* @type {INopeEventEmitter<{
* added: T[],
* removed: T[]
* }>}
* @memberof MergeData
*/
readonly onChange: INopeEventEmitter<{
added: T[];
removed: T[];
}>;
/**
* Contains the current data.
*
* @author M.Karkowski
* @type {INopeObservable<T[]>}
* @memberof MergeData
*/
readonly data: INopeObservable<T[]>;
constructor(
public originalData: D,
protected _extractData: (data: D) => Set<T>
) {
this.onChange = new NopeEventEmitter();
this.data = new NopeObservable();
this.data.setContent([]);
}
/**
* Update the underlying data.
*
* @author M.Karkowski
* @param {*} [data=this.originalData]
* @memberof MergeData
*/
public update(data: D = null): void {
if (data !== null) {
this.originalData = data;
}
const afterAdding = this._extractData(this.originalData);
const diff = determineDifference(
new Set(this.data.getContent()),
afterAdding
);
if (diff.removed.size > 0 || diff.added.size > 0) {
// Update the currently used subscriptions
this.data.setContent(Array.from(afterAdding));
// Now emit, that there is a new subscription.
this.onChange.emit({
added: Array.from(diff.added),
removed: Array.from(diff.removed),
});
}
}
/**
* Disposes the Element.
*
* @author M.Karkowski
* @memberof MergeData
*/
public dispose() {
this.data.dispose();
this.onChange.dispose();
}
}
export class MapBasedMergeData<T, K, V>
extends MergeData<T, Map<K, V>>
implements IMergeData<T, Map<K, V>>
{
public amountOf: Map<T, number>;
public simplified: Map<K, T>;
public reverseSimplified: Map<T, Set<K>>;
constructor(originalData: Map<K, V>, protected _path = "") {
super(originalData, (m) => {
return extractUniqueValues(m, _path);
});
this.amountOf = new Map();
this.simplified = new Map();
this.reverseSimplified = new Map();
}
/**
* Update the underlying data.
*
* @author M.Karkowski
* @param {*} [data=this.originalData]
* @memberof MergeData
*/
public update(data: Map<K, V> = null): void {
if (data !== null) {
this.originalData = data;
}
// Now lets update the amount of the data:
this.amountOf = countElements(extractValues(this.originalData, this._path));
this.simplified = transformValues(this.originalData, this._path);
this.reverseSimplified = reverse(this.simplified);
super.update(data);
}
}