Merge "Resolve Bug:522"
[controller.git] / opendaylight / md-sal / sal-binding-broker / src / main / java / org / opendaylight / controller / md / sal / binding / impl / AbstractForwardedDataBroker.java
1 /*
2  * Copyright (c) 2014 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.md.sal.binding.impl;
9
10 import java.util.HashMap;
11 import java.util.HashSet;
12 import java.util.Map;
13 import java.util.Map.Entry;
14 import java.util.Set;
15
16 import org.eclipse.xtext.xbase.lib.Exceptions;
17 import org.opendaylight.controller.md.sal.binding.api.BindingDataChangeListener;
18 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
19 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
20 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
21 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
22 import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener;
23 import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentConnector;
24 import org.opendaylight.controller.sal.binding.impl.forward.DomForwardedBroker;
25 import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
26 import org.opendaylight.yangtools.concepts.AbstractListenerRegistration;
27 import org.opendaylight.yangtools.concepts.Delegator;
28 import org.opendaylight.yangtools.concepts.ListenerRegistration;
29 import org.opendaylight.yangtools.yang.binding.DataObject;
30 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
31 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
32 import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
33 import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
34 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
35 import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBroker>, DomForwardedBroker, SchemaContextListener {
40
41     private static final Logger LOG = LoggerFactory.getLogger(AbstractForwardedDataBroker.class);
42     // The Broker to whom we do all forwarding
43     private final DOMDataBroker domDataBroker;
44
45     // Mapper to convert from Binding Independent objects to Binding Aware
46     // objects
47     private final BindingIndependentMappingService mappingService;
48
49     private final BindingToNormalizedNodeCodec codec;
50     private BindingIndependentConnector connector;
51     private ProviderSession context;
52
53     protected AbstractForwardedDataBroker(final DOMDataBroker domDataBroker,
54             final BindingIndependentMappingService mappingService) {
55         this.domDataBroker = domDataBroker;
56         this.mappingService = mappingService;
57         this.codec = new BindingToNormalizedNodeCodec(mappingService);
58     }
59
60     protected BindingToNormalizedNodeCodec getCodec() {
61         return codec;
62     }
63
64     protected BindingIndependentMappingService getMappingService() {
65         return mappingService;
66     }
67
68     @Override
69     public DOMDataBroker getDelegate() {
70         return domDataBroker;
71     }
72
73     @Override
74     public void onGlobalContextUpdated(final SchemaContext ctx) {
75         codec.onGlobalContextUpdated(ctx);
76     }
77
78     public ListenerRegistration<BindingDataChangeListener> registerDataChangeListener(final LogicalDatastoreType store,
79             final InstanceIdentifier<?> path, final BindingDataChangeListener listener,
80             final DataChangeScope triggeringScope) {
81         DOMDataChangeListener domDataChangeListener = new TranslatingDataChangeInvoker(store, path, listener,
82                 triggeringScope);
83         org.opendaylight.yangtools.yang.data.api.InstanceIdentifier domPath = codec.toNormalized(path);
84         ListenerRegistration<DOMDataChangeListener> domRegistration = domDataBroker.registerDataChangeListener(store, domPath, domDataChangeListener, triggeringScope);
85         return new ListenerRegistrationImpl(listener, domRegistration);
86     }
87
88     protected Map<InstanceIdentifier<?>, DataObject> fromDOMToData(
89             final Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, ? extends NormalizedNode<?, ?>> normalized) {
90         Map<InstanceIdentifier<?>, DataObject> newMap = new HashMap<>();
91         for (Map.Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, ? extends NormalizedNode<?, ?>> entry : normalized
92                 .entrySet()) {
93             try {
94                 Entry<InstanceIdentifier<? extends DataObject>, DataObject> binding = getCodec().toBinding(entry);
95                 newMap.put(binding.getKey(), binding.getValue());
96             } catch (DeserializationException e) {
97                 LOG.debug("Ommiting {}",entry,e);
98             }
99         }
100         return newMap;
101     }
102
103     private class TranslatingDataChangeInvoker implements DOMDataChangeListener {
104         private final BindingDataChangeListener bindingDataChangeListener;
105         private final LogicalDatastoreType store;
106         private final InstanceIdentifier<?> path;
107         private final DataChangeScope triggeringScope;
108
109         public TranslatingDataChangeInvoker(final LogicalDatastoreType store, final InstanceIdentifier<?> path,
110                 final BindingDataChangeListener bindingDataChangeListener, final DataChangeScope triggeringScope) {
111             this.store = store;
112             this.path = path;
113             this.bindingDataChangeListener = bindingDataChangeListener;
114             this.triggeringScope = triggeringScope;
115         }
116
117         @Override
118         public void onDataChanged(
119                 final AsyncDataChangeEvent<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> change) {
120             bindingDataChangeListener.onDataChanged(new TranslatedDataChangeEvent(change,path));
121         }
122     }
123
124     private class TranslatedDataChangeEvent implements AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> {
125         private final AsyncDataChangeEvent<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> domEvent;
126         private InstanceIdentifier<?> path;
127
128         public TranslatedDataChangeEvent(
129                 final AsyncDataChangeEvent<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> change) {
130             this.domEvent = change;
131         }
132
133         public TranslatedDataChangeEvent(
134                 final AsyncDataChangeEvent<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> change,
135                 final InstanceIdentifier<?> path) {
136             this.domEvent = change;
137             this.path = path;
138         }
139
140         @Override
141         public Map<InstanceIdentifier<?>, DataObject> getCreatedData() {
142             return fromDOMToData(domEvent.getCreatedData());
143         }
144
145         @Override
146         public Map<InstanceIdentifier<?>, DataObject> getUpdatedData() {
147             return fromDOMToData(domEvent.getUpdatedData());
148
149         }
150
151         @Override
152         public Set<InstanceIdentifier<?>> getRemovedPaths() {
153             final Set<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier> removedPaths = domEvent
154                     .getRemovedPaths();
155             final Set<InstanceIdentifier<?>> output = new HashSet<>();
156             for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier instanceIdentifier : removedPaths) {
157                 try {
158                     output.add(mappingService.fromDataDom(instanceIdentifier));
159                 } catch (DeserializationException e) {
160                     Exceptions.sneakyThrow(e);
161                 }
162             }
163
164             return output;
165         }
166
167         @Override
168         public Map<InstanceIdentifier<?>, ? extends DataObject> getOriginalData() {
169             return fromDOMToData(domEvent.getOriginalData());
170
171         }
172
173         @Override
174         public DataObject getOriginalSubtree() {
175
176             return toBindingData(path,domEvent.getOriginalSubtree());
177         }
178
179         @Override
180         public DataObject getUpdatedSubtree() {
181
182             return toBindingData(path,domEvent.getUpdatedSubtree());
183         }
184
185         @Override
186         public String toString() {
187             return "TranslatedDataChangeEvent [domEvent=" + domEvent + "]";
188         }
189     }
190
191     private static class ListenerRegistrationImpl extends AbstractListenerRegistration<BindingDataChangeListener> {
192         private final ListenerRegistration<DOMDataChangeListener> registration;
193
194         public ListenerRegistrationImpl(final BindingDataChangeListener listener,
195                 final ListenerRegistration<DOMDataChangeListener> registration) {
196             super(listener);
197             this.registration = registration;
198         }
199
200         @Override
201         protected void removeRegistration() {
202             registration.close();
203         }
204     }
205
206     protected DataObject toBindingData(final InstanceIdentifier<?> path, final NormalizedNode<?, ?> data) {
207         try {
208             return getCodec().toBinding(path, data);
209         } catch (DeserializationException e) {
210             return null;
211         }
212     }
213
214
215     @Override
216     public BindingIndependentConnector getConnector() {
217         return this.connector;
218     }
219
220     @Override
221     public ProviderSession getDomProviderContext() {
222         return this.context;
223     }
224
225     @Override
226     public void setConnector(final BindingIndependentConnector connector) {
227         this.connector = connector;
228     }
229
230     @Override
231     public void setDomProviderContext(final ProviderSession domProviderContext) {
232        this.context = domProviderContext;
233     }
234
235     @Override
236     public void startForwarding() {
237         // NOOP
238     }
239
240
241
242
243 }