1 package org.opendaylight.controller.md.sal.dom.store.impl;
3 import static org.opendaylight.controller.md.sal.dom.store.impl.DOMImmutableDataChangeEvent.builder;
4 import static org.opendaylight.controller.md.sal.dom.store.impl.StoreUtils.append;
5 import static org.opendaylight.controller.md.sal.dom.store.impl.tree.TreeNodeUtils.getChild;
7 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
8 import org.opendaylight.controller.md.sal.dom.store.impl.DOMImmutableDataChangeEvent.Builder;
9 import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerRegistrationNode;
10 import org.opendaylight.controller.md.sal.dom.store.impl.tree.NodeModification;
11 import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
12 import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerRegistrationNode.DataChangeListenerRegistration;
13 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
14 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
15 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
17 import com.google.common.base.Optional;
18 import com.google.common.collect.ImmutableList;
19 import com.google.common.collect.ImmutableSet;
21 public class DataChangeEventResolver {
23 private static final DOMImmutableDataChangeEvent NO_CHANGE = builder().build();
24 private InstanceIdentifier rootPath;
25 private ListenerRegistrationNode listenerRoot;
26 private NodeModification modificationRoot;
27 private Optional<StoreMetadataNode> beforeRoot;
28 private Optional<StoreMetadataNode> afterRoot;
29 private final ImmutableList.Builder<ChangeListenerNotifyTask> tasks = ImmutableList.builder();
31 protected InstanceIdentifier getRootPath() {
35 protected DataChangeEventResolver setRootPath(final InstanceIdentifier rootPath) {
36 this.rootPath = rootPath;
40 protected ListenerRegistrationNode getListenerRoot() {
44 protected DataChangeEventResolver setListenerRoot(final ListenerRegistrationNode listenerRoot) {
45 this.listenerRoot = listenerRoot;
49 protected NodeModification getModificationRoot() {
50 return modificationRoot;
53 protected DataChangeEventResolver setModificationRoot(final NodeModification modificationRoot) {
54 this.modificationRoot = modificationRoot;
58 protected Optional<StoreMetadataNode> getBeforeRoot() {
62 protected DataChangeEventResolver setBeforeRoot(final Optional<StoreMetadataNode> beforeRoot) {
63 this.beforeRoot = beforeRoot;
67 protected Optional<StoreMetadataNode> getAfterRoot() {
71 protected DataChangeEventResolver setAfterRoot(final Optional<StoreMetadataNode> afterRoot) {
72 this.afterRoot = afterRoot;
76 public Iterable<ChangeListenerNotifyTask> resolve() {
77 resolveAnyChangeEvent(rootPath, Optional.of(listenerRoot), modificationRoot, beforeRoot, afterRoot);
81 private DOMImmutableDataChangeEvent resolveAnyChangeEvent(final InstanceIdentifier path,
82 final Optional<ListenerRegistrationNode> listeners, final NodeModification modification,
83 final Optional<StoreMetadataNode> before, final Optional<StoreMetadataNode> after) {
84 // No listeners are present in listener registration subtree
85 // no before and after state is present
86 if (!before.isPresent() && !after.isPresent()) {
89 switch (modification.getModificationType()) {
90 case SUBTREE_MODIFIED:
91 return resolveSubtreeChangeEvent(path, listeners, modification, before.get(), after.get());
93 if (before.isPresent()) {
94 return resolveReplacedEvent(path, listeners, modification, before.get(), after.get());
96 return resolveCreateEvent(path, listeners, after.get());
99 return resolveDeleteEvent(path, listeners, before.get());
107 * Resolves create events deep down the interest listener tree.
115 private DOMImmutableDataChangeEvent resolveCreateEvent(final InstanceIdentifier path,
116 final Optional<ListenerRegistrationNode> listeners, final StoreMetadataNode afterState) {
117 final NormalizedNode<?, ?> node = afterState.getData();
118 Builder builder = builder().setAfter(node).addCreated(path, node);
120 for (StoreMetadataNode child : afterState.getChildren()) {
121 PathArgument childId = child.getIdentifier();
122 Optional<ListenerRegistrationNode> childListeners = getChild(listeners, childId);
124 InstanceIdentifier childPath = StoreUtils.append(path, childId);
125 builder.merge(resolveCreateEvent(childPath, childListeners, child));
127 DOMImmutableDataChangeEvent event = builder.build();
128 if (listeners.isPresent()) {
129 addNotifyTask(listeners.get().getListeners(), event);
134 private DOMImmutableDataChangeEvent resolveDeleteEvent(final InstanceIdentifier path,
135 final Optional<ListenerRegistrationNode> listeners, final StoreMetadataNode beforeState) {
136 final NormalizedNode<?, ?> node = beforeState.getData();
137 Builder builder = builder().setBefore(node).addRemoved(path, node);
139 for (StoreMetadataNode child : beforeState.getChildren()) {
140 PathArgument childId = child.getIdentifier();
141 Optional<ListenerRegistrationNode> childListeners = getChild(listeners, childId);
142 InstanceIdentifier childPath = StoreUtils.append(path, childId);
143 builder.merge(resolveDeleteEvent(childPath, childListeners, child));
145 DOMImmutableDataChangeEvent event = builder.build();
146 if (listeners.isPresent()) {
147 addNotifyTask(listeners.get().getListeners(), event);
153 private DOMImmutableDataChangeEvent resolveSubtreeChangeEvent(final InstanceIdentifier path,
154 final Optional<ListenerRegistrationNode> listeners, final NodeModification modification,
155 final StoreMetadataNode before, final StoreMetadataNode after) {
157 Builder one = builder().setBefore(before.getData()).setAfter(after.getData());
159 Builder subtree = builder();
161 for (NodeModification childMod : modification.getModifications()) {
162 PathArgument childId = childMod.getIdentifier();
163 InstanceIdentifier childPath = append(path, childId);
164 Optional<ListenerRegistrationNode> childListen = getChild(listeners, childId);
166 Optional<StoreMetadataNode> childBefore = before.getChild(childId);
167 Optional<StoreMetadataNode> childAfter = after.getChild(childId);
169 switch (childMod.getModificationType()) {
172 one.merge(resolveAnyChangeEvent(childPath, childListen, childMod, childBefore, childBefore));
174 case SUBTREE_MODIFIED:
175 subtree.merge(resolveSubtreeChangeEvent(childPath, childListen, childMod, childBefore.get(),
180 DOMImmutableDataChangeEvent oneChangeEvent = one.build();
181 subtree.merge(oneChangeEvent);
182 DOMImmutableDataChangeEvent subtreeEvent = subtree.build();
183 if (listeners.isPresent()) {
184 addNotifyTask(listeners.get(), DataChangeScope.ONE, oneChangeEvent);
185 addNotifyTask(listeners.get(), DataChangeScope.SUBTREE, subtreeEvent);
190 private DOMImmutableDataChangeEvent resolveReplacedEvent(final InstanceIdentifier path,
191 final Optional<ListenerRegistrationNode> listeners, final NodeModification modification,
192 final StoreMetadataNode before, final StoreMetadataNode after) {
194 return builder().build();
197 private void addNotifyTask(final ListenerRegistrationNode listenerRegistrationNode, final DataChangeScope one,
198 final DOMImmutableDataChangeEvent event) {
204 private void addNotifyTask(final Iterable<DataChangeListenerRegistration<?>> listeners,
205 final DOMImmutableDataChangeEvent event) {
206 tasks .add(new ChangeListenerNotifyTask(ImmutableSet.copyOf(listeners),event));
209 public static DataChangeEventResolver create() {
210 return new DataChangeEventResolver();