Deprecate all MD-SAL APIs
[controller.git] / opendaylight / md-sal / sal-dom-spi / src / main / java / org / opendaylight / controller / sal / core / spi / data / AbstractDOMStoreTreeChangePublisher.java
1 /*
2  * Copyright (c) 2015 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.core.spi.data;
9
10 import java.util.Collection;
11 import java.util.List;
12 import org.eclipse.jdt.annotation.NonNull;
13 import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeChangeListener;
14 import org.opendaylight.controller.md.sal.dom.spi.AbstractDOMDataTreeChangeListenerRegistration;
15 import org.opendaylight.mdsal.dom.spi.AbstractRegistrationTree;
16 import org.opendaylight.mdsal.dom.spi.RegistrationTreeNode;
17 import org.opendaylight.mdsal.dom.spi.RegistrationTreeSnapshot;
18 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
19 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
20 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
21 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNode;
22 import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
25
26 /**
27  * Abstract base class for {@link DOMStoreTreeChangePublisher} implementations.
28  *
29  * @deprecated Use {@link org.opendaylight.mdsal.dom.spi.store.AbstractDOMStoreTreeChangePublisher} instead.
30  */
31 @Deprecated
32 public abstract class AbstractDOMStoreTreeChangePublisher
33         extends AbstractRegistrationTree<AbstractDOMDataTreeChangeListenerRegistration<?>>
34         implements DOMStoreTreeChangePublisher {
35     private static final Logger LOG = LoggerFactory.getLogger(AbstractDOMStoreTreeChangePublisher.class);
36
37     /**
38      * Callback for subclass to notify specified registrations of a candidate at a specified path. This method is
39      * guaranteed to be only called from within {@link #processCandidateTree(DataTreeCandidate)}.
40      *
41      * @param registrations Registrations which are affected by the candidate node
42      * @param path Path of changed candidate node. Guaranteed to match the path specified by the registration
43      * @param node Candidate node
44      */
45     protected abstract void notifyListeners(@NonNull Collection<AbstractDOMDataTreeChangeListenerRegistration<?>>
46             registrations, @NonNull YangInstanceIdentifier path, @NonNull DataTreeCandidateNode node);
47
48     /**
49      * Callback notifying the subclass that the specified registration is being closed and it's user no longer
50      * wishes to receive notifications. This notification is invoked while the
51      * {@link org.opendaylight.yangtools.concepts.ListenerRegistration#close()}
52      * method is executing. Subclasses can use this callback to properly remove any delayed notifications pending
53      * towards the registration.
54      *
55      * @param registration Registration which is being closed
56      */
57     protected abstract void registrationRemoved(@NonNull AbstractDOMDataTreeChangeListenerRegistration<?> registration);
58
59     /**
60      * Process a candidate tree with respect to registered listeners.
61      *
62      * @param candidate candidate three which needs to be processed
63      */
64     protected final void processCandidateTree(final @NonNull DataTreeCandidate candidate) {
65         final DataTreeCandidateNode node = candidate.getRootNode();
66         if (node.getModificationType() == ModificationType.UNMODIFIED) {
67             LOG.debug("Skipping unmodified candidate {}", candidate);
68             return;
69         }
70
71         try (RegistrationTreeSnapshot<AbstractDOMDataTreeChangeListenerRegistration<?>> snapshot = takeSnapshot()) {
72             lookupAndNotify(candidate.getRootPath().getPathArguments(), 0, snapshot.getRootNode(), candidate);
73         }
74     }
75
76     @Override
77     public final <L extends DOMDataTreeChangeListener> AbstractDOMDataTreeChangeListenerRegistration<L>
78             registerTreeChangeListener(final YangInstanceIdentifier treeId, final L listener) {
79         // Take the write lock
80         takeLock();
81         try {
82             final RegistrationTreeNode<AbstractDOMDataTreeChangeListenerRegistration<?>> node =
83                     findNodeFor(treeId.getPathArguments());
84             final AbstractDOMDataTreeChangeListenerRegistration<L> reg =
85                 new AbstractDOMDataTreeChangeListenerRegistration<L>(listener) {
86                     @Override
87                     protected void removeRegistration() {
88                         AbstractDOMStoreTreeChangePublisher.this.removeRegistration(node, this);
89                         registrationRemoved(this);
90                     }
91             };
92
93             addRegistration(node, reg);
94             return reg;
95         } finally {
96             // Always release the lock
97             releaseLock();
98         }
99     }
100
101     private void lookupAndNotify(final List<PathArgument> args, final int offset,
102             final RegistrationTreeNode<AbstractDOMDataTreeChangeListenerRegistration<?>> node,
103             final DataTreeCandidate candidate) {
104         if (args.size() != offset) {
105             final PathArgument arg = args.get(offset);
106
107             final RegistrationTreeNode<AbstractDOMDataTreeChangeListenerRegistration<?>> exactChild =
108                     node.getExactChild(arg);
109             if (exactChild != null) {
110                 lookupAndNotify(args, offset + 1, exactChild, candidate);
111             }
112
113             for (RegistrationTreeNode<AbstractDOMDataTreeChangeListenerRegistration<?>> c :
114                     node.getInexactChildren(arg)) {
115                 lookupAndNotify(args, offset + 1, c, candidate);
116             }
117         } else {
118             notifyNode(candidate.getRootPath(), node, candidate.getRootNode());
119         }
120     }
121
122     private void notifyNode(final YangInstanceIdentifier path,
123             final RegistrationTreeNode<AbstractDOMDataTreeChangeListenerRegistration<?>> regNode,
124             final DataTreeCandidateNode candNode) {
125         if (candNode.getModificationType() == ModificationType.UNMODIFIED) {
126             LOG.debug("Skipping unmodified candidate {}", path);
127             return;
128         }
129
130         final Collection<AbstractDOMDataTreeChangeListenerRegistration<?>> regs = regNode.getRegistrations();
131         if (!regs.isEmpty()) {
132             notifyListeners(regs, path, candNode);
133         }
134
135         for (DataTreeCandidateNode candChild : candNode.getChildNodes()) {
136             if (candChild.getModificationType() != ModificationType.UNMODIFIED) {
137                 final RegistrationTreeNode<AbstractDOMDataTreeChangeListenerRegistration<?>> regChild =
138                         regNode.getExactChild(candChild.getIdentifier());
139                 if (regChild != null) {
140                     notifyNode(path.node(candChild.getIdentifier()), regChild, candChild);
141                 }
142
143                 for (RegistrationTreeNode<AbstractDOMDataTreeChangeListenerRegistration<?>> rc :
144                         regNode.getInexactChildren(candChild.getIdentifier())) {
145                     notifyNode(path.node(candChild.getIdentifier()), rc, candChild);
146                 }
147             }
148         }
149     }
150 }