diff --git a/src/ts/@overflow/commons/application/application.ts b/src/ts/@overflow/commons/application/application.ts index a62f9d6..55608fa 100644 --- a/src/ts/@overflow/commons/application/application.ts +++ b/src/ts/@overflow/commons/application/application.ts @@ -12,45 +12,69 @@ import { RunnerAnnotation, WebApplicationAnnotation, } from './decorators'; -import { InstanceDefinition } from '@overflow/commons/di/factory'; export class Application { - private _primaryClass: ClassType; + private _appClass: Class; + private _appAnnotation: WebApplicationAnnotation; private _applicationContext: ApplicationContext; - public static async run(primaryClass: ClassType): Promise { - let app: Application = new Application(primaryClass); - return app.run(); + public constructor(primaryClass: ClassType) { + this.initialize(primaryClass); } - public constructor(primaryClass: ClassType) { - this._primaryClass = primaryClass; + private initialize(primaryClass: ClassType): void { + let clazz: Class = Class.forClassType(primaryClass); - this.createContext(); + let wa: WebApplicationAnnotation = clazz.getOwnAnnotation(WebApplicationAnnotation); + if (undefined === wa) { + throw new Error(`Class is not WebApplication type. add @WebApplication annotation to class[${primaryClass.name}]`); + } + + this._appClass = clazz; + this._appAnnotation = wa; + } + + public static async run(primaryClass: ClassType): Promise { + return new Application(primaryClass).run(); } /** * run */ public run(): ApplicationContext { + this._applicationContext = new ApplicationContext(); + + let injectables: ClassType[] = this.getInjectables(); + this._applicationContext.instanceDefinitionReader.registerInjectables(...injectables); + let runner = this.findRunner(); if (undefined === runner) { - throw new Error(`There is not exist @Runner on Application[${this._primaryClass.name}]`); + throw new Error(`There is not exist @Runner on Application[${this._appClass.getName()}]`); } let instanceFactory = this._applicationContext.instanceFactory; - let clazz: Class = Class.forClassType(this._primaryClass); - let instance = clazz.getConstructor().newInstance(); - instanceFactory.applyInstance(this._primaryClass, instance); + let instance = instanceFactory.getInstance(); runner.invoke(instance); return this._applicationContext; } + private getInjectables(): ClassType[] { + let injectables: Set = new Set(); + injectables.add(this._appClass.getType()); + this._appAnnotation.attributes.injectables.forEach(injectableType => { + injectables.add(injectableType); + }); + this._appAnnotation.attributes.configurations.forEach(configurationType => { + injectables.add(configurationType); + }); + + return Array.from(injectables); + } + private findRunner(): Method | undefined { - let clazz: Class = Class.forClassType(this._primaryClass); - let methods = clazz.getOwnMethods(); + let methods = this._appClass.getOwnMethods(); for (let key of Array.from(methods.keys())) { let method = methods.get(key); @@ -64,59 +88,58 @@ export class Application { return undefined; } - private createContext(): ApplicationContext { - let clazz: Class = Class.forClassType(this._primaryClass); +// private createContext(): ApplicationContext { +// let clazz: Class = Class.forClassType(this._primaryClass); - let ans = TypeUtil.ancestorsOf(this._primaryClass); - let wa: WebApplicationAnnotation = clazz.getOwnAnnotation(WebApplicationAnnotation); - if (undefined === wa) { - throw new Error(`Class is not WebApplication type. add @WebApplication annotation to class[${this._primaryClass.name}]`); - } - this._applicationContext = new ApplicationContext(wa.attributes.injectables); +// let wa: WebApplicationAnnotation = clazz.getOwnAnnotation(WebApplicationAnnotation); +// if (undefined === wa) { +// throw new Error(`Class is not WebApplication type. add @WebApplication annotation to class[${this._primaryClass.name}]`); +// } +// this._applicationContext = new ApplicationContext(wa.attributes.injectables); - this.registerJSONSources(wa.attributes.jsonSources); - this.registerConfigurations(wa.attributes.configurations); +// this.registerJSONSources(wa.attributes.jsonSources); +// this.registerConfigurations(wa.attributes.configurations); - return this._applicationContext; - } +// return this._applicationContext; +// } - private registerJSONSources(jsonSources: any[]): void { - if (undefined === jsonSources || null === jsonSources) { - return; - } - let instanceFactory = this._applicationContext.instanceFactory; - let jsons = Object.assign({}, ...jsonSources); - instanceFactory.registerJSON(jsons); - } +// private registerJSONSources(jsonSources: any[]): void { +// if (undefined === jsonSources || null === jsonSources) { +// return; +// } +// let instanceFactory = this._applicationContext.instanceFactory; +// let jsons = Object.assign({}, ...jsonSources); +// instanceFactory.registerJSON(jsons); +// } - private registerConfigurations(configurationTypes: ClassType[]): void { - if (undefined === configurationTypes || null === configurationTypes) { - return; - } - let instanceFactory = this._applicationContext.instanceFactory; +// private registerConfigurations(configurationTypes: ClassType[]): void { +// if (undefined === configurationTypes || null === configurationTypes) { +// return; +// } +// let instanceFactory = this._applicationContext.instanceFactory; - configurationTypes.forEach(configurationType => { - let clazz: Class = Class.forClassType(configurationType); - let configAnnotation: ConfigurationAnnotation = clazz.getOwnAnnotation(ConfigurationAnnotation); - if (undefined === configAnnotation) { - throw new Error(`Class is not Configuration type. add @Configuration annotation to class[${configurationType.name}]`); - } - let methods = clazz.getOwnMethods(); - if (null === methods) { - return; - } - let instance = clazz.getConstructor().newInstance(); - instanceFactory.applyInstance(configurationType, instance); - methods.forEach(method => { - let instanceAnnotation = method.getOwnAnnotation(InstanceAnnotation); - if (undefined === instanceAnnotation) { - return; - } - let singletonName = null === instanceAnnotation.attributes.name ? method.getName() : instanceAnnotation.attributes.name; - let result = method.invoke(instance); - instanceFactory.registerSingleton(singletonName, method.getReturnType(), result); - }); - }); - } +// configurationTypes.forEach(configurationType => { +// let clazz: Class = Class.forClassType(configurationType); +// let configAnnotation: ConfigurationAnnotation = clazz.getOwnAnnotation(ConfigurationAnnotation); +// if (undefined === configAnnotation) { +// throw new Error(`Class is not Configuration type. add @Configuration annotation to class[${configurationType.name}]`); +// } +// let methods = clazz.getOwnMethods(); +// if (null === methods) { +// return; +// } +// let instance = clazz.getConstructor().newInstance(); +// instanceFactory.applyInstance(configurationType, instance); +// methods.forEach(method => { +// let instanceAnnotation = method.getOwnAnnotation(InstanceAnnotation); +// if (undefined === instanceAnnotation) { +// return; +// } +// let singletonName = null === instanceAnnotation.attributes.name ? method.getName() : instanceAnnotation.attributes.name; +// let result = method.invoke(instance); +// instanceFactory.registerSingleton(singletonName, method.getReturnType(), result); +// }); +// }); +// } } diff --git a/src/ts/@overflow/commons/application/context/__application_context.ts b/src/ts/@overflow/commons/application/context/__application_context.ts deleted file mode 100644 index 0545816..0000000 --- a/src/ts/@overflow/commons/application/context/__application_context.ts +++ /dev/null @@ -1,46 +0,0 @@ -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 5285d7e..e6e97de 100644 --- a/src/ts/@overflow/commons/application/context/application_context.ts +++ b/src/ts/@overflow/commons/application/context/application_context.ts @@ -1,3 +1,7 @@ +import { + ClassType, +} from '@overflow/commons/core/type'; + import { InstanceFactory, } from '@overflow/commons/di/factory'; @@ -10,66 +14,52 @@ import { InstanceDefinitionReader } from './instance_definition_reader'; export class ApplicationContext { public static readonly MESSAGE_SOURCE_INSTANCE_NAME: string = 'messageSource'; - private readonly instanceFactoryPostProcessors: InstanceFactoryPostProcessor[] = []; - - private id: ApplicationContextIDType; - private parent: ApplicationContext; - private messageSource: MessageSource; - private instanceFactory: InstanceFactory; - private instanceDefinitionReader: InstanceDefinitionReader; + private _id: ApplicationContextIDType; + private _parent: ApplicationContext; + private _messageSource: MessageSource; + private _instanceFactory: InstanceFactory; + private _instanceDefinitionReader: InstanceDefinitionReader; public constructor(parent?: ApplicationContext) { - this.setParent(parent); + this.parent = parent; + this._instanceFactory = new InstanceFactory(); + this._instanceDefinitionReader = new InstanceDefinitionReader(this._instanceFactory.instanceDefinitionRegistry); } + // Context - public getID(): ApplicationContextIDType { + public get id(): ApplicationContextIDType { return this.id; } - public setID(id: ApplicationContextIDType): void { + public set id(id: ApplicationContextIDType) { this.id = id; } - public getApplicationName(): string { + public get applicationName(): string { return undefined; } - public getParent(): ApplicationContext { - return this.parent; + public get parent(): ApplicationContext { + return this._parent; } - public setParent(parent: ApplicationContext): void { - this.parent = parent; + public set parent(parent: ApplicationContext) { + this._parent = parent; } - public getInstanceFactory(): InstanceFactory { - return undefined; + public get instanceFactory(): InstanceFactory { + return this._instanceFactory; + } + + public get instanceDefinitionReader(): InstanceDefinitionReader { + return this._instanceDefinitionReader; } // 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; + public get messageSource(): MessageSource { + return this._messageSource; } // Lifecycle diff --git a/src/ts/@overflow/commons/application/context/index.ts b/src/ts/@overflow/commons/application/context/index.ts index 1c19132..a265c0f 100644 --- a/src/ts/@overflow/commons/application/context/index.ts +++ b/src/ts/@overflow/commons/application/context/index.ts @@ -1,2 +1,4 @@ export * from './application_context'; export * from './instance_definition_reader'; +export * from './scope_metadata'; +export * from './scope_metadata_resolver'; diff --git a/src/ts/@overflow/commons/application/context/instance_definition_reader.ts b/src/ts/@overflow/commons/application/context/instance_definition_reader.ts index 841be84..3ca6992 100644 --- a/src/ts/@overflow/commons/application/context/instance_definition_reader.ts +++ b/src/ts/@overflow/commons/application/context/instance_definition_reader.ts @@ -2,30 +2,63 @@ import { ClassType, } from '@overflow/commons/core/type'; -import { Assert } from '@overflow/commons/core/util'; +import { Annotation } from '@overflow/commons/core/reflect'; + +import { + Assert, + AnnotationUtils, +} from '@overflow/commons/core/util'; import { - InstanceDefinitionRegistry, InstanceNameGenerator, InstanceDefinition, + InstanceDefinitionRegistry, + InstanceNameGenerator, } from '@overflow/commons/di/factory'; +import { + InstanceNameType, + NotInjectableError, +} from '@overflow/commons/di/type'; + +import { ScopeMetadataResolver } from './scope_metadata_resolver'; +import { InjectableAnnotation, QualifierAnnotation } from '@overflow/commons/di/decorators'; + export class InstanceDefinitionReader { private instanceDefinitionRegistry: InstanceDefinitionRegistry; - private instanceNameGenerator: InstanceNameGenerator; + private instanceNameGenerator: InstanceNameGenerator = new InstanceNameGenerator(); + private scopeMetadataResolver: ScopeMetadataResolver = new ScopeMetadataResolver(); public constructor(registry: InstanceDefinitionRegistry) { Assert.notNull(registry, 'InstanceDefinitionRegistry must not be null'); this.instanceDefinitionRegistry = registry; } - public register(...injectables: ClassType[]): void { + public registerInjectables(...injectables: ClassType[]): void { injectables.forEach(injectable => { - this.registerInstance(injectable); + this.registerInjectable(injectable, undefined); }); } - public registerInstance(injectable: ClassType): void { - let instanceDefinition: InstanceDefinition = new InstanceDefinition(injectable); + public registerInjectable(injectable: ClassType, name: InstanceNameType | undefined, ...qualifiers: QualifierAnnotation[]): void { + if (!AnnotationUtils.hasAnnotation(injectable, InjectableAnnotation)) { + throw new NotInjectableError(); + } + + let definition: InstanceDefinition = new InstanceDefinition(injectable); + let scopeMeta = this.scopeMetadataResolver.resolveScopeMetadata(definition); + definition.scope = scopeMeta.scope; + let instanceName = + undefined !== name + ? name + : this.instanceNameGenerator.generateInstanceName(definition, this.instanceDefinitionRegistry); + + if (undefined !== qualifiers) { + qualifiers.forEach(qualifier => { + definition.addQualifier(qualifier); + }); + } + + this.instanceDefinitionRegistry.registerInstanceDefinition(instanceName, definition); } } diff --git a/src/ts/@overflow/commons/application/context/scope_metadata.ts b/src/ts/@overflow/commons/application/context/scope_metadata.ts new file mode 100644 index 0000000..67674ee --- /dev/null +++ b/src/ts/@overflow/commons/application/context/scope_metadata.ts @@ -0,0 +1,13 @@ +import { ScopeType } from '@overflow/commons/di/type'; + +export class ScopeMetadata { + private _scope: ScopeType = ScopeType.Singleton; + + public get scope(): ScopeType { + return this._scope; + } + public set scope(scope: ScopeType) { + this._scope = scope; + } + +} diff --git a/src/ts/@overflow/commons/application/context/scope_metadata_resolver.ts b/src/ts/@overflow/commons/application/context/scope_metadata_resolver.ts index 6be8ab2..82aa580 100644 --- a/src/ts/@overflow/commons/application/context/scope_metadata_resolver.ts +++ b/src/ts/@overflow/commons/application/context/scope_metadata_resolver.ts @@ -9,12 +9,14 @@ import { import { ScopeAnnotation } from '@overflow/commons/di/decorators'; import { InstanceDefinition } from '@overflow/commons/di/factory'; import { ScopeType } from '@overflow/commons/di/type'; +import { ScopeMetadata } from './scope_metadata'; export class ScopeMetadataResolver { protected static scopeAnnotationType: ClassType = ScopeAnnotation; - public resolveScopeMetadata(definition: InstanceDefinition): ScopeType { + public resolveScopeMetadata(definition: InstanceDefinition): ScopeMetadata { + let scopeMetadata: ScopeMetadata = new ScopeMetadata(); let scope: ScopeType = ScopeType.Default; } diff --git a/src/ts/@overflow/commons/application/decorators/instance.ts b/src/ts/@overflow/commons/application/decorators/instance.ts index 6191811..486f555 100644 --- a/src/ts/@overflow/commons/application/decorators/instance.ts +++ b/src/ts/@overflow/commons/application/decorators/instance.ts @@ -14,13 +14,15 @@ import { export interface InstanceAnnotationAttributes { name?: InstanceNameType; + initMethod?: Function; + destroyMethod?: Function; } export class InstanceAnnotation extends Annotation { public readonly attributes: InstanceAnnotationAttributes = { }; - public constructor(name: InstanceNameType | InstanceNameType[] | InstanceAnnotationAttributes) { + public constructor(name: InstanceNameType | InstanceAnnotationAttributes) { super(); if (undefined === name) { return; diff --git a/src/ts/@overflow/commons/application/decorators/web_application.ts b/src/ts/@overflow/commons/application/decorators/web_application.ts index d0b4ddb..988d0ef 100644 --- a/src/ts/@overflow/commons/application/decorators/web_application.ts +++ b/src/ts/@overflow/commons/application/decorators/web_application.ts @@ -8,12 +8,15 @@ import { PropertyKeyType, } from '@overflow/commons/core/type'; +import { Configuration } from './configuration'; + export interface WebApplicationAnnotationAttributes { jsonSources?: any[]; injectables?: ClassType[]; configurations?: ClassType[]; } +@Configuration() export class WebApplicationAnnotation extends Annotation { public readonly attributes: WebApplicationAnnotationAttributes = { }; diff --git a/src/ts/@overflow/commons/core/util/annotation.ts b/src/ts/@overflow/commons/core/util/annotation.ts new file mode 100644 index 0000000..1d04bbe --- /dev/null +++ b/src/ts/@overflow/commons/core/util/annotation.ts @@ -0,0 +1,36 @@ +import { Class, Annotation } from '@overflow/commons/core/reflect'; +import { ClassType } from '@overflow/commons/core/type'; + +export abstract class AnnotationUtils { + public static hasAnnotation(classType: ClassType, annotationClass: ClassType): boolean { + let annotation = AnnotationUtils.getAnnotation(classType, annotationClass); + if (undefined !== annotation) { + return true; + } + return false; + } + + public static getAnnotation(classType: ClassType, annotationClass: ClassType): T | undefined { + let clazz = Class.forClassType(classType); + if (undefined === clazz) { + return undefined; + } + + let annotations = clazz.getAnnotations(); + if (0 === annotations.size) { + return undefined; + } + + for (const annonClassType of Array.from(annotations.keys())) { + if (annonClassType === annotationClass) { + return annotations.get(annonClassType); + } + let annotation = AnnotationUtils.getAnnotation(annonClassType, annotationClass); + if (undefined !== annotation) { + return annotation; + } + } + + return undefined; + } +} diff --git a/src/ts/@overflow/commons/core/util/assert.ts b/src/ts/@overflow/commons/core/util/assert.ts index 075abe2..efef2ab 100644 --- a/src/ts/@overflow/commons/core/util/assert.ts +++ b/src/ts/@overflow/commons/core/util/assert.ts @@ -1,5 +1,5 @@ import { IllegalArgumentError } from '../type/error'; -import { StringUtil, StringUtils } from './string'; +import { StringUtils } from './string'; diff --git a/src/ts/@overflow/commons/core/util/index.ts b/src/ts/@overflow/commons/core/util/index.ts index d253650..788cdbf 100644 --- a/src/ts/@overflow/commons/core/util/index.ts +++ b/src/ts/@overflow/commons/core/util/index.ts @@ -1,3 +1,4 @@ +export * from './annotation'; export * from './assert'; export * from './locale'; export * from './registry'; diff --git a/src/ts/@overflow/commons/di/decorators/index.ts b/src/ts/@overflow/commons/di/decorators/index.ts index 9fb9d18..11ed455 100644 --- a/src/ts/@overflow/commons/di/decorators/index.ts +++ b/src/ts/@overflow/commons/di/decorators/index.ts @@ -1,6 +1,5 @@ export * from './inject'; export * from './injectable'; -export * from './named'; export * from './post_construct'; export * from './pre_destroy'; export * from './qualifier'; diff --git a/src/ts/@overflow/commons/di/decorators/inject.ts b/src/ts/@overflow/commons/di/decorators/inject.ts index bf5b2b5..9c8b04a 100644 --- a/src/ts/@overflow/commons/di/decorators/inject.ts +++ b/src/ts/@overflow/commons/di/decorators/inject.ts @@ -13,25 +13,25 @@ import { } from '@overflow/commons/di/type'; export interface InjectAnnotationAttributes { - name?: InstanceNameType; + required?: boolean; } export class InjectAnnotation extends Annotation { public readonly attributes: InjectAnnotationAttributes = { - + required: true, }; - public constructor(name: InstanceNameType | InjectAnnotationAttributes) { + public constructor(required?: boolean | InjectAnnotationAttributes) { super(); - if (undefined === name) { + if (undefined === required) { return; } - if (TypeUtil.isString(name)) { - this.attributes.name = name; + if (TypeUtil.isBoolean(required)) { + this.attributes.required = required; } else { - this.copyAttributes(this.attributes, name); + this.copyAttributes(this.attributes, required); } } diff --git a/src/ts/@overflow/commons/di/decorators/injectable.ts b/src/ts/@overflow/commons/di/decorators/injectable.ts index 4eac262..e061eda 100644 --- a/src/ts/@overflow/commons/di/decorators/injectable.ts +++ b/src/ts/@overflow/commons/di/decorators/injectable.ts @@ -13,24 +13,22 @@ import { } from '@overflow/commons/di/type'; export interface InjectableAnnotationAttributes { - name?: InstanceNameType[]; + name?: InstanceNameType; } export class InjectableAnnotation extends Annotation { public readonly attributes: InjectableAnnotationAttributes = { - + name: undefined, }; - public constructor(name: InstanceNameType | InstanceNameType[] | InjectableAnnotationAttributes) { + public constructor(name?: InstanceNameType | InjectableAnnotationAttributes) { super(); if (undefined === name) { return; } if (TypeUtil.isString(name)) { - this.attributes.name = [name]; - } else if (TypeUtil.isArray(name)) { - this.attributes.name = name; + this.attributes.name = name; } else { this.copyAttributes(this.attributes, name); } @@ -40,11 +38,6 @@ export class InjectableAnnotation extends Annotation { console.log('Injectable'); } - public methodDecorator(target: Object, propertyKey: PropertyKeyType, - descriptor: TypedPropertyDescriptor): TypedPropertyDescriptor | void { - console.log('Injectable'); - } - } export const Injectable = Decorator.create(InjectableAnnotation); diff --git a/src/ts/@overflow/commons/di/decorators/named.ts b/src/ts/@overflow/commons/di/decorators/named.ts deleted file mode 100644 index e69de29..0000000 diff --git a/src/ts/@overflow/commons/di/decorators/post_construct.ts b/src/ts/@overflow/commons/di/decorators/post_construct.ts index 4f4f464..3d5a96e 100644 --- a/src/ts/@overflow/commons/di/decorators/post_construct.ts +++ b/src/ts/@overflow/commons/di/decorators/post_construct.ts @@ -9,25 +9,14 @@ import { } from '@overflow/commons/core/type'; export interface PostConstructAnnotationAttributes { - name?: string[]; } export class PostConstructAnnotation extends Annotation { public readonly attributes: PostConstructAnnotationAttributes = { - }; - public constructor(name: string | string[] | PostConstructAnnotationAttributes) { + public constructor() { super(); - if (undefined === name) { - return; - } - - if (TypeUtil.isString(name)) { - this.attributes.name = [name]; - } else { - this.copyAttributes(this.attributes, name); - } } public methodDecorator(target: Object, propertyKey: PropertyKeyType, diff --git a/src/ts/@overflow/commons/di/decorators/pre_destroy.ts b/src/ts/@overflow/commons/di/decorators/pre_destroy.ts index 7ce453c..37ab461 100644 --- a/src/ts/@overflow/commons/di/decorators/pre_destroy.ts +++ b/src/ts/@overflow/commons/di/decorators/pre_destroy.ts @@ -9,7 +9,6 @@ import { } from '@overflow/commons/core/type'; export interface PreDestroyAnnotationAttributes { - name?: string[]; } export class PreDestroyAnnotation extends Annotation { @@ -17,17 +16,8 @@ export class PreDestroyAnnotation extends Annotation { }; - public constructor(name: string | string[] | PreDestroyAnnotationAttributes) { + public constructor() { super(); - if (undefined === name) { - return; - } - - if (TypeUtil.isString(name)) { - this.attributes.name = [name]; - } else { - this.copyAttributes(this.attributes, name); - } } public methodDecorator(target: Object, propertyKey: PropertyKeyType, diff --git a/src/ts/@overflow/commons/di/decorators/qualifier.ts b/src/ts/@overflow/commons/di/decorators/qualifier.ts index e69de29..a21b8b0 100644 --- a/src/ts/@overflow/commons/di/decorators/qualifier.ts +++ b/src/ts/@overflow/commons/di/decorators/qualifier.ts @@ -0,0 +1,55 @@ +import { + Annotation, + Decorator, +} from '@overflow/commons/core/reflect'; + +import { + PropertyKeyType, + TypeUtil, +} from '@overflow/commons/core/type'; + +import { + InstanceNameType, +} from '@overflow/commons/di/type'; + +export interface QualifierAnnotationAttributes { + name?: InstanceNameType; +} + +export class QualifierAnnotation extends Annotation { + public readonly attributes: QualifierAnnotationAttributes = { + name: '', + }; + + public constructor(name: InstanceNameType | QualifierAnnotationAttributes) { + super(); + if (undefined === name) { + return; + } + + if (TypeUtil.isString(name)) { + this.attributes.name = name; + } else { + this.copyAttributes(this.attributes, name); + } + } + + public classDecorator(target: TFunction): TFunction | void { + console.log('Qualifier'); + } + + public propertyDecorator(target: Object, propertyKey: PropertyKeyType): void { + console.log('Qualifier'); + } + + public methodDecorator(target: Object, propertyKey: PropertyKeyType, + descriptor: TypedPropertyDescriptor): TypedPropertyDescriptor | void { + console.log('Qualifier'); + } + + public parameterDecorator(target: Object, propertyKey: PropertyKeyType, parameterIndex: number): void { + console.log('Qualifier'); + } +} + +export const Qualifier = Decorator.create(QualifierAnnotation); diff --git a/src/ts/@overflow/commons/di/decorators/resource.ts b/src/ts/@overflow/commons/di/decorators/resource.ts index b0fadc0..a5b2b46 100644 --- a/src/ts/@overflow/commons/di/decorators/resource.ts +++ b/src/ts/@overflow/commons/di/decorators/resource.ts @@ -46,10 +46,6 @@ export class ResourceAnnotation extends Annotation { descriptor: TypedPropertyDescriptor): TypedPropertyDescriptor | void { console.log('Resource'); } - - public parameterDecorator(target: Object, propertyKey: PropertyKeyType, parameterIndex: number): void { - console.log('Resource'); - } } export const Resource = Decorator.create(ResourceAnnotation); diff --git a/src/ts/@overflow/commons/di/decorators/scope.ts b/src/ts/@overflow/commons/di/decorators/scope.ts index a87ddd1..d52cddb 100644 --- a/src/ts/@overflow/commons/di/decorators/scope.ts +++ b/src/ts/@overflow/commons/di/decorators/scope.ts @@ -14,21 +14,21 @@ import { } from '@overflow/commons/di/type'; export interface ScopeAnnotationAttributes { - value?: ScopeType; + scope?: ScopeType; } export class ScopeAnnotation extends Annotation { public readonly attributes: ScopeAnnotationAttributes = { - value: ScopeType.Default, + scope: ScopeType.Default, }; - public constructor(value: ScopeType | ScopeAnnotationAttributes) { + public constructor(scope: ScopeType | ScopeAnnotationAttributes) { super(); - if (undefined !== (value).value) { - this.copyAttributes(this.attributes, value); + if (undefined !== (scope).scope) { + this.copyAttributes(this.attributes, scope); } else { - this.attributes.value = value; + this.attributes.scope = scope; } } diff --git a/src/ts/@overflow/commons/di/decorators/value.ts b/src/ts/@overflow/commons/di/decorators/value.ts index 78d5a0f..ba28736 100644 --- a/src/ts/@overflow/commons/di/decorators/value.ts +++ b/src/ts/@overflow/commons/di/decorators/value.ts @@ -34,6 +34,11 @@ export class ValueAnnotation extends Annotation { console.log('Value'); } + public methodDecorator(target: Object, propertyKey: PropertyKeyType, + descriptor: TypedPropertyDescriptor): TypedPropertyDescriptor | void { + console.log('Value'); + } + public parameterDecorator(target: Object, propertyKey: PropertyKeyType, parameterIndex: number): void { console.log('Value'); } diff --git a/src/ts/@overflow/commons/di/factory/__instance_definition.ts b/src/ts/@overflow/commons/di/factory/__instance_definition similarity index 100% rename from src/ts/@overflow/commons/di/factory/__instance_definition.ts rename to src/ts/@overflow/commons/di/factory/__instance_definition diff --git a/src/ts/@overflow/commons/di/factory/__instance_factory.ts b/src/ts/@overflow/commons/di/factory/__instance_factory similarity index 100% rename from src/ts/@overflow/commons/di/factory/__instance_factory.ts rename to src/ts/@overflow/commons/di/factory/__instance_factory diff --git a/src/ts/@overflow/commons/di/factory/index.ts b/src/ts/@overflow/commons/di/factory/index.ts index 94c42ed..620fe06 100644 --- a/src/ts/@overflow/commons/di/factory/index.ts +++ b/src/ts/@overflow/commons/di/factory/index.ts @@ -2,3 +2,4 @@ export * from './instance_definition_registry'; export * from './instance_definition'; export * from './instance_factory'; export * from './instance_name_generator'; +export * from './singleton_instance_registry'; diff --git a/src/ts/@overflow/commons/di/factory/instance_definition.ts b/src/ts/@overflow/commons/di/factory/instance_definition.ts index 16c8abb..4246b68 100644 --- a/src/ts/@overflow/commons/di/factory/instance_definition.ts +++ b/src/ts/@overflow/commons/di/factory/instance_definition.ts @@ -1,39 +1,41 @@ +import { + Class, +} from '@overflow/commons/core/reflect'; + +import { + ClassType, +} from '@overflow/commons/core/type'; + import { Assert } from '@overflow/commons/core/util'; -import { ScopeType, InjectModeType } from '@overflow/commons/di/type'; + +import { + QualifierAnnotation, +} from '@overflow/commons/di/decorators'; + +import { + ScopeType, + InjectModeType, + NotInjectableError, +} from '@overflow/commons/di/type'; export class InstanceDefinition { private readonly attributes: Map = new Map(); - private scope: ScopeType = ScopeType.Default; - private injectMode: InjectModeType = InjectModeType.No; + private _instanceClass: Class; + private _scope: ScopeType = ScopeType.Default; + private _injectMode: InjectModeType = InjectModeType.No; - // Attributes - 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); + public constructor(instanceClassType: ClassType) { + let clazz = Class.forClassType(instanceClassType); + if (undefined === clazz) { + throw new NotInjectableError(); } + + this._instanceClass = clazz; } - public getAttribute(name: string): any | undefined { - Assert.notNull(name, 'Name must not be null'); - return this.attributes.get(name); - } - - 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 get instanceClass(): Class { + return this._instanceClass; } // Metadata @@ -41,14 +43,22 @@ export class InstanceDefinition { return undefined; } - public setScope(scope: ScopeType): void { + public set scope(scope: ScopeType) { this.scope = scope; } - public getScope(): ScopeType { + public get scope(): ScopeType { return this.scope; } + public get injectMode(): InjectModeType { + return this._injectMode; + } + + public set injectMode(injectMode: InjectModeType) { + this._injectMode = injectMode; + } + public isSingleton(): boolean { return ScopeType.Singleton === this.scope || ScopeType.Default === this.scope; } @@ -57,12 +67,7 @@ export class InstanceDefinition { return ScopeType.Transiant === this.scope; } - public setInjectMode(injectMode: InjectModeType): void { - this.injectMode = injectMode; + public addQualifier(qualifier: QualifierAnnotation): void { + // } - - 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 7f8d92c..24e46d8 100644 --- a/src/ts/@overflow/commons/di/factory/instance_factory.ts +++ b/src/ts/@overflow/commons/di/factory/instance_factory.ts @@ -7,7 +7,7 @@ import { } from '@overflow/commons/core/type'; import { - InjectType, + InjectModeType, InstanceNameType, } from '@overflow/commons/di/type'; @@ -15,9 +15,13 @@ import { InstanceDefinition } from './instance_definition'; import { InstanceDefinitionRegistry } from './instance_definition_registry'; export class InstanceFactory { - private instanceDefinitionRegistry: InstanceDefinitionRegistry; + private _instanceDefinitionRegistry: InstanceDefinitionRegistry; + public get instanceDefinitionRegistry(): InstanceDefinitionRegistry { + return this._instanceDefinitionRegistry; + } + // Instance public getInstance(name: InstanceNameType | undefined, requiredType: ClassType | undefined, ...args: any[]): any | undefined { @@ -44,7 +48,7 @@ export class InstanceFactory { // Create Instance - public createInstance(clazzType: ClassType, injectMode?: InjectType, dependencyCheck?: boolean): T { + public createInstance(clazzType: ClassType, injectMode?: InjectModeType, dependencyCheck?: boolean): T { return undefined; } @@ -52,11 +56,11 @@ export class InstanceFactory { // } - public inject(clazzType: ClassType, injectMode?: InjectType, dependencyCheck?: boolean): any { + public inject(clazzType: ClassType, injectMode?: InjectModeType, dependencyCheck?: boolean): any { // } - public injectInstanceProperties(instance: any, injectMode: InjectType, dependencyCheck: boolean): void { + public injectInstanceProperties(instance: any, injectMode: InjectModeType, dependencyCheck: boolean): void { // } diff --git a/src/ts/@overflow/commons/di/type/error.ts b/src/ts/@overflow/commons/di/type/error.ts index 1ade987..689fc10 100644 --- a/src/ts/@overflow/commons/di/type/error.ts +++ b/src/ts/@overflow/commons/di/type/error.ts @@ -5,6 +5,13 @@ export class InstanceError extends Error { } } +export class NotInjectableError extends InstanceError { + public constructor(message?: string) { + super(message); + Object.setPrototypeOf(this, new.target.prototype); + } +} + export class NoSuchInstanceDefinitionError extends InstanceError { public constructor(message?: string) { super(message);