From 81fe770489cfecf5c0cf9d065c9ac5b9a45036f7 Mon Sep 17 00:00:00 2001 From: crusader Date: Tue, 2 Jan 2018 21:25:09 +0900 Subject: [PATCH] ing --- .../commons/application/application.ts | 4 +- .../context/__application_context.ts | 46 ++++ .../context/application_context.ts | 99 +++++-- .../commons/application/context/index.ts | 1 + .../context/instance_definition_reader.ts | 24 ++ .../application/context/message_source.ts | 7 + .../commons/application/type/type.ts | 5 + src/ts/@overflow/commons/core/type/error.ts | 9 + src/ts/@overflow/commons/core/type/type.ts | 7 + src/ts/@overflow/commons/core/util/assert.ts | 67 +++++ src/ts/@overflow/commons/core/util/index.ts | 3 + src/ts/@overflow/commons/core/util/locale.ts | 3 + src/ts/@overflow/commons/core/util/string.ts | 73 +++++ .../di/factory/__instance_definition.ts | 42 +++ .../commons/di/factory/__instance_factory.ts | 178 +++++++++++++ .../di/factory/dependency_descriptor.ts | 7 + src/ts/@overflow/commons/di/factory/index.ts | 1 + .../commons/di/factory/instance_definition.ts | 81 +++--- .../commons/di/factory/instance_factory.ts | 252 ++++++++---------- .../di/factory/instance_name_generator.ts | 8 + .../di/factory/singleton_instance_registry.ts | 21 ++ src/ts/@overflow/commons/di/type/error.ts | 15 ++ src/ts/@overflow/commons/di/type/index.ts | 1 + src/ts/@overflow/commons/di/type/type.ts | 7 + 24 files changed, 757 insertions(+), 204 deletions(-) create mode 100644 src/ts/@overflow/commons/application/context/__application_context.ts create mode 100644 src/ts/@overflow/commons/application/context/instance_definition_reader.ts create mode 100644 src/ts/@overflow/commons/application/context/message_source.ts create mode 100644 src/ts/@overflow/commons/core/util/assert.ts create mode 100644 src/ts/@overflow/commons/core/util/locale.ts create mode 100644 src/ts/@overflow/commons/core/util/string.ts create mode 100644 src/ts/@overflow/commons/di/factory/__instance_definition.ts create mode 100644 src/ts/@overflow/commons/di/factory/__instance_factory.ts create mode 100644 src/ts/@overflow/commons/di/factory/dependency_descriptor.ts create mode 100644 src/ts/@overflow/commons/di/factory/instance_name_generator.ts create mode 100644 src/ts/@overflow/commons/di/factory/singleton_instance_registry.ts create mode 100644 src/ts/@overflow/commons/di/type/error.ts diff --git a/src/ts/@overflow/commons/application/application.ts b/src/ts/@overflow/commons/application/application.ts index 1152919..a62f9d6 100644 --- a/src/ts/@overflow/commons/application/application.ts +++ b/src/ts/@overflow/commons/application/application.ts @@ -32,7 +32,7 @@ export class Application { /** * run */ - public async run(): Promise { + public run(): ApplicationContext { let runner = this.findRunner(); if (undefined === runner) { throw new Error(`There is not exist @Runner on Application[${this._primaryClass.name}]`); @@ -43,7 +43,7 @@ export class Application { let instance = clazz.getConstructor().newInstance(); instanceFactory.applyInstance(this._primaryClass, instance); - await runner.invoke(instance); + runner.invoke(instance); return this._applicationContext; } diff --git a/src/ts/@overflow/commons/application/context/__application_context.ts b/src/ts/@overflow/commons/application/context/__application_context.ts new file mode 100644 index 0000000..0545816 --- /dev/null +++ b/src/ts/@overflow/commons/application/context/__application_context.ts @@ -0,0 +1,46 @@ +import { + ClassType, +} from '@overflow/commons/core/type'; + +import { + Class, +} from '@overflow/commons/core/reflect'; + +import { + InstanceDefinition, + InstanceFactory, +} from '@overflow/commons/di/factory'; + +import { InstanceDefinitionReader } from './instance_definition_reader'; + +export class ApplicationContext { + private _instanceFactory: InstanceFactory; + private _instanceDefinitionReader: InstanceDefinitionReader; + + public constructor(injectables: ClassType[]) { + this._instanceFactory = new InstanceFactory(); + this._instanceDefinitionReader = new InstanceDefinitionReader(); + + this.initializeInjectables(injectables); + } + + private initializeInjectables(injectables: ClassType[]): void { + if (undefined === injectables) { + return; + } + injectables.forEach(injectable => { + let name = injectable.name; + let definition: InstanceDefinition = new InstanceDefinition(injectable); + this._instanceFactory.registerInstanceDefinition(name, definition); + }); + } + + /** + * instanceFactory + */ + public get instanceFactory(): InstanceFactory { + return this._instanceFactory; + } + + +} diff --git a/src/ts/@overflow/commons/application/context/application_context.ts b/src/ts/@overflow/commons/application/context/application_context.ts index 4824fd1..5285d7e 100644 --- a/src/ts/@overflow/commons/application/context/application_context.ts +++ b/src/ts/@overflow/commons/application/context/application_context.ts @@ -1,41 +1,86 @@ import { - ClassType, -} from '@overflow/commons/core/type'; - -import { - Class, -} from '@overflow/commons/core/reflect'; - -import { - InstanceDefinition, InstanceFactory, } from '@overflow/commons/di/factory'; +import { ApplicationContextIDType } from '@overflow/commons/application/type'; + +import { MessageSource } from './message_source'; +import { InstanceDefinitionReader } from './instance_definition_reader'; + export class ApplicationContext { - private _instanceFactory: InstanceFactory; + public static readonly MESSAGE_SOURCE_INSTANCE_NAME: string = 'messageSource'; - public constructor(injectables: ClassType[]) { - this._instanceFactory = new InstanceFactory(); - this.initializeInjectables(injectables); + private readonly instanceFactoryPostProcessors: InstanceFactoryPostProcessor[] = []; + + private id: ApplicationContextIDType; + private parent: ApplicationContext; + private messageSource: MessageSource; + private instanceFactory: InstanceFactory; + private instanceDefinitionReader: InstanceDefinitionReader; + + public constructor(parent?: ApplicationContext) { + this.setParent(parent); } - private initializeInjectables(injectables: ClassType[]): void { - if (undefined === injectables) { - return; - } - injectables.forEach(injectable => { - let name = injectable.name; - let definition: InstanceDefinition = new InstanceDefinition(injectable); - this._instanceFactory.registerInstanceDefinition(name, definition); - }); + // Context + + public getID(): ApplicationContextIDType { + return this.id; + } + public setID(id: ApplicationContextIDType): void { + this.id = id; } - /** - * instanceFactory - */ - public get instanceFactory(): InstanceFactory { - return this._instanceFactory; + public getApplicationName(): string { + return undefined; } + public getParent(): ApplicationContext { + return this.parent; + } + public setParent(parent: ApplicationContext): void { + this.parent = parent; + } + public getInstanceFactory(): InstanceFactory { + return undefined; + } + + // Configuration + + public addInstanceFactoryPostProcessor(instanceFactoryPostProcessor: InstanceFactoryPostProcessor): void { + this.instanceFactoryPostProcessors.push(instanceFactoryPostProcessor); + } + public getInstanceFactoryPostProcessor(): InstanceFactoryPostProcessor[] { + return this.instanceFactoryPostProcessors; + } + + public addApplicationListener(listener: ApplicationListener): void { + // + } + + public registerShutdownHook(): void { + // + } + + public initMessageSource(): void { + // + } + + // MessageSource + public getMessageSource(): MessageSource { + return this.messageSource; + } + + // Lifecycle + + public start(): void { + // + } + public stop(): void { + // + } + public isRunning(): boolean { + return false; + } } diff --git a/src/ts/@overflow/commons/application/context/index.ts b/src/ts/@overflow/commons/application/context/index.ts index 6b996eb..1c19132 100644 --- a/src/ts/@overflow/commons/application/context/index.ts +++ b/src/ts/@overflow/commons/application/context/index.ts @@ -1 +1,2 @@ export * from './application_context'; +export * from './instance_definition_reader'; diff --git a/src/ts/@overflow/commons/application/context/instance_definition_reader.ts b/src/ts/@overflow/commons/application/context/instance_definition_reader.ts new file mode 100644 index 0000000..dba6480 --- /dev/null +++ b/src/ts/@overflow/commons/application/context/instance_definition_reader.ts @@ -0,0 +1,24 @@ +import { + ClassType, +} from '@overflow/commons/core/type'; + +import { + InstanceDefinitionRegistry, InstanceNameGenerator, +} from '@overflow/commons/di/factory'; + +export class InstanceDefinitionReader { + private instanceDefinitionRegistry: InstanceDefinitionRegistry; + private instanceNameGenerator: InstanceNameGenerator; + + public constructor(registry: InstanceDefinitionRegistry) { + // + } + + public register(...injectables: ClassType[]): void { + // + } + + public registerInstance(injectable: ClassType): void { + // + } +} diff --git a/src/ts/@overflow/commons/application/context/message_source.ts b/src/ts/@overflow/commons/application/context/message_source.ts new file mode 100644 index 0000000..2848cba --- /dev/null +++ b/src/ts/@overflow/commons/application/context/message_source.ts @@ -0,0 +1,7 @@ +import { Locale } from '@overflow/commons/core/util'; + +export class MessageSource { + public getMessage(code: string, args: any[], defaultMessage: string | undefined, locale: Locale): string { + return undefined; + } +} diff --git a/src/ts/@overflow/commons/application/type/type.ts b/src/ts/@overflow/commons/application/type/type.ts index dd0a672..c1affea 100644 --- a/src/ts/@overflow/commons/application/type/type.ts +++ b/src/ts/@overflow/commons/application/type/type.ts @@ -1,3 +1,7 @@ +import { IdentityType } from '@overflow/commons/core/type'; + +export type ApplicationContextIDType = IdentityType; + // import { // ClassType, // } from '@overflow/commons/core/type'; @@ -20,3 +24,4 @@ // } // export type InjectablesType = ClassType | InjectableClass | InjectableFactory | InjectableValue; + diff --git a/src/ts/@overflow/commons/core/type/error.ts b/src/ts/@overflow/commons/core/type/error.ts index 79d65b2..f90d611 100644 --- a/src/ts/@overflow/commons/core/type/error.ts +++ b/src/ts/@overflow/commons/core/type/error.ts @@ -1,6 +1,15 @@ +export class IllegalArgumentError extends Error { + public constructor(message?: string) { + super(message); + Object.setPrototypeOf(this, new.target.prototype); + } +} + export class NotSupportedDecoratorError extends Error { public constructor(message?: string) { super(message); Object.setPrototypeOf(this, new.target.prototype); } } + + diff --git a/src/ts/@overflow/commons/core/type/type.ts b/src/ts/@overflow/commons/core/type/type.ts index 2260719..e6190ab 100644 --- a/src/ts/@overflow/commons/core/type/type.ts +++ b/src/ts/@overflow/commons/core/type/type.ts @@ -22,3 +22,10 @@ export enum DecoratorType { METHOD = 'method', PARAMETER = 'parameter', } + +export enum LocaleDisplayType { + LANGUAGE = 'LANGUAGE', + COUNTRY = 'COUNTRY', + VARIANT = 'VARIANT', + SCRIPT = 'SCRIPT', +} diff --git a/src/ts/@overflow/commons/core/util/assert.ts b/src/ts/@overflow/commons/core/util/assert.ts new file mode 100644 index 0000000..075abe2 --- /dev/null +++ b/src/ts/@overflow/commons/core/util/assert.ts @@ -0,0 +1,67 @@ +import { IllegalArgumentError } from '../type/error'; +import { StringUtil, StringUtils } from './string'; + + + +export abstract class Assert { + /** + * isTrue + */ + public static isTrue(expression: boolean, message?: string): void { + if (!expression) { + throw new IllegalArgumentError(undefined !== message ? message : '[Assertion failed] - this expression must be true'); + } + } + + /** + * isUndefined + */ + public static isUndefined(obj: any, message?: string): void { + if (undefined !== obj) { + throw new IllegalArgumentError(undefined !== message ? message : '[Assertion failed] - the object argument must be undefined'); + } + } + + /** + * notUndefined + */ + public static notUndefined(obj: any, message?: string): void { + if (undefined === obj) { + throw new IllegalArgumentError(undefined !== message ? message : '[Assertion failed] - the object argument must not be undefined'); + } + } + + + /** + * isNull + */ + public static isNull(obj: any, message?: string): void { + if (undefined === obj || null !== obj) { + throw new IllegalArgumentError(undefined !== message ? message : '[Assertion failed] - the object argument must be null'); + } + } + + /** + * isNull + */ + public static notNull(obj: any, message?: string): void { + if (undefined === obj || null === obj) { + throw new IllegalArgumentError(undefined !== message ? message : '[Assertion failed] - the object argument must not be null'); + } + } + + /** + * isNull + */ + public static hasLength(text: string, message?: string): void { + if (!StringUtils.hasLength(text)) { + throw new IllegalArgumentError( + undefined !== message + ? message + : '[Assertion failed] - this String argument must have length; it must not be null or empty', + ); + } + } + + +} diff --git a/src/ts/@overflow/commons/core/util/index.ts b/src/ts/@overflow/commons/core/util/index.ts index 585b667..d253650 100644 --- a/src/ts/@overflow/commons/core/util/index.ts +++ b/src/ts/@overflow/commons/core/util/index.ts @@ -1 +1,4 @@ +export * from './assert'; +export * from './locale'; export * from './registry'; +export * from './string'; diff --git a/src/ts/@overflow/commons/core/util/locale.ts b/src/ts/@overflow/commons/core/util/locale.ts new file mode 100644 index 0000000..f5ba31e --- /dev/null +++ b/src/ts/@overflow/commons/core/util/locale.ts @@ -0,0 +1,3 @@ +export class Locale { + +} diff --git a/src/ts/@overflow/commons/core/util/string.ts b/src/ts/@overflow/commons/core/util/string.ts new file mode 100644 index 0000000..580477a --- /dev/null +++ b/src/ts/@overflow/commons/core/util/string.ts @@ -0,0 +1,73 @@ +export abstract class StringUtils { + private static readonly FOLDER_SEPARATOR: string = '/'; + private static readonly WINDOWS_FOLDER_SEPARATOR: string = '\\'; + private static readonly TOP_PATH: string = '..'; + private static readonly CURRENT_PATH: string = '.'; + private static readonly EXTENSION_SEPARATOR: string = '.'; + + /** + * isEmpty + */ + public static isEmpty(str: string): boolean { + return (undefined === str || null === str || '' === str); + } + + /** + * hasLength + */ + public static hasLength(str: string): boolean { + return (undefined !== str && null !== str || 0 < str.length); + } + + /** + * hasText + */ + public static hasText(str: string): boolean { + if (!StringUtils.hasLength(str)) { + return false; + } + let t = StringUtils.trimAllWhitespace(str); + return 0 !== t.length; + } + + /** + * containsWhitespace + */ + public static containsWhitespace(str: string): boolean { + if (!StringUtils.hasLength(str)) { + return false; + } + return /\s/.test(str); + } + + /** + * trimAllWhitespace + */ + public static trimAllWhitespace(str: string): string { + if (!StringUtils.hasLength(str)) { + return str; + } + return str.replace(/^\s+|\s+$/g, ''); + } + + /** + * trimLeadingWhitespace + */ + public static trimLeadingWhitespace(str: string): string { + if (!StringUtils.hasLength(str)) { + return str; + } + return str.replace(/^\s*/, ''); + } + + /** + * trimTrailingWhitespace + */ + public static trimTrailingWhitespace(str: string): string { + if (!StringUtils.hasLength(str)) { + return str; + } + return str.replace(/\s*$/, ''); + } + +} diff --git a/src/ts/@overflow/commons/di/factory/__instance_definition.ts b/src/ts/@overflow/commons/di/factory/__instance_definition.ts new file mode 100644 index 0000000..028b065 --- /dev/null +++ b/src/ts/@overflow/commons/di/factory/__instance_definition.ts @@ -0,0 +1,42 @@ +import { + ClassType, PropertyKeyType, +} from '@overflow/commons/core/type'; + +import { + Class, +} from '@overflow/commons/core/reflect'; + +import { + InstanceNameType, +} from '@overflow/commons/di/type'; +import { InjectableAnnotation } from '@overflow/commons/di/decorators'; + +export class InstanceDefinition { + private _instanceClass: Class; + private _injectableAnnotation: InjectableAnnotation; + + public constructor(instanceClassType: ClassType) { + let clazz = Class.forClassType(instanceClassType); + if (undefined === clazz) { + throw new Error(`Class[${instanceClassType.name}] is not injectable type. Add @Injectable annotation.`); + } + + let injectableAnnotation: InjectableAnnotation = clazz.getOwnAnnotation(InjectableAnnotation); + if (undefined === injectableAnnotation) { + throw new Error(`Class is not Injectable type. Add @Injectable annotation to class[${instanceClassType.name}]`); + } + this._injectableAnnotation = injectableAnnotation; + } + + public get instanceClass(): Class { + return this._instanceClass; + } + + /** + * getAttribute + */ + public get annotation(): InjectableAnnotation { + return this._injectableAnnotation; + } + +} diff --git a/src/ts/@overflow/commons/di/factory/__instance_factory.ts b/src/ts/@overflow/commons/di/factory/__instance_factory.ts new file mode 100644 index 0000000..736a49f --- /dev/null +++ b/src/ts/@overflow/commons/di/factory/__instance_factory.ts @@ -0,0 +1,178 @@ +import { + ClassType, PropertyKeyType, +} from '@overflow/commons/core/type'; +import { + Class, Annotation, Field, +} from '@overflow/commons/core/reflect'; + +import { + ValueAnnotation, InjectAnnotation, ResourceAnnotation, +} from '@overflow/commons/di/decorators'; + +import { + InstanceNameType, + InstanceFactoryType, +} from '@overflow/commons/di/type'; + + +import {InstanceDefinitionRegistry} from './instance_definition_registry'; +import {InstanceDefinition} from './instance_definition'; + +export class InstanceFactory implements InstanceDefinitionRegistry { + private _singletonObjects: Map = new Map(); + private _singletonFactories: Map = new Map(); + private _instanceDefinitionMap: Map = new Map(); + private _instanceDefinitionNames: Set = new Set(); + private _values: any; + /** + * getInstance + */ + public getInstance(name: InstanceNameType | undefined, requiredType: ClassType | undefined, ...args: any[]): any | undefined { + if (undefined === name && undefined === requiredType) { + throw new Error('One of name or requiredType must be specified.'); + } + + if (undefined === name) { + name = requiredType.name; + } + + let sharedInstance = this.getSingleton(name); + if (undefined !== sharedInstance) { + return sharedInstance; + } + + let instanceDefinition = this.getInstanceDefinition(name); + let clazz = instanceDefinition.instanceClass; + let ctor = clazz.getConstructor(); + let ctorParams = ctor.getParameters(); + let ctorArgs = []; + if (0 < ctorParams.length) { + // + } + + let instance = ctor.newInstance(ctorArgs); + + this.applyInstance(clazz.getType(), instance); + + return instance; + } + + /** + * applyInstance + */ + public injectByName(name: InstanceNameType, instanceDefinition: InstanceDefinition): void { + // + } + + public injectByType(name: InstanceNameType, instanceDefinition: InstanceDefinition): void { + // + } + + /** + * applyInstance + */ + public applyInstance(clazzType: ClassType, instance: any): void { + let clazz: Class = Class.forClassType(clazzType); + + let fields = clazz.getFields(); + + fields.forEach((field: Field, key: PropertyKeyType, map: Map): void => { + let fieldAnnotations = field.getAnnotations(); + fieldAnnotations.forEach((value: Annotation, annonType: ClassType, annonMap: Map): void => { + switch (annonType) { + case ValueAnnotation: + { + let annon = value; + instance[field.getName()] = this.getValue(annon.attributes.value); + } + break; + case InjectAnnotation: + { + let annon = value; + instance[field.getName()] = this.getInstance(annon.attributes.name, field.getType()); + } + break; + case ResourceAnnotation: + { + let annon = value; + instance[field.getName()] = this.getSingleton(annon.attributes.name || field.getName()); + } + break; + default: + break; + } + }); + + }); + } + + private getSingleton(name: InstanceNameType): any | undefined { + let singletonObject = this._singletonObjects.get(name); + return singletonObject; + } + + /** + * containsInstance + */ + public containsInstance(name: InstanceNameType): boolean { + return false; + } + + public registerJSON(json: any): void { + this._values = json; + } + + /** + * getValue + */ + public getValue(keyPath: string): any { + let paths = keyPath.split('.'); + let result = this._values; + for (let i = 0, len = paths.length; i < len; i++) { + result = result[paths[i]]; + } + return result; + } + + public registerSingleton(name: InstanceNameType, instanceType: any, instance: any): void { + this._singletonObjects.set(name, instance); + } + + public registerInstanceDefinition(name: InstanceNameType, instanceDefinition: InstanceDefinition): void { + let oldInstanceDefinition = this._instanceDefinitionMap.get(name); + if (undefined !== oldInstanceDefinition) { + throw new Error(`InstanceDefinition[${name}] is already exist.`); + } + this._instanceDefinitionNames.add(name); + this._instanceDefinitionMap.set(name, instanceDefinition); + } + + public removeInstanceDefinition(name: InstanceNameType): void { + if (!this._instanceDefinitionMap.has(name)) { + throw new Error(`InstanceDefinition[${name}] is not exist.`); + } + this._instanceDefinitionNames.delete(name); + this._instanceDefinitionMap.delete(name); + } + + public getInstanceDefinition(name: InstanceNameType): InstanceDefinition | undefined { + return this._instanceDefinitionMap.get(name); + } + + public containsInstanceDefinition(name: InstanceNameType): boolean { + return this._instanceDefinitionMap.has(name); + } + + public getInstanceDefinitionNames(): Set { + return this._instanceDefinitionNames; + } + + public getInstanceDefinitionCount(): number { + return this._instanceDefinitionMap.size; + } + + public isInstanceNameInUse(name: InstanceNameType): boolean { + return false; + } + +} diff --git a/src/ts/@overflow/commons/di/factory/dependency_descriptor.ts b/src/ts/@overflow/commons/di/factory/dependency_descriptor.ts new file mode 100644 index 0000000..aee052c --- /dev/null +++ b/src/ts/@overflow/commons/di/factory/dependency_descriptor.ts @@ -0,0 +1,7 @@ + + +export class DependencyDescriptor { + private methodParameter: MethodParameter; + private field: Field; + private declaringClass: ClassType; +} diff --git a/src/ts/@overflow/commons/di/factory/index.ts b/src/ts/@overflow/commons/di/factory/index.ts index a90a909..94c42ed 100644 --- a/src/ts/@overflow/commons/di/factory/index.ts +++ b/src/ts/@overflow/commons/di/factory/index.ts @@ -1,3 +1,4 @@ export * from './instance_definition_registry'; export * from './instance_definition'; export * from './instance_factory'; +export * from './instance_name_generator'; diff --git a/src/ts/@overflow/commons/di/factory/instance_definition.ts b/src/ts/@overflow/commons/di/factory/instance_definition.ts index 028b065..512c5f1 100644 --- a/src/ts/@overflow/commons/di/factory/instance_definition.ts +++ b/src/ts/@overflow/commons/di/factory/instance_definition.ts @@ -1,42 +1,63 @@ -import { - ClassType, PropertyKeyType, -} from '@overflow/commons/core/type'; - -import { - Class, -} from '@overflow/commons/core/reflect'; - -import { - InstanceNameType, -} from '@overflow/commons/di/type'; -import { InjectableAnnotation } from '@overflow/commons/di/decorators'; +import { Assert } from '@overflow/commons/core/util'; +import { ScopeType, InjectModeType } from '@overflow/commons/di/type'; export class InstanceDefinition { - private _instanceClass: Class; - private _injectableAnnotation: InjectableAnnotation; + private readonly attributes: Map = new Map(); + private scope: ScopeType = ScopeType.Default; + private injectMode: InjectModeType = InjectModeType.No; - public constructor(instanceClassType: ClassType) { - let clazz = Class.forClassType(instanceClassType); - if (undefined === clazz) { - throw new Error(`Class[${instanceClassType.name}] is not injectable type. Add @Injectable annotation.`); - } + // Attributes - let injectableAnnotation: InjectableAnnotation = clazz.getOwnAnnotation(InjectableAnnotation); - if (undefined === injectableAnnotation) { - throw new Error(`Class is not Injectable type. Add @Injectable annotation to class[${instanceClassType.name}]`); + public setAttribute(name: string, value?: any): void { + Assert.notNull(name, 'Name must not be null'); + if (value !== undefined) { + this.attributes.set(name, value); + } else { + this.removeAttribute(name); } - this._injectableAnnotation = injectableAnnotation; } - public get instanceClass(): Class { - return this._instanceClass; + public getAttribute(name: string): any | undefined { + Assert.notNull(name, 'Name must not be null'); + return this.attributes.get(name); } - /** - * getAttribute - */ - public get annotation(): InjectableAnnotation { - return this._injectableAnnotation; + public removeAttribute(name: string): boolean { + Assert.notNull(name, 'Name must not be null'); + return this.attributes.delete(name); + } + + public hasAttribute(name: string): boolean { + Assert.notNull(name, 'Name must not be null'); + return this.attributes.has(name); + } + + public attributeNames(): IterableIterator { + return this.attributes.keys(); + } + + public setScope(scope: ScopeType): void { + this.scope = scope; + } + + public getScope(): ScopeType { + return this.scope; + } + + public isSingleton(): boolean { + return ScopeType.Singleton === this.scope || ScopeType.Default === this.scope; + } + + public isTransiant(): boolean { + return ScopeType.Transiant === this.scope; + } + + public setInjectMode(injectMode: InjectModeType): void { + this.injectMode = injectMode; + } + + public getInjectMode(): InjectModeType { + return this.injectMode; } } diff --git a/src/ts/@overflow/commons/di/factory/instance_factory.ts b/src/ts/@overflow/commons/di/factory/instance_factory.ts index 736a49f..7f8d92c 100644 --- a/src/ts/@overflow/commons/di/factory/instance_factory.ts +++ b/src/ts/@overflow/commons/di/factory/instance_factory.ts @@ -1,178 +1,140 @@ import { - ClassType, PropertyKeyType, -} from '@overflow/commons/core/type'; -import { - Class, Annotation, Field, + Annotation, } from '@overflow/commons/core/reflect'; import { - ValueAnnotation, InjectAnnotation, ResourceAnnotation, -} from '@overflow/commons/di/decorators'; + ClassType, +} from '@overflow/commons/core/type'; import { + InjectType, InstanceNameType, - InstanceFactoryType, } from '@overflow/commons/di/type'; +import { InstanceDefinition } from './instance_definition'; +import { InstanceDefinitionRegistry } from './instance_definition_registry'; -import {InstanceDefinitionRegistry} from './instance_definition_registry'; -import {InstanceDefinition} from './instance_definition'; +export class InstanceFactory { + private instanceDefinitionRegistry: InstanceDefinitionRegistry; + + + // Instance -export class InstanceFactory implements InstanceDefinitionRegistry { - private _singletonObjects: Map = new Map(); - private _singletonFactories: Map = new Map(); - private _instanceDefinitionMap: Map = new Map(); - private _instanceDefinitionNames: Set = new Set(); - private _values: any; - /** - * getInstance - */ public getInstance(name: InstanceNameType | undefined, requiredType: ClassType | undefined, ...args: any[]): any | undefined { - if (undefined === name && undefined === requiredType) { - throw new Error('One of name or requiredType must be specified.'); - } - - if (undefined === name) { - name = requiredType.name; - } - - let sharedInstance = this.getSingleton(name); - if (undefined !== sharedInstance) { - return sharedInstance; - } - - let instanceDefinition = this.getInstanceDefinition(name); - let clazz = instanceDefinition.instanceClass; - let ctor = clazz.getConstructor(); - let ctorParams = ctor.getParameters(); - let ctorArgs = []; - if (0 < ctorParams.length) { - // - } - - let instance = ctor.newInstance(ctorArgs); - - this.applyInstance(clazz.getType(), instance); - - return instance; + return undefined; } - - /** - * applyInstance - */ - public injectByName(name: InstanceNameType, instanceDefinition: InstanceDefinition): void { - // - } - - public injectByType(name: InstanceNameType, instanceDefinition: InstanceDefinition): void { - // - } - - /** - * applyInstance - */ - public applyInstance(clazzType: ClassType, instance: any): void { - let clazz: Class = Class.forClassType(clazzType); - - let fields = clazz.getFields(); - - fields.forEach((field: Field, key: PropertyKeyType, map: Map): void => { - let fieldAnnotations = field.getAnnotations(); - fieldAnnotations.forEach((value: Annotation, annonType: ClassType, annonMap: Map): void => { - switch (annonType) { - case ValueAnnotation: - { - let annon = value; - instance[field.getName()] = this.getValue(annon.attributes.value); - } - break; - case InjectAnnotation: - { - let annon = value; - instance[field.getName()] = this.getInstance(annon.attributes.name, field.getType()); - } - break; - case ResourceAnnotation: - { - let annon = value; - instance[field.getName()] = this.getSingleton(annon.attributes.name || field.getName()); - } - break; - default: - break; - } - }); - - }); - } - - private getSingleton(name: InstanceNameType): any | undefined { - let singletonObject = this._singletonObjects.get(name); - return singletonObject; - } - - /** - * containsInstance - */ public containsInstance(name: InstanceNameType): boolean { return false; } - - public registerJSON(json: any): void { - this._values = json; + public isSingleton(name: InstanceNameType): boolean { + return false; + } + public isTransiant(name: InstanceNameType): boolean { + return false; + } + public isTypeMatch(name: InstanceNameType, typeToMatch: ClassType): boolean { + return false; + } + public getType(name: InstanceNameType): ClassType { + return undefined; + } + public getAliases(name: InstanceNameType): InstanceNameType[] { + return undefined; } - /** - * getValue - */ - public getValue(keyPath: string): any { - let paths = keyPath.split('.'); - let result = this._values; - for (let i = 0, len = paths.length; i < len; i++) { - result = result[paths[i]]; - } - return result; + // Create Instance + + public createInstance(clazzType: ClassType, injectMode?: InjectType, dependencyCheck?: boolean): T { + return undefined; } - public registerSingleton(name: InstanceNameType, instanceType: any, instance: any): void { - this._singletonObjects.set(name, instance); + public injectInstance(instance: any): void { + // } - public registerInstanceDefinition(name: InstanceNameType, instanceDefinition: InstanceDefinition): void { - let oldInstanceDefinition = this._instanceDefinitionMap.get(name); - if (undefined !== oldInstanceDefinition) { - throw new Error(`InstanceDefinition[${name}] is already exist.`); - } - this._instanceDefinitionNames.add(name); - this._instanceDefinitionMap.set(name, instanceDefinition); + public inject(clazzType: ClassType, injectMode?: InjectType, dependencyCheck?: boolean): any { + // } - public removeInstanceDefinition(name: InstanceNameType): void { - if (!this._instanceDefinitionMap.has(name)) { - throw new Error(`InstanceDefinition[${name}] is not exist.`); - } - this._instanceDefinitionNames.delete(name); - this._instanceDefinitionMap.delete(name); + public injectInstanceProperties(instance: any, injectMode: InjectType, dependencyCheck: boolean): void { + // } - public getInstanceDefinition(name: InstanceNameType): InstanceDefinition | undefined { - return this._instanceDefinitionMap.get(name); + public applyInstancePropertyValues(instance: any, name: InstanceNameType): void { + // + } + + public initializeInstance(instance: any, name: InstanceNameType): any { + // + } + + public applyInstancePostProcessorsBeforeInitialization(instance: any, name: InstanceNameType): any { + // + } + + public applyInstancePostProcessorsAfterInitialization(instance: any, name: InstanceNameType): any { + // + } + + public configureInstance(instance: any, name: InstanceNameType): any { + // + } + + public destroyInstance(instance: any): any { + // + } + + public resolveDependency(descriptor: DependencyDescriptor, name: InstanceNameType, injectInstanceNames?: Set): any { + // + } + + public getInstanceNamesIterator(): IterableIterator { + return undefined; + } + + // InstanceDefinition + + public getInstanceDefinition(): InstanceDefinition { + return undefined; } public containsInstanceDefinition(name: InstanceNameType): boolean { - return this._instanceDefinitionMap.has(name); - } - - public getInstanceDefinitionNames(): Set { - return this._instanceDefinitionNames; - } - - public getInstanceDefinitionCount(): number { - return this._instanceDefinitionMap.size; - } - - public isInstanceNameInUse(name: InstanceNameType): boolean { return false; } + public getInstanceDefinitionCount(): number { + return 0; + } + public getInstanceDefinitionNames(): InstanceNameType[] { + return undefined; + } + public getInstanceNamesForType(clazzType: ClassType, includeNonSingletons?: boolean, allowEagerInit?: boolean): InstanceNameType[] { + return undefined; + } + public getInstancesOfType(clazzType: ClassType, includeNonSingletons?: boolean, allowEagerInit?: boolean): Map { + return undefined; + } + public getInstanceNamesForAnnotation(annotation: AnnotationType): InstanceNameType[] { + return undefined; + } + public getInstancesWithAnnotation(annotation: AnnotationType): Map { + return undefined; + } + public findAnnotationOnInstance(name: InstanceNameType, annotation: AnnotationType): AnnotationType { + return undefined; + } + + // Configuration + + public ignoreDependencyType(clazzType: ClassType): void { + // + } + + public registerResolvableDependency(dependencyType: ClassType, injectValue: any): void { + // + } + + public isInjectCandidate(name: InstanceNameType, descriptor: DependencyDescriptor): boolean { + return false; + } } diff --git a/src/ts/@overflow/commons/di/factory/instance_name_generator.ts b/src/ts/@overflow/commons/di/factory/instance_name_generator.ts new file mode 100644 index 0000000..c4aca24 --- /dev/null +++ b/src/ts/@overflow/commons/di/factory/instance_name_generator.ts @@ -0,0 +1,8 @@ +import { InstanceDefinition } from './instance_definition'; +import { InstanceDefinitionRegistry } from './instance_definition_registry'; + +export class InstanceNameGenerator { + public generateInstanceName(definition: InstanceDefinition, registry: InstanceDefinitionRegistry): string { + return undefined; + } +} diff --git a/src/ts/@overflow/commons/di/factory/singleton_instance_registry.ts b/src/ts/@overflow/commons/di/factory/singleton_instance_registry.ts new file mode 100644 index 0000000..b422d80 --- /dev/null +++ b/src/ts/@overflow/commons/di/factory/singleton_instance_registry.ts @@ -0,0 +1,21 @@ +import { + InstanceNameType, +} from '@overflow/commons/di/type'; + +export class SingletonInstanceRegistry { + public registerSingleton(name: InstanceNameType, singleton: any): void { + // + } + public getSingleton(name: InstanceNameType): any { + return undefined; + } + public containsSingleton(name: InstanceNameType): boolean { + return false; + } + public getSingletonNames(): InstanceNameType[] { + return undefined; + } + public getSingletonCount(): number { + return 0; + } +} diff --git a/src/ts/@overflow/commons/di/type/error.ts b/src/ts/@overflow/commons/di/type/error.ts new file mode 100644 index 0000000..1ade987 --- /dev/null +++ b/src/ts/@overflow/commons/di/type/error.ts @@ -0,0 +1,15 @@ +export class InstanceError extends Error { + public constructor(message?: string) { + super(message); + Object.setPrototypeOf(this, new.target.prototype); + } +} + +export class NoSuchInstanceDefinitionError extends InstanceError { + public constructor(message?: string) { + super(message); + Object.setPrototypeOf(this, new.target.prototype); + } +} + + diff --git a/src/ts/@overflow/commons/di/type/index.ts b/src/ts/@overflow/commons/di/type/index.ts index b38ebc9..ad66f68 100644 --- a/src/ts/@overflow/commons/di/type/index.ts +++ b/src/ts/@overflow/commons/di/type/index.ts @@ -1 +1,2 @@ +export * from './error'; export * from './type'; diff --git a/src/ts/@overflow/commons/di/type/type.ts b/src/ts/@overflow/commons/di/type/type.ts index 3dd918c..84306c2 100644 --- a/src/ts/@overflow/commons/di/type/type.ts +++ b/src/ts/@overflow/commons/di/type/type.ts @@ -6,6 +6,13 @@ export type InstanceNameType = IdentityType; export type InstanceFactoryType = (...args: any[]) => any; export enum ScopeType { + Default = '', Singleton = 'Singleton', Transiant = 'Transiant', } + +export enum InjectModeType { + No = 'No', + ByName = 'ByName', + ByType = 'ByType', +}