public OverloadedMethod add(MethodAccess methodAccess) { if (lock) { Exceptions.die(); } methodAccessList.add(methodAccess); if (!methodAccess.method().isVarArgs()) { List<MethodAccess> methodAccesses = methodAccessListByArgNumber.get(methodAccess.parameterTypes().length); if (methodAccesses == null) { methodAccesses = new ArrayList<>(); methodAccessListByArgNumber.set(methodAccess.parameterTypes().length, methodAccesses); } methodAccesses.add(methodAccess); } else { List<MethodAccess> methodAccesses = methodAccessListByArgNumberWithVarArg.get(methodAccess.parameterTypes().length); if (methodAccesses == null) { methodAccesses = new ArrayList<>(); methodAccessListByArgNumberWithVarArg.set( methodAccess.parameterTypes().length, methodAccesses); } methodAccesses.add(methodAccess); } return this; }
private void invokeEventMethod(Event<Object> event, MethodAccess methodAccess, Object listener) { if (event.body() instanceof Object[]) { methodAccess.invokeDynamic(listener, (Object[]) event.body()); } else if (event.body() instanceof List) { final List body = (List) event.body(); methodAccess.invokeDynamic(listener, body.toArray(new Object[body.size()])); } else { methodAccess.invokeDynamic(listener, event.body()); } }
@SuppressWarnings("Convert2Lambda") private void extractListenerForRegularObject( final Object listener, final MethodAccess methodAccess, final String channel, final boolean consume) { logger.info( "EventManager {}:: {} is listening with method {} on channel {} and is consuming? {}", name, listener.getClass().getSimpleName(), methodAccess.name(), channel, consume); if (consume) { /* Do not use Lambda, this has to be a consume! */ this.register( channel, new EventConsumer<Object>() { @Override public void listen(Event<Object> event) { invokeEventMethod(event, methodAccess, listener); } }); } else { /* Do not use Lambda, this has to be a subscriber! */ this.register( channel, new EventSubscriber<Object>() { @Override public void listen(Event<Object> event) { invokeEventMethod(event, methodAccess, listener); } }); } }
private void extractEventListenerFromMethod( final Object listener, final MethodAccess methodAccess, final AnnotationData listen, final ServiceQueue serviceQueue) { logger.info( "EventManager {} ::extractEventListenerFromMethod :: " + "{} is listening with method {} using annotation data {} ", name, serviceQueue, methodAccess.name(), listen.getValues()); final String channel = listen.getValues().get("value").toString(); final boolean consume = (boolean) listen.getValues().get("consume"); if (serviceQueue == null) { extractListenerForRegularObject(listener, methodAccess, channel, consume); } else { extractListenerForService(serviceQueue, channel, consume); } }
@Override public Object invokeDynamic(Object object, Object... args) { final int length = args.length; final List<MethodAccess> methodAccesses = this.methodAccessListByArgNumber.get(length); int maxScore = Integer.MIN_VALUE; MethodAccess methodAccess = null; for (MethodAccess m : methodAccesses) { int score = 1; final List<TypeType> paramTypeEnumList = m.paramTypeEnumList(); if (object == null && !m.isStatic()) { continue; } loop: for (int argIndex = 0; argIndex < args.length; argIndex++) { TypeType type = paramTypeEnumList.get(argIndex); Object arg = args[argIndex]; final TypeType instanceType = TypeType.getInstanceType(arg); if (instanceType == type) { score += 2_000; continue; } switch (type) { case BYTE_WRAPPER: case BYTE: score = handleByteArg(score, arg, instanceType); break; case SHORT_WRAPPER: case SHORT: score = handleShortArg(score, arg, instanceType); break; case INTEGER_WRAPPER: case INT: score = handleIntArg(score, arg, instanceType); break; case NULL: score--; break; case LONG_WRAPPER: case LONG: score = handleLongArg(score, arg, instanceType); break; case FLOAT_WRAPPER: case FLOAT: score = handleFloatArg(score, arg, instanceType); break; case DOUBLE_WRAPPER: case DOUBLE: score = handleDoubleArg(score, arg, instanceType); break; case CHAR_WRAPPER: case CHAR: if (instanceType == TypeType.CHAR || instanceType == TypeType.CHAR_WRAPPER) { score += 1000; } break; case STRING: if (instanceType == TypeType.STRING) { score += 1_000; } else if (instanceType == TypeType.CHAR_SEQUENCE || arg instanceof CharSequence) { score += 500; } break; case INSTANCE: if (instanceType == TypeType.INSTANCE) { if (m.parameterTypes()[argIndex].isInstance(arg)) { score += 1000; } } else if (instanceType == TypeType.MAP) { score += 1_000; } else if (instanceType == TypeType.LIST) { score += 500; } break; default: if (instanceType == type) { score += 1000; } else { if (m.parameterTypes()[argIndex].isInstance(arg)) { score += 1000; } } } } if (score > maxScore) { maxScore = score; methodAccess = m; } } if (methodAccess != null) { return methodAccess.invokeDynamic(object, args); } else { /* Place holder for now. */ List<MethodAccess> varargMethods = this.methodAccessListByArgNumberWithVarArg.get(0); if (varargMethods != null) { varargMethods.get(0).invokeDynamic(args); } } return null; }
private void doListen(final Object listener, final ServiceQueue serviceQueue) { if (debug) { logger.debug( "EventManager {} registering listener {} with serviceQueue {}", name, listener, serviceQueue); } final ClassMeta<?> listenerClassMeta = ClassMeta.classMeta(listener.getClass()); final Iterable<MethodAccess> listenerMethods = listenerClassMeta.methods(); /* Add methods as listeners if they have a listen annotation. */ for (final MethodAccess methodAccess : listenerMethods) { AnnotationData listenAnnotationData = getListenAnnotation(methodAccess); if (listenAnnotationData == null) continue; extractEventListenerFromMethod(listener, methodAccess, listenAnnotationData, serviceQueue); } /* Look for listener channel implementations. */ final Class<?>[] interfacesFromListener = listenerClassMeta.cls().getInterfaces(); /* Iterate through interfaces and see if any are marked with the event channel annotation. */ for (Class<?> interfaceClass : interfacesFromListener) { final ClassMeta<?> metaFromListenerInterface = classMeta(interfaceClass); final AnnotationData eventChannelAnnotation = metaFromListenerInterface.annotation(AnnotationUtils.EVENT_CHANNEL_ANNOTATION_NAME); if (eventChannelAnnotation == null) { continue; } /* If we got this far, then we are dealing with an event channel interface so register the methods from this interface as channel listeners. */ final Iterable<MethodAccess> interfaceMethods = metaFromListenerInterface.methods(); final String classEventBusName = getClassEventChannelName(metaFromListenerInterface, eventChannelAnnotation); for (MethodAccess methodAccess : interfaceMethods) { /* By default the method name forms part of the event bus name, but this can be overridden by the EVENT_CHANNEL_ANNOTATION_NAME annotation on the method. */ final AnnotationData methodAnnotation = methodAccess.annotation(AnnotationUtils.EVENT_CHANNEL_ANNOTATION_NAME); String methodEventBusName = methodAnnotation != null && methodAnnotation.getValues().get("value") != null ? methodAnnotation.getValues().get("value").toString() : null; if (Str.isEmpty(methodEventBusName)) { methodEventBusName = methodAccess.name(); } final String channelName = createChannelName(null, classEventBusName, methodEventBusName); if (serviceQueue == null) { extractListenerForRegularObject(listener, methodAccess, channelName, false); } else { extractListenerForService(serviceQueue, channelName, false); } } } }
public Response<Object> mapArgsAsyncHandlersAndInvoke( MethodCall<Object> serviceMethodCall, MethodAccess serviceMethod) { if (serviceMethod.parameterTypes().length == 0 && !(serviceMethod.returnType() == Promise.class)) { Object returnValue = serviceMethod.invokeDynamicObject(boonServiceMethodCallHandler.service, null); return boonServiceMethodCallHandler.response(serviceMethod, serviceMethodCall, returnValue); } boolean hasHandlers = boonServiceMethodCallHandler.hasHandlers(serviceMethodCall, serviceMethod); Object returnValue; if (hasHandlers) { Object body = serviceMethodCall.body(); List<Object> argsList = boonServiceMethodCallHandler.prepareArgumentList( serviceMethodCall, serviceMethod.parameterTypes()); if (body instanceof List || body instanceof Object[]) { boonServiceMethodCallHandler.extractHandlersFromArgumentList( serviceMethodCall.callback(), serviceMethod, body, argsList); } else { if (argsList.size() == 1 && !(argsList.get(0) instanceof Callback)) { argsList.set(0, body); } } returnValue = serviceMethod.invokeDynamicObject(boonServiceMethodCallHandler.service, argsList); if (returnValue instanceof Promise) { final Promise<Object> promise = ((Promise<Object>) returnValue); promise .then( value -> { boonServiceMethodCallHandler.responseSendQueue.send( ResponseImpl.response(serviceMethodCall, value)); }) .catchError( error -> { boonServiceMethodCallHandler.responseSendQueue.send( ResponseImpl.error(serviceMethodCall, error)); }) .invoke(); return ServiceConstants.VOID; } } else { if (serviceMethodCall.body() instanceof List) { final List argsList = (List) serviceMethodCall.body(); returnValue = serviceMethod.invokeDynamic( boonServiceMethodCallHandler.service, argsList.toArray(new Object[argsList.size()])); } else if (serviceMethodCall.body() instanceof Object[]) { final Object[] argsList = (Object[]) serviceMethodCall.body(); returnValue = serviceMethod.invokeDynamic(boonServiceMethodCallHandler.service, argsList); } else { returnValue = serviceMethod.invokeDynamic( boonServiceMethodCallHandler.service, serviceMethodCall.body()); } } return boonServiceMethodCallHandler.response(serviceMethod, serviceMethodCall, returnValue); }