/* * Copyright 2014 Avanza Bank AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.avanza.astrix.remoting.client; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; import rx.Observable; import rx.functions.Func1; import com.avanza.astrix.core.AstrixRemoteResult; import com.avanza.astrix.core.RemoteResultReducer; import com.avanza.astrix.core.util.ReflectionUtil; /** * * @author Elias Lindholm (elilin) * */ public class BroadcastedRemoteServiceMethod implements RemoteServiceMethod { private final String signature; private final Class<? extends RemoteResultReducer> reducer; private final RemotingEngine remotingEngine; private final Type returnType; public BroadcastedRemoteServiceMethod(String signature, Class<? extends RemoteResultReducer> reducer, RemotingEngine remotingEngine, Type returnType) { this.signature = signature; this.reducer = reducer; this.remotingEngine = remotingEngine; this.returnType = returnType; } public String getSignature() { return signature; } private RemoteResultReducer<?> newReducer() { return ReflectionUtil.newInstance(this.reducer); } @Override public Observable<?> invoke(AstrixServiceInvocationRequest invocationRequest, Object[] args) throws Exception { return submitBroadcastRequest(invocationRequest, args); } private <T> Observable<T> submitBroadcastRequest( AstrixServiceInvocationRequest request, Object[] args) throws InstantiationException, IllegalAccessException { request.setArguments(remotingEngine.marshall(args)); final RemoteResultReducer<T> reducer = (RemoteResultReducer<T>) newReducer(); Observable<List<AstrixServiceInvocationResponse>> responesObservable = remotingEngine.submitBroadcastRequest(request); if (returnType.equals(Void.TYPE) || returnType.equals(Void.class)) { return responesObservable.map(responses -> { readResponses(responses); return null; }); } return responesObservable.map(responses -> { List<AstrixRemoteResult<T>> unmarshalledResponses = new ArrayList<>(); for (AstrixServiceInvocationResponse response : responses) { AstrixRemoteResult<T> result = remotingEngine.toRemoteResult(response, returnType); unmarshalledResponses.add(result); } return reducer.reduce(unmarshalledResponses); }); } private void readResponses(List<AstrixServiceInvocationResponse> responses) { responses.forEach(res -> remotingEngine.toRemoteResult(res, returnType).getResult()); } }