Merge "Fix a race PingPongTransactionChain"
[controller.git] / opendaylight / md-sal / sal-binding-broker / src / main / java / org / opendaylight / controller / sal / binding / impl / connect / dom / BindingIndependentConnector.java
index 0a769921d80410742cb22b4ad7ee8cc0e9920f0a..f63ce1016528c34ff179ac63be435c8a03758268 100644 (file)
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
 package org.opendaylight.controller.sal.binding.impl.connect.dom;
 
-import java.lang.ref.WeakReference;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.ParameterizedType;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
 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;
-import java.util.WeakHashMap;
-import java.util.concurrent.Callable;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-
-
-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.routing.RouteChange;
-import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
+
+import org.opendaylight.controller.md.sal.binding.impl.AbstractForwardedDataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.DataReader;
+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.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.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.spi.RpcContextIdentifier;
-import org.opendaylight.controller.sal.binding.spi.RpcRouter;
-import org.opendaylight.controller.sal.common.util.Rpcs;
-import org.opendaylight.controller.sal.core.api.Provider;
 import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
-import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.controller.sal.core.api.Provider;
 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.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;
-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.RpcInput;
-import org.opendaylight.yangtools.yang.binding.RpcService;
-import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
-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.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.ImmutableSet;
-
-import static com.google.common.base.Preconditions.*;
-import static org.opendaylight.yangtools.concepts.util.ClassLoaderUtils.*;
-
 public class BindingIndependentConnector implements //
-        RuntimeDataProvider, //
+        DataReader<InstanceIdentifier<? extends DataObject>, DataObject>, //
         Provider, //
         AutoCloseable {
 
-    private final Logger LOG = LoggerFactory.getLogger(BindingIndependentConnector.class);
-
-    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
+    private static final Logger LOG = LoggerFactory.getLogger(BindingIndependentConnector.class);
+    private static final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier ROOT_BI = org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier
             .builder().toInstance();
 
     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;
+    private final ConcurrentMap<Object, DomToBindingTransaction> bindingOpenedTransactions;
+    private final BindingToDomCommitHandler bindingToDomCommitHandler;
+    private final DomToBindingCommitHandler domToBindingCommitHandler;
 
-    private BindingToDomCommitHandler bindingToDomCommitHandler = new BindingToDomCommitHandler();
-    private DomToBindingCommitHandler domToBindingCommitHandler = new DomToBindingCommitHandler();
+    private Registration biCommitHandlerRegistration;
+    private RpcProvisionRegistry biRpcRegistry;
+    private RpcProviderRegistry baRpcRegistry;
 
-    private Registration<DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject>> baCommitHandlerRegistration;
+    private ListenerRegistration<DomToBindingRpcForwardingManager> domToBindingRpcManager;
 
-    private Registration<DataCommitHandler<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode>> biCommitHandlerRegistration;
+    private boolean rpcForwarding;
+    private boolean dataForwarding;
+    private boolean notificationForwarding;
 
-    private RpcProvisionRegistry biRpcRegistry;
-    private RpcProviderRegistryImpl baRpcRegistry;
+    private RpcProviderRegistryImpl baRpcRegistryImpl;
 
-    private ListenerRegistration<DomToBindingRpcForwardingManager> domToBindingRpcManager;
-    // private ListenerRegistration<BindingToDomRpcForwardingManager>
-    // bindingToDomRpcManager;
+    private NotificationProviderService baNotifyService;
 
-    private Function<InstanceIdentifier<?>, org.opendaylight.yangtools.yang.data.api.InstanceIdentifier> toDOMInstanceIdentifier = new Function<InstanceIdentifier<?>, org.opendaylight.yangtools.yang.data.api.InstanceIdentifier>() {
+    private NotificationPublishService domNotificationService;
 
-        @Override
-        public org.opendaylight.yangtools.yang.data.api.InstanceIdentifier apply(InstanceIdentifier<?> input) {
-            return mappingService.toDataDom(input);
-        }
+    public BindingIndependentConnector() {
+        domOpenedTransactions = new ConcurrentHashMap<>();
+        bindingOpenedTransactions = new ConcurrentHashMap<>();
 
-    };
+        bindingToDomCommitHandler = new BindingToDomCommitHandler(bindingOpenedTransactions, domOpenedTransactions);
+        domToBindingCommitHandler = new DomToBindingCommitHandler(bindingOpenedTransactions, domOpenedTransactions);
+        rpcForwarding = false;
+        dataForwarding = false;
+        notificationForwarding = false;
+    }
 
     @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);
+            org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier biPath = mappingService.toDataDom(path);
             CompositeNode result = biDataService.readOperationalData(biPath);
-            return potentialAugmentationRead(path,biPath,result);
+            return potentialAugmentationRead(path, biPath, result);
         } catch (DeserializationException e) {
             throw new IllegalStateException(e);
         }
     }
 
-    private DataObject potentialAugmentationRead(InstanceIdentifier<? extends DataObject> path, org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath, CompositeNode result) throws DeserializationException {
+    private DataObject potentialAugmentationRead(InstanceIdentifier<? extends DataObject> path,
+            final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier biPath, final CompositeNode result)
+            throws DeserializationException {
         Class<? extends DataObject> targetType = path.getTargetType();
         if (Augmentation.class.isAssignableFrom(targetType)) {
             path = mappingService.fromDataDom(biPath);
@@ -136,126 +112,106 @@ 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);
+            org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier biPath = mappingService.toDataDom(path);
             CompositeNode result = biDataService.readConfigurationData(biPath);
-            return potentialAugmentationRead(path,biPath,result);
+            return potentialAugmentationRead(path, biPath, result);
         } catch (DeserializationException e) {
             throw new IllegalStateException(e);
         }
     }
 
-    private DataModificationTransaction createBindingToDomTransaction(
-            DataModification<InstanceIdentifier<? extends DataObject>, DataObject> source) {
-        DataModificationTransaction target = biDataService.beginTransaction();
-        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());
-        }
-        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());
-        }
-        for (InstanceIdentifier<? extends DataObject> entry : source.getRemovedConfigurationData()) {
-            org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
-            target.removeConfigurationData(biEntry);
-        }
-        for (InstanceIdentifier<? extends DataObject> entry : source.getRemovedOperationalData()) {
-            org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
-            target.removeOperationalData(biEntry);
-        }
-        return target;
-    }
-
-    private org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction createDomToBindingTransaction(
-            DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> source) {
-        org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction target = baDataService
-                .beginTransaction();
-        for (Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> entry : source
-                .getUpdatedConfigurationData().entrySet()) {
-            try {
-                InstanceIdentifier<?> baKey = mappingService.fromDataDom(entry.getKey());
-                DataObject baData = mappingService.dataObjectFromDataDom(baKey, entry.getValue());
-                target.putConfigurationData(baKey, baData);
-            } catch (DeserializationException e) {
-                LOG.error("Ommiting from BA transaction: {}.", entry.getKey(), e);
-            }
-        }
-        for (Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> entry : source
-                .getUpdatedOperationalData().entrySet()) {
-            try {
-
-                InstanceIdentifier<?> baKey = mappingService.fromDataDom(entry.getKey());
-                DataObject baData = mappingService.dataObjectFromDataDom(baKey, entry.getValue());
-                target.putOperationalData(baKey, baData);
-            } catch (DeserializationException e) {
-                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;
-    }
-
     public org.opendaylight.controller.sal.core.api.data.DataProviderService getBiDataService() {
         return biDataService;
     }
 
-    public void setBiDataService(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;
+        bindingToDomCommitHandler.setBindingIndependentDataService(this.biDataService);
     }
 
     public DataProviderService getBaDataService() {
         return baDataService;
     }
 
-    public void setBaDataService(DataProviderService baDataService) {
+    protected void setBindingDataService(final DataProviderService baDataService) {
         this.baDataService = baDataService;
+        domToBindingCommitHandler.setBindingAwareDataService(this.baDataService);
     }
 
     public RpcProviderRegistry getRpcRegistry() {
         return baRpcRegistry;
     }
 
-    public void setRpcRegistry(RpcProviderRegistryImpl rpcRegistry) {
+    protected void setBindingRpcRegistry(final RpcProviderRegistry rpcRegistry) {
         this.baRpcRegistry = rpcRegistry;
     }
 
-    public void start() {
-        baDataService.registerDataReader(ROOT, this);
-        baCommitHandlerRegistration = baDataService.registerCommitHandler(ROOT, bindingToDomCommitHandler);
-        biCommitHandlerRegistration = biDataService.registerCommitHandler(ROOT_BI, domToBindingCommitHandler);
-        baDataService.registerCommitHandlerListener(domToBindingCommitHandler);
+    public void startDataForwarding() {
+        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 (baRpcRegistry != null && biRpcRegistry != null) {
-            domToBindingRpcManager = baRpcRegistry.registerRouteChangeListener(new DomToBindingRpcForwardingManager());
+        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;
+    }
+
+    //WTF? - cycle references to biFwdManager - need to solve :-/
+    public void startRpcForwarding() {
+        checkNotNull(mappingService, "Unable to start Rpc forwarding. Reason: Mapping Service is not initialized properly!");
+        if (biRpcRegistry != null && baRpcRegistry instanceof RouteChangePublisher<?, ?>) {
+            checkState(!rpcForwarding, "Connector is already forwarding RPCs");
+            final DomToBindingRpcForwardingManager biFwdManager = new DomToBindingRpcForwardingManager(mappingService, biRpcRegistry, baRpcRegistry);
+
+            domToBindingRpcManager = baRpcRegistry.registerRouteChangeListener(biFwdManager);
+            biRpcRegistry.addRpcRegistrationListener(biFwdManager);
+            if (baRpcRegistry instanceof RpcProviderRegistryImpl) {
+                baRpcRegistryImpl = (RpcProviderRegistryImpl) baRpcRegistry;
+                baRpcRegistryImpl.registerRouterInstantiationListener(domToBindingRpcManager.getInstance());
+                baRpcRegistryImpl.registerGlobalRpcRegistrationListener(domToBindingRpcManager.getInstance());
+                biFwdManager.setRegistryImpl(baRpcRegistryImpl);
+            }
+            rpcForwarding = true;
+        }
+    }
 
+    public void startNotificationForwarding() {
+        checkState(!notificationForwarding, "Connector is already forwarding notifications.");
+        if (mappingService == null) {
+            LOG.warn("Unable to start Notification forwarding. Reason: Mapping Service is not initialized properly!");
+        } else if (baNotifyService == null) {
+            LOG.warn("Unable to start Notification forwarding. Reason: Binding Aware Notify Service is not initialized properly!");
+        } else if (domNotificationService == null) {
+            LOG.warn("Unable to start Notification forwarding. Reason: DOM Notification Service is not initialized properly!");
+        } else {
+            baNotifyService.registerInterestListener(
+                new DomToBindingNotificationForwarder(mappingService, baNotifyService, domNotificationService));
+            notificationForwarding = true;
         }
     }
 
-    public void setMappingService(BindingIndependentMappingService mappingService) {
+    protected void setMappingService(final BindingIndependentMappingService mappingService) {
         this.mappingService = mappingService;
+        bindingToDomCommitHandler.setMappingService(this.mappingService);
+        domToBindingCommitHandler.setMappingService(this.mappingService);
     }
 
     @Override
@@ -264,370 +220,45 @@ public class BindingIndependentConnector implements //
     }
 
     @Override
-    public void onSessionInitiated(ProviderSession session) {
-        setBiDataService(session.getService(org.opendaylight.controller.sal.core.api.data.DataProviderService.class));
-        start();
-    }
-
-    public <T extends RpcService> void onRpcRouterCreated(Class<T> serviceType, RpcRouter<T> router) {
+    public void onSessionInitiated(final ProviderSession session) {
+        setDomDataService(session.getService(org.opendaylight.controller.sal.core.api.data.DataProviderService.class));
+        setDomRpcRegistry(session.getService(RpcProvisionRegistry.class));
 
     }
 
-    public void setDomRpcRegistry(RpcProvisionRegistry registry) {
+    public void setDomRpcRegistry(final RpcProvisionRegistry registry) {
         biRpcRegistry = registry;
     }
 
     @Override
     public void close() throws Exception {
-        if (baCommitHandlerRegistration != null) {
-            baCommitHandlerRegistration.close();
-        }
         if (biCommitHandlerRegistration != null) {
             biCommitHandlerRegistration.close();
         }
-
     }
 
-    private class DomToBindingTransaction implements
-            DataCommitTransaction<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> {
-
-        private final org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction backing;
-        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) {
-            super();
-            this.backing = backing;
-            this.modification = modification;
-            bindingOpenedTransactions.put(backing.getIdentifier(), this);
-        }
-
-        @Override
-        public DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getModification() {
-            return modification;
-        }
-
-        @Override
-        public RpcResult<Void> rollback() throws IllegalStateException {
-            // backing.cancel();
-            return Rpcs.<Void> getRpcResult(true, null, Collections.<RpcError> emptySet());
-        }
-
-        @Override
-        public RpcResult<Void> finish() throws IllegalStateException {
-            Future<RpcResult<TransactionStatus>> result = backing.commit();
-            try {
-                RpcResult<TransactionStatus> baResult = result.get();
-                return Rpcs.<Void> getRpcResult(baResult.isSuccessful(), null, baResult.getErrors());
-            } catch (InterruptedException e) {
-                throw new IllegalStateException("", e);
-            } catch (ExecutionException e) {
-                throw new IllegalStateException("", e);
-            }
-        }
+    public boolean isRpcForwarding() {
+        return rpcForwarding;
     }
 
-    private class BindingToDomTransaction implements
-            DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> {
-
-        private DataModificationTransaction backing;
-        private DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification;
-
-        public BindingToDomTransaction(DataModificationTransaction backing,
-                DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
-            this.backing = backing;
-            this.modification = modification;
-            domOpenedTransactions.put(backing.getIdentifier(), this);
-        }
-
-        @Override
-        public DataModification<InstanceIdentifier<? extends DataObject>, DataObject> getModification() {
-            return modification;
-        }
-
-        @Override
-        public RpcResult<Void> finish() throws IllegalStateException {
-            Future<RpcResult<TransactionStatus>> result = backing.commit();
-            try {
-                RpcResult<TransactionStatus> biResult = result.get();
-                return Rpcs.<Void> getRpcResult(biResult.isSuccessful(), null, biResult.getErrors());
-            } catch (InterruptedException e) {
-                throw new IllegalStateException("", e);
-            } catch (ExecutionException e) {
-                throw new IllegalStateException("", e);
-            } finally {
-                domOpenedTransactions.remove(backing.getIdentifier());
-            }
-        }
-
-        @Override
-        public RpcResult<Void> rollback() throws IllegalStateException {
-            domOpenedTransactions.remove(backing.getIdentifier());
-            return Rpcs.<Void> getRpcResult(true, null, Collections.<RpcError> emptySet());
-        }
+    public boolean isDataForwarding() {
+        return dataForwarding;
     }
 
-    private class BindingToDomCommitHandler implements
-            DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> {
-
-        @Override
-        public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> requestCommit(
-                DataModification<InstanceIdentifier<? extends DataObject>, DataObject> bindingTransaction) {
-
-            /**
-             * Transaction was created as DOM transaction, in that case we do
-             * not need to forward it back.
-             */
-            if (bindingOpenedTransactions.containsKey(bindingTransaction.getIdentifier())) {
-
-                return CommitHandlersTransactions.allwaysSuccessfulTransaction(bindingTransaction);
-            }
-            DataModificationTransaction domTransaction = createBindingToDomTransaction(bindingTransaction);
-            BindingToDomTransaction wrapped = new BindingToDomTransaction(domTransaction, bindingTransaction);
-            LOG.info("Forwarding Binding Transaction: {} as DOM Transaction: {} .", bindingTransaction.getIdentifier(),
-                    domTransaction.getIdentifier());
-            return wrapped;
-        }
+    public boolean isNotificationForwarding() {
+        return notificationForwarding;
     }
 
-    private class DomToBindingCommitHandler implements //
-            RegistrationListener<DataCommitHandlerRegistration<InstanceIdentifier<?>, DataObject>>, //
-            DataCommitHandler<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> {
-
-        @Override
-        public void onRegister(DataCommitHandlerRegistration<InstanceIdentifier<?>, DataObject> registration) {
-
-            org.opendaylight.yangtools.yang.data.api.InstanceIdentifier domPath = mappingService.toDataDom(registration
-                    .getPath());
-
-        }
-
-        @Override
-        public void onUnregister(DataCommitHandlerRegistration<InstanceIdentifier<?>, DataObject> registration) {
-            // NOOP for now
-            // FIXME: do registration based on only active commit handlers.
-        }
-
-        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) {
-            Object identifier = domTransaction.getIdentifier();
-
-            /**
-             * We checks if the transcation was originated in this mapper. If it
-             * was originated in this mapper we are returing allways success
-             * commit hanlder to prevent creating loop in two-phase commit and
-             * duplicating data.
-             */
-            if (domOpenedTransactions.containsKey(identifier)) {
-                return CommitHandlersTransactions.allwaysSuccessfulTransaction(domTransaction);
-            }
-
-            org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction baTransaction = createDomToBindingTransaction(domTransaction);
-            DomToBindingTransaction forwardedTransaction = new DomToBindingTransaction(baTransaction, domTransaction);
-            LOG.info("Forwarding DOM Transaction: {} as Binding Transaction: {}.", domTransaction.getIdentifier(),
-                    baTransaction.getIdentifier());
-            return forwardedTransaction;
-        }
+    public BindingIndependentMappingService getMappingService() {
+        return mappingService;
     }
 
-    private class DomToBindingRpcForwardingManager implements
-            RouteChangeListener<RpcContextIdentifier, InstanceIdentifier<?>> {
-
-        private final Map<Class<? extends RpcService>, DomToBindingRpcForwarder> forwarders = new WeakHashMap<>();
-
-        @Override
-        public void onRouteChange(RouteChange<RpcContextIdentifier, InstanceIdentifier<?>> change) {
-            for (Entry<RpcContextIdentifier, Set<InstanceIdentifier<?>>> entry : change.getAnnouncements().entrySet()) {
-                bindingRoutesAdded(entry);
-            }
-        }
-
-        private void bindingRoutesAdded(Entry<RpcContextIdentifier, Set<InstanceIdentifier<?>>> entry) {
-            Class<? extends BaseIdentity> context = entry.getKey().getRoutingContext();
-            Class<? extends RpcService> service = entry.getKey().getRpcService();
-            if (context != null) {
-                getRpcForwarder(service, context).registerPaths(context, service, entry.getValue());
-            }
-        }
-
-        private DomToBindingRpcForwarder getRpcForwarder(Class<? extends RpcService> service,
-                Class<? extends BaseIdentity> context) {
-            DomToBindingRpcForwarder potential = forwarders.get(service);
-            if (potential != null) {
-                return potential;
-            }
-            if (context == null) {
-                potential = new DomToBindingRpcForwarder(service);
-            } else {
-                potential = new DomToBindingRpcForwarder(service, context);
-            }
-            forwarders.put(service, potential);
-            return potential;
-        }
+    public void setBindingNotificationService(final NotificationProviderService baService) {
+        this.baNotifyService = baService;
 
     }
 
-    private class DomToBindingRpcForwarder implements RpcImplementation {
-
-        private final Set<QName> supportedRpcs;
-        private final WeakReference<Class<? extends RpcService>> rpcServiceType;
-        private Set<org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration> registrations;
-
-        public DomToBindingRpcForwarder(Class<? extends RpcService> service) {
-            this.rpcServiceType = new WeakReference<Class<? extends RpcService>>(service);
-            this.supportedRpcs = mappingService.getRpcQNamesFor(service);
-            for (QName rpc : supportedRpcs) {
-                biRpcRegistry.addRpcImplementation(rpc, this);
-            }
-            registrations = ImmutableSet.of();
-        }
-
-        public DomToBindingRpcForwarder(Class<? extends RpcService> service, Class<? extends BaseIdentity> context) {
-            this.rpcServiceType = new WeakReference<Class<? extends RpcService>>(service);
-            this.supportedRpcs = mappingService.getRpcQNamesFor(service);
-            registrations = new HashSet<>();
-            for (QName rpc : supportedRpcs) {
-                registrations.add(biRpcRegistry.addRoutedRpcImplementation(rpc, this));
-            }
-            registrations = ImmutableSet.copyOf(registrations);
-        }
-
-        public void registerPaths(Class<? extends BaseIdentity> context, Class<? extends RpcService> service,
-                Set<InstanceIdentifier<?>> set) {
-            QName ctx = BindingReflections.findQName(context);
-            for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier path : FluentIterable.from(set).transform(
-                    toDOMInstanceIdentifier)) {
-                for (org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration reg : registrations) {
-                    reg.registerPath(ctx, path);
-                }
-            }
-        }
-
-        public void removePaths(Class<? extends BaseIdentity> context, Class<? extends RpcService> service,
-                Set<InstanceIdentifier<?>> set) {
-            QName ctx = BindingReflections.findQName(context);
-            for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier path : FluentIterable.from(set).transform(
-                    toDOMInstanceIdentifier)) {
-                for (org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration reg : registrations) {
-                    reg.unregisterPath(ctx, path);
-                }
-            }
-        }
-
-        @Override
-        public Set<QName> getSupportedRpcs() {
-            return supportedRpcs;
-        }
-
-        @Override
-        public RpcResult<CompositeNode> invokeRpc(QName rpc, CompositeNode domInput) {
-            checkArgument(rpc != null);
-            checkArgument(domInput != null);
-
-            Class<? extends RpcService> rpcType = rpcServiceType.get();
-            checkState(rpcType != null);
-            RpcService rpcService = baRpcRegistry.getRpcService(rpcType);
-            checkState(rpcService != null);
-            CompositeNode domUnwrappedInput = domInput.getFirstCompositeByName(QName.create(rpc, "input"));
-            try {
-                return resolveInvocationStrategy(rpc, rpcType).invokeOn(rpcService, domUnwrappedInput);
-            } catch (Exception e) {
-                throw new IllegalStateException(e);
-            }
-        }
-
-        private RpcInvocationStrategy resolveInvocationStrategy(final QName rpc,
-                final Class<? extends RpcService> rpcType) throws Exception {
-            return ClassLoaderUtils.withClassLoader(rpcType.getClassLoader(), new Callable<RpcInvocationStrategy>() {
-                @Override
-                public RpcInvocationStrategy call() throws Exception {
-                    String methodName = BindingMapping.getMethodName(rpc);
-                    Method targetMethod = null;
-                    for (Method possibleMethod : rpcType.getMethods()) {
-                        if (possibleMethod.getName().equals(methodName)
-                                && BindingReflections.isRpcMethod(possibleMethod)) {
-                            targetMethod = possibleMethod;
-                            break;
-                        }
-                    }
-                    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(targetMethod, outputClass.get(), inputClass.get());
-                        } else {
-                            strategy = new NoInputNoOutputInvocationStrategy(targetMethod);
-                        }
-                    } else {
-                        strategy = null;
-                    }
-                    return strategy;
-                }
-
-            });
-        }
-    }
-
-    private abstract class RpcInvocationStrategy {
-
-        protected final Method targetMethod;
-
-        public RpcInvocationStrategy(Method targetMethod) {
-            this.targetMethod = targetMethod;
-        }
-
-        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);
-        }
-    }
-
-    private class DefaultInvocationStrategy extends RpcInvocationStrategy {
-
-        @SuppressWarnings("rawtypes")
-        private WeakReference<Class> inputClass;
-
-        @SuppressWarnings("rawtypes")
-        private WeakReference<Class> outputClass;
-
-        public DefaultInvocationStrategy(Method targetMethod, Class<?> outputClass,
-                Class<? extends DataContainer> inputClass) {
-            super(targetMethod);
-            this.outputClass = new WeakReference(outputClass);
-            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);
-            }
-            RpcResult<?> bindingResult = result.get();
-            return Rpcs.getRpcResult(true);
-        }
-
-    }
-
-    private class NoInputNoOutputInvocationStrategy extends RpcInvocationStrategy {
-
-        public NoInputNoOutputInvocationStrategy(Method targetMethod) {
-            super(targetMethod);
-        }
-
-        public RpcResult<CompositeNode> uncheckedInvoke(RpcService rpcService, CompositeNode domInput) throws Exception {
-            Future<RpcResult<Void>> result = (Future<RpcResult<Void>>) targetMethod.invoke(rpcService);
-            RpcResult<Void> bindingResult = result.get();
-            return Rpcs.getRpcResult(bindingResult.isSuccessful(), bindingResult.getErrors());
-        }
-
+    public void setDomNotificationService(final NotificationPublishService domService) {
+        this.domNotificationService = domService;
     }
 }