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=c4f43d19ebf1c7e5944b31ad03fb26134e4f243d;hb=11408d627adca7eb71ac956c3ad01f75b6b91596;hp=bffb506c7f97dd1d50d2962edcc308aa031ec879;hpb=465c7e6c9d5bcaa647cf2e86aa3e1c65fc0d591d;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 bffb506c7f..c4f43d19eb 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 @@ -8,19 +8,24 @@ package org.opendaylight.mdsal.dom.spi.store; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ListMultimap; +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 javax.annotation.Nonnull; +import org.eclipse.jdt.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.ModificationType; +import org.opendaylight.yangtools.yang.data.tree.api.DataTreeCandidate; +import org.opendaylight.yangtools.yang.data.tree.api.DataTreeCandidateNode; +import org.opendaylight.yangtools.yang.data.tree.api.ModificationType; +import org.opendaylight.yangtools.yang.data.tree.spi.DataTreeCandidates; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -33,16 +38,13 @@ public abstract class AbstractDOMStoreTreeChangePublisher private static final Logger LOG = LoggerFactory.getLogger(AbstractDOMStoreTreeChangePublisher.class); /** - * 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 List changes); /** * Callback notifying the subclass that the specified registration is being @@ -56,25 +58,32 @@ public abstract class AbstractDOMStoreTreeChangePublisher * @param registration Registration which is being closed */ protected abstract void registrationRemoved( - @Nonnull AbstractDOMDataTreeChangeListenerRegistration registration); + @NonNull AbstractDOMDataTreeChangeListenerRegistration registration); /** * Process a candidate tree with respect to registered listeners. * * @param candidate candidate three which needs to be processed + * @return true if at least one listener was notified or false. */ - protected final void processCandidateTree(@Nonnull final DataTreeCandidate candidate) { + protected final boolean processCandidateTree(final @NonNull DataTreeCandidate candidate) { final DataTreeCandidateNode node = candidate.getRootNode(); if (node.getModificationType() == ModificationType.UNMODIFIED) { LOG.debug("Skipping unmodified candidate {}", candidate); - return; + return false; } - try (final RegistrationTreeSnapshot> snapshot - = takeSnapshot()) { - final List toLookup - = ImmutableList.copyOf(candidate.getRootPath().getPathArguments()); - lookupAndNotify(toLookup, 0, snapshot.getRootNode(), candidate); + try (var snapshot = takeSnapshot()) { + final List toLookup = ImmutableList.copyOf(candidate.getRootPath().getPathArguments()); + final ListMultimap, DataTreeCandidate> listenerChanges = + Multimaps.newListMultimap(new IdentityHashMap<>(), ArrayList::new); + lookupAndNotify(toLookup, 0, snapshot.getRootNode(), candidate, listenerChanges); + + for (var entry : Multimaps.asMap(listenerChanges).entrySet()) { + notifyListener(entry.getKey(), entry.getValue()); + } + + return !listenerChanges.isEmpty(); } } @@ -86,8 +95,7 @@ public abstract class AbstractDOMStoreTreeChangePublisher try { final RegistrationTreeNode> node = findNodeFor(treeId.getPathArguments()); - final AbstractDOMDataTreeChangeListenerRegistration reg = - new AbstractDOMDataTreeChangeListenerRegistration(listener) { + final var reg = new AbstractDOMDataTreeChangeListenerRegistration<>(listener) { @Override protected void removeRegistration() { AbstractDOMStoreTreeChangePublisher.this.removeRegistration(node, this); @@ -105,28 +113,30 @@ public abstract class AbstractDOMStoreTreeChangePublisher private void lookupAndNotify(final List args, final int offset, final RegistrationTreeNode> node, - final DataTreeCandidate candidate) { + final DataTreeCandidate candidate, + final Multimap, DataTreeCandidate> listenerChanges) { if (args.size() != offset) { final PathArgument arg = args.get(offset); 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); + 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) { + final DataTreeCandidateNode candNode, + final Multimap, DataTreeCandidate> listenerChanges) { if (candNode.getModificationType() == ModificationType.UNMODIFIED) { LOG.debug("Skipping unmodified candidate {}", path); return; @@ -134,7 +144,7 @@ public abstract class AbstractDOMStoreTreeChangePublisher final Collection> regs = regNode.getRegistrations(); if (!regs.isEmpty()) { - notifyListeners(regs, path, candNode); + addToListenerChanges(regs, path, candNode, listenerChanges); } for (DataTreeCandidateNode candChild : candNode.getChildNodes()) { @@ -142,14 +152,25 @@ public abstract class AbstractDOMStoreTreeChangePublisher 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); + 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); + } + } }