Proxy MD-SAL interfaces in DOMMountPointServiceImpl
[controller.git] / opendaylight / md-sal / sal-dom-broker / src / main / java / org / opendaylight / controller / md / sal / dom / broker / impl / DOMRpcRouter.java
index 3d57aac6010702caea06ed5525604a6c4c135ec6..b6604232231a9a53d15c343830e40c2a72244961 100644 (file)
@@ -10,59 +10,32 @@ package org.opendaylight.controller.md.sal.dom.broker.impl;
 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 =
@@ -71,17 +44,24 @@ public final class DOMRpcRouter implements AutoCloseable, DOMRpcService, DOMRpcP
     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
@@ -90,20 +70,19 @@ public final class DOMRpcRouter implements AutoCloseable, DOMRpcService, DOMRpcP
         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();
@@ -114,8 +93,7 @@ public final class DOMRpcRouter implements AutoCloseable, DOMRpcService, DOMRpcP
 
         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
@@ -126,48 +104,20 @@ public final class DOMRpcRouter implements AutoCloseable, DOMRpcService, DOMRpcP
         };
     }
 
-    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
@@ -175,7 +125,7 @@ public final class DOMRpcRouter implements AutoCloseable, DOMRpcService, DOMRpcP
                     // 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;
                 }
             });
 
@@ -194,8 +144,8 @@ public final class DOMRpcRouter implements AutoCloseable, DOMRpcService, DOMRpcP
     @Override
     @VisibleForTesting
     public void onGlobalContextUpdated(final SchemaContext context) {
-        if (delegateRpcService instanceof SchemaContextListener) {
-            ((SchemaContextListener)delegateRpcService).onGlobalContextUpdated(context);
+        if (delegateSchemaContextListener != null) {
+            delegateSchemaContextListener.onGlobalContextUpdated(context);
         }
     }
 }