import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.CheckedFuture;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.MoreExecutors;
-import java.util.Collection;
+import com.google.common.util.concurrent.FluentFuture;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
-import java.util.stream.Collectors;
import org.opendaylight.controller.md.sal.dom.api.DOMRpcAvailabilityListener;
import org.opendaylight.controller.md.sal.dom.api.DOMRpcException;
import org.opendaylight.controller.md.sal.dom.api.DOMRpcIdentifier;
import org.opendaylight.controller.md.sal.dom.api.DOMRpcImplementation;
-import org.opendaylight.controller.md.sal.dom.api.DOMRpcImplementationNotAvailableException;
import org.opendaylight.controller.md.sal.dom.api.DOMRpcImplementationRegistration;
import org.opendaylight.controller.md.sal.dom.api.DOMRpcProviderService;
import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult;
import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
-import org.opendaylight.controller.md.sal.dom.api.DefaultDOMRpcException;
import org.opendaylight.controller.md.sal.dom.spi.AbstractDOMRpcImplementationRegistration;
-import org.opendaylight.controller.md.sal.dom.spi.DefaultDOMRpcResult;
-import org.opendaylight.mdsal.common.api.MappingCheckedFuture;
+import org.opendaylight.controller.sal.core.compat.DOMRpcServiceAdapter;
+import org.opendaylight.controller.sal.core.compat.LegacyDOMRpcResultFutureAdapter;
+import org.opendaylight.controller.sal.core.compat.MdsalDOMRpcResultFutureAdapter;
+import org.opendaylight.controller.sal.core.compat.RpcAvailabilityListenerAdapter;
import org.opendaylight.yangtools.concepts.AbstractListenerRegistration;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.util.concurrent.ExceptionMapper;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
public final class DOMRpcRouter implements AutoCloseable, DOMRpcService, DOMRpcProviderService, SchemaContextListener {
- private static final ExceptionMapper<org.opendaylight.mdsal.dom.api.DOMRpcException> MDSAL_DOM_RPC_EX_MAPPER =
- new ExceptionMapper<org.opendaylight.mdsal.dom.api.DOMRpcException>(
- "rpc", org.opendaylight.mdsal.dom.api.DOMRpcException.class) {
- @Override
- protected org.opendaylight.mdsal.dom.api.DOMRpcException newWithCause(String message, Throwable cause) {
- return cause instanceof org.opendaylight.mdsal.dom.api.DOMRpcException
- ? (org.opendaylight.mdsal.dom.api.DOMRpcException)cause
- : new org.opendaylight.mdsal.dom.api.DefaultDOMRpcException("RPC failed", cause);
- }
- };
-
- private static final ExceptionMapper<DOMRpcException> LEGACY_DOM_RPC_EX_MAPPER =
- new ExceptionMapper<DOMRpcException>("rpc", DOMRpcException.class) {
- @Override
- protected DOMRpcException newWithCause(String message, Throwable cause) {
- return cause instanceof DOMRpcException ? (DOMRpcException)cause
- : cause instanceof org.opendaylight.mdsal.dom.api.DOMRpcImplementationNotAvailableException
- ? new DOMRpcImplementationNotAvailableException(cause.getMessage(), cause.getCause())
- : new DefaultDOMRpcException("RPC failed", cause);
- }
- };
-
// This mapping is used to translate mdsal DOMRpcImplementations to their corresponding legacy
// DOMRpcImplementations registered thru this interface when invoking a DOMRpcAvailabilityListener.
private final Map<org.opendaylight.mdsal.dom.api.DOMRpcImplementation, DOMRpcImplementation> implMapping =
private final org.opendaylight.mdsal.dom.api.DOMRpcService delegateRpcService;
private final org.opendaylight.mdsal.dom.api.DOMRpcProviderService delegateRpcProviderService;
+ // Note - this is only used for backward compatibility for UTs that use the empty constructor which creates
+ // a local mdsal DOMRpcRouter that needs to be updated with the SchemaContext. In production, the mdsal API
+ // services are passed via the constructor and are set up externally with the SchemaContext.
+ private final SchemaContextListener delegateSchemaContextListener;
+
@VisibleForTesting
public DOMRpcRouter() {
org.opendaylight.mdsal.dom.broker.DOMRpcRouter delegate = new org.opendaylight.mdsal.dom.broker.DOMRpcRouter();
- this.delegateRpcService = delegate;
- this.delegateRpcProviderService = delegate;
+ this.delegateRpcService = delegate.getRpcService();
+ this.delegateRpcProviderService = delegate.getRpcProviderService();
+ this.delegateSchemaContextListener = delegate;
}
public DOMRpcRouter(final org.opendaylight.mdsal.dom.api.DOMRpcService delegateRpcService,
final org.opendaylight.mdsal.dom.api.DOMRpcProviderService delegateRpcProviderService) {
this.delegateRpcService = delegateRpcService;
this.delegateRpcProviderService = delegateRpcProviderService;
+ this.delegateSchemaContextListener = null;
}
@Override
return registerRpcImplementation(implementation, ImmutableSet.copyOf(rpcs));
}
- @SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public synchronized <T extends DOMRpcImplementation> DOMRpcImplementationRegistration<T> registerRpcImplementation(
final T implementation, final Set<DOMRpcIdentifier> rpcs) {
org.opendaylight.mdsal.dom.api.DOMRpcImplementation delegateImpl =
new org.opendaylight.mdsal.dom.api.DOMRpcImplementation() {
@Override
- public CheckedFuture<org.opendaylight.mdsal.dom.api.DOMRpcResult,
- org.opendaylight.mdsal.dom.api.DOMRpcException> invokeRpc(
- org.opendaylight.mdsal.dom.api.DOMRpcIdentifier rpc, NormalizedNode<?, ?> input) {
- final ListenableFuture future = implementation.invokeRpc(convert(rpc), input);
- return MappingCheckedFuture.create(future, MDSAL_DOM_RPC_EX_MAPPER);
+ public FluentFuture<org.opendaylight.mdsal.dom.api.DOMRpcResult> invokeRpc(
+ final org.opendaylight.mdsal.dom.api.DOMRpcIdentifier rpc, final NormalizedNode<?, ?> input) {
+ return new MdsalDOMRpcResultFutureAdapter(implementation.invokeRpc(DOMRpcIdentifier.fromMdsal(rpc),
+ input));
}
+
@Override
public long invocationCost() {
return implementation.invocationCost();
final org.opendaylight.mdsal.dom.api.DOMRpcImplementationRegistration
<org.opendaylight.mdsal.dom.api.DOMRpcImplementation> reg = delegateRpcProviderService
- .registerRpcImplementation(delegateImpl,
- rpcs.stream().map(DOMRpcRouter::convert).collect(Collectors.toSet()));
+ .registerRpcImplementation(delegateImpl, DOMRpcServiceAdapter.convert(rpcs));
return new AbstractDOMRpcImplementationRegistration<T>(implementation) {
@Override
};
}
- private static org.opendaylight.mdsal.dom.api.DOMRpcIdentifier convert(DOMRpcIdentifier from) {
- return org.opendaylight.mdsal.dom.api.DOMRpcIdentifier.create(from.getType(), from.getContextReference());
- }
-
- private static DOMRpcIdentifier convert(org.opendaylight.mdsal.dom.api.DOMRpcIdentifier from) {
- return DOMRpcIdentifier.create(from.getType(), from.getContextReference());
- }
-
- private static ListenableFuture<DOMRpcResult> convert(org.opendaylight.mdsal.dom.api.DOMRpcResult from) {
- return from == null ? Futures.immediateFuture(null)
- : from instanceof DOMRpcResult ? Futures.immediateFuture((DOMRpcResult)from)
- : Futures.immediateFuture(new DefaultDOMRpcResult(from.getResult(), from.getErrors()));
- }
-
- private static Collection<DOMRpcIdentifier> convert(
- Collection<org.opendaylight.mdsal.dom.api.DOMRpcIdentifier> from) {
- return from.stream().map(DOMRpcRouter::convert).collect(Collectors.toList());
- }
-
@Override
public CheckedFuture<DOMRpcResult, DOMRpcException> invokeRpc(final SchemaPath type,
final NormalizedNode<?, ?> input) {
- final ListenableFuture<DOMRpcResult> future = Futures.transformAsync(delegateRpcService.invokeRpc(type, input),
- DOMRpcRouter::convert, MoreExecutors.directExecutor());
- return MappingCheckedFuture.create(future, LEGACY_DOM_RPC_EX_MAPPER);
+ final FluentFuture<org.opendaylight.mdsal.dom.api.DOMRpcResult> future =
+ delegateRpcService.invokeRpc(type, input);
+ return future instanceof MdsalDOMRpcResultFutureAdapter ? ((MdsalDOMRpcResultFutureAdapter)future).delegate()
+ : new LegacyDOMRpcResultFutureAdapter(future);
}
@Override
public synchronized <T extends DOMRpcAvailabilityListener> ListenerRegistration<T> registerRpcListener(
final T listener) {
final ListenerRegistration<org.opendaylight.mdsal.dom.api.DOMRpcAvailabilityListener> reg =
- delegateRpcService.registerRpcListener(new org.opendaylight.mdsal.dom.api.DOMRpcAvailabilityListener() {
- @Override
- public void onRpcAvailable(Collection<org.opendaylight.mdsal.dom.api.DOMRpcIdentifier> rpcs) {
- listener.onRpcAvailable(convert(rpcs));
- }
-
- @Override
- public void onRpcUnavailable(Collection<org.opendaylight.mdsal.dom.api.DOMRpcIdentifier> rpcs) {
- listener.onRpcUnavailable(convert(rpcs));
- }
-
+ delegateRpcService.registerRpcListener(new RpcAvailabilityListenerAdapter<T>(listener) {
@Override
public boolean acceptsImplementation(final org.opendaylight.mdsal.dom.api.DOMRpcImplementation impl) {
// If the DOMRpcImplementation wasn't registered thru this interface then the mapping won't be
// behavior. This should be fine since a legacy listener would not be aware of implementation types
// registered via the new mdsal API.
final DOMRpcImplementation legacyImpl = implMapping.get(impl);
- return legacyImpl != null ? listener.acceptsImplementation(legacyImpl) : true;
+ return legacyImpl != null ? delegate().acceptsImplementation(legacyImpl) : true;
}
});
@Override
@VisibleForTesting
public void onGlobalContextUpdated(final SchemaContext context) {
- if (delegateRpcService instanceof SchemaContextListener) {
- ((SchemaContextListener)delegateRpcService).onGlobalContextUpdated(context);
+ if (delegateSchemaContextListener != null) {
+ delegateSchemaContextListener.onGlobalContextUpdated(context);
}
}
}