Skip to content

Commit

Permalink
[#56] Metadata Decorator Refactoring
Browse files Browse the repository at this point in the history
- refactored the @EnableCaching, @Profile, @qualifier, @RequestMapping and @view decorators
[work-in-progress]
  • Loading branch information
Dragan Andonovski authored and Dragan Andonovski committed Sep 23, 2016
1 parent 2a4d9fb commit ac19de2
Show file tree
Hide file tree
Showing 12 changed files with 82 additions and 55 deletions.
6 changes: 3 additions & 3 deletions src/lib/decorators/ComponentDecorator.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { InjectionDataDecoratorMetadata } from "./InjectionDecorators";
import {InjectionDataDecoratorMetadata, Inject} from "./InjectionDecorators";
import { Interceptor } from "./InterceptorDecorator";
import {
ComponentDefinitionPostProcessor
Expand All @@ -14,7 +14,7 @@ import { DecoratorMetadata } from "./common/DecoratorMetadata";
export class ComponentDecoratorMetadata extends DecoratorMetadata<ComponentDecoratorMetadata> {
componentName: string;
classToken: symbol;
aliasTokens: Array<symbol>;
aliasTokens: Array<Symbol>;
injectionData: InjectionDataDecoratorMetadata;
profiles: Array<string>;

Expand Down Expand Up @@ -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 {
Expand Down
18 changes: 0 additions & 18 deletions src/lib/decorators/EnableCachingDecorator.ts

This file was deleted.

10 changes: 4 additions & 6 deletions src/lib/decorators/InjectionDecorators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
15 changes: 11 additions & 4 deletions src/lib/decorators/ProfileDecorators.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
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<string>) {
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 = <ComponentDecoratorMetadata> DecoratorHelper.getOwnMetadata(target, Component);
componentDecoratorMetadata.profiles.push(profile);
DecoratorHelper.setMetadata(target, Component, componentDecoratorMetadata);
});
};
}

export function ActiveProfiles(...profiles: Array<string>) {
return function (target) {
DecoratorUtil.throwOnWrongType(ActiveProfiles, DecoratorType.CLASS, [...arguments]);
ConfigurationUtil.throwWhenNotOnConfigurationClass(ActiveProfiles, [...arguments]);
ConfigurationUtil.getConfigurationData(target).activeProfiles.push(...profiles);
let configurationDecoratorMetadata = <ConfigurationDecoratorMetadata> DecoratorHelper.getMetadata(target, Configuration);
configurationDecoratorMetadata.activeProfiles.push(...profiles);
DecoratorHelper.setMetadata(target, Configuration, configurationDecoratorMetadata);
};
}
8 changes: 6 additions & 2 deletions src/lib/decorators/QualifierDecorator.ts
Original file line number Diff line number Diff line change
@@ -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 = <ComponentDecoratorMetadata> DecoratorHelper.getOwnMetadata(target, Component);
componentDecoratorMetadata.aliasTokens.push(token);
DecoratorHelper.setMetadata(target, Component, componentDecoratorMetadata);
};
}
41 changes: 30 additions & 11 deletions src/lib/decorators/RequestMappingDecorator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -41,6 +43,24 @@ export class RouterConfig {
routes: Array<RouterConfigItem> = [];
}

export class RequestMappingDecoratorMetadata extends StandaloneDecoratorMetadata<RequestMappingDecoratorMetadata> {
routes: Array<RouterConfigItem>;
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);
Expand All @@ -52,39 +72,38 @@ 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) {
routeConfig.requestConfig = config;
} 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<RouterConfigItem> {
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());
}
}
9 changes: 7 additions & 2 deletions src/lib/decorators/ViewDecorator.ts
Original file line number Diff line number Diff line change
@@ -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
Expand Down
3 changes: 1 addition & 2 deletions src/lib/decorators/aspect/AroundDecorator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ export class ProceedingJoinPoint {
}

async proceed(): Promise<any> {
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)]);
}
}
11 changes: 8 additions & 3 deletions src/lib/decorators/cache/EnableCachingDecorator.ts
Original file line number Diff line number Diff line change
@@ -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";

/**
*
Expand All @@ -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<EnableCacheDecoratorMetadata> {

}
11 changes: 9 additions & 2 deletions src/lib/di/ApplicationContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand All @@ -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...');
Expand All @@ -48,6 +52,8 @@ export class ApplicationContext {
this.configurationData = ConfigurationUtil.getConfigurationData(configurationClass);
this.initializeEnvironment();
this.configurationData.loadAllComponents(this.environment);

this.configurationClass = configurationClass;
}

getComponent <T>(componentClass): T {
Expand Down Expand Up @@ -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 = <CacheDefinitionPostProcessor>
this.injector.getComponent(ComponentUtil.getClassToken(CacheDefinitionPostProcessor));
cacheDefinitionPostProcessor.setInjector(this.injector);
Expand Down Expand Up @@ -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()) {
Expand Down
3 changes: 2 additions & 1 deletion src/lib/helpers/ReflectUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down
2 changes: 1 addition & 1 deletion src/lib/web/Dispatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand Down

0 comments on commit ac19de2

Please sign in to comment.