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=0b38025b2a030d056bae3dba3037eb66b6811d3f;hb=b8a896e6dfc47374f99efee157683dc8a7ef8860;hp=8bc0499f6bd1a7aca8bf1fd094baec752f06e4b5;hpb=fa49cff3709ce3bb64f0d4c473af477431d10cf0;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 8bc0499f6b..0b38025b2a 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,26 +7,22 @@ */ package org.opendaylight.mdsal.dom.spi.store; -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 org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.NonNullByDefault; 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.concepts.AbstractObjectRegistration; +import org.opendaylight.yangtools.concepts.Registration; 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.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; @@ -34,32 +30,73 @@ import org.slf4j.LoggerFactory; * Abstract base class for {@link DOMStoreTreeChangePublisher} implementations. */ public abstract class AbstractDOMStoreTreeChangePublisher - extends AbstractRegistrationTree> + extends AbstractRegistrationTree implements DOMStoreTreeChangePublisher { + /** + * A handle to a registered {@link DOMDataTreeChangeListener}. Implementations of this interface are guaranteed to + * use identity-based equality. + */ + @NonNullByDefault + protected sealed interface Reg permits RegImpl { + /** + * Return the underlying listener. + * + * @return the underlying listener + */ + DOMDataTreeChangeListener listener(); + + /** + * Check if this handle has not been closed yet. + * + * @return {@code true} if this handle is still open + */ + boolean notClosed(); + } + + /** + * Registration handle for a {@link DOMDataTreeChangeListener}. This class is exposed to subclasses only as a + * convenience, so they can use its identity-based equality while at the same time having access to the listener. + * + *

+ * Implementations must not invoke {@link #close()} nor should otherwise interact with the registration. + */ + @NonNullByDefault + final class RegImpl extends AbstractObjectRegistration implements Reg { + private RegImpl(final DOMDataTreeChangeListener instance) { + super(instance); + } + + @Override + public DOMDataTreeChangeListener listener() { + return getInstance(); + } + + @Override + protected void removeRegistration() { + registrationRemoved(this); + } + } + private static final Logger LOG = LoggerFactory.getLogger(AbstractDOMStoreTreeChangePublisher.class); /** * 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 registration the registration to notify * @param changes the list of DataTreeCandidate changes */ - protected abstract void notifyListener(@NonNull AbstractDOMDataTreeChangeListenerRegistration registration, - @NonNull Collection changes); + protected abstract void notifyListener(@NonNull Reg registration, @NonNull List 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 - * towards the registration. + * 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.Registration#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 Reg registration); /** * Process a candidate tree with respect to registered listeners. @@ -68,21 +105,18 @@ public abstract class AbstractDOMStoreTreeChangePublisher * @return true if at least one listener was notified or false. */ protected final boolean processCandidateTree(final @NonNull DataTreeCandidate candidate) { - final DataTreeCandidateNode node = candidate.getRootNode(); - if (node.getModificationType() == ModificationType.UNMODIFIED) { + final var node = candidate.getRootNode(); + if (node.modificationType() == ModificationType.UNMODIFIED) { LOG.debug("Skipping unmodified candidate {}", candidate); return false; } - try (RegistrationTreeSnapshot> snapshot - = takeSnapshot()) { - final List toLookup = ImmutableList.copyOf(candidate.getRootPath().getPathArguments()); - final Multimap, DataTreeCandidate> listenerChanges = - Multimaps.newListMultimap(new IdentityHashMap<>(), ArrayList::new); + try (var snapshot = takeSnapshot()) { + final var toLookup = List.copyOf(candidate.getRootPath().getPathArguments()); + final var listenerChanges = new IdentityHashMap>(); lookupAndNotify(toLookup, 0, snapshot.getRootNode(), candidate, listenerChanges); - for (Map.Entry, Collection> entry: - listenerChanges.asMap().entrySet()) { + for (var entry : listenerChanges.entrySet()) { notifyListener(entry.getKey(), entry.getValue()); } @@ -91,23 +125,13 @@ public abstract class AbstractDOMStoreTreeChangePublisher } @Override - public AbstractDOMDataTreeChangeListenerRegistration - registerTreeChangeListener(final YangInstanceIdentifier treeId, final L listener) { + public final Registration registerTreeChangeListener(final YangInstanceIdentifier treeId, + final DOMDataTreeChangeListener listener) { // Take the write lock takeLock(); try { - final RegistrationTreeNode> node = - findNodeFor(treeId.getPathArguments()); - final AbstractDOMDataTreeChangeListenerRegistration reg = - new AbstractDOMDataTreeChangeListenerRegistration(listener) { - @Override - protected void removeRegistration() { - AbstractDOMStoreTreeChangePublisher.this.removeRegistration(node, this); - registrationRemoved(this); - } - }; - - addRegistration(node, reg); + final var reg = new RegImpl(listener); + addRegistration(findNodeFor(treeId.getPathArguments()), reg); return reg; } finally { // Always release the lock @@ -115,66 +139,63 @@ public abstract class AbstractDOMStoreTreeChangePublisher } } - 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); - if (exactChild != null) { - lookupAndNotify(args, offset + 1, exactChild, candidate, listenerChanges); - } + /** + * {@inheritDoc} + * + *

+ * This implementation calls {@link #registerTreeChangeListener(YangInstanceIdentifier, DOMDataTreeChangeListener)}, + * override if necessary. + */ + @Override + @Deprecated(since = "13.0.0", forRemoval = true) + public Registration registerLegacyTreeChangeListener(final YangInstanceIdentifier treeId, + final DOMDataTreeChangeListener listener) { + return registerTreeChangeListener(treeId, listener); + } - for (RegistrationTreeNode> c : - node.getInexactChildren(arg)) { - lookupAndNotify(args, offset + 1, c, candidate, listenerChanges); - } - } else { + private void lookupAndNotify(final List args, final int offset, final Node node, + final DataTreeCandidate candidate, final Map> listenerChanges) { + if (args.size() == offset) { notifyNode(candidate.getRootPath(), node, candidate.getRootNode(), listenerChanges); + return; + } + + final var arg = args.get(offset); + final var exactChild = node.getExactChild(arg); + if (exactChild != null) { + lookupAndNotify(args, offset + 1, exactChild, candidate, listenerChanges); + } + for (var child : node.getInexactChildren(arg)) { + lookupAndNotify(args, offset + 1, child, candidate, listenerChanges); } } - private void notifyNode(final YangInstanceIdentifier path, - final RegistrationTreeNode> regNode, - final DataTreeCandidateNode candNode, - final Multimap, DataTreeCandidate> listenerChanges) { - if (candNode.getModificationType() == ModificationType.UNMODIFIED) { + private void notifyNode(final YangInstanceIdentifier path, final Node regNode, + final DataTreeCandidateNode candNode, final Map> listenerChanges) { + if (candNode.modificationType() == ModificationType.UNMODIFIED) { LOG.debug("Skipping unmodified candidate {}", path); return; } - final Collection> regs = regNode.getRegistrations(); + final var regs = regNode.getRegistrations(); if (!regs.isEmpty()) { - addToListenerChanges(regs, path, candNode, listenerChanges); + final var dataTreeCandidate = DataTreeCandidates.newDataTreeCandidate(path, candNode); + for (var reg : regs) { + listenerChanges.computeIfAbsent(reg, ignored -> new ArrayList<>()).add(dataTreeCandidate); + } } - for (DataTreeCandidateNode candChild : candNode.getChildNodes()) { - if (candChild.getModificationType() != ModificationType.UNMODIFIED) { - final RegistrationTreeNode> regChild = - regNode.getExactChild(candChild.getIdentifier()); + for (var candChild : candNode.childNodes()) { + if (candChild.modificationType() != ModificationType.UNMODIFIED) { + final var regChild = regNode.getExactChild(candChild.name()); if (regChild != null) { - notifyNode(path.node(candChild.getIdentifier()), regChild, candChild, listenerChanges); + notifyNode(path.node(candChild.name()), regChild, candChild, listenerChanges); } - for (RegistrationTreeNode> rc : - regNode.getInexactChildren(candChild.getIdentifier())) { - notifyNode(path.node(candChild.getIdentifier()), rc, candChild, listenerChanges); + for (var rc : regNode.getInexactChildren(candChild.name())) { + notifyNode(path.node(candChild.name()), 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); - } - } }