BUG-4688: Add flexible match support to NamespaceStorageSupport
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / stmt / reactor / NamespaceBehaviourWithListeners.java
index 1f10c18a96bcc33a7d1e00d3f5e49836af7b9bb8..9aa6ecc41e2717bb5802412023cf4d2535aa2c5a 100644 (file)
@@ -7,10 +7,13 @@
  */
 package org.opendaylight.yangtools.yang.parser.stmt.reactor;
 
+import static java.util.Objects.requireNonNull;
+
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import javax.annotation.Nonnull;
 import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour;
 
@@ -19,65 +22,82 @@ abstract class NamespaceBehaviourWithListeners<K, V, N extends IdentifierNamespa
 
     abstract static class ValueAddedListener<K> {
         private final NamespaceStorageNode ctxNode;
-        private K key;
 
-        public ValueAddedListener(final NamespaceStorageNode contextNode, K key) {
-            this.ctxNode = contextNode;
-            this.key = key;
+        ValueAddedListener(final NamespaceStorageNode contextNode) {
+            this.ctxNode = requireNonNull(contextNode);
         }
 
-        public NamespaceStorageNode getCtxNode() {
+        final NamespaceStorageNode getCtxNode() {
             return ctxNode;
         }
 
-        public K getKey() {
+    }
+
+    abstract static class KeyedValueAddedListener<K> extends ValueAddedListener<K> {
+        private final K key;
+
+        KeyedValueAddedListener(final NamespaceStorageNode contextNode, final K key) {
+            super(contextNode);
+            this.key = requireNonNull(key);
+        }
+
+        final K getKey() {
             return key;
         }
 
-        abstract void onValueAdded(Object key, Object value);
+        final <V> boolean isRequestedValue(final NamespaceBehaviour<K, ? , ?> behavior,
+                final NamespaceStorageNode storage, final V value) {
+            return value == behavior.getFrom(getCtxNode(), key);
+        }
+
+        abstract void onValueAdded(Object value);
     }
 
-    private final NamespaceBehaviour<K, V, N> delegate;
-    private final List<VirtualNamespaceContext<?, V, ?>> derivedNamespaces = new ArrayList<>();
+    abstract static class PredicateValueAddedListener<K, V> extends ValueAddedListener<K> {
+        PredicateValueAddedListener(final NamespaceStorageNode contextNode) {
+            super(contextNode);
+        }
+
+        abstract boolean onValueAdded(@Nonnull K key, @Nonnull V value);
+    }
 
+    protected final NamespaceBehaviour<K, V, N> delegate;
+    private final List<VirtualNamespaceContext<?, V, ?, K>> derivedNamespaces = new ArrayList<>();
 
     protected NamespaceBehaviourWithListeners(final NamespaceBehaviour<K, V, N> delegate) {
         super(delegate.getIdentifier());
         this.delegate = delegate;
     }
 
-    protected abstract void addListener(K key, ValueAddedListener<K> listener);
+    abstract void addListener(KeyedValueAddedListener<K> listener);
 
-    protected abstract Iterator<ValueAddedListener<K>> getMutableListeners(K key);
-
-    protected abstract boolean isRequestedValue(ValueAddedListener<K> listener, NamespaceStorageNode storage, V value);
+    abstract void addListener(PredicateValueAddedListener<K, V> listener);
 
     @Override
-    public void addTo(final NamespaceStorageNode storage, final K key, final V value) {
-        delegate.addTo(storage, key, value);
+    public abstract void addTo(NamespaceStorageNode storage, K key, V value);
 
-        Iterator<ValueAddedListener<K>> keyListeners = getMutableListeners(key);
-        List<ValueAddedListener<K>> toNotify = new ArrayList<>();
+    protected void notifyListeners(final NamespaceStorageNode storage,
+            final Iterator<? extends KeyedValueAddedListener<K>> keyListeners, final V value) {
+        List<KeyedValueAddedListener<K>> toNotify = new ArrayList<>();
         while (keyListeners.hasNext()) {
-            ValueAddedListener<K> listener = keyListeners.next();
-            if (isRequestedValue(listener, storage, value)) {
+            final KeyedValueAddedListener<K> listener = keyListeners.next();
+            if (listener.isRequestedValue(this, storage, value)) {
                 keyListeners.remove();
                 toNotify.add(listener);
             }
         }
-        for(ValueAddedListener<K> listener : toNotify) {
-            listener.onValueAdded(key, value);
-        }
-        for (VirtualNamespaceContext<?, V, ?> derived : derivedNamespaces) {
-            derived.addTo(storage, null, value);
+        for (KeyedValueAddedListener<K> listener : toNotify) {
+            listener.onValueAdded(value);
         }
     }
 
-    final void addValueListener(final ValueAddedListener<K> listener) {
-        addListener(listener.key, listener);
+    protected void notifyDerivedNamespaces(final NamespaceStorageNode storage, final K key, final V value) {
+        for (VirtualNamespaceContext<?, V, ?, K> derived : derivedNamespaces) {
+            derived.addedToSourceNamespace(storage, key, value);
+        }
     }
 
-    final void addDerivedNamespace(VirtualNamespaceContext<?, V, ?> namespace) {
+    final void addDerivedNamespace(final VirtualNamespaceContext<?, V, ?, K> namespace) {
         derivedNamespaces.add(namespace);
     }