71253d02d66ff0230ad483dea2297afee072c8ba
[controller.git] / opendaylight / md-sal / sal-binding-broker / src / main / java / org / opendaylight / controller / sal / binding / impl / connect / dom / BindingIndependentConnector.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.controller.sal.binding.impl.connect.dom;
9
10 import static com.google.common.base.Preconditions.checkNotNull;
11 import static com.google.common.base.Preconditions.checkState;
12
13 import java.util.Collection;
14 import java.util.Collections;
15
16 import java.util.concurrent.ConcurrentHashMap;
17 import java.util.concurrent.ConcurrentMap;
18 import org.opendaylight.controller.md.sal.binding.impl.AbstractForwardedDataBroker;
19 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
20 import org.opendaylight.controller.md.sal.common.api.routing.RouteChangePublisher;
21 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
22 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
23 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
24 import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider;
25 import org.opendaylight.controller.sal.binding.impl.DataBrokerImpl;
26 import org.opendaylight.controller.sal.binding.impl.MountPointManagerImpl.BindingMountPointImpl;
27 import org.opendaylight.controller.sal.binding.impl.RpcProviderRegistryImpl;
28 import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
29 import org.opendaylight.controller.sal.core.api.Provider;
30 import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
31 import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService;
32 import org.opendaylight.yangtools.concepts.ListenerRegistration;
33 import org.opendaylight.yangtools.concepts.Registration;
34 import org.opendaylight.yangtools.yang.binding.Augmentable;
35 import org.opendaylight.yangtools.yang.binding.Augmentation;
36 import org.opendaylight.yangtools.yang.binding.DataObject;
37 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
38 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
39 import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
40 import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
43
44 public class BindingIndependentConnector implements //
45         RuntimeDataProvider, //
46         Provider, //
47         AutoCloseable {
48
49     private static final Logger LOG = LoggerFactory.getLogger(BindingIndependentConnector.class);
50     private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier ROOT_BI = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
51             .builder().toInstance();
52
53     private BindingIndependentMappingService mappingService;
54     private org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService;
55     private DataProviderService baDataService;
56
57     private final ConcurrentMap<Object, BindingToDomTransaction> domOpenedTransactions;
58     private final ConcurrentMap<Object, DomToBindingTransaction> bindingOpenedTransactions;
59     private final BindingToDomCommitHandler bindingToDomCommitHandler;
60     private final DomToBindingCommitHandler domToBindingCommitHandler;
61
62     private Registration<DataCommitHandler<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode>> biCommitHandlerRegistration;
63     private RpcProvisionRegistry biRpcRegistry;
64     private RpcProviderRegistry baRpcRegistry;
65
66     private ListenerRegistration<DomToBindingRpcForwardingManager> domToBindingRpcManager;
67
68     private boolean rpcForwarding;
69     private boolean dataForwarding;
70     private boolean notificationForwarding;
71
72     private RpcProviderRegistryImpl baRpcRegistryImpl;
73
74     private NotificationProviderService baNotifyService;
75
76     private NotificationPublishService domNotificationService;
77
78     public BindingIndependentConnector() {
79         domOpenedTransactions = new ConcurrentHashMap<>();
80         bindingOpenedTransactions = new ConcurrentHashMap<>();
81
82         bindingToDomCommitHandler = new BindingToDomCommitHandler(bindingOpenedTransactions, domOpenedTransactions);
83         domToBindingCommitHandler = new DomToBindingCommitHandler(bindingOpenedTransactions, domOpenedTransactions);
84         rpcForwarding = false;
85         dataForwarding = false;
86         notificationForwarding = false;
87     }
88
89     @Override
90     public DataObject readOperationalData(final InstanceIdentifier<? extends DataObject> path) {
91         try {
92             org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath = mappingService.toDataDom(path);
93             CompositeNode result = biDataService.readOperationalData(biPath);
94             return potentialAugmentationRead(path, biPath, result);
95         } catch (DeserializationException e) {
96             throw new IllegalStateException(e);
97         }
98     }
99
100     private DataObject potentialAugmentationRead(InstanceIdentifier<? extends DataObject> path,
101             final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath, final CompositeNode result)
102             throws DeserializationException {
103         Class<? extends DataObject> targetType = path.getTargetType();
104         if (Augmentation.class.isAssignableFrom(targetType)) {
105             path = mappingService.fromDataDom(biPath);
106             Class<? extends Augmentation<?>> augmentType = (Class<? extends Augmentation<?>>) targetType;
107             DataObject parentTo = mappingService.dataObjectFromDataDom(path, result);
108             if (parentTo instanceof Augmentable<?>) {
109                 return (DataObject) ((Augmentable) parentTo).getAugmentation(augmentType);
110             }
111         }
112         return mappingService.dataObjectFromDataDom(path, result);
113     }
114
115     @Override
116     public DataObject readConfigurationData(final InstanceIdentifier<? extends DataObject> path) {
117         try {
118             org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath = mappingService.toDataDom(path);
119             CompositeNode result = biDataService.readConfigurationData(biPath);
120             return potentialAugmentationRead(path, biPath, result);
121         } catch (DeserializationException e) {
122             throw new IllegalStateException(e);
123         }
124     }
125
126     public org.opendaylight.controller.sal.core.api.data.DataProviderService getBiDataService() {
127         return biDataService;
128     }
129
130     protected void setDomDataService(
131             final org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService) {
132         this.biDataService = biDataService;
133         bindingToDomCommitHandler.setBindingIndependentDataService(this.biDataService);
134     }
135
136     public DataProviderService getBaDataService() {
137         return baDataService;
138     }
139
140     protected void setBindingDataService(final DataProviderService baDataService) {
141         this.baDataService = baDataService;
142         domToBindingCommitHandler.setBindingAwareDataService(this.baDataService);
143     }
144
145     public RpcProviderRegistry getRpcRegistry() {
146         return baRpcRegistry;
147     }
148
149     protected void setBindingRpcRegistry(final RpcProviderRegistry rpcRegistry) {
150         this.baRpcRegistry = rpcRegistry;
151     }
152
153     public void startDataForwarding() {
154         if (baDataService instanceof AbstractForwardedDataBroker) {
155             dataForwarding = true;
156             return;
157         }
158
159         final DataProviderService baData;
160         if (baDataService instanceof BindingMountPointImpl) {
161             baData = ((BindingMountPointImpl) baDataService).getDataBrokerImpl();
162             LOG.debug("Extracted BA Data provider {} from mount point {}", baData, baDataService);
163         } else {
164             baData = baDataService;
165         }
166
167         if (baData instanceof DataBrokerImpl) {
168             checkState(!dataForwarding, "Connector is already forwarding data.");
169             ((DataBrokerImpl) baData).setDataReadDelegate(this);
170             ((DataBrokerImpl) baData).setRootCommitHandler(bindingToDomCommitHandler);
171             biCommitHandlerRegistration = biDataService.registerCommitHandler(ROOT_BI, domToBindingCommitHandler);
172             baDataService.registerCommitHandlerListener(domToBindingCommitHandler);
173         }
174
175         dataForwarding = true;
176     }
177
178     //WTF? - cycle references to biFwdManager - need to solve :-/
179     public void startRpcForwarding() {
180         checkNotNull(mappingService, "Unable to start Rpc forwarding. Reason: Mapping Service is not initialized properly!");
181         if (biRpcRegistry != null && baRpcRegistry instanceof RouteChangePublisher<?, ?>) {
182             checkState(!rpcForwarding, "Connector is already forwarding RPCs");
183             final DomToBindingRpcForwardingManager biFwdManager = new DomToBindingRpcForwardingManager(mappingService, biRpcRegistry, baRpcRegistry);
184
185             domToBindingRpcManager = baRpcRegistry.registerRouteChangeListener(biFwdManager);
186             biRpcRegistry.addRpcRegistrationListener(biFwdManager);
187             if (baRpcRegistry instanceof RpcProviderRegistryImpl) {
188                 baRpcRegistryImpl = (RpcProviderRegistryImpl) baRpcRegistry;
189                 baRpcRegistryImpl.registerRouterInstantiationListener(domToBindingRpcManager.getInstance());
190                 baRpcRegistryImpl.registerGlobalRpcRegistrationListener(domToBindingRpcManager.getInstance());
191                 biFwdManager.setRegistryImpl(baRpcRegistryImpl);
192             }
193             rpcForwarding = true;
194         }
195     }
196
197     public void startNotificationForwarding() {
198         checkState(!notificationForwarding, "Connector is already forwarding notifications.");
199         if (mappingService == null) {
200             LOG.warn("Unable to start Notification forwarding. Reason: Mapping Service is not initialized properly!");
201         } else if (baNotifyService == null) {
202             LOG.warn("Unable to start Notification forwarding. Reason: Binding Aware Notify Service is not initialized properly!");
203         } else if (domNotificationService == null) {
204             LOG.warn("Unable to start Notification forwarding. Reason: DOM Notification Service is not initialized properly!");
205         } else {
206             baNotifyService.registerInterestListener(
207                 new DomToBindingNotificationForwarder(mappingService, baNotifyService, domNotificationService));
208             notificationForwarding = true;
209         }
210     }
211
212     protected void setMappingService(final BindingIndependentMappingService mappingService) {
213         this.mappingService = mappingService;
214         bindingToDomCommitHandler.setMappingService(this.mappingService);
215         domToBindingCommitHandler.setMappingService(this.mappingService);
216     }
217
218     @Override
219     public Collection<ProviderFunctionality> getProviderFunctionality() {
220         return Collections.emptyList();
221     }
222
223     @Override
224     public void onSessionInitiated(final ProviderSession session) {
225         setDomDataService(session.getService(org.opendaylight.controller.sal.core.api.data.DataProviderService.class));
226         setDomRpcRegistry(session.getService(RpcProvisionRegistry.class));
227
228     }
229
230     public void setDomRpcRegistry(final RpcProvisionRegistry registry) {
231         biRpcRegistry = registry;
232     }
233
234     @Override
235     public void close() throws Exception {
236         if (biCommitHandlerRegistration != null) {
237             biCommitHandlerRegistration.close();
238         }
239     }
240
241     public boolean isRpcForwarding() {
242         return rpcForwarding;
243     }
244
245     public boolean isDataForwarding() {
246         return dataForwarding;
247     }
248
249     public boolean isNotificationForwarding() {
250         return notificationForwarding;
251     }
252
253     public BindingIndependentMappingService getMappingService() {
254         return mappingService;
255     }
256
257     public void setBindingNotificationService(final NotificationProviderService baService) {
258         this.baNotifyService = baService;
259
260     }
261
262     public void setDomNotificationService(final NotificationPublishService domService) {
263         this.domNotificationService = domService;
264     }
265 }