ing
This commit is contained in:
parent
b1ec678681
commit
b0df948bc4
|
@ -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 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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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>;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
public getOwnMethod(propertyKey: PropertyKeyType): Method {
|
||||
tClazz.getOwnFields().forEach((value: Field, key: PropertyKeyType, map: Map<PropertyKeyType, Field>): void => {
|
||||
fields.set(key, value);
|
||||
});
|
||||
}
|
||||
|
||||
return fields;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,3 +3,4 @@ import {
|
|||
} from '@overflow/commons/core/type';
|
||||
|
||||
export type InstanceNameType = IdentityType<string>;
|
||||
export type InstanceFactoryType = (...args: any[]) => any;
|
||||
|
|
|
@ -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';
|
||||
|
|
6
src/ts/@overflow/webapp/config/json_sources.ts
Normal file
6
src/ts/@overflow/webapp/config/json_sources.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
import * as webapp from './jsons/webapp.json';
|
||||
|
||||
export const jsonSources: any[] = [
|
||||
webapp,
|
||||
|
||||
];
|
7
src/ts/@overflow/webapp/config/jsons/webapp.json
Normal file
7
src/ts/@overflow/webapp/config/jsons/webapp.json
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"html": {
|
||||
"container": {
|
||||
"id": "appContainer"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
4
src/ts/typings.d.ts
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
declare module '*.json' {
|
||||
const value: any;
|
||||
export default value;
|
||||
}
|
Loading…
Reference in New Issue
Block a user