1 package org.opendaylight.controller.md.sal.dom.store.impl.tree;
3 import java.util.Collection;
4 import java.util.HashMap;
5 import java.util.HashSet;
8 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
9 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
10 import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
11 import org.opendaylight.yangtools.concepts.Identifiable;
12 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
13 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
14 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
15 import org.slf4j.Logger;
16 import org.slf4j.LoggerFactory;
18 import com.google.common.base.Optional;
20 public class ListenerRegistrationNode implements StoreTreeNode<ListenerRegistrationNode>, Identifiable<PathArgument> {
22 private static final Logger LOG = LoggerFactory.getLogger(ListenerRegistrationNode.class);
24 private final ListenerRegistrationNode parent;
25 private final Map<PathArgument, ListenerRegistrationNode> children;
26 private final PathArgument identifier;
27 private final HashSet<DataChangeListenerRegistration<?>> listeners;
29 private ListenerRegistrationNode(final PathArgument identifier) {
30 this(null, identifier);
33 private ListenerRegistrationNode(final ListenerRegistrationNode parent, final PathArgument identifier) {
35 this.identifier = identifier;
36 children = new HashMap<>();
37 listeners = new HashSet<>();
40 public final static ListenerRegistrationNode createRoot() {
41 return new ListenerRegistrationNode(null);
45 public PathArgument getIdentifier() {
50 * Return the list of current listeners. Any caller wishing to use this method
51 * has to make sure the collection remains unchanged while it's executing. This
52 * means the caller has to synchronize externally both the registration and
53 * unregistration process.
55 * @return the list of current listeners
57 @SuppressWarnings({ "rawtypes", "unchecked" })
58 public Collection<org.opendaylight.controller.md.sal.dom.store.impl.DataChangeListenerRegistration<?>> getListeners() {
59 return (Collection) listeners;
63 public synchronized Optional<ListenerRegistrationNode> getChild(final PathArgument child) {
64 return Optional.fromNullable(children.get(child));
67 public synchronized ListenerRegistrationNode ensureChild(final PathArgument child) {
68 ListenerRegistrationNode potential = (children.get(child));
69 if (potential == null) {
70 potential = new ListenerRegistrationNode(this, child);
71 children.put(child, potential);
77 * Registers listener on this node.
79 * @param path Full path on which listener is registered.
80 * @param listener Listener
81 * @param scope Scope of triggering event.
84 public synchronized <L extends AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>> DataChangeListenerRegistration<L> registerDataChangeListener(final InstanceIdentifier path,
85 final L listener, final DataChangeScope scope) {
87 DataChangeListenerRegistration<L> listenerReg = new DataChangeListenerRegistration<L>(path,listener, scope, this);
88 listeners.add(listenerReg);
89 LOG.debug("Listener {} registered", listener);
93 private synchronized void removeListener(final DataChangeListenerRegistration<?> listener) {
94 listeners.remove(listener);
95 LOG.debug("Listener {} unregistered", listener);
99 private void removeThisIfUnused() {
100 if (parent != null && listeners.isEmpty() && children.isEmpty()) {
101 parent.removeChildIfUnused(this);
105 public boolean isUnused() {
106 return (listeners.isEmpty() && children.isEmpty()) || areChildrenUnused();
109 private boolean areChildrenUnused() {
110 for (ListenerRegistrationNode child : children.values()) {
111 if (!child.isUnused()) {
118 private void removeChildIfUnused(final ListenerRegistrationNode listenerRegistrationNode) {
119 // FIXME Remove unnecessary
122 public static class DataChangeListenerRegistration<T extends AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>>
123 extends AbstractObjectRegistration<T> implements
124 org.opendaylight.controller.md.sal.dom.store.impl.DataChangeListenerRegistration<T> {
126 private final DataChangeScope scope;
127 private ListenerRegistrationNode node;
128 private final InstanceIdentifier path;
130 public DataChangeListenerRegistration(final InstanceIdentifier path,final T listener, final DataChangeScope scope,
131 final ListenerRegistrationNode node) {
139 public DataChangeScope getScope() {
144 protected void removeRegistration() {
145 node.removeListener(this);
150 public InstanceIdentifier getPath() {