Changes config from a function that returns an objectinto a more aptly named BaseObservableMapDefaults class

This commit is contained in:
Isaiah Becker-Mayer 2022-07-10 00:21:30 -04:00
parent bed66ada88
commit 73b83fdab8
9 changed files with 105 additions and 115 deletions

View File

@ -14,9 +14,9 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {BaseObservableMap, BaseObservableMapConfig} from "./BaseObservableMap"; import {BaseObservableMap} from "./BaseObservableMap";
import {SubscriptionHandle} from "../BaseObservable"; import {SubscriptionHandle} from "../BaseObservable";
import {config, Mapper, Updater, Comparator, Filter} from "./config"; import {BaseObservableMapDefaults, Mapper, Updater, Comparator, Filter} from "./BaseObservableMapDefaults";
import {JoinedMap} from "./JoinedMap"; import {JoinedMap} from "./JoinedMap";
import {MappedMap} from "./MappedMap"; import {MappedMap} from "./MappedMap";
import {FilteredMap} from "./FilteredMap"; import {FilteredMap} from "./FilteredMap";
@ -24,16 +24,16 @@ import {SortedMapList} from "../list/SortedMapList.js";
export class ApplyMap<K, V> extends BaseObservableMap<K, V> { export class ApplyMap<K, V> extends BaseObservableMap<K, V> {
private _defaults = new BaseObservableMapDefaults<K, V>();
private _source: BaseObservableMap<K, V>; private _source: BaseObservableMap<K, V>;
private _subscription?: SubscriptionHandle; private _subscription?: SubscriptionHandle;
private _apply?: Apply<K, V>; private _apply?: Apply<K, V>;
private _config: BaseObservableMapConfig<K, V>;
constructor(source: BaseObservableMap<K, V>, apply?: Apply<K, V>) { constructor(source: BaseObservableMap<K, V>, apply?: Apply<K, V>) {
super(); super();
this._source = source; this._source = source;
this._apply = apply; this._apply = apply;
this._config = config<K, V>();
} }
hasApply(): boolean { hasApply(): boolean {
@ -105,19 +105,19 @@ export class ApplyMap<K, V> extends BaseObservableMap<K, V> {
} }
join(...otherMaps: Array<typeof this>): JoinedMap<K, V> { join(...otherMaps: Array<typeof this>): JoinedMap<K, V> {
return this._config.join(this, ...otherMaps); return this._defaults.join(this, ...otherMaps);
} }
mapValues(mapper: Mapper<V>, updater?: Updater<V>): MappedMap<K, V> { mapValues(mapper: Mapper<V>, updater?: Updater<V>): MappedMap<K, V> {
return this._config.mapValues(this, mapper, updater); return this._defaults.mapValues(this, mapper, updater);
} }
sortValues(comparator: Comparator<V>): SortedMapList { sortValues(comparator: Comparator<V>): SortedMapList {
return this._config.sortValues(this, comparator); return this._defaults.sortValues(this, comparator);
} }
filterValues(filter: Filter<K, V>): FilteredMap<K, V> { filterValues(filter: Filter<K, V>): FilteredMap<K, V> {
return this._config.filterValues(this, filter); return this._defaults.filterValues(this, filter);
} }
} }

View File

@ -19,7 +19,7 @@ import {JoinedMap} from "../map/JoinedMap";
import {MappedMap} from "../map/MappedMap"; import {MappedMap} from "../map/MappedMap";
import {FilteredMap} from "../map/FilteredMap"; import {FilteredMap} from "../map/FilteredMap";
import {SortedMapList} from "../list/SortedMapList.js"; import {SortedMapList} from "../list/SortedMapList.js";
import {Mapper, Updater, Comparator, Filter} from "./config"; import {Mapper, Updater, Comparator, Filter} from "./BaseObservableMapDefaults";
export interface IMapObserver<K, V> { export interface IMapObserver<K, V> {
onReset(): void; onReset(): void;
@ -28,13 +28,6 @@ export interface IMapObserver<K, V> {
onRemove(key: K, value: V): void onRemove(key: K, value: V): void
} }
export type BaseObservableMapConfig<K, V> = {
join(_this: BaseObservableMap<K, V>, ...otherMaps: Array<BaseObservableMap<K, V>>): JoinedMap<K, V>;
mapValues(_this: BaseObservableMap<K, V>, mapper: any, updater?: Updater<V>): MappedMap<K, V>;
sortValues(_this: BaseObservableMap<K, V>, comparator: Comparator<V>): SortedMapList;
filterValues(_this: BaseObservableMap<K, V>, filter: Filter<K, V>): FilteredMap<K, V>;
}
export abstract class BaseObservableMap<K, V> extends BaseObservable<IMapObserver<K, V>> { export abstract class BaseObservableMap<K, V> extends BaseObservable<IMapObserver<K, V>> {
emitReset(): void { emitReset(): void {
for(let h of this._handlers) { for(let h of this._handlers) {
@ -62,10 +55,11 @@ export abstract class BaseObservableMap<K, V> extends BaseObservable<IMapObserve
} }
// The following group of functions have a default implementation // The following group of functions have a default implementation
// in the neighboring `config.ts`. See the comment in that file for // in the neighboring `BaseObservableMapDefaults.ts`. See the comment
// the explanation for why the default implementation isn't defined // in that file for the explanation for why the default implementation
// here. See the neighboring `ObservableMap.ts` for an example of how // isn't defined here. See the neighboring `ObservableMap.ts` for an
// to easily use the default implementation in a class that extends // example of how to easily add the boilerplate for using the default
// implementations of these functions in a class that extends
// this one (which is most likely what you want to do). // this one (which is most likely what you want to do).
abstract join(...otherMaps: Array<typeof this>): JoinedMap<K, V>; abstract join(...otherMaps: Array<typeof this>): JoinedMap<K, V>;
abstract mapValues(mapper: Mapper<V>, updater?: Updater<V>): MappedMap<K, V>; abstract mapValues(mapper: Mapper<V>, updater?: Updater<V>): MappedMap<K, V>;

View File

@ -0,0 +1,55 @@
/*
Copyright 2022 Isaiah Becker-Mayer <ibeckermayer@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import {BaseObservableMap} from "./BaseObservableMap";
import {FilteredMap} from "./FilteredMap";
import {MappedMap} from "./MappedMap";
import {JoinedMap} from "./JoinedMap";
import {SortedMapList} from "../list/SortedMapList.js";
// This class is used as a default implementation of
// the respective abstract functions in BaseObservableMap.
// It is kept as its own class in its own file in order to avoid a circular
// dependency between the classes that extend BaseObservableMap which are
// instantiated here (i.e. `new JoinedMap()`).
export class BaseObservableMapDefaults<K, V> {
join(_this: BaseObservableMap<K, V>, ...otherMaps: Array<BaseObservableMap<K, V>>): JoinedMap<K, V> {
return new JoinedMap([_this].concat(otherMaps));
}
mapValues(_this: BaseObservableMap<K, V>, mapper: Mapper<V>, updater?: Updater<V>): MappedMap<K, V> {
return new MappedMap(_this, mapper, updater);
}
sortValues(_this: BaseObservableMap<K, V>, comparator: Comparator<V>): SortedMapList {
return new SortedMapList(_this, comparator);
}
filterValues(_this: BaseObservableMap<K, V>, filter: Filter<K, V>): FilteredMap<K, V> {
return new FilteredMap(_this, filter);
}
}
export type Mapper<V> = (
value: V,
emitSpontaneousUpdate: any,
) => V;
export type Updater<V> = (params: any, mappedValue?: V, value?: V) => void;
export type Comparator<V> = (a: V, b: V) => number;
export type Filter<K, V> = (v: V, k: K) => boolean;

View File

@ -14,16 +14,16 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {BaseObservableMap, BaseObservableMapConfig} from "./BaseObservableMap"; import {BaseObservableMap} from "./BaseObservableMap";
import {SubscriptionHandle} from "../BaseObservable"; import {SubscriptionHandle} from "../BaseObservable";
import {config, Mapper, Updater, Comparator, Filter} from "./config"; import {BaseObservableMapDefaults, Mapper, Updater, Comparator, Filter} from "./BaseObservableMapDefaults";
import {JoinedMap} from "./JoinedMap"; import {JoinedMap} from "./JoinedMap";
import {MappedMap} from "./MappedMap"; import {MappedMap} from "./MappedMap";
import {SortedMapList} from "../list/SortedMapList.js"; import {SortedMapList} from "../list/SortedMapList.js";
export class FilteredMap<K, V> extends BaseObservableMap<K, V> { export class FilteredMap<K, V> extends BaseObservableMap<K, V> {
private _defaults = new BaseObservableMapDefaults<K, V>();
private _source: BaseObservableMap<K, V>; private _source: BaseObservableMap<K, V>;
private _config: BaseObservableMapConfig<K, V>;
private _filter: Filter<K, V>; private _filter: Filter<K, V>;
private _included?: Map<K, boolean>; private _included?: Map<K, boolean>;
private _subscription?: SubscriptionHandle; private _subscription?: SubscriptionHandle;
@ -32,7 +32,6 @@ export class FilteredMap<K, V> extends BaseObservableMap<K, V> {
super(); super();
this._source = source; this._source = source;
this._filter = filter; this._filter = filter;
this._config = config<K, V>();
} }
setFilter(filter: Filter<K, V>): void { setFilter(filter: Filter<K, V>): void {
@ -165,19 +164,19 @@ export class FilteredMap<K, V> extends BaseObservableMap<K, V> {
} }
join(...otherMaps: Array<typeof this>): JoinedMap<K, V> { join(...otherMaps: Array<typeof this>): JoinedMap<K, V> {
return this._config.join(this, ...otherMaps); return this._defaults.join(this, ...otherMaps);
} }
mapValues(mapper: Mapper<V>, updater?: Updater<V>): MappedMap<K, V>{ mapValues(mapper: Mapper<V>, updater?: Updater<V>): MappedMap<K, V>{
return this._config.mapValues(this, mapper, updater); return this._defaults.mapValues(this, mapper, updater);
} }
sortValues(comparator: Comparator<V>): SortedMapList { sortValues(comparator: Comparator<V>): SortedMapList {
return this._config.sortValues(this, comparator); return this._defaults.sortValues(this, comparator);
} }
filterValues(filter: Filter<K, V>): FilteredMap<K, V> { filterValues(filter: Filter<K, V>): FilteredMap<K, V> {
return this._config.filterValues(this, filter); return this._defaults.filterValues(this, filter);
} }
} }

View File

@ -14,8 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {BaseObservableMap, BaseObservableMapConfig} from "./BaseObservableMap"; import {BaseObservableMap} from "./BaseObservableMap";
import {config, Mapper, Updater, Comparator, Filter} from "./config"; import {BaseObservableMapDefaults, Mapper, Updater, Comparator, Filter} from "./BaseObservableMapDefaults";
import {FilteredMap} from "./FilteredMap"; import {FilteredMap} from "./FilteredMap";
import {MappedMap} from "./MappedMap"; import {MappedMap} from "./MappedMap";
import {SortedMapList} from "../list/SortedMapList.js"; import {SortedMapList} from "../list/SortedMapList.js";
@ -23,14 +23,13 @@ import {SubscriptionHandle} from "../BaseObservable";
export class JoinedMap<K, V> extends BaseObservableMap<K, V> { export class JoinedMap<K, V> extends BaseObservableMap<K, V> {
private _defaults = new BaseObservableMapDefaults<K, V>();
protected _sources: BaseObservableMap<K, V>[]; protected _sources: BaseObservableMap<K, V>[];
private _config: BaseObservableMapConfig<K, V>;
private _subscriptions?: SourceSubscriptionHandler<K, V>[]; private _subscriptions?: SourceSubscriptionHandler<K, V>[];
constructor(sources: BaseObservableMap<K, V>[]) { constructor(sources: BaseObservableMap<K, V>[]) {
super(); super();
this._sources = sources; this._sources = sources;
this._config = config<K, V>();
} }
onAdd(source: BaseObservableMap<K, V>, key: K, value: V): void { onAdd(source: BaseObservableMap<K, V>, key: K, value: V): void {
@ -136,19 +135,19 @@ export class JoinedMap<K, V> extends BaseObservableMap<K, V> {
} }
join(...otherMaps: Array<typeof this>): JoinedMap<K, V> { join(...otherMaps: Array<typeof this>): JoinedMap<K, V> {
return this._config.join(this, ...otherMaps); return this._defaults.join(this, ...otherMaps);
} }
mapValues(mapper: Mapper<V>, updater?: Updater<V>): MappedMap<K, V> { mapValues(mapper: Mapper<V>, updater?: Updater<V>): MappedMap<K, V> {
return this._config.mapValues(this, mapper, updater); return this._defaults.mapValues(this, mapper, updater);
} }
sortValues(comparator: Comparator<V>): SortedMapList { sortValues(comparator: Comparator<V>): SortedMapList {
return this._config.sortValues(this, comparator); return this._defaults.sortValues(this, comparator);
} }
filterValues(filter: Filter<K, V>): FilteredMap<K, V> { filterValues(filter: Filter<K, V>): FilteredMap<K, V> {
return this._config.filterValues(this, filter); return this._defaults.filterValues(this, filter);
} }
} }

View File

@ -14,8 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {BaseObservableMap, BaseObservableMapConfig} from "./BaseObservableMap"; import {BaseObservableMap} from "./BaseObservableMap";
import {config, Mapper, Updater, Comparator, Filter} from "./config"; import {BaseObservableMapDefaults, Mapper, Updater, Comparator, Filter} from "./BaseObservableMapDefaults";
import {FilteredMap} from "./FilteredMap"; import {FilteredMap} from "./FilteredMap";
import {MappedMap} from "./MappedMap"; import {MappedMap} from "./MappedMap";
import {JoinedMap} from "./JoinedMap"; import {JoinedMap} from "./JoinedMap";
@ -25,17 +25,15 @@ import {ILogItem, LabelOrValues} from "../../logging/types";
import {LogLevel} from "../../logging/LogFilter"; import {LogLevel} from "../../logging/LogFilter";
export class LogMap<K, V> extends BaseObservableMap<K, V> { export class LogMap<K, V> extends BaseObservableMap<K, V> {
private _defaults = new BaseObservableMapDefaults<K, V>();
private _source: BaseObservableMap<K, V>; private _source: BaseObservableMap<K, V>;
private _subscription?: SubscriptionHandle; private _subscription?: SubscriptionHandle;
private _log: ILogItem; private _log: ILogItem;
private _config: BaseObservableMapConfig<K, V>
constructor(source: BaseObservableMap<K, V>, log: ILogItem) { constructor(source: BaseObservableMap<K, V>, log: ILogItem) {
super(); super();
this._source = source; this._source = source;
this._log = log; this._log = log;
this._config = config<K, V>();
} }
private log(labelOrValues: LabelOrValues, logLevel?: LogLevel): ILogItem { private log(labelOrValues: LabelOrValues, logLevel?: LogLevel): ILogItem {
@ -88,19 +86,19 @@ export class LogMap<K, V> extends BaseObservableMap<K, V> {
} }
join(...otherMaps: Array<typeof this>): JoinedMap<K, V> { join(...otherMaps: Array<typeof this>): JoinedMap<K, V> {
return this._config.join(this, ...otherMaps); return this._defaults.join(this, ...otherMaps);
} }
mapValues(mapper: Mapper<V>, updater?: Updater<V>): MappedMap<K, V> { mapValues(mapper: Mapper<V>, updater?: Updater<V>): MappedMap<K, V> {
return this._config.mapValues(this, mapper, updater); return this._defaults.mapValues(this, mapper, updater);
} }
sortValues(comparator: Comparator<V>): SortedMapList { sortValues(comparator: Comparator<V>): SortedMapList {
return this._config.sortValues(this, comparator); return this._defaults.sortValues(this, comparator);
} }
filterValues(filter: Filter<K, V>): FilteredMap<K, V> { filterValues(filter: Filter<K, V>): FilteredMap<K, V> {
return this._config.filterValues(this, filter); return this._defaults.filterValues(this, filter);
} }
} }

View File

@ -14,8 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {BaseObservableMap, BaseObservableMapConfig} from "./BaseObservableMap"; import {BaseObservableMap} from "./BaseObservableMap";
import {config, Mapper, Updater, Comparator, Filter} from "./config"; import {BaseObservableMapDefaults, Mapper, Updater, Comparator, Filter} from "./BaseObservableMapDefaults";
import {JoinedMap} from "./JoinedMap"; import {JoinedMap} from "./JoinedMap";
import {FilteredMap} from "./FilteredMap"; import {FilteredMap} from "./FilteredMap";
import {SortedMapList} from "../list/SortedMapList.js"; import {SortedMapList} from "../list/SortedMapList.js";
@ -26,12 +26,13 @@ so a mapped value can emit updates on it's own with this._emitSpontaneousUpdate
how should the mapped value be notified of an update though? and can it then decide to not propagate the update? how should the mapped value be notified of an update though? and can it then decide to not propagate the update?
*/ */
export class MappedMap<K, V> extends BaseObservableMap<K, V> { export class MappedMap<K, V> extends BaseObservableMap<K, V> {
private _defaults = new BaseObservableMapDefaults<K, V>();
private _source: BaseObservableMap<K, V>; private _source: BaseObservableMap<K, V>;
private _mapper: Mapper<V>; private _mapper: Mapper<V>;
private _updater?: Updater<V>; private _updater?: Updater<V>;
private _mappedValues: Map<K, V>; private _mappedValues: Map<K, V>;
private _subscription?: SubscriptionHandle; private _subscription?: SubscriptionHandle;
private _config: BaseObservableMapConfig<K, V>
constructor( constructor(
source: BaseObservableMap<K, V>, source: BaseObservableMap<K, V>,
@ -43,7 +44,6 @@ export class MappedMap<K, V> extends BaseObservableMap<K, V> {
this._mapper = mapper; this._mapper = mapper;
this._updater = updater; this._updater = updater;
this._mappedValues = new Map<K, V>(); this._mappedValues = new Map<K, V>();
this._config = config<K, V>();
} }
_emitSpontaneousUpdate(key: K, params: any): void { _emitSpontaneousUpdate(key: K, params: any): void {
@ -115,18 +115,18 @@ export class MappedMap<K, V> extends BaseObservableMap<K, V> {
} }
join(...otherMaps: Array<typeof this>): JoinedMap<K, V> { join(...otherMaps: Array<typeof this>): JoinedMap<K, V> {
return this._config.join(this, ...otherMaps); return this._defaults.join(this, ...otherMaps);
} }
mapValues(mapper: Mapper<V>, updater?: Updater<V>): MappedMap<K, V>{ mapValues(mapper: Mapper<V>, updater?: Updater<V>): MappedMap<K, V>{
return this._config.mapValues(this, mapper, updater); return this._defaults.mapValues(this, mapper, updater);
} }
sortValues(comparator: Comparator<V>): SortedMapList { sortValues(comparator: Comparator<V>): SortedMapList {
return this._config.sortValues(this, comparator); return this._defaults.sortValues(this, comparator);
} }
filterValues(filter: Filter<K, V>): FilteredMap<K, V> { filterValues(filter: Filter<K, V>): FilteredMap<K, V> {
return this._config.filterValues(this, filter); return this._defaults.filterValues(this, filter);
} }
} }

View File

@ -14,8 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {BaseObservableMap, BaseObservableMapConfig} from "./BaseObservableMap"; import {BaseObservableMap} from "./BaseObservableMap";
import {config, Mapper, Updater, Comparator, Filter} from "./config"; import {BaseObservableMapDefaults, Mapper, Updater, Comparator, Filter} from "./BaseObservableMapDefaults";
import {JoinedMap} from "./JoinedMap"; import {JoinedMap} from "./JoinedMap";
import {MappedMap} from "./MappedMap"; import {MappedMap} from "./MappedMap";
import {FilteredMap} from "./FilteredMap"; import {FilteredMap} from "./FilteredMap";
@ -23,12 +23,11 @@ import {SortedMapList} from "../list/SortedMapList.js";
export class ObservableMap<K, V> extends BaseObservableMap<K, V> { export class ObservableMap<K, V> extends BaseObservableMap<K, V> {
private _config: BaseObservableMapConfig<K, V> private _defaults = new BaseObservableMapDefaults<K, V>();
private readonly _values: Map<K, V>; private readonly _values: Map<K, V>;
constructor(initialValues?: (readonly [K, V])[]) { constructor(initialValues?: (readonly [K, V])[]) {
super(); super();
this._config = config<K, V>();
this._values = new Map(initialValues); this._values = new Map(initialValues);
} }
@ -101,19 +100,19 @@ export class ObservableMap<K, V> extends BaseObservableMap<K, V> {
} }
join(...otherMaps: Array<typeof this>): JoinedMap<K, V> { join(...otherMaps: Array<typeof this>): JoinedMap<K, V> {
return this._config.join(this, ...otherMaps); return this._defaults.join(this, ...otherMaps);
} }
mapValues(mapper: Mapper<V>, updater?: Updater<V>): MappedMap<K, V> { mapValues(mapper: Mapper<V>, updater?: Updater<V>): MappedMap<K, V> {
return this._config.mapValues(this, mapper, updater); return this._defaults.mapValues(this, mapper, updater);
} }
sortValues(comparator: Comparator<V>): SortedMapList { sortValues(comparator: Comparator<V>): SortedMapList {
return this._config.sortValues(this, comparator); return this._defaults.sortValues(this, comparator);
} }
filterValues(filter: Filter<K, V>): FilteredMap<K, V> { filterValues(filter: Filter<K, V>): FilteredMap<K, V> {
return this._config.filterValues(this, filter); return this._defaults.filterValues(this, filter);
} }
}; };

View File

@ -1,54 +0,0 @@
/*
Copyright 2022 Isaiah Becker-Mayer <ibeckermayer@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import {BaseObservableMap, BaseObservableMapConfig} from "./BaseObservableMap";
import {FilteredMap} from "./FilteredMap";
import {MappedMap} from "./MappedMap";
import {JoinedMap} from "./JoinedMap";
import {SortedMapList} from "../list/SortedMapList.js";
// This function is used as a default implementation of
// the respective abstract functions in BaseObservableMap.
// We implement it this way in order to avoid a circular
// dependency between the classes that are instantiated here
// (i.e. `new JoinedMap()`) and BaseObservableMap (as they extend it).
export function config<K, V>(): BaseObservableMapConfig<K, V> {
return {
join: (_this: BaseObservableMap<K, V>, ...otherMaps: Array<BaseObservableMap<K, V>>): JoinedMap<K, V> => {
return new JoinedMap([_this].concat(otherMaps));
},
mapValues: (_this: BaseObservableMap<K, V>, mapper: Mapper<V>, updater?: Updater<V>): MappedMap<K, V> => {
return new MappedMap(_this, mapper, updater);
},
sortValues: (_this: BaseObservableMap<K, V>, comparator: Comparator<V>): SortedMapList => {
return new SortedMapList(_this, comparator);
},
filterValues: (_this: BaseObservableMap<K, V>, filter: Filter<K, V>): FilteredMap<K, V> => {
return new FilteredMap(_this, filter);
}
};
}
export type Mapper<V> = (
value: V,
emitSpontaneousUpdate: any,
) => V;
export type Updater<V> = (params: any, mappedValue?: V, value?: V) => void;
export type Comparator<V> = (a: V, b: V) => number;
export type Filter<K, V> = (v: V, k: K) => boolean;