refactor to allow switching ICategoryCollection context #40

This commit is contained in:
undergroundwires
2021-01-05 22:28:38 +01:00
parent 3455a2ca6c
commit 2e40605d59
32 changed files with 897 additions and 232 deletions

View File

@@ -1,20 +1,72 @@
import { IApplicationContext } from './IApplicationContext';
import { IApplicationContext, IApplicationContextChangedEvent } from './IApplicationContext';
import { ICategoryCollectionState } from './State/ICategoryCollectionState';
import { CategoryCollectionState } from './State/CategoryCollectionState';
import applicationFile from 'js-yaml-loader!@/application/application.yaml';
import { parseCategoryCollection } from '../Parser/CategoryCollectionParser';
import { IApplication } from '@/domain/IApplication';
import { OperatingSystem } from '@/domain/OperatingSystem';
import { ICategoryCollection } from '@/domain/ICategoryCollection';
import { Signal } from '@/infrastructure/Events/Signal';
export function createContext(): IApplicationContext {
const application = parseCategoryCollection(applicationFile);
const context = new ApplicationContext(application);
return context;
}
type StateMachine = Map<OperatingSystem, ICategoryCollectionState>;
export class ApplicationContext implements IApplicationContext {
public readonly state: ICategoryCollectionState;
public constructor(public readonly collection: ICategoryCollection) {
this.state = new CategoryCollectionState(collection);
public readonly contextChanged = new Signal<IApplicationContextChangedEvent>();
public collection: ICategoryCollection;
public currentOs: OperatingSystem;
public get state(): ICategoryCollectionState {
return this.states[this.collection.os];
}
private readonly states: StateMachine;
public constructor(
public readonly app: IApplication,
initialContext: OperatingSystem) {
validateApp(app);
validateOs(initialContext);
this.states = initializeStates(app);
this.changeContext(initialContext);
}
public changeContext(os: OperatingSystem): void {
if (this.currentOs === os) {
return;
}
this.collection = this.app.getCollection(os);
if (!this.collection) {
throw new Error(`os "${OperatingSystem[os]}" is not defined in application`);
}
const event: IApplicationContextChangedEvent = {
newState: this.state,
newCollection: this.collection,
newOs: os,
};
this.contextChanged.notify(event);
this.currentOs = os;
}
}
function validateApp(app: IApplication) {
if (!app) {
throw new Error('undefined app');
}
}
function validateOs(os: OperatingSystem) {
if (os === undefined) {
throw new Error('undefined os');
}
if (os === OperatingSystem.Unknown) {
throw new Error('unknown os');
}
if (!(os in OperatingSystem)) {
throw new Error(`os "${os}" is out of range`);
}
}
function initializeStates(app: IApplication): StateMachine {
const machine = new Map<OperatingSystem, ICategoryCollectionState>();
for (const collection of app.collections) {
machine[collection.os] = new CategoryCollectionState(collection);
}
return machine;
}

View File

@@ -1,9 +1,32 @@
import { ApplicationContext } from './ApplicationContext';
import { IApplicationContext } from '@/application/Context/IApplicationContext';
import applicationFile from 'js-yaml-loader!@/application/application.yaml';
import { parseCategoryCollection } from '@/application/Parser/CategoryCollectionParser';
import { OperatingSystem } from '@/domain/OperatingSystem';
import { Environment } from '../Environment/Environment';
import { IApplication } from '@/domain/IApplication';
import { IEnvironment } from '../Environment/IEnvironment';
import { parseApplication } from '../Parser/ApplicationParser';
export function buildContext(): IApplicationContext {
const application = parseCategoryCollection(applicationFile);
return new ApplicationContext(application);
export type ApplicationParserType = () => IApplication;
const ApplicationParser: ApplicationParserType = parseApplication;
export function buildContext(
parser = ApplicationParser,
environment = Environment.CurrentEnvironment): IApplicationContext {
const app = parser();
const os = getInitialOs(app, environment);
return new ApplicationContext(app, os);
}
function getInitialOs(app: IApplication, environment: IEnvironment): OperatingSystem {
const currentOs = environment.os;
const supportedOsList = app.getSupportedOsList();
if (supportedOsList.includes(currentOs)) {
return currentOs;
}
supportedOsList.sort((os1, os2) => {
const os1SupportLevel = app.collections[os1].totalScripts;
const os2SupportLevel = app.collections[os2].totalScripts;
return os1SupportLevel - os2SupportLevel;
});
return supportedOsList[0];
}

View File

@@ -1,7 +1,20 @@
import { ICategoryCollectionState } from './State/ICategoryCollectionState';
import { ICategoryCollection } from '@/domain/ICategoryCollection';
import { OperatingSystem } from '@/domain/OperatingSystem';
import { ISignal } from '@/infrastructure/Events/ISignal';
import { IApplication } from '@/domain/IApplication';
export interface IApplicationContext {
readonly currentOs: OperatingSystem;
readonly app: IApplication;
readonly collection: ICategoryCollection;
readonly state: ICategoryCollectionState;
readonly contextChanged: ISignal<IApplicationContextChangedEvent>;
changeContext(os: OperatingSystem): void;
}
export interface IApplicationContextChangedEvent {
readonly newState: ICategoryCollectionState;
readonly newCollection: ICategoryCollection;
readonly newOs: OperatingSystem;
}