@dolittle/sdk.common
Version:
Dolittle is a decentralized, distributed, event-driven microservice platform built to harness the power of events.
204 lines • 21.4 kB
JavaScript
;
// Copyright (c) Dolittle. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
Object.defineProperty(exports, "__esModule", { value: true });
exports.ModelBuilder = void 0;
const CannotUnbindIdentifierFromProcessorBuilderThatIsNotBound_1 = require("./CannotUnbindIdentifierFromProcessorBuilderThatIsNotBound");
const CannotUnbindIdentifierFromTypeThatIsNotBound_1 = require("./CannotUnbindIdentifierFromTypeThatIsNotBound");
const IModelBuilder_1 = require("./IModelBuilder");
const Model_1 = require("./Model");
/**
* Represents an implementation of {@link IModelBuilder}.
*/
class ModelBuilder extends IModelBuilder_1.IModelBuilder {
constructor() {
super(...arguments);
this._typesByIdentifier = new Map();
this._processorBuildersByIdentifier = new Map();
}
/** @inheritdoc */
bindIdentifierToType(identifier, type) {
const types = this.getMapList(this._typesByIdentifier, identifier);
types.push([identifier, type]);
}
/** @inheritdoc */
unbindIdentifierFromType(identifier, type) {
const types = this.getMapList(this._typesByIdentifier, identifier);
const foundIndex = this.findListIndex(types, identifier, type);
if (foundIndex < 0) {
throw new CannotUnbindIdentifierFromTypeThatIsNotBound_1.CannotUnbindIdentifierFromTypeThatIsNotBound(identifier, type);
}
types.splice(foundIndex, 1);
}
/** @inheritdoc */
bindIdentifierToProcessorBuilder(identifier, processorBuilder) {
const processorBuilders = this.getMapList(this._processorBuildersByIdentifier, identifier);
processorBuilders.push([identifier, processorBuilder]);
}
/** @inheritdoc */
unbindIdentifierFromProcessorBuilder(identifier, processorBuilder) {
const processorBuilders = this.getMapList(this._processorBuildersByIdentifier, identifier);
const foundIndex = this.findListIndex(processorBuilders, identifier, processorBuilder);
if (foundIndex < 0) {
throw new CannotUnbindIdentifierFromProcessorBuilderThatIsNotBound_1.CannotUnbindIdentifierFromProcessorBuilderThatIsNotBound(identifier, processorBuilder);
}
processorBuilders.splice(foundIndex, 1);
}
/** @inheritdoc */
build(buildResults) {
const deduplicatedTypes = this.deduplicateBindings(this._typesByIdentifier, (left, right) => left === right, (identifier, type, duplicates) => {
buildResults.addInformation(`Type binding from ${identifier.constructor.name} to ${type.name} appeared ${duplicates} times`);
});
const deduplicatedProcessorBuilders = this.deduplicateBindings(this._processorBuildersByIdentifier, (left, right) => left.equals(right), (identifier, processorBuilder, duplicates) => {
buildResults.addInformation(`Processor binding from ${identifier.constructor.name} to ${processorBuilder.constructor.name} appeared ${duplicates} times`);
});
const singlyBoundTypes = this.singlyBoundValues(deduplicatedTypes, (left, right) => left === right, (type, identifiers) => {
buildResults.addFailure(`Type ${type.name} is bound to multiple identifiers:`);
for (const identifier of identifiers) {
buildResults.addFailure(`\t ${identifier}. This binding will be ignored`);
}
});
const singlyProcessorBuilders = this.singlyBoundValues(deduplicatedProcessorBuilders, (left, right) => left.equals(right), (processorBuilder, identifiers) => {
buildResults.addFailure(`Type ${processorBuilder.constructor.name} is bound to multiple identifiers:`);
for (const identifier of identifiers) {
buildResults.addFailure(`\t ${identifier}. This binding will be ignored`);
}
});
const validTypeBindings = [];
const validProcessorBuilderBindings = [];
const ids = new Set([...singlyBoundTypes.keys(), ...singlyProcessorBuilders.keys()]);
for (const id of ids) {
const [coexistentTypes, conflictingTypes] = this.splitCoexistingAndConflictingBindings(singlyBoundTypes, id, (left, right) => left === right);
const [coexistentProcessorBuilders, conflictingProcessorBuilders] = this.splitCoexistingAndConflictingBindings(deduplicatedProcessorBuilders, id, (left, right) => left.equals(right));
if (conflictingTypes.length === 0 && conflictingProcessorBuilders.length === 0) {
validTypeBindings.push(...coexistentTypes);
validProcessorBuilderBindings.push(...coexistentProcessorBuilders);
continue;
}
const conflicts = [];
if (conflictingTypes.length > 0)
conflicts.push('types');
if (conflictingProcessorBuilders.length > 0)
conflicts.push('processors');
buildResults.addFailure(`The identifier ${id} was bound to conflicting ${conflicts.join(' and ')}:`);
for (const [identifier, type] of conflictingTypes) {
buildResults.addFailure(`\t ${identifier} was bound to ${type.name}. This binding will be ignored`);
}
for (const [identifier, processorBuilder] of conflictingProcessorBuilders) {
buildResults.addFailure(`\t ${identifier} was bound to ${processorBuilder.constructor.name}. This binding will be ignored`);
}
if (coexistentTypes.length > 0 || coexistentProcessorBuilders.length > 0) {
buildResults.addFailure(`The identifier ${id} was also bound to:`);
}
for (const [identifier, type] of coexistentTypes) {
buildResults.addFailure(`\t ${identifier} binding to ${type.name}. This binding will be ignored`);
}
for (const [identifier, processorBuilder] of coexistentProcessorBuilders) {
buildResults.addFailure(`\t ${identifier} binding to ${processorBuilder.constructor.name}. This binding will be ignored`);
}
}
for (const [identifier, type] of validTypeBindings) {
buildResults.addInformation(`${identifier} will be bound to type ${type.name}`);
}
for (const [identifier, processorBuilder] of validProcessorBuilderBindings) {
buildResults.addInformation(`${identifier} will be bound to processor builder ${processorBuilder.constructor.name}`);
}
return new Model_1.Model(validTypeBindings, validProcessorBuilderBindings);
}
getMapList(map, identifier) {
const key = identifier.id.value.toString();
if (!map.has(key)) {
const list = [];
map.set(key, list);
return list;
}
else {
return map.get(key);
}
}
;
findListIndex(list, identifier, value) {
return list.findIndex(([existingIdentifier, existingValue]) => {
return existingIdentifier.equals(identifier) && existingValue === value;
});
}
;
deduplicateBindings(map, comparer, callback) {
const filteredMap = new Map();
for (const [key, bindings] of map.entries()) {
const countedBindings = [];
counting: for (const [identifier, value] of bindings) {
for (const existing of countedBindings) {
const [existingIdentifier, existingValue, duplicates] = existing;
if (existingIdentifier.equals(identifier) && comparer(existingValue, value)) {
existing[2] = duplicates + 1;
continue counting;
}
}
countedBindings.push([identifier, value, 1]);
}
const filteredBindings = [];
for (const [identifier, value, duplicates] of countedBindings) {
if (duplicates > 1) {
callback(identifier, value, duplicates);
}
filteredBindings.push([identifier, value]);
}
filteredMap.set(key, filteredBindings);
}
return filteredMap;
}
singlyBoundValues(map, comparer, callback) {
const groupedValues = [];
const allValues = Array.from(map.values()).flat();
grouping: for (const [identifier, value] of allValues) {
for (const [groupedValue, groupedIdentifiers] of groupedValues) {
if (comparer(value, groupedValue)) {
groupedIdentifiers.push(identifier);
continue grouping;
}
}
groupedValues.push([value, [identifier]]);
}
const singlyBoundMap = new Map();
for (const [value, identifiers] of groupedValues) {
if (identifiers.length === 1) {
const identifier = identifiers[0];
singlyBoundMap.set(identifier.id.value.toString(), [[identifier, value]]);
}
else {
callback(value, identifiers);
}
}
return singlyBoundMap;
}
splitCoexistingAndConflictingBindings(map, key, comparer) {
if (!map.has(key))
return [[], []];
const bindings = map.get(key);
const conflicts = new Set();
for (const [identifier, value] of bindings) {
for (const [otherIdentifier, otherValue] of bindings) {
const canCoexist = (identifier.equals(otherIdentifier) && comparer(value, otherValue)) ||
(identifier.canCoexistWith(otherIdentifier) && !comparer(value, otherValue));
if (!canCoexist) {
conflicts.add(identifier);
conflicts.add(otherIdentifier);
}
}
}
const coexisting = [];
const conflicting = [];
for (const [identifier, value] of bindings) {
if (conflicts.has(identifier)) {
conflicting.push([identifier, value]);
}
else {
coexisting.push([identifier, value]);
}
}
return [coexisting, conflicting];
}
}
exports.ModelBuilder = ModelBuilder;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTW9kZWxCdWlsZGVyLmpzIiwic291cmNlUm9vdCI6Ii4uLyIsInNvdXJjZXMiOlsiTW9kZWwvTW9kZWxCdWlsZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSwrQ0FBK0M7QUFDL0MscUdBQXFHOzs7QUFLckcseUlBQXNJO0FBQ3RJLGlIQUE4RztBQUk5RyxtREFBZ0Q7QUFDaEQsbUNBQWdDO0FBS2hDOztHQUVHO0FBQ0gsTUFBYSxZQUFhLFNBQVEsNkJBQWE7SUFBL0M7O1FBQ3FCLHVCQUFrQixHQUFvQyxJQUFJLEdBQUcsRUFBRSxDQUFDO1FBQ2hFLG1DQUE4QixHQUFvQyxJQUFJLEdBQUcsRUFBRSxDQUFDO0lBb09qRyxDQUFDO0lBbE9HLGtCQUFrQjtJQUNsQixvQkFBb0IsQ0FBQyxVQUF5QixFQUFFLElBQXNCO1FBQ2xFLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFLFVBQVUsQ0FBQyxDQUFDO1FBQ25FLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxVQUFVLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUNuQyxDQUFDO0lBRUQsa0JBQWtCO0lBQ2xCLHdCQUF3QixDQUFDLFVBQXlCLEVBQUUsSUFBc0I7UUFDdEUsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsa0JBQWtCLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFDbkUsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxLQUFLLEVBQUUsVUFBVSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQy9ELElBQUksVUFBVSxHQUFHLENBQUMsRUFBRTtZQUNoQixNQUFNLElBQUksMkZBQTRDLENBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxDQUFDO1NBQzVFO1FBQ0QsS0FBSyxDQUFDLE1BQU0sQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDaEMsQ0FBQztJQUVELGtCQUFrQjtJQUNsQixn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