From ac19de25efa0baf1be177111ff92be8b41f2deb4 Mon Sep 17 00:00:00 2001 From: Dragan Andonovski Date: Fri, 23 Sep 2016 14:15:51 +0200 Subject: [PATCH] [#56] Metadata Decorator Refactoring - refactored the @EnableCaching, @Profile, @Qualifier, @RequestMapping and @View decorators [work-in-progress] --- src/lib/decorators/ComponentDecorator.ts | 6 +-- src/lib/decorators/EnableCachingDecorator.ts | 18 -------- src/lib/decorators/InjectionDecorators.ts | 10 ++--- src/lib/decorators/ProfileDecorators.ts | 15 +++++-- src/lib/decorators/QualifierDecorator.ts | 8 +++- src/lib/decorators/RequestMappingDecorator.ts | 41 ++++++++++++++----- src/lib/decorators/ViewDecorator.ts | 9 +++- src/lib/decorators/aspect/AroundDecorator.ts | 3 +- .../cache/EnableCachingDecorator.ts | 11 +++-- src/lib/di/ApplicationContext.ts | 11 ++++- src/lib/helpers/ReflectUtils.ts | 3 +- src/lib/web/Dispatcher.ts | 2 +- 12 files changed, 82 insertions(+), 55 deletions(-) delete mode 100644 src/lib/decorators/EnableCachingDecorator.ts diff --git a/src/lib/decorators/ComponentDecorator.ts b/src/lib/decorators/ComponentDecorator.ts index 0b7f465..4f4f65f 100644 --- a/src/lib/decorators/ComponentDecorator.ts +++ b/src/lib/decorators/ComponentDecorator.ts @@ -1,4 +1,4 @@ -import { InjectionDataDecoratorMetadata } from "./InjectionDecorators"; +import {InjectionDataDecoratorMetadata, Inject} from "./InjectionDecorators"; import { Interceptor } from "./InterceptorDecorator"; import { ComponentDefinitionPostProcessor @@ -14,7 +14,7 @@ import { DecoratorMetadata } from "./common/DecoratorMetadata"; export class ComponentDecoratorMetadata extends DecoratorMetadata { componentName: string; classToken: symbol; - aliasTokens: Array; + aliasTokens: Array; injectionData: InjectionDataDecoratorMetadata; profiles: Array; @@ -67,7 +67,7 @@ export class ComponentUtil { } static getInjectionData(target): InjectionDataDecoratorMetadata { - return this.getComponentData(target).injectionData; + return DecoratorHelper.getMetadata(target, Inject, new InjectionDataDecoratorMetadata()); } static isController(target): boolean { diff --git a/src/lib/decorators/EnableCachingDecorator.ts b/src/lib/decorators/EnableCachingDecorator.ts deleted file mode 100644 index c2055cb..0000000 --- a/src/lib/decorators/EnableCachingDecorator.ts +++ /dev/null @@ -1,18 +0,0 @@ -import {ConfigurationUtil} from "./ConfigurationDecorator"; -import {CacheDefinitionPostProcessor} from '../processors/cache/CacheDefinitionPostProcessor'; -import { DecoratorType, DecoratorUtil } from "../helpers/DecoratorUtils"; - -/** - * - * A decorator which enables the caching decorators (@Cacheable, @CacheEvict, @CachePut) - * May only be put on @Configuration() classes. - */ -export function EnableCaching() { - return function (target) { - DecoratorUtil.throwOnWrongType(EnableCaching, DecoratorType.CLASS, [...arguments]); - ConfigurationUtil.throwWhenNotOnConfigurationClass(EnableCaching, [...arguments]); - - ConfigurationUtil.getConfigurationData(target).componentDefinitionPostProcessorFactory.components - .push(CacheDefinitionPostProcessor); - }; -} \ No newline at end of file diff --git a/src/lib/decorators/InjectionDecorators.ts b/src/lib/decorators/InjectionDecorators.ts index 3858802..9444002 100644 --- a/src/lib/decorators/InjectionDecorators.ts +++ b/src/lib/decorators/InjectionDecorators.ts @@ -5,9 +5,7 @@ import { DecoratorType, DecoratorUtil } from "../helpers/DecoratorUtils"; import "reflect-metadata"; import { DecoratorHelper } from "./common/DecoratorHelper"; import { DecoratorMetadata } from "./common/DecoratorMetadata"; -import { Decorator } from "./common/DecoratorDefinition"; -const INJECT_DECORATOR_TOKEN = Symbol('injector_decorator_token'); export class DependencyData { token: Symbol; @@ -65,13 +63,13 @@ export function Autowired() { }; } -export function Value(preopertyKey) { +export function Value(propertyKey) { return function (target: any, fieldName: string) { DecoratorUtil.throwOnWrongType(Value, DecoratorType.PROPERTY, [...arguments]); - let injectionData = DecoratorHelper.getOwnMetadata(target, Value, new InjectionDataDecoratorMetadata(), true); - injectionData.properties.set(fieldName, preopertyKey); - DecoratorHelper.setMetadata(target, Value, injectionData); + let injectionData = DecoratorHelper.getOwnMetadata(target, Inject, new InjectionDataDecoratorMetadata(), true); + injectionData.properties.set(fieldName, propertyKey); + DecoratorHelper.setMetadata(target, Inject, injectionData); }; } DecoratorHelper.createDecorator(Value, DecoratorType.PROPERTY); diff --git a/src/lib/decorators/ProfileDecorators.ts b/src/lib/decorators/ProfileDecorators.ts index ebba8c1..09f7409 100644 --- a/src/lib/decorators/ProfileDecorators.ts +++ b/src/lib/decorators/ProfileDecorators.ts @@ -1,12 +1,17 @@ -import { ComponentUtil } from "./ComponentDecorator"; -import { ConfigurationUtil } from "./ConfigurationDecorator"; +import {ComponentUtil, ComponentDecoratorMetadata, Component} from "./ComponentDecorator"; +import {ConfigurationUtil, Configuration, ConfigurationDecoratorMetadata} from "./ConfigurationDecorator"; import { DecoratorUtil, DecoratorType } from "../helpers/DecoratorUtils"; +import {DecoratorHelper} from "./common/DecoratorHelper"; export function Profile(...profiles: Array) { return function (target) { DecoratorUtil.throwOnWrongType(Profile, DecoratorType.CLASS, [...arguments]); ComponentUtil.throwWhenNotOnComponentClass(Profile, [...arguments]); - profiles.forEach((profile) => ComponentUtil.getComponentData(target).profiles.push(profile)); + profiles.forEach((profile) => { + let componentDecoratorMetadata = DecoratorHelper.getOwnMetadata(target, Component); + componentDecoratorMetadata.profiles.push(profile); + DecoratorHelper.setMetadata(target, Component, componentDecoratorMetadata); + }); }; } @@ -14,6 +19,8 @@ export function ActiveProfiles(...profiles: Array) { return function (target) { DecoratorUtil.throwOnWrongType(ActiveProfiles, DecoratorType.CLASS, [...arguments]); ConfigurationUtil.throwWhenNotOnConfigurationClass(ActiveProfiles, [...arguments]); - ConfigurationUtil.getConfigurationData(target).activeProfiles.push(...profiles); + let configurationDecoratorMetadata = DecoratorHelper.getMetadata(target, Configuration); + configurationDecoratorMetadata.activeProfiles.push(...profiles); + DecoratorHelper.setMetadata(target, Configuration, configurationDecoratorMetadata); }; } \ No newline at end of file diff --git a/src/lib/decorators/QualifierDecorator.ts b/src/lib/decorators/QualifierDecorator.ts index 8bee2ea..15ce977 100644 --- a/src/lib/decorators/QualifierDecorator.ts +++ b/src/lib/decorators/QualifierDecorator.ts @@ -1,10 +1,14 @@ -import { ComponentUtil } from "./ComponentDecorator"; +import {ComponentUtil, Component, ComponentDecoratorMetadata} from "./ComponentDecorator"; import { DecoratorType, DecoratorUtil } from "../helpers/DecoratorUtils"; +import {DecoratorHelper} from "./common/DecoratorHelper"; export function Qualifier(token: Symbol) { return function (target) { DecoratorUtil.throwOnWrongType(Qualifier, DecoratorType.CLASS, [...arguments]); ComponentUtil.throwWhenNotOnComponentClass(Qualifier, [...arguments]); - ComponentUtil.getAliasTokens(target).push(token); + + let componentDecoratorMetadata = DecoratorHelper.getOwnMetadata(target, Component); + componentDecoratorMetadata.aliasTokens.push(token); + DecoratorHelper.setMetadata(target, Component, componentDecoratorMetadata); }; } \ No newline at end of file diff --git a/src/lib/decorators/RequestMappingDecorator.ts b/src/lib/decorators/RequestMappingDecorator.ts index 7c73325..949e56b 100644 --- a/src/lib/decorators/RequestMappingDecorator.ts +++ b/src/lib/decorators/RequestMappingDecorator.ts @@ -2,6 +2,8 @@ import * as _ from "lodash"; import { DecoratorUtil, DecoratorType } from "../helpers/DecoratorUtils"; import { DecoratorUsageTypeError } from "../errors/DecoratorUsageErrors"; import { BadArgumentError } from "../errors/BadArgumentErrors"; +import {StandaloneDecoratorMetadata} from "./common/DecoratorMetadata"; +import {DecoratorHelper} from "./common/DecoratorHelper"; // NOTE: These are methods defined on the Express Router // http://expressjs.com/en/4x/api.html#router @@ -41,6 +43,24 @@ export class RouterConfig { routes: Array = []; } +export class RequestMappingDecoratorMetadata extends StandaloneDecoratorMetadata { + routes: Array; + path: string; + + constructor() { + super(); + this.path = ""; + this.routes = []; + } + + setPath(path: string) { + this.routes.forEach((value, index) => { + let routePath = path + value.requestConfig.path; + value.requestConfig.path = routePath; + }); + } +} + export function RequestMapping(config: RequestMappingConfig) { return function (...args) { let type = DecoratorUtil.getType(args); @@ -52,7 +72,7 @@ export function RequestMapping(config: RequestMappingConfig) { (`When using @${RequestMapping.name} on methods you must provide the request method type`); } let method = args[1]; - let routerConfig = RequestMappingUtil.initRouterConfigIfDoesntExist(target); + let routerConfig = DecoratorHelper.getOwnMetadata(target, RequestMapping, new RequestMappingDecoratorMetadata(), true); let routeConfig = _.find(routerConfig.routes, {methodHandler: method}); // TODO: Override bug #51 if (routeConfig) { @@ -60,31 +80,30 @@ export function RequestMapping(config: RequestMappingConfig) { } else { routerConfig.routes.push(new RouterConfigItem(config, method)); } + DecoratorHelper.setMetadata(target, RequestMapping, routerConfig); } else if (type === DecoratorType.CLASS) { // TODO: refactor when new options are added on @RequestMapping for classes - target[CLASS_ROUTER_CONFIG] = config.path; + let decoratorMetadata: RequestMappingDecoratorMetadata = + DecoratorHelper.getOwnMetadata(target, RequestMapping, new RequestMappingDecoratorMetadata()); + decoratorMetadata.path = config.path; + decoratorMetadata.setPath(config.path); + DecoratorHelper.setMetadata(target, RequestMapping, decoratorMetadata); } else { let subjectName = DecoratorUtil.getSubjectName(args); throw new DecoratorUsageTypeError(RequestMapping, "classes and methods", subjectName); } }; } +DecoratorHelper.createDecorator(RequestMapping, DecoratorType.CLASS, DecoratorType.METHOD); export class RequestMappingUtil { static getValidRoutes(target): Array { - let routerConfig = this.initRouterConfigIfDoesntExist(target.prototype); + let routerConfig = DecoratorHelper.getMetadata(target, RequestMapping, new RequestMappingDecoratorMetadata()); return _.filter(routerConfig.routes, (route) => route.isValid()); } - static initRouterConfigIfDoesntExist(target): RouterConfig { - if (_.isUndefined(target[ROUTER_CONFIG])) { - target[ROUTER_CONFIG] = new RouterConfig(); - } - return target[ROUTER_CONFIG]; - } - static getControllerRequestMappingPath(target) { - return target[CLASS_ROUTER_CONFIG] || ""; + return DecoratorHelper.getMetadata(target, RequestMapping, new RequestMappingDecoratorMetadata()); } } \ No newline at end of file diff --git a/src/lib/decorators/ViewDecorator.ts b/src/lib/decorators/ViewDecorator.ts index 736e217..8a3078c 100644 --- a/src/lib/decorators/ViewDecorator.ts +++ b/src/lib/decorators/ViewDecorator.ts @@ -1,12 +1,17 @@ import * as _ from "lodash"; -import { RequestMappingUtil, RouterConfigItem } from "../decorators/RequestMappingDecorator"; +import { + RequestMappingUtil, RouterConfigItem, RequestMapping, + RequestMappingDecoratorMetadata +} from "../decorators/RequestMappingDecorator"; import { DecoratorUtil, DecoratorType } from "../helpers/DecoratorUtils"; +import {DecoratorHelper} from "./common/DecoratorHelper"; export function View(name?: string) { return function (target, methodName) { DecoratorUtil.throwOnWrongType(View, DecoratorType.METHOD, [...arguments]); let viewName = name || methodName; - let routerConfig = RequestMappingUtil.initRouterConfigIfDoesntExist(target); + let routerConfig = DecoratorHelper.getOwnMetadata(target, RequestMapping, new RequestMappingDecoratorMetadata(), true); + // TODO: fix this with the refactoring let routeConfig = _.find(routerConfig.routes, {methodHandler: methodName}); if (!routeConfig) { // NOTE: in case when @View is before @RequestMapping diff --git a/src/lib/decorators/aspect/AroundDecorator.ts b/src/lib/decorators/aspect/AroundDecorator.ts index e32f9a6..a19542d 100644 --- a/src/lib/decorators/aspect/AroundDecorator.ts +++ b/src/lib/decorators/aspect/AroundDecorator.ts @@ -26,7 +26,6 @@ export class ProceedingJoinPoint { } async proceed(): Promise { - let result = await Promise.race([Reflect.apply(this.methodRef, this.thisArg, this.args)]); - return result; + return await Promise.race([Reflect.apply(this.methodRef, this.thisArg, this.args)]); } } \ No newline at end of file diff --git a/src/lib/decorators/cache/EnableCachingDecorator.ts b/src/lib/decorators/cache/EnableCachingDecorator.ts index d6cf3ed..1acac09 100644 --- a/src/lib/decorators/cache/EnableCachingDecorator.ts +++ b/src/lib/decorators/cache/EnableCachingDecorator.ts @@ -1,6 +1,7 @@ import {ConfigurationUtil} from "../ConfigurationDecorator"; -import {CacheDefinitionPostProcessor} from '../../processors/cache/CacheDefinitionPostProcessor'; import { DecoratorType, DecoratorUtil } from "../../helpers/DecoratorUtils"; +import {StandaloneDecoratorMetadata} from "../common/DecoratorMetadata"; +import {DecoratorHelper} from "../common/DecoratorHelper"; /** * @@ -12,7 +13,11 @@ export function EnableCaching() { DecoratorUtil.throwOnWrongType(EnableCaching, DecoratorType.CLASS, [...arguments]); ConfigurationUtil.throwWhenNotOnConfigurationClass(EnableCaching, [...arguments]); - ConfigurationUtil.getConfigurationData(target).componentDefinitionPostProcessorFactory.components - .push(CacheDefinitionPostProcessor); + DecoratorHelper.setMetadata(target, EnableCaching, new EnableCacheDecoratorMetadata()); }; +} +DecoratorHelper.createDecorator(EnableCaching, DecoratorType.CLASS); + +export class EnableCacheDecoratorMetadata extends StandaloneDecoratorMetadata { + } \ No newline at end of file diff --git a/src/lib/di/ApplicationContext.ts b/src/lib/di/ApplicationContext.ts index aac11fc..ea34c6f 100644 --- a/src/lib/di/ApplicationContext.ts +++ b/src/lib/di/ApplicationContext.ts @@ -22,6 +22,8 @@ import { import {DynamicDependencyResolver} from "./DynamicDependencyResolver"; import { CacheDefinitionPostProcessor } from "../processors/cache/CacheDefinitionPostProcessor"; import { LoggerFactory } from "../helpers/logging/LoggerFactory"; +import {DecoratorHelper} from "../decorators/common/DecoratorHelper"; +import {EnableCaching} from "../decorators/cache/EnableCachingDecorator"; let logger = LoggerFactory.getInstance(); @@ -40,6 +42,8 @@ export class ApplicationContext { private configurationData: ConfigurationDecoratorMetadata; private unRegisterExitListenerCallback: Function; + private configurationClass; + constructor(configurationClass) { this.state = ApplicationContextState.NOT_INITIALIZED; logger.info('Constructing the application context...'); @@ -48,6 +52,8 @@ export class ApplicationContext { this.configurationData = ConfigurationUtil.getConfigurationData(configurationClass); this.initializeEnvironment(); this.configurationData.loadAllComponents(this.environment); + + this.configurationClass = configurationClass; } getComponent (componentClass): T { @@ -112,8 +118,7 @@ export class ApplicationContext { } private wireCacheDefinitionPostProcessor() { - if (this.configurationData.componentDefinitionPostProcessorFactory - .components.indexOf(CacheDefinitionPostProcessor) !== -1) { + if (DecoratorHelper.hasMetadata(this.configurationClass, EnableCaching)){ let cacheDefinitionPostProcessor = this.injector.getComponent(ComponentUtil.getClassToken(CacheDefinitionPostProcessor)); cacheDefinitionPostProcessor.setInjector(this.injector); @@ -200,6 +205,8 @@ export class ApplicationContext { logger.verbose('Initializing component definition post processors...'); // NOTE: add custom defined component definition post processors this.configurationData.componentDefinitionPostProcessorFactory.components.push(AspectDefinitionPostProcessor); + if (DecoratorHelper.hasMetadata(this.configurationClass, EnableCaching)) + this.configurationData.componentDefinitionPostProcessorFactory.components.push(CacheDefinitionPostProcessor); // NOTE: initialize all component definition post processors for (let CompConstructor of this.getActiveDefinitionPostProcessors()) { diff --git a/src/lib/helpers/ReflectUtils.ts b/src/lib/helpers/ReflectUtils.ts index 005c8c3..af3d2c2 100644 --- a/src/lib/helpers/ReflectUtils.ts +++ b/src/lib/helpers/ReflectUtils.ts @@ -33,7 +33,8 @@ export class ReflectUtils { allSymbols = allSymbols.concat(Object.getOwnPropertySymbols(target)); } else { allSymbols = Object.getOwnPropertySymbols(target); - allSymbols = allSymbols.concat(Object.getOwnPropertySymbols(target.prototype)); + if (target.prototype !== undefined) + allSymbols = allSymbols.concat(Object.getOwnPropertySymbols(target.prototype)); } if (allSymbols.indexOf(token) !== -1) { return target[token] || target.prototype[token]; diff --git a/src/lib/web/Dispatcher.ts b/src/lib/web/Dispatcher.ts index 8c03b8e..3cceb93 100644 --- a/src/lib/web/Dispatcher.ts +++ b/src/lib/web/Dispatcher.ts @@ -38,7 +38,7 @@ export class Dispatcher { logger.debug(`Registering controller ${ComponentUtil.getComponentData(clazz).componentName}.`); let controllerMappingPath = RequestMappingUtil.getControllerRequestMappingPath(clazz); for (let route of RequestMappingUtil.getValidRoutes(clazz)) { - route.requestConfig.path = controllerMappingPath + route.requestConfig.path; + // route.requestConfig.path = controllerMappingPath + route.requestConfig.path; this.routerConfigurer.registerHandler(route, instance); } }