Search in sources :

Example 1 with MethodInfo

use of io.scalecube.services.methods.MethodInfo in project scalecube by scalecube.

the class ServiceCall method api.

/**
 * Create proxy creates a java generic proxy instance by a given service interface.
 *
 * @param serviceInterface Service Interface type.
 * @return newly created service proxy object.
 */
@SuppressWarnings("unchecked")
public <T> T api(Class<T> serviceInterface) {
    final ServiceCall serviceCall = this;
    final Map<Method, MethodInfo> genericReturnTypes = Reflect.methodsInfo(serviceInterface);
    // noinspection unchecked,Convert2Lambda
    return (T) Proxy.newProxyInstance(getClass().getClassLoader(), new Class[] { serviceInterface }, new InvocationHandler() {

        @Override
        public Object invoke(Object proxy, Method method, Object[] params) {
            Optional<Object> check = toStringOrEqualsOrHashCode(method.getName(), serviceInterface, params);
            if (check.isPresent()) {
                // toString, hashCode was invoked.
                return check.get();
            }
            final MethodInfo methodInfo = genericReturnTypes.get(method);
            final Type returnType = methodInfo.parameterizedReturnType();
            final boolean isServiceMessage = methodInfo.isReturnTypeServiceMessage();
            Object request = methodInfo.requestType() == Void.TYPE ? null : params[0];
            switch(methodInfo.communicationMode()) {
                case FIRE_AND_FORGET:
                    return serviceCall.oneWay(toServiceMessage(methodInfo, request));
                case REQUEST_RESPONSE:
                    return serviceCall.requestOne(toServiceMessage(methodInfo, request), returnType).transform(asMono(isServiceMessage));
                case REQUEST_STREAM:
                    return serviceCall.requestMany(toServiceMessage(methodInfo, request), returnType).transform(asFlux(isServiceMessage));
                case REQUEST_CHANNEL:
                    // noinspection rawtypes
                    return serviceCall.requestBidirectional(Flux.from((Publisher) request).map(data -> toServiceMessage(methodInfo, data)), returnType).transform(asFlux(isServiceMessage));
                default:
                    throw new IllegalArgumentException("Communication mode is not supported: " + method);
            }
        }
    });
}
Also used : Method(java.lang.reflect.Method) Publisher(org.reactivestreams.Publisher) InvocationHandler(java.lang.reflect.InvocationHandler) Type(java.lang.reflect.Type) MethodInfo(io.scalecube.services.methods.MethodInfo)

Aggregations

MethodInfo (io.scalecube.services.methods.MethodInfo)1 InvocationHandler (java.lang.reflect.InvocationHandler)1 Method (java.lang.reflect.Method)1 Type (java.lang.reflect.Type)1 Publisher (org.reactivestreams.Publisher)1