lik/ts/lik.objectmap.ts
2022-05-27 17:53:02 +02:00

247 lines
5.8 KiB
TypeScript

import * as plugins from './lik.plugins.js';
import { FastMap } from './lik.fastmap.js';
export const uni = (prefix: string = 'uni') => {
return `${prefix}xxxxxxxxxxx`.replace(/[xy]/g, (c) => {
const r = (Math.random() * 16) | 0;
const v = c === 'x' ? r : (r & 0x3) | 0x8;
return v.toString(16);
});
};
export interface IObjectmapForEachFunction<T> {
(itemArg: T): void;
}
export interface IObjectmapFindFunctionSync<T> {
(itemArg: T): boolean;
}
export interface IObjectmapFindFunction<T> {
(itemArg: T): Promise<boolean>;
}
export interface IObjectMapEventData<T> {
operation: 'add' | 'remove';
payload: T;
}
/**
* allows keeping track of objects
*/
export class ObjectMap<T> {
private fastMap = new FastMap<T>();
// events
public eventSubject = new plugins.smartrx.rxjs.Subject<IObjectMapEventData<T>>();
/**
* returns a new instance
*/
constructor() {
// nothing here
}
/**
* adds an object mapped to a string
* the string must be unique
*/
addMappedUnique(uniqueKeyArg: string, objectArg: T) {
this.fastMap.addToMap(uniqueKeyArg, objectArg);
}
/**
* fastest way to get an object from the map
* @param uniqueKey
*/
public getMappedUnique(uniqueKeyArg: string) {
return this.fastMap.getByKey(uniqueKeyArg);
}
/**
* remove key
* @param functionArg
*/
public removeMappedUnique(uniqueKey: string) {
const object = this.getMappedUnique(uniqueKey);
}
/**
* add object to Objectmap
* returns false if the object is already in the map
* returns true if the object was added successfully
*/
public add(objectArg: T): string {
// lets search for an existing unique key
for (const keyArg of this.fastMap.getKeys()) {
const object = this.fastMap.getByKey(keyArg);
if (object === objectArg) {
return keyArg;
}
}
// otherwise lets create it
const uniqueKey = uni('key');
this.addMappedUnique(uniqueKey, objectArg);
this.eventSubject.next({
operation: 'add',
payload: objectArg
});
return uniqueKey;
}
/**
* like .add but adds an whole array of objects
*/
public addArray(objectArrayArg: T[]) {
for (const item of objectArrayArg) {
this.add(item);
}
}
/**
* check if object is in Objectmap
*/
public checkForObject(objectArg: T): boolean {
return !!this.getKeyForObject(objectArg);
}
/**
* get key for object
* @param findFunction
*/
public getKeyForObject(objectArg: T) {
let foundKey: string = null;
for (const keyArg of this.fastMap.getKeys()) {
if (!foundKey && this.fastMap.getByKey(keyArg) === objectArg) {
foundKey = keyArg;
} else {
continue;
}
}
return foundKey;
}
/**
* find object
*/
public async find(findFunction: IObjectmapFindFunction<T>): Promise<T> {
return this.fastMap.find(findFunction);
}
public findSync(findFunction: IObjectmapFindFunctionSync<T>): T {
for (const keyArg of this.fastMap.getKeys()) {
if (findFunction(this.fastMap.getByKey(keyArg))) {
return this.getMappedUnique(keyArg);
}
}
}
/**
* finds a specific element and then removes it
*/
public async findOneAndRemove(findFunction: IObjectmapFindFunction<T>): Promise<T> {
const foundElement = await this.find(findFunction);
if (foundElement) {
this.remove(foundElement);
}
return foundElement;
}
public findOneAndRemoveSync(findFunction: IObjectmapFindFunctionSync<T>): T {
const foundElement = this.findSync(findFunction);
if (foundElement) {
this.remove(foundElement);
}
return foundElement;
}
/**
* run function for each item in Objectmap
*/
public async forEach(functionArg: IObjectmapForEachFunction<T>) {
for (const keyArg of this.fastMap.getKeys()) {
await functionArg(this.fastMap.getByKey(keyArg));
}
}
/**
* gets an object in the Observablemap and removes it, so it can't be retrieved again
*/
public getOneAndRemove(): T {
const keys = this.fastMap.getKeys();
if (keys.length === 0) {
return null;
} else {
const keyToUse = keys[0];
const removedItem = this.fastMap.removeFromMap(keyToUse);
this.eventSubject.next({
operation: 'remove',
payload: removedItem
});
return removedItem;
}
}
/**
* returns a cloned array of all the objects currently in the Objectmap
*/
public getArray(): T[] {
const returnArray: any[] = [];
for (const keyArg of this.fastMap.getKeys()) {
returnArray.push(this.fastMap.getByKey(keyArg));
}
return returnArray;
}
/**
* check if Objectmap ist empty
*/
public isEmpty(): boolean {
return this.fastMap.getKeys().length === 0;
}
/**
* remove object from Objectmap
*/
public remove(objectArg: T): T {
if (this.checkForObject(objectArg)) {
const keyArg = this.getKeyForObject(objectArg);
const removedObject = this.fastMap.removeFromMap(keyArg);
this.eventSubject.next({
operation: 'remove',
payload: removedObject
});
return removedObject;
}
return null;
}
/**
* wipe Objectmap
*/
public wipe() {
for (const keyArg of this.fastMap.getKeys()) {
this.fastMap.removeFromMap(keyArg);
}
}
/**
* returns a new Objectmap that includes
*/
public concat(objectMapArg: ObjectMap<T>) {
const concattedObjectMap = new ObjectMap<T>();
concattedObjectMap.fastMap.addAllFromOther(this.fastMap);
concattedObjectMap.fastMap.addAllFromOther(objectMapArg.fastMap);
return concattedObjectMap;
}
/**
* tries to merge another Objectmap
* Note: uniqueKeyCollisions will cause overwrite
* @param objectMapArg
*/
public addAllFromOther(objectMapArg: ObjectMap<T>) {
this.fastMap.addAllFromOther(objectMapArg.fastMap);
}
}