This commit is contained in:
crusader 2017-12-28 22:51:04 +09:00
parent b1ec678681
commit b0df948bc4
15 changed files with 218 additions and 53 deletions

View File

@ -45,15 +45,22 @@ export class Application {
private findRunner(): Method {
let clazz: Class = Class.forClass(this._primaryClass);
let methods = clazz.getMethods();
for (let i = 0; i < methods.length; i++) {
const method = methods[i];
let runnerAnnotation = method.getOwnAnnotation(RunnerAnnotation);
if (undefined === runnerAnnotation) {
continue;
}
return method;
let methods = clazz.getOwnMethods();
if (null === methods || 0 === methods.size) {
return null;
}
for (const key in methods.keys()) {
if (methods.hasOwnProperty(key)) {
const method = methods[key];
let runnerAnnotation = method.getOwnAnnotation(RunnerAnnotation);
if (undefined === runnerAnnotation) {
continue;
}
return method;
}
}
return null;
}
@ -94,8 +101,12 @@ export class Application {
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 = instanceFactory.getInstance(null, configurationType);
clazz.getMethods().forEach(method => {
methods.forEach(method => {
let instanceAnnotation = method.getOwnAnnotation(InstanceAnnotation);
if (undefined === instanceAnnotation) {
return;

View File

@ -21,7 +21,7 @@ export abstract class AccessibleObject implements AnnotatedElement {
return null !== this.getAnnotation(annotationClass);
}
public getOwnAnnotation<AnnotationType extends Annotation>(annotationClass: ClassType<AnnotationType>): AnnotationType {
public getOwnAnnotation<AnnotationType extends Annotation>(annotationClass: ClassType<AnnotationType>): AnnotationType | undefined {
return <AnnotationType>this._annotations.get(annotationClass);
}
@ -29,7 +29,7 @@ export abstract class AccessibleObject implements AnnotatedElement {
return this._annotations;
}
public getAnnotation<AnnotationType extends Annotation>(annotationClass: ClassType<AnnotationType>): AnnotationType {
public getAnnotation<AnnotationType extends Annotation>(annotationClass: ClassType<AnnotationType>): AnnotationType | undefined {
return this.getOwnAnnotation(annotationClass);
}

View File

@ -8,8 +8,8 @@ export interface AnnotatedElement {
_addAnnotation<AnnotationType extends Annotation>(annotation: AnnotationType): void;
isAnnotationPresent<AnnotationType extends Annotation>(annotationClass: ClassType<AnnotationType>): boolean;
getOwnAnnotation<AnnotationType extends Annotation>(annotationClass: ClassType<AnnotationType>): AnnotationType;
getOwnAnnotation<AnnotationType extends Annotation>(annotationClass: ClassType<AnnotationType>): AnnotationType | undefined;
getOwnAnnotations(): Map<ClassType, Annotation>;
getAnnotation<AnnotationType extends Annotation>(annotationClass: ClassType<AnnotationType>): AnnotationType;
getAnnotation<AnnotationType extends Annotation>(annotationClass: ClassType<AnnotationType>): AnnotationType | undefined;
getAnnotations(): Map<ClassType, Annotation>;
}

View File

@ -1,10 +1,12 @@
import {
ClassType,
PropertyKeyType,
Metadata,
PropertyKeyType,
TypeUtil,
} from '@overflow/commons/core/type';
import {AccessibleObject} from './accessible_object';
import {Annotation} from './annotation';
import {systemClassRegistry} from './class_registry';
import {Constructor} from './constructor';
import {Field} from './field';
@ -21,7 +23,7 @@ export class Class extends AccessibleObject {
/**
* forClass
*/
public static forClass(clazzType: ClassType): Class {
public static forClass(clazzType: ClassType): Class | undefined {
return systemClassRegistry.get(clazzType);
}
@ -97,7 +99,7 @@ export class Class extends AccessibleObject {
return this._constructor;
}
public getOwnField(propertyKey: PropertyKeyType): Field {
public getOwnField(propertyKey: PropertyKeyType): Field | undefined {
return this._fields.get(propertyKey);
}
@ -105,15 +107,35 @@ export class Class extends AccessibleObject {
return this._fields;
}
public getField(propertyKey: PropertyKeyType): Field {
return null;
public getField(propertyKey: PropertyKeyType): Field | undefined {
let fields = this.getFields();
return fields.get(propertyKey);
}
public getFields(): Field[] {
return null;
public getFields(): Map<PropertyKeyType, Field> {
let fields: Map<PropertyKeyType, Field> = new Map();
let clazzTypes = TypeUtil.ancestorsOf(this._clazzType);
if (null === clazzTypes || 0 === clazzTypes.length) {
return fields;
}
for (let i = 0; i < clazzTypes.length; i++) {
const tClazzType = clazzTypes[i];
let tClazz = Class.forClass(tClazzType);
if (undefined === tClazz) {
continue;
}
tClazz.getOwnFields().forEach((value: Field, key: PropertyKeyType, map: Map<PropertyKeyType, Field>): void => {
fields.set(key, value);
});
}
return fields;
}
public getOwnMethod(propertyKey: PropertyKeyType): Method {
public getOwnMethod(propertyKey: PropertyKeyType): Method | undefined {
return this._methods.get(propertyKey);
}
@ -121,15 +143,64 @@ export class Class extends AccessibleObject {
return this._methods;
}
public getMethod(propertyKey: PropertyKeyType): Method {
return null;
public getMethod(propertyKey: PropertyKeyType): Method | undefined {
let methods = this.getMethods();
return methods.get(propertyKey);
}
public getMethods(): Method[] {
return null;
public getMethods(): Map<PropertyKeyType, Method> {
let methods: Map<PropertyKeyType, Method> = new Map();
let clazzTypes = TypeUtil.ancestorsOf(this._clazzType);
if (null === clazzTypes || 0 === clazzTypes.length) {
return methods;
}
for (let i = 0; i < clazzTypes.length; i++) {
const tClazzType = clazzTypes[i];
let tClazz = Class.forClass(tClazzType);
if (undefined === tClazz) {
continue;
}
tClazz.getOwnMethods().forEach((value: Method, key: PropertyKeyType, map: Map<PropertyKeyType, Method>): void => {
methods.set(key, value);
});
}
return methods;
}
public getAnnotation<AnnotationType extends Annotation>(annotationClass: ClassType<AnnotationType>): AnnotationType | undefined {
let annotations = this.getAnnotations();
return <AnnotationType>annotations.get(annotationClass);
}
public getAnnotations(): Map<ClassType, Annotation> {
let annotations: Map<ClassType, Annotation> = new Map();
let clazzTypes = TypeUtil.ancestorsOf(this._clazzType);
if (null === clazzTypes || 0 === clazzTypes.length) {
return annotations;
}
for (let i = 0; i < clazzTypes.length; i++) {
const tClazzType = clazzTypes[i];
let tClazz = Class.forClass(tClazzType);
if (undefined === tClazz) {
continue;
}
tClazz.getOwnAnnotations().forEach((value: Annotation, key: ClassType, map: Map<ClassType, Annotation>): void => {
annotations.set(key, value);
});
}
return annotations;
}
public getName(): string {
return null;
return this._clazzType.name;
}
}

View File

@ -54,18 +54,18 @@ export abstract class Executable extends AccessibleObject implements Member {
/**
* getParameters
*/
public getParameters(): Parameter[] {
public getParameters(): Parameter[] | undefined {
return this._parameters;
}
/**
* getParameter
*/
public getParameter(index: number): Parameter {
public getParameter(index: number): Parameter | undefined {
if (null === this._parameters) {
return null;
return undefined;
}
if (0 > index || this._parameters.length <= index) {
return null;
return undefined;
}
return this._parameters[index];
}

View File

@ -315,7 +315,7 @@ export class TypeUtil {
* @param target
* @returns {any}
*/
public static getInheritedClass(target: any): any {
public static getInheritedClass(target: ClassType): ClassType {
return Object.getPrototypeOf(target);
}
@ -388,8 +388,8 @@ export class TypeUtil {
* @param target
* @returns {Array}
*/
public static ancestorsOf(target: any): any[] {
const classes = [];
public static ancestorsOf(target: ClassType): ClassType[] {
const classes: ClassType[] = [];
let currentTarget = TypeUtil.getClass(target);

View File

@ -7,7 +7,7 @@ export abstract class Registry<K, V> {
this._map = new Map<K, V>();
}
public get parent(): Registry<K, V> {
public get parent(): Registry<K, V> | undefined {
return this._parent;
}

View File

@ -4,21 +4,47 @@ import {
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<InstanceNameType, any> = new Map();
private singletonFactories: Map<InstanceNameType, InstanceFactoryType> = new Map();
private instanceDefinitionMap: Map<InstanceNameType, InstanceDefinition> = new Map();
private instanceDefinitionNames: Set<InstanceNameType> = new Set();
/**
* getInstance
*/
public getInstance(name: InstanceNameType, requiredType: ClassType, ...args: any[]): any {
if (null === name) {
return this.getInstanceByType(requiredType);
}
let sharedInstance = this.getSingleton(name);
if (undefined !== sharedInstance) {
return sharedInstance;
}
return null;
}
private getInstanceByName(requiredType: ClassType): any {
}
private getInstanceByType(requiredType: ClassType): any {
}
private getSingleton(name: InstanceNameType): any | undefined {
let singletonObject = this.singletonObjects.get(name);
}
/**
* containsInstance
*/
@ -35,31 +61,40 @@ export class InstanceFactory implements InstanceDefinitionRegistry {
}
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 {
//
public getInstanceDefinition(name: InstanceNameType): InstanceDefinition | undefined {
return this.instanceDefinitionMap.get(name);
}
public containsInstanceDefinition(name: InstanceNameType): boolean {
//
return this.instanceDefinitionMap.has(name);
}
public getInstanceDefinitionNames(): InstanceNameType[] {
//
public getInstanceDefinitionNames(): Set<InstanceNameType> {
return this.instanceDefinitionNames;
}
public getInstanceDefinitionCount(): number {
//
return this.instanceDefinitionMap.size;
}
public isInstanceNameInUse(name: InstanceNameType): boolean {
//
return false;
}
}

View File

@ -3,3 +3,4 @@ import {
} from '@overflow/commons/core/type';
export type InstanceNameType = IdentityType<string>;
export type InstanceFactoryType = (...args: any[]) => any;

View File

@ -1,4 +1,5 @@
export * from './injectables';
export * from './json_sources';
export * from './reducer_configuration';
export * from './rest_api_configuration';
export * from './rpc_api_configuration';

View File

@ -0,0 +1,6 @@
import * as webapp from './jsons/webapp.json';
export const jsonSources: any[] = [
webapp,
];

View File

@ -0,0 +1,7 @@
{
"html": {
"container": {
"id": "appContainer"
}
}
}

View File

@ -2,14 +2,26 @@ import {
Configuration,
Instance,
} from '@overflow/commons/application/decorators';
import { Value } from '@overflow/commons/di/decorators';
@Configuration()
export class WebAppConfiguration {
@Value('html.container.id')
private htmlContainerID: string;
/**
* container
*/
@Instance()
public container(): HTMLElement {
return null;
public container(): Promise<HTMLElement> {
function getContainer(containerID: string): Promise<HTMLElement> {
return new Promise<HTMLElement>(resolve => {
document.addEventListener('DOMContentLoaded', () => {
resolve(document.getElementById(containerID));
});
});
}
return getContainer(this.htmlContainerID);
}
}

View File

@ -36,10 +36,12 @@ import {
import {
Inject,
Resource,
Value,
} from '@overflow/commons/di/decorators';
import config, {
injectables,
jsonSources,
ReducerConfiguration,
RestAPIConfiguration,
RpcAPIConfiguration,
@ -58,8 +60,14 @@ declare global {
const module: { hot: any };
}
class A {
}
class B extends A {
}
@WebApplication({
injectables: injectables,
jsonSources: jsonSources,
configurations: [
ReducerConfiguration,
RestAPIConfiguration,
@ -67,11 +75,12 @@ declare global {
WebAppConfiguration,
],
})
class WebAppApplication {
class WebAppApplication extends B {
private static isProduction:boolean = process.env.NODE_ENV === 'production' ? true : false;
private static useReduxDevTools:boolean = window.devToolsExtension && !WebAppApplication.isProduction ? true : false;
@Resource()
@Value('html.container.id')
private htmlContainerID: string;
private container: HTMLElement;
@Inject()
@ -81,14 +90,10 @@ class WebAppApplication {
@Inject()
private dispatcherReducer: WebAppDispatcherReducer;
public constructor() {
this.container = document.getElementById('appContainer');
this.history = createHashHistory();
}
@Runner()
public async run(): Promise<void> {
try {
this.container = await this.getContainer();
this.renderLoading();
let reducer: WebAppDispatcherReducer = new WebAppDispatcherReducer();
reducer.registerReducers(config.redux.reducers);
@ -100,6 +105,18 @@ class WebAppApplication {
}
}
private getContainer(): Promise<HTMLElement> {
function getContainer(containerID: string): Promise<HTMLElement> {
return new Promise<HTMLElement>(resolve => {
document.addEventListener('DOMContentLoaded', () => {
resolve(document.getElementById(containerID));
});
});
}
return getContainer(this.htmlContainerID);
}
private renderLoading(): void {
ReactDOM.render(
<div style={{

4
src/ts/typings.d.ts vendored Normal file
View File

@ -0,0 +1,4 @@
declare module '*.json' {
const value: any;
export default value;
}