app/src/commons/service/probe.service.ts
crusader 7765d1ce77 ing
2018-09-06 12:34:22 +09:00

164 lines
4.6 KiB
TypeScript

import { Injectable } from '@angular/core';
import {
Client,
ClientNotificationCodec,
WebSocketClientRWC,
WebSocketClientRWCConfig,
JSONClientCodec
} from '@overflow/rpc-js';
import { Subscription } from 'rxjs';
import { TypeUtil, Class, Annotation, PropertyKeyType, Method, ReflectionUtil, Decorator } from '@overflow/core-js';
import { RPCSubscriberDecoratorAttribute, RPCSubscriberDecorator } from '@overflow/commons/ui/decorator/RPCSubscriber';
export const requesterID = 'scannerUser';
export interface SubscriberMethod {
className: PropertyKeyType;
methodName: PropertyKeyType;
parameterTypes: string[];
method: Method;
instance: any;
}
export class SubscriberParameterError extends Error {
public constructor(message?: string) {
super(message);
Object.setPrototypeOf(this, new.target.prototype);
}
}
export class SubscriberExistError extends Error {
public constructor(message?: string) {
super(message);
Object.setPrototypeOf(this, new.target.prototype);
}
}
const config: WebSocketClientRWCConfig = {
url: 'ws://localhost:60000/scanner?requesterID=' + requesterID
};
const rwc = new WebSocketClientRWC(config);
const codec = new JSONClientCodec();
@Injectable({
providedIn: 'root'
})
export class ProbeService extends Client {
private notiSubscription: Subscription;
private subscriberMap: Map<any, string[]>;
private subscriberMethodMap: Map<string, SubscriberMethod[]>;
public constructor() {
super(codec, rwc);
this.subscriberMap = new Map();
this.subscriberMethodMap = new Map();
this.connect();
this.notiSubscription = this.notification()
.subscribe((notiCodec: ClientNotificationCodec) => {
const method = notiCodec.method();
const params = notiCodec.params();
const subscriberMethods: SubscriberMethod[] = this.subscriberMethodMap.get(method);
if (undefined === subscriberMethods) {
console.warn(`Subscriber for method[${method}] is not exist`);
return;
}
subscriberMethods.forEach((subscriberMethod) => {
try {
const args = this.converNotificationParams(params, subscriberMethod.parameterTypes);
subscriberMethod.method.invoke(subscriberMethod.instance, ...args);
} catch (error) {
console.error(error);
}
});
});
this.connectionStatus().subscribe(isConnected => {
if (!isConnected) {
console.log('disconnected');
} else {
console.log('connected');
}
});
}
/**
* subscribeNotification
*/
public subscribeNotification(subscriber: any) {
if (this.subscriberMap.has(subscriber)) {
throw new SubscriberExistError();
}
const type = TypeUtil.getType(subscriber);
const clazz = Class.forType(type);
if (undefined === clazz) {
console.log(`Type[${subscriber.name}] is not decorated type`);
return;
}
const subscriberMethodNames: string[] = [];
this.subscriberMap.set(subscriber, subscriberMethodNames);
const methods = clazz.getMethods();
methods.forEach((method, propertyKey) => {
const annon = method.getAnnotation(RPCSubscriberDecorator);
if (undefined === annon) {
return;
}
const subscriberMethodName = annon.attribute.method;
subscriberMethodNames.push(subscriberMethodName);
let subscriberMethods: SubscriberMethod[] = this.subscriberMethodMap.get(subscriberMethodName);
if (undefined === subscriberMethods) {
subscriberMethods = [];
this.subscriberMethodMap.set(subscriberMethodName, subscriberMethods);
}
const paramTypes = ReflectionUtil.getParamTypeStrings(method);
const subscriberMethod: SubscriberMethod = {
className: clazz.getName(),
methodName: method.getName(),
parameterTypes: paramTypes,
method: method,
instance: subscriber,
};
subscriberMethods.push(subscriberMethod);
});
}
/**
* subscribeNotification
*/
public unsubscribeNotification(subscriber: any) {
if (!this.subscriberMap.has(subscriber)) {
return;
}
const subscriberMethodNames = this.subscriberMap.get(subscriber);
this.subscriberMap.delete(subscriber);
subscriberMethodNames.forEach(methodName => {
if (!this.subscriberMethodMap.has(methodName)) {
return;
}
const subscriberMethods = this.subscriberMethodMap.get(methodName);
subscriberMethods.some((subscriberMethod, index): boolean => {
if (subscriberMethod.instance === subscriber) {
delete subscriberMethods[index];
}
return false;
});
});
}
}