Merge "Cosmetics: check in pom.xml files as _sort_pom_ wants them to be"
[controller.git] / opendaylight / md-sal / sal-binding-broker / src / main / java / org / opendaylight / controller / sal / binding / impl / connect / dom / BindingIndependentConnector.java
index aaed12f740ea7224c540fdc936f544308ccb1a3e..5bbebe6f1b00544021bb64d5cdf0ea4bf77c82a5 100644 (file)
@@ -17,6 +17,7 @@ import java.lang.reflect.Proxy;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
@@ -27,23 +28,25 @@ import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 
+import org.opendaylight.controller.md.sal.binding.impl.AbstractForwardedDataBroker;
 import org.opendaylight.controller.md.sal.common.api.RegistrationListener;
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandlerRegistration;
 import org.opendaylight.controller.md.sal.common.api.data.DataModification;
-import org.opendaylight.controller.md.sal.common.api.data.DataReader;
 import org.opendaylight.controller.md.sal.common.api.routing.RouteChange;
 import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
 import org.opendaylight.controller.md.sal.common.api.routing.RouteChangePublisher;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService.NotificationInterestListener;
 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
 import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider;
 import org.opendaylight.controller.sal.binding.api.rpc.RpcContextIdentifier;
 import org.opendaylight.controller.sal.binding.api.rpc.RpcRouter;
-import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
-import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
+import org.opendaylight.controller.sal.binding.impl.DataBrokerImpl;
+import org.opendaylight.controller.sal.binding.impl.MountPointManagerImpl.BindingMountPointImpl;
 import org.opendaylight.controller.sal.binding.impl.RpcProviderRegistryImpl;
 import org.opendaylight.controller.sal.binding.impl.RpcProviderRegistryImpl.GlobalRpcRegistrationListener;
 import org.opendaylight.controller.sal.binding.impl.RpcProviderRegistryImpl.RouterInstantiationListener;
@@ -55,9 +58,10 @@ import org.opendaylight.controller.sal.core.api.Provider;
 import org.opendaylight.controller.sal.core.api.RpcImplementation;
 import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
 import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.core.api.notify.NotificationListener;
+import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.concepts.Registration;
-import org.opendaylight.yangtools.concepts.util.ClassLoaderUtils;
 import org.opendaylight.yangtools.yang.binding.Augmentable;
 import org.opendaylight.yangtools.yang.binding.Augmentation;
 import org.opendaylight.yangtools.yang.binding.BaseIdentity;
@@ -65,54 +69,50 @@ import org.opendaylight.yangtools.yang.binding.BindingMapping;
 import org.opendaylight.yangtools.yang.binding.DataContainer;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.Notification;
 import org.opendaylight.yangtools.yang.binding.RpcService;
 import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.binding.util.ClassLoaderUtils;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
+import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Function;
 import com.google.common.base.Optional;
 import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.ImmutableSet.Builder;
 import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
 
 public class BindingIndependentConnector implements //
         RuntimeDataProvider, //
         Provider, //
         AutoCloseable {
 
-
-
     private final Logger LOG = LoggerFactory.getLogger(BindingIndependentConnector.class);
 
-    @SuppressWarnings( "deprecation")
-    private static final InstanceIdentifier<? extends DataObject> ROOT = InstanceIdentifier.builder().toInstance();
-
     private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier ROOT_BI = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
             .builder().toInstance();
 
     private final static Method EQUALS_METHOD;
 
-
     private BindingIndependentMappingService mappingService;
 
     private org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService;
 
     private DataProviderService baDataService;
 
-    private ConcurrentMap<Object, BindingToDomTransaction> domOpenedTransactions = new ConcurrentHashMap<>();
-    private ConcurrentMap<Object, DomToBindingTransaction> bindingOpenedTransactions = new ConcurrentHashMap<>();
+    private final ConcurrentMap<Object, BindingToDomTransaction> domOpenedTransactions = new ConcurrentHashMap<>();
+    private final ConcurrentMap<Object, DomToBindingTransaction> bindingOpenedTransactions = new ConcurrentHashMap<>();
 
-    private BindingToDomCommitHandler bindingToDomCommitHandler = new BindingToDomCommitHandler();
-    private DomToBindingCommitHandler domToBindingCommitHandler = new DomToBindingCommitHandler();
+    private final BindingToDomCommitHandler bindingToDomCommitHandler = new BindingToDomCommitHandler();
+    private final DomToBindingCommitHandler domToBindingCommitHandler = new DomToBindingCommitHandler();
 
     private Registration<DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject>> baCommitHandlerRegistration;
 
@@ -125,17 +125,15 @@ public class BindingIndependentConnector implements //
     // private ListenerRegistration<BindingToDomRpcForwardingManager>
     // bindingToDomRpcManager;
 
-    private Function<InstanceIdentifier<?>, org.opendaylight.yangtools.yang.data.api.InstanceIdentifier> toDOMInstanceIdentifier = new Function<InstanceIdentifier<?>, org.opendaylight.yangtools.yang.data.api.InstanceIdentifier>() {
+    private final Function<InstanceIdentifier<?>, org.opendaylight.yangtools.yang.data.api.InstanceIdentifier> toDOMInstanceIdentifier = new Function<InstanceIdentifier<?>, org.opendaylight.yangtools.yang.data.api.InstanceIdentifier>() {
 
         @Override
-        public org.opendaylight.yangtools.yang.data.api.InstanceIdentifier apply(InstanceIdentifier<?> input) {
+        public org.opendaylight.yangtools.yang.data.api.InstanceIdentifier apply(final InstanceIdentifier<?> input) {
             return mappingService.toDataDom(input);
         }
 
     };
 
-    private Registration<DataReader<InstanceIdentifier<? extends DataObject>, DataObject>> baDataReaderRegistration;
-
     private boolean rpcForwarding = false;
 
     private boolean dataForwarding = false;
@@ -144,19 +142,20 @@ public class BindingIndependentConnector implements //
 
     private RpcProviderRegistryImpl baRpcRegistryImpl;
 
-    private org.opendaylight.controller.sal.dom.broker.spi.RpcRouter biRouter;
+    private NotificationProviderService baNotifyService;
 
+    private NotificationPublishService domNotificationService;
 
     static {
         try {
-        EQUALS_METHOD = Object.class.getMethod("equals", Object.class);
+            EQUALS_METHOD = Object.class.getMethod("equals", Object.class);
         } catch (Exception e) {
             throw new RuntimeException(e);
         }
     }
 
     @Override
-    public DataObject readOperationalData(InstanceIdentifier<? extends DataObject> path) {
+    public DataObject readOperationalData(final InstanceIdentifier<? extends DataObject> path) {
         try {
             org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath = mappingService.toDataDom(path);
             CompositeNode result = biDataService.readOperationalData(biPath);
@@ -167,7 +166,7 @@ public class BindingIndependentConnector implements //
     }
 
     private DataObject potentialAugmentationRead(InstanceIdentifier<? extends DataObject> path,
-            org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath, CompositeNode result)
+            final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath, final CompositeNode result)
             throws DeserializationException {
         Class<? extends DataObject> targetType = path.getTargetType();
         if (Augmentation.class.isAssignableFrom(targetType)) {
@@ -182,7 +181,7 @@ public class BindingIndependentConnector implements //
     }
 
     @Override
-    public DataObject readConfigurationData(InstanceIdentifier<? extends DataObject> path) {
+    public DataObject readConfigurationData(final InstanceIdentifier<? extends DataObject> path) {
         try {
             org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath = mappingService.toDataDom(path);
             CompositeNode result = biDataService.readConfigurationData(biPath);
@@ -193,40 +192,59 @@ public class BindingIndependentConnector implements //
     }
 
     private DataModificationTransaction createBindingToDomTransaction(
-            DataModification<InstanceIdentifier<? extends DataObject>, DataObject> source) {
+            final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> source) {
         DataModificationTransaction target = biDataService.beginTransaction();
-        LOG.debug("Created DOM Transaction {} for {},", target.getIdentifier(),source.getIdentifier());
+        LOG.debug("Created DOM Transaction {} for {},", target.getIdentifier(), source.getIdentifier());
+        for (InstanceIdentifier<? extends DataObject> entry : source.getRemovedConfigurationData()) {
+            org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
+            target.removeConfigurationData(biEntry);
+            LOG.debug("Delete of Binding Configuration Data {} is translated to {}", entry, biEntry);
+        }
+        for (InstanceIdentifier<? extends DataObject> entry : source.getRemovedOperationalData()) {
+            org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
+            target.removeOperationalData(biEntry);
+            LOG.debug("Delete of Binding Operational Data {} is translated to {}", entry, biEntry);
+        }
         for (Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : source.getUpdatedConfigurationData()
                 .entrySet()) {
             Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> biEntry = mappingService
                     .toDataDom(entry);
             target.putConfigurationData(biEntry.getKey(), biEntry.getValue());
-            LOG.debug("Update of Binding Configuration Data {} is translated to {}",entry,biEntry);
+            LOG.debug("Update of Binding Configuration Data {} is translated to {}", entry, biEntry);
         }
         for (Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : source.getUpdatedOperationalData()
                 .entrySet()) {
             Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> biEntry = mappingService
                     .toDataDom(entry);
             target.putOperationalData(biEntry.getKey(), biEntry.getValue());
-            LOG.debug("Update of Binding Operational Data {} is translated to {}",entry,biEntry);
-        }
-        for (InstanceIdentifier<? extends DataObject> entry : source.getRemovedConfigurationData()) {
-            org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
-            target.removeConfigurationData(biEntry);
-            LOG.debug("Delete of Binding Configuration Data {} is translated to {}",entry,biEntry);
-        }
-        for (InstanceIdentifier<? extends DataObject> entry : source.getRemovedOperationalData()) {
-            org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
-            target.removeOperationalData(biEntry);
-            LOG.debug("Delete of Binding Operational Data {} is translated to {}",entry,biEntry);
+            LOG.debug("Update of Binding Operational Data {} is translated to {}", entry, biEntry);
         }
+
         return target;
     }
 
     private org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction createDomToBindingTransaction(
-            DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> source) {
+            final DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> source) {
         org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction target = baDataService
                 .beginTransaction();
+        for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry : source.getRemovedConfigurationData()) {
+            try {
+
+                InstanceIdentifier<?> baEntry = mappingService.fromDataDom(entry);
+                target.removeConfigurationData(baEntry);
+            } catch (DeserializationException e) {
+                LOG.error("Ommiting from BA transaction: {}.", entry, e);
+            }
+        }
+        for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry : source.getRemovedOperationalData()) {
+            try {
+
+                InstanceIdentifier<?> baEntry = mappingService.fromDataDom(entry);
+                target.removeOperationalData(baEntry);
+            } catch (DeserializationException e) {
+                LOG.error("Ommiting from BA transaction: {}.", entry, e);
+            }
+        }
         for (Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> entry : source
                 .getUpdatedConfigurationData().entrySet()) {
             try {
@@ -248,24 +266,6 @@ public class BindingIndependentConnector implements //
                 LOG.error("Ommiting from BA transaction: {}.", entry.getKey(), e);
             }
         }
-        for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry : source.getRemovedConfigurationData()) {
-            try {
-
-                InstanceIdentifier<?> baEntry = mappingService.fromDataDom(entry);
-                target.removeConfigurationData(baEntry);
-            } catch (DeserializationException e) {
-                LOG.error("Ommiting from BA transaction: {}.", entry, e);
-            }
-        }
-        for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry : source.getRemovedOperationalData()) {
-            try {
-
-                InstanceIdentifier<?> baEntry = mappingService.fromDataDom(entry);
-                target.removeOperationalData(baEntry);
-            } catch (DeserializationException e) {
-                LOG.error("Ommiting from BA transaction: {}.", entry, e);
-            }
-        }
         return target;
     }
 
@@ -273,7 +273,8 @@ public class BindingIndependentConnector implements //
         return biDataService;
     }
 
-    protected void setDomDataService(org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService) {
+    protected void setDomDataService(
+            final org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService) {
         this.biDataService = biDataService;
     }
 
@@ -281,7 +282,7 @@ public class BindingIndependentConnector implements //
         return baDataService;
     }
 
-    protected void setBindingDataService(DataProviderService baDataService) {
+    protected void setBindingDataService(final DataProviderService baDataService) {
         this.baDataService = baDataService;
     }
 
@@ -289,21 +290,37 @@ public class BindingIndependentConnector implements //
         return baRpcRegistry;
     }
 
-    protected void setBindingRpcRegistry(RpcProviderRegistry rpcRegistry) {
+    protected void setBindingRpcRegistry(final RpcProviderRegistry rpcRegistry) {
         this.baRpcRegistry = rpcRegistry;
     }
 
     public void startDataForwarding() {
-        checkState(!dataForwarding, "Connector is already forwarding data.");
-        baDataReaderRegistration = baDataService.registerDataReader(ROOT, this);
-        baCommitHandlerRegistration = baDataService.registerCommitHandler(ROOT, bindingToDomCommitHandler);
-        biCommitHandlerRegistration = biDataService.registerCommitHandler(ROOT_BI, domToBindingCommitHandler);
-        baDataService.registerCommitHandlerListener(domToBindingCommitHandler);
+        if (baDataService instanceof AbstractForwardedDataBroker) {
+            dataForwarding = true;
+            return;
+        }
+
+        final DataProviderService baData;
+        if (baDataService instanceof BindingMountPointImpl) {
+            baData = ((BindingMountPointImpl) baDataService).getDataBrokerImpl();
+            LOG.debug("Extracted BA Data provider {} from mount point {}", baData, baDataService);
+        } else {
+            baData = baDataService;
+        }
+
+        if (baData instanceof DataBrokerImpl) {
+            checkState(!dataForwarding, "Connector is already forwarding data.");
+            ((DataBrokerImpl) baData).setDataReadDelegate(this);
+            ((DataBrokerImpl) baData).setRootCommitHandler(bindingToDomCommitHandler);
+            biCommitHandlerRegistration = biDataService.registerCommitHandler(ROOT_BI, domToBindingCommitHandler);
+            baDataService.registerCommitHandlerListener(domToBindingCommitHandler);
+        }
+
         dataForwarding = true;
     }
 
     public void startRpcForwarding() {
-        if (baRpcRegistry != null && biRpcRegistry != null && baRpcRegistry instanceof RouteChangePublisher<?, ?>) {
+        if (biRpcRegistry != null && baRpcRegistry instanceof RouteChangePublisher<?, ?>) {
             checkState(!rpcForwarding, "Connector is already forwarding RPCs");
             domToBindingRpcManager = baRpcRegistry.registerRouteChangeListener(new DomToBindingRpcForwardingManager());
             if (baRpcRegistry instanceof RpcProviderRegistryImpl) {
@@ -311,19 +328,20 @@ public class BindingIndependentConnector implements //
                 baRpcRegistryImpl.registerRouterInstantiationListener(domToBindingRpcManager.getInstance());
                 baRpcRegistryImpl.registerGlobalRpcRegistrationListener(domToBindingRpcManager.getInstance());
             }
-            if(biRpcRegistry instanceof org.opendaylight.controller.sal.dom.broker.spi.RpcRouter) {
-                biRouter = (org.opendaylight.controller.sal.dom.broker.spi.RpcRouter) biRpcRegistry;
-            }
             rpcForwarding = true;
         }
     }
 
     public void startNotificationForwarding() {
         checkState(!notificationForwarding, "Connector is already forwarding notifications.");
-        notificationForwarding = true;
+        if (baNotifyService != null && domNotificationService != null) {
+            baNotifyService.registerInterestListener(new DomToBindingNotificationForwarder());
+
+            notificationForwarding = true;
+        }
     }
 
-    protected void setMappingService(BindingIndependentMappingService mappingService) {
+    protected void setMappingService(final BindingIndependentMappingService mappingService) {
         this.mappingService = mappingService;
     }
 
@@ -333,17 +351,17 @@ public class BindingIndependentConnector implements //
     }
 
     @Override
-    public void onSessionInitiated(ProviderSession session) {
+    public void onSessionInitiated(final ProviderSession session) {
         setDomDataService(session.getService(org.opendaylight.controller.sal.core.api.data.DataProviderService.class));
         setDomRpcRegistry(session.getService(RpcProvisionRegistry.class));
 
     }
 
-    public <T extends RpcService> void onRpcRouterCreated(Class<T> serviceType, RpcRouter<T> router) {
+    public <T extends RpcService> void onRpcRouterCreated(final Class<T> serviceType, final RpcRouter<T> router) {
 
     }
 
-    public void setDomRpcRegistry(RpcProvisionRegistry registry) {
+    public void setDomRpcRegistry(final RpcProvisionRegistry registry) {
         biRpcRegistry = registry;
     }
 
@@ -365,8 +383,8 @@ public class BindingIndependentConnector implements //
         private final DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> modification;
 
         public DomToBindingTransaction(
-                org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction backing,
-                DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> modification) {
+                final org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction backing,
+                final DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> modification) {
             super();
             this.backing = backing;
             this.modification = modification;
@@ -401,11 +419,11 @@ public class BindingIndependentConnector implements //
     private class BindingToDomTransaction implements
             DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> {
 
-        private DataModificationTransaction backing;
-        private DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification;
+        private final DataModificationTransaction backing;
+        private final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification;
 
-        public BindingToDomTransaction(DataModificationTransaction backing,
-                DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
+        public BindingToDomTransaction(final DataModificationTransaction backing,
+                final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
             this.backing = backing;
             this.modification = modification;
             domOpenedTransactions.put(backing.getIdentifier(), this);
@@ -443,7 +461,7 @@ public class BindingIndependentConnector implements //
 
         @Override
         public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> requestCommit(
-                DataModification<InstanceIdentifier<? extends DataObject>, DataObject> bindingTransaction) {
+                final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> bindingTransaction) {
 
             /**
              * Transaction was created as DOM transaction, in that case we do
@@ -455,8 +473,8 @@ public class BindingIndependentConnector implements //
             }
             DataModificationTransaction domTransaction = createBindingToDomTransaction(bindingTransaction);
             BindingToDomTransaction wrapped = new BindingToDomTransaction(domTransaction, bindingTransaction);
-            LOG.trace("Forwarding Binding Transaction: {} as DOM Transaction: {} .", bindingTransaction.getIdentifier(),
-                    domTransaction.getIdentifier());
+            LOG.trace("Forwarding Binding Transaction: {} as DOM Transaction: {} .",
+                    bindingTransaction.getIdentifier(), domTransaction.getIdentifier());
             return wrapped;
         }
     }
@@ -466,7 +484,8 @@ public class BindingIndependentConnector implements //
             DataCommitHandler<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> {
 
         @Override
-        public void onRegister(DataCommitHandlerRegistration<InstanceIdentifier<? extends DataObject>, DataObject> registration) {
+        public void onRegister(
+                final DataCommitHandlerRegistration<InstanceIdentifier<? extends DataObject>, DataObject> registration) {
 
             org.opendaylight.yangtools.yang.data.api.InstanceIdentifier domPath = mappingService.toDataDom(registration
                     .getPath());
@@ -474,13 +493,15 @@ public class BindingIndependentConnector implements //
         }
 
         @Override
-        public void onUnregister(DataCommitHandlerRegistration<InstanceIdentifier<? extends DataObject>, DataObject> registration) {
+        public void onUnregister(
+                final DataCommitHandlerRegistration<InstanceIdentifier<? extends DataObject>, DataObject> registration) {
             // NOOP for now
             // FIXME: do registration based on only active commit handlers.
         }
 
+        @Override
         public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> requestCommit(
-                DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> domTransaction) {
+                final DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> domTransaction) {
             Object identifier = domTransaction.getIdentifier();
 
             /**
@@ -507,8 +528,7 @@ public class BindingIndependentConnector implements //
      *
      */
     private class DomToBindingRpcForwardingManager implements
-            RouteChangeListener<RpcContextIdentifier, InstanceIdentifier<?>>,
-            RouterInstantiationListener,
+            RouteChangeListener<RpcContextIdentifier, InstanceIdentifier<?>>, RouterInstantiationListener,
             GlobalRpcRegistrationListener {
 
         private final Map<Class<? extends RpcService>, DomToBindingRpcForwarder> forwarders = new WeakHashMap<>();
@@ -518,34 +538,34 @@ public class BindingIndependentConnector implements //
             return registryImpl;
         }
 
-        public void setRegistryImpl(RpcProviderRegistryImpl registryImpl) {
+        public void setRegistryImpl(final RpcProviderRegistryImpl registryImpl) {
             this.registryImpl = registryImpl;
         }
 
         @Override
-        public void onGlobalRpcRegistered(Class<? extends RpcService> cls) {
+        public void onGlobalRpcRegistered(final Class<? extends RpcService> cls) {
             getRpcForwarder(cls, null);
         }
 
         @Override
-        public void onGlobalRpcUnregistered(Class<? extends RpcService> cls) {
+        public void onGlobalRpcUnregistered(final Class<? extends RpcService> cls) {
             // NOOP
         }
 
         @Override
-        public void onRpcRouterCreated(RpcRouter<?> router) {
+        public void onRpcRouterCreated(final RpcRouter<?> router) {
             Class<? extends BaseIdentity> ctx = router.getContexts().iterator().next();
             getRpcForwarder(router.getServiceType(), ctx);
         }
 
         @Override
-        public void onRouteChange(RouteChange<RpcContextIdentifier, InstanceIdentifier<?>> change) {
+        public void onRouteChange(final RouteChange<RpcContextIdentifier, InstanceIdentifier<?>> change) {
             for (Entry<RpcContextIdentifier, Set<InstanceIdentifier<?>>> entry : change.getAnnouncements().entrySet()) {
                 bindingRoutesAdded(entry);
             }
         }
 
-        private void bindingRoutesAdded(Entry<RpcContextIdentifier, Set<InstanceIdentifier<?>>> entry) {
+        private void bindingRoutesAdded(final Entry<RpcContextIdentifier, Set<InstanceIdentifier<?>>> entry) {
             Class<? extends BaseIdentity> context = entry.getKey().getRoutingContext();
             Class<? extends RpcService> service = entry.getKey().getRpcService();
             if (context != null) {
@@ -553,8 +573,8 @@ public class BindingIndependentConnector implements //
             }
         }
 
-        private DomToBindingRpcForwarder getRpcForwarder(Class<? extends RpcService> service,
-                Class<? extends BaseIdentity> context) {
+        private DomToBindingRpcForwarder getRpcForwarder(final Class<? extends RpcService> service,
+                final Class<? extends BaseIdentity> context) {
             DomToBindingRpcForwarder potential = forwarders.get(service);
             if (potential != null) {
                 return potential;
@@ -575,11 +595,11 @@ public class BindingIndependentConnector implements //
 
         private final Set<QName> supportedRpcs;
         private final WeakReference<Class<? extends RpcService>> rpcServiceType;
-        private Set<org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration> registrations;
-        private Map<QName, RpcInvocationStrategy> strategiesByQName = new HashMap<>();
-        private WeakHashMap<Method, RpcInvocationStrategy> strategiesByMethod = new WeakHashMap<>();
+        private final Set<org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration> registrations;
+        private final Map<QName, RpcInvocationStrategy> strategiesByQName = new HashMap<>();
+        private final WeakHashMap<Method, RpcInvocationStrategy> strategiesByMethod = new WeakHashMap<>();
 
-        public DomToBindingRpcForwarder(Class<? extends RpcService> service) {
+        public DomToBindingRpcForwarder(final Class<? extends RpcService> service) {
             this.rpcServiceType = new WeakReference<Class<? extends RpcService>>(service);
             this.supportedRpcs = mappingService.getRpcQNamesFor(service);
             try {
@@ -591,7 +611,7 @@ public class BindingIndependentConnector implements //
                 }
 
             } catch (Exception e) {
-                LOG.error("Could not forward Rpcs of type {}", service.getName(),e);
+                LOG.error("Could not forward Rpcs of type {}", service.getName(), e);
             }
             registrations = ImmutableSet.of();
         }
@@ -602,7 +622,8 @@ public class BindingIndependentConnector implements //
          * @param service
          * @param context
          */
-        public DomToBindingRpcForwarder(Class<? extends RpcService> service, Class<? extends BaseIdentity> context) {
+        public DomToBindingRpcForwarder(final Class<? extends RpcService> service,
+                final Class<? extends BaseIdentity> context) {
             this.rpcServiceType = new WeakReference<Class<? extends RpcService>>(service);
             this.supportedRpcs = mappingService.getRpcQNamesFor(service);
             Builder<RoutedRpcRegistration> registrationsBuilder = ImmutableSet
@@ -616,13 +637,13 @@ public class BindingIndependentConnector implements //
                 }
                 createDefaultDomForwarder();
             } catch (Exception e) {
-                LOG.error("Could not forward Rpcs of type {}", service.getName(),e);
+                LOG.error("Could not forward Rpcs of type {}", service.getName(), e);
             }
             registrations = registrationsBuilder.build();
         }
 
-        public void registerPaths(Class<? extends BaseIdentity> context, Class<? extends RpcService> service,
-                Set<InstanceIdentifier<?>> set) {
+        public void registerPaths(final Class<? extends BaseIdentity> context,
+                final Class<? extends RpcService> service, final Set<InstanceIdentifier<?>> set) {
             QName ctx = BindingReflections.findQName(context);
             for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier path : FluentIterable.from(set).transform(
                     toDOMInstanceIdentifier)) {
@@ -632,24 +653,23 @@ public class BindingIndependentConnector implements //
             }
         }
 
-
         @Override
-        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-            if(EQUALS_METHOD.equals(method)) {
+        public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
+            if (EQUALS_METHOD.equals(method)) {
                 return false;
             }
             RpcInvocationStrategy strategy = strategiesByMethod.get(method);
             checkState(strategy != null);
             checkArgument(args.length <= 2);
-            if(args.length == 1) {
+            if (args.length == 1) {
                 checkArgument(args[0] instanceof DataObject);
                 return strategy.forwardToDomBroker((DataObject) args[0]);
             }
             return strategy.forwardToDomBroker(null);
         }
 
-        public void removePaths(Class<? extends BaseIdentity> context, Class<? extends RpcService> service,
-                Set<InstanceIdentifier<?>> set) {
+        public void removePaths(final Class<? extends BaseIdentity> context, final Class<? extends RpcService> service,
+                final Set<InstanceIdentifier<?>> set) {
             QName ctx = BindingReflections.findQName(context);
             for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier path : FluentIterable.from(set).transform(
                     toDOMInstanceIdentifier)) {
@@ -677,7 +697,7 @@ public class BindingIndependentConnector implements //
         }
 
         @Override
-        public RpcResult<CompositeNode> invokeRpc(QName rpc, CompositeNode domInput) {
+        public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(final QName rpc, final CompositeNode domInput) {
             checkArgument(rpc != null);
             checkArgument(domInput != null);
 
@@ -686,14 +706,15 @@ public class BindingIndependentConnector implements //
             RpcService rpcService = baRpcRegistry.getRpcService(rpcType);
             checkState(rpcService != null);
             CompositeNode domUnwrappedInput = domInput.getFirstCompositeByName(QName.create(rpc, "input"));
+
             try {
-                return resolveInvocationStrategy(rpc).invokeOn(rpcService, domUnwrappedInput);
+                return Futures.immediateFuture(resolveInvocationStrategy(rpc).invokeOn(rpcService, domUnwrappedInput));
             } catch (Exception e) {
-                throw new IllegalStateException(e);
+                return Futures.immediateFailedFuture(e);
             }
         }
 
-        private RpcInvocationStrategy resolveInvocationStrategy(QName rpc) {
+        private RpcInvocationStrategy resolveInvocationStrategy(final QName rpc) {
             return strategiesByQName.get(rpc);
         }
 
@@ -712,166 +733,76 @@ public class BindingIndependentConnector implements //
                         }
                     }
                     checkState(targetMethod != null, "Rpc method not found");
-                    Optional<Class<?>> outputClass = BindingReflections.resolveRpcOutputClass(targetMethod);
-                    Optional<Class<? extends DataContainer>> inputClass = BindingReflections
-                            .resolveRpcInputClass(targetMethod);
-
-                    RpcInvocationStrategy strategy = null;
-                    if (outputClass.isPresent()) {
-                        if (inputClass.isPresent()) {
-                            strategy = new DefaultInvocationStrategy(rpc,targetMethod, outputClass.get(), inputClass.get());
-                        } else {
-                            strategy = new NoInputNoOutputInvocationStrategy(rpc,targetMethod);
-                        }
-                    } else if(inputClass.isPresent()){
-                        strategy = new NoOutputInvocationStrategy(rpc,targetMethod, inputClass.get());
-                    } else {
-                        strategy = new NoInputNoOutputInvocationStrategy(rpc,targetMethod);
-                    }
-                    return strategy;
+                    return  new RpcInvocationStrategy(rpc,targetMethod, mappingService, biRpcRegistry);
                 }
 
             });
         }
     }
 
-    private abstract class RpcInvocationStrategy {
-
-        protected final Method targetMethod;
-        protected final QName rpc;
-
-        public RpcInvocationStrategy(QName rpc,Method targetMethod) {
-            this.targetMethod = targetMethod;
-            this.rpc = rpc;
-        }
-
-        public abstract Future<RpcResult<?>> forwardToDomBroker(DataObject input);
-
-        public abstract RpcResult<CompositeNode> uncheckedInvoke(RpcService rpcService, CompositeNode domInput)
-                throws Exception;
-
-        public RpcResult<CompositeNode> invokeOn(RpcService rpcService, CompositeNode domInput) throws Exception {
-            return uncheckedInvoke(rpcService, domInput);
-        }
+    public boolean isRpcForwarding() {
+        return rpcForwarding;
     }
 
-    private class DefaultInvocationStrategy extends RpcInvocationStrategy {
-
-        @SuppressWarnings("rawtypes")
-        private WeakReference<Class> inputClass;
-
-        @SuppressWarnings("rawtypes")
-        private WeakReference<Class> outputClass;
+    public boolean isDataForwarding() {
+        return dataForwarding;
+    }
 
-        @SuppressWarnings({ "rawtypes", "unchecked" })
-        public DefaultInvocationStrategy(QName rpc, Method targetMethod, Class<?> outputClass,
-                Class<? extends DataContainer> inputClass) {
-            super(rpc,targetMethod);
-            this.outputClass = new WeakReference(outputClass);
-            this.inputClass = new WeakReference(inputClass);
-        }
+    public boolean isNotificationForwarding() {
+        return notificationForwarding;
+    }
 
-        @Override
-        public RpcResult<CompositeNode> uncheckedInvoke(RpcService rpcService, CompositeNode domInput) throws Exception {
-            DataContainer bindingInput = mappingService.dataObjectFromDataDom(inputClass.get(), domInput);
-            Future<RpcResult<?>> result = (Future<RpcResult<?>>) targetMethod.invoke(rpcService, bindingInput);
-            if (result == null) {
-                return Rpcs.getRpcResult(false);
-            }
-            RpcResult<?> bindingResult = result.get();
-            return Rpcs.getRpcResult(true);
-        }
+    public BindingIndependentMappingService getMappingService() {
+        return mappingService;
+    }
 
-        @Override
-        public Future<RpcResult<?>> forwardToDomBroker(DataObject input) {
-            if(biRouter != null) {
-                CompositeNode xml = mappingService.toDataDom(input);
-                CompositeNode wrappedXml = ImmutableCompositeNode.create(rpc,ImmutableList.<Node<?>>of(xml));
-                RpcResult<CompositeNode> result = biRouter.invokeRpc(rpc, wrappedXml);
-                Object baResultValue = null;
-                if(result.getResult() != null) {
-                    baResultValue = mappingService.dataObjectFromDataDom(outputClass.get(), result.getResult());
-                }
-                RpcResult<?> baResult = Rpcs.getRpcResult(result.isSuccessful(), baResultValue, result.getErrors());
-                return Futures.<RpcResult<?>>immediateFuture(baResult);
-            }
-            return Futures.<RpcResult<?>>immediateFuture(Rpcs.getRpcResult(false));
-        }
+    public void setBindingNotificationService(final NotificationProviderService baService) {
+        this.baNotifyService = baService;
 
     }
 
-    private class NoInputNoOutputInvocationStrategy extends RpcInvocationStrategy {
+    public void setDomNotificationService(final NotificationPublishService domService) {
+        this.domNotificationService = domService;
+    }
 
-        public NoInputNoOutputInvocationStrategy(QName rpc, Method targetMethod) {
-            super(rpc,targetMethod);
-        }
+    private class DomToBindingNotificationForwarder implements NotificationInterestListener, NotificationListener {
 
-        public RpcResult<CompositeNode> uncheckedInvoke(RpcService rpcService, CompositeNode domInput) throws Exception {
-            @SuppressWarnings("unchecked")
-            Future<RpcResult<Void>> result = (Future<RpcResult<Void>>) targetMethod.invoke(rpcService);
-            RpcResult<Void> bindingResult = result.get();
-            return Rpcs.getRpcResult(bindingResult.isSuccessful(), bindingResult.getErrors());
-        }
+        private final ConcurrentMap<QName, WeakReference<Class<? extends Notification>>> notifications = new ConcurrentHashMap<>();
+        private final Set<QName> supportedNotifications = new HashSet<>();
 
         @Override
-        public Future<RpcResult<?>> forwardToDomBroker(DataObject input) {
-            return Futures.immediateFuture(null);
+        public Set<QName> getSupportedNotifications() {
+            return Collections.unmodifiableSet(supportedNotifications);
         }
-    }
-    
-    private class NoOutputInvocationStrategy extends RpcInvocationStrategy {
 
-        
-        @SuppressWarnings("rawtypes")
-        private WeakReference<Class> inputClass;
-
-        @SuppressWarnings({ "rawtypes", "unchecked" })
-        public NoOutputInvocationStrategy(QName rpc, Method targetMethod, 
-                Class<? extends DataContainer> inputClass) {
-            super(rpc,targetMethod);
-            this.inputClass = new WeakReference(inputClass);
-        }
-        
-        
         @Override
-        public RpcResult<CompositeNode> uncheckedInvoke(RpcService rpcService, CompositeNode domInput) throws Exception {
-            DataContainer bindingInput = mappingService.dataObjectFromDataDom(inputClass.get(), domInput);
-            Future<RpcResult<?>> result = (Future<RpcResult<?>>) targetMethod.invoke(rpcService, bindingInput);
-            if (result == null) {
-                return Rpcs.getRpcResult(false);
+        public void onNotification(final CompositeNode notification) {
+            QName qname = notification.getNodeType();
+            WeakReference<Class<? extends Notification>> potential = notifications.get(qname);
+            if (potential != null) {
+                Class<? extends Notification> potentialClass = potential.get();
+                if (potentialClass != null) {
+                    final DataContainer baNotification = mappingService.dataObjectFromDataDom(potentialClass,
+                            notification);
+
+                    if (baNotification instanceof Notification) {
+                        baNotifyService.publish((Notification) baNotification);
+                    }
+                }
             }
-            RpcResult<?> bindingResult = result.get();
-            return Rpcs.getRpcResult(true);
         }
 
         @Override
-        public Future<RpcResult<?>> forwardToDomBroker(DataObject input) {
-            if(biRouter != null) {
-                CompositeNode xml = mappingService.toDataDom(input);
-                CompositeNode wrappedXml = ImmutableCompositeNode.create(rpc,ImmutableList.<Node<?>>of(xml));
-                RpcResult<CompositeNode> result = biRouter.invokeRpc(rpc, wrappedXml);
-                Object baResultValue = null;
-                RpcResult<?> baResult = Rpcs.<Void>getRpcResult(result.isSuccessful(), null, result.getErrors());
-                return Futures.<RpcResult<?>>immediateFuture(baResult);
+        public void onNotificationSubscribtion(final Class<? extends Notification> notificationType) {
+            QName qname = BindingReflections.findQName(notificationType);
+            if (qname != null) {
+                WeakReference<Class<? extends Notification>> already = notifications.putIfAbsent(qname,
+                        new WeakReference<Class<? extends Notification>>(notificationType));
+                if (already == null) {
+                    domNotificationService.addNotificationListener(qname, this);
+                    supportedNotifications.add(qname);
+                }
             }
-            return Futures.<RpcResult<?>>immediateFuture(Rpcs.getRpcResult(false));
         }
-
-    }
-
-    public boolean isRpcForwarding() {
-        return rpcForwarding;
-    }
-
-    public boolean isDataForwarding() {
-        return dataForwarding;
-    }
-
-    public boolean isNotificationForwarding() {
-        return notificationForwarding;
-    }
-
-    public BindingIndependentMappingService getMappingService() {
-        return mappingService;
     }
 }