164 lines
4.6 KiB
TypeScript
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;
|
|
});
|
|
});
|
|
}
|
|
|
|
}
|