X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=dom%2Fmdsal-dom-spi%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fmdsal%2Fdom%2Fspi%2Fstore%2FAbstractDOMStoreTreeChangePublisher.java;h=2d9bf97364cb73ba280e2af39ac95d97289e6c04;hb=refs%2Fchanges%2F29%2F60629%2F3;hp=b0091681409f32aa348335cfbef4615f666bf23e;hpb=43e28da95d3511cf73882c16368c88295df7d35d;p=mdsal.git diff --git a/dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/store/AbstractDOMStoreTreeChangePublisher.java b/dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/store/AbstractDOMStoreTreeChangePublisher.java index b009168140..2d9bf97364 100644 --- a/dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/store/AbstractDOMStoreTreeChangePublisher.java +++ b/dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/store/AbstractDOMStoreTreeChangePublisher.java @@ -7,20 +7,26 @@ */ package org.opendaylight.mdsal.dom.spi.store; -import org.opendaylight.mdsal.dom.spi.AbstractDOMDataTreeChangeListenerRegistration; -import org.opendaylight.mdsal.dom.spi.AbstractRegistrationTree; -import org.opendaylight.mdsal.dom.spi.RegistrationTreeNode; -import org.opendaylight.mdsal.dom.spi.RegistrationTreeSnapshot; - -import org.opendaylight.mdsal.dom.api.DOMDataTreeChangeListener; +import com.google.common.base.Supplier; import com.google.common.collect.ImmutableList; +import com.google.common.collect.Multimap; +import com.google.common.collect.Multimaps; +import java.util.ArrayList; import java.util.Collection; +import java.util.IdentityHashMap; import java.util.List; +import java.util.Map; import javax.annotation.Nonnull; +import org.opendaylight.mdsal.dom.api.DOMDataTreeChangeListener; +import org.opendaylight.mdsal.dom.spi.AbstractDOMDataTreeChangeListenerRegistration; +import org.opendaylight.mdsal.dom.spi.AbstractRegistrationTree; +import org.opendaylight.mdsal.dom.spi.RegistrationTreeNode; +import org.opendaylight.mdsal.dom.spi.RegistrationTreeSnapshot; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate; import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNode; +import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidates; import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -28,28 +34,35 @@ import org.slf4j.LoggerFactory; /** * Abstract base class for {@link DOMStoreTreeChangePublisher} implementations. */ -public abstract class AbstractDOMStoreTreeChangePublisher extends AbstractRegistrationTree> implements DOMStoreTreeChangePublisher { +public abstract class AbstractDOMStoreTreeChangePublisher + extends AbstractRegistrationTree> + implements DOMStoreTreeChangePublisher { private static final Logger LOG = LoggerFactory.getLogger(AbstractDOMStoreTreeChangePublisher.class); + private static final Supplier> LIST_SUPPLIER = () -> new ArrayList<>(); + /** - * Callback for subclass to notify specified registrations of a candidate at a specified path. This method is guaranteed + * Callback for subclass to notify a specified registration of a list of candidates. This method is guaranteed * to be only called from within {@link #processCandidateTree(DataTreeCandidate)}. - * - * @param registrations Registrations which are affected by the candidate node - * @param path Path of changed candidate node. Guaranteed to match the path specified by the registration - * @param node Candidate node + * @param registration the registration to notify + * @param changes the list of DataTreeCandidate changes */ - protected abstract void notifyListeners(@Nonnull Collection> registrations, @Nonnull YangInstanceIdentifier path, @Nonnull DataTreeCandidateNode node); + protected abstract void notifyListener(@Nonnull AbstractDOMDataTreeChangeListenerRegistration registration, + @Nonnull Collection changes); /** - * Callback notifying the subclass that the specified registration is being closed and it's user no longer - * wishes to receive notifications. This notification is invoked while the {@link org.opendaylight.yangtools.concepts.ListenerRegistration#close()} - * method is executing. Subclasses can use this callback to properly remove any delayed notifications pending + * Callback notifying the subclass that the specified registration is being + * closed and it's user no longer + * wishes to receive notifications. This notification is invoked while + * the {@link org.opendaylight.yangtools.concepts.ListenerRegistration#close()} + * method is executing. Subclasses can use this callback to properly + * remove any delayed notifications pending * towards the registration. * * @param registration Registration which is being closed */ - protected abstract void registrationRemoved(@Nonnull AbstractDOMDataTreeChangeListenerRegistration registration); + protected abstract void registrationRemoved( + @Nonnull AbstractDOMDataTreeChangeListenerRegistration registration); /** * Process a candidate tree with respect to registered listeners. @@ -63,19 +76,30 @@ public abstract class AbstractDOMStoreTreeChangePublisher extends AbstractRegist return; } - try (final RegistrationTreeSnapshot> snapshot = takeSnapshot()) { + try (RegistrationTreeSnapshot> snapshot + = takeSnapshot()) { final List toLookup = ImmutableList.copyOf(candidate.getRootPath().getPathArguments()); - lookupAndNotify(toLookup, 0, snapshot.getRootNode(), candidate); + final Multimap, DataTreeCandidate> listenerChanges = + Multimaps.newListMultimap(new IdentityHashMap<>(), LIST_SUPPLIER); + lookupAndNotify(toLookup, 0, snapshot.getRootNode(), candidate, listenerChanges); + + for (Map.Entry, Collection> entry: + listenerChanges.asMap().entrySet()) { + notifyListener(entry.getKey(), entry.getValue()); + } } } @Override - public final AbstractDOMDataTreeChangeListenerRegistration registerTreeChangeListener(final YangInstanceIdentifier treeId, final L listener) { + public AbstractDOMDataTreeChangeListenerRegistration + registerTreeChangeListener(final YangInstanceIdentifier treeId, final L listener) { // Take the write lock takeLock(); try { - final RegistrationTreeNode> node = findNodeFor(treeId.getPathArguments()); - final AbstractDOMDataTreeChangeListenerRegistration reg = new AbstractDOMDataTreeChangeListenerRegistration(listener) { + final RegistrationTreeNode> node = + findNodeFor(treeId.getPathArguments()); + final AbstractDOMDataTreeChangeListenerRegistration reg = + new AbstractDOMDataTreeChangeListenerRegistration(listener) { @Override protected void removeRegistration() { AbstractDOMStoreTreeChangePublisher.this.removeRegistration(node, this); @@ -91,24 +115,32 @@ public abstract class AbstractDOMStoreTreeChangePublisher extends AbstractRegist } } - private void lookupAndNotify(final List args, final int offset, final RegistrationTreeNode> node, final DataTreeCandidate candidate) { + private void lookupAndNotify(final List args, + final int offset, final RegistrationTreeNode> node, + final DataTreeCandidate candidate, + final Multimap, DataTreeCandidate> listenerChanges) { if (args.size() != offset) { final PathArgument arg = args.get(offset); - final RegistrationTreeNode> exactChild = node.getExactChild(arg); + final RegistrationTreeNode> exactChild + = node.getExactChild(arg); if (exactChild != null) { - lookupAndNotify(args, offset + 1, exactChild, candidate); + lookupAndNotify(args, offset + 1, exactChild, candidate, listenerChanges); } - for (RegistrationTreeNode> c : node.getInexactChildren(arg)) { - lookupAndNotify(args, offset + 1, c, candidate); + for (RegistrationTreeNode> c : + node.getInexactChildren(arg)) { + lookupAndNotify(args, offset + 1, c, candidate, listenerChanges); } } else { - notifyNode(candidate.getRootPath(), node, candidate.getRootNode()); + notifyNode(candidate.getRootPath(), node, candidate.getRootNode(), listenerChanges); } } - private void notifyNode(final YangInstanceIdentifier path, final RegistrationTreeNode> regNode, final DataTreeCandidateNode candNode) { + private void notifyNode(final YangInstanceIdentifier path, + final RegistrationTreeNode> regNode, + final DataTreeCandidateNode candNode, + final Multimap, DataTreeCandidate> listenerChanges) { if (candNode.getModificationType() == ModificationType.UNMODIFIED) { LOG.debug("Skipping unmodified candidate {}", path); return; @@ -116,20 +148,33 @@ public abstract class AbstractDOMStoreTreeChangePublisher extends AbstractRegist final Collection> regs = regNode.getRegistrations(); if (!regs.isEmpty()) { - notifyListeners(regs, path, candNode); + addToListenerChanges(regs, path, candNode, listenerChanges); } for (DataTreeCandidateNode candChild : candNode.getChildNodes()) { if (candChild.getModificationType() != ModificationType.UNMODIFIED) { - final RegistrationTreeNode> regChild = regNode.getExactChild(candChild.getIdentifier()); + final RegistrationTreeNode> regChild = + regNode.getExactChild(candChild.getIdentifier()); if (regChild != null) { - notifyNode(path.node(candChild.getIdentifier()), regChild, candChild); + notifyNode(path.node(candChild.getIdentifier()), regChild, candChild, listenerChanges); } - for (RegistrationTreeNode> rc : regNode.getInexactChildren(candChild.getIdentifier())) { - notifyNode(path.node(candChild.getIdentifier()), rc, candChild); + for (RegistrationTreeNode> rc : + regNode.getInexactChildren(candChild.getIdentifier())) { + notifyNode(path.node(candChild.getIdentifier()), rc, candChild, listenerChanges); } } } } + + private static void addToListenerChanges( + final Collection> registrations, + final YangInstanceIdentifier path, final DataTreeCandidateNode node, + final Multimap, DataTreeCandidate> listenerChanges) { + final DataTreeCandidate dataTreeCandidate = DataTreeCandidates.newDataTreeCandidate(path, node); + + for (AbstractDOMDataTreeChangeListenerRegistration reg : registrations) { + listenerChanges.put(reg, dataTreeCandidate); + } + } }