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.concepts.ListenerRegistration;
13 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
14 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
15 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
16 import org.slf4j.Logger;
17 import org.slf4j.LoggerFactory;
19 import com.google.common.base.Optional;
21 public class ListenerRegistrationNode implements StoreTreeNode<ListenerRegistrationNode>, Identifiable<PathArgument> {
23 private final Logger LOG = LoggerFactory.getLogger(ListenerRegistrationNode.class);
25 private final ListenerRegistrationNode parent;
26 private final Map<PathArgument, ListenerRegistrationNode> children;
27 private final PathArgument identifier;
28 private final HashSet<DataChangeListenerRegistration<?>> listeners;
30 private ListenerRegistrationNode(final PathArgument identifier) {
31 this(null, identifier);
34 private ListenerRegistrationNode(final ListenerRegistrationNode parent, final PathArgument identifier) {
36 this.identifier = identifier;
37 children = new HashMap<>();
38 listeners = new HashSet<>();
41 public final static ListenerRegistrationNode createRoot() {
42 return new ListenerRegistrationNode(null);
46 public PathArgument getIdentifier() {
50 @SuppressWarnings({ "rawtypes", "unchecked" })
51 public Collection<org.opendaylight.controller.md.sal.dom.store.impl.DataChangeListenerRegistration<?>> getListeners() {
52 return (Collection) listeners;
56 public synchronized Optional<ListenerRegistrationNode> getChild(final PathArgument child) {
57 return Optional.fromNullable(children.get(child));
60 public synchronized ListenerRegistrationNode ensureChild(final PathArgument child) {
61 ListenerRegistrationNode potential = (children.get(child));
62 if (potential == null) {
63 potential = new ListenerRegistrationNode(this, child);
64 children.put(child, potential);
71 * Registers listener on this node.
73 * @param path Full path on which listener is registered.
74 * @param listener Listener
75 * @param scope Scope of triggering event.
78 public <L extends AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>> ListenerRegistration<L> registerDataChangeListener(final InstanceIdentifier path,
79 final L listener, final DataChangeScope scope) {
81 DataChangeListenerRegistration<L> listenerReg = new DataChangeListenerRegistration<L>(path,listener, scope, this);
82 listeners.add(listenerReg);
86 private void removeListener(final DataChangeListenerRegistration<?> listener) {
87 listeners.remove(listener);
91 private void removeThisIfUnused() {
92 if (parent != null && listeners.isEmpty() && children.isEmpty()) {
93 parent.removeChildIfUnused(this);
97 public boolean isUnused() {
98 return (listeners.isEmpty() && children.isEmpty()) || areChildrenUnused();
101 private boolean areChildrenUnused() {
102 for (ListenerRegistrationNode child : children.values()) {
103 if (!child.isUnused()) {
110 private void removeChildIfUnused(final ListenerRegistrationNode listenerRegistrationNode) {
111 // FIXME Remove unnecessary
114 public static class DataChangeListenerRegistration<T extends AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>>
115 extends AbstractObjectRegistration<T> implements
116 org.opendaylight.controller.md.sal.dom.store.impl.DataChangeListenerRegistration<T> {
118 private final DataChangeScope scope;
119 private ListenerRegistrationNode node;
120 private final InstanceIdentifier path;
122 public DataChangeListenerRegistration(final InstanceIdentifier path,final T listener, final DataChangeScope scope,
123 final ListenerRegistrationNode node) {
131 public DataChangeScope getScope() {
136 protected void removeRegistration() {
137 node.removeListener(this);
142 public InstanceIdentifier getPath() {