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
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.yangtools.yang.parser.stmt.reactor;
9
10 import static java.util.Objects.requireNonNull;
11
12 import java.util.ArrayList;
13 import java.util.Iterator;
14 import java.util.List;
15 import java.util.Map;
16 import javax.annotation.Nonnull;
17 import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
18 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour;
19
20 abstract class NamespaceBehaviourWithListeners<K, V, N extends IdentifierNamespace<K, V>>
21         extends NamespaceBehaviour<K, V, N> {
22
23     abstract static class ValueAddedListener<K> {
24         private final NamespaceStorageNode ctxNode;
25
26         ValueAddedListener(final NamespaceStorageNode contextNode) {
27             this.ctxNode = requireNonNull(contextNode);
28         }
29
30         final NamespaceStorageNode getCtxNode() {
31             return ctxNode;
32         }
33
34     }
35
36     abstract static class KeyedValueAddedListener<K> extends ValueAddedListener<K> {
37         private final K key;
38
39         KeyedValueAddedListener(final NamespaceStorageNode contextNode, final K key) {
40             super(contextNode);
41             this.key = requireNonNull(key);
42         }
43
44         final K getKey() {
45             return key;
46         }
47
48         final <V> boolean isRequestedValue(final NamespaceBehaviour<K, ? , ?> behavior,
49                 final NamespaceStorageNode storage, final V value) {
50             return value == behavior.getFrom(getCtxNode(), key);
51         }
52
53         abstract void onValueAdded(Object value);
54     }
55
56     abstract static class PredicateValueAddedListener<K, V> extends ValueAddedListener<K> {
57         PredicateValueAddedListener(final NamespaceStorageNode contextNode) {
58             super(contextNode);
59         }
60
61         abstract boolean onValueAdded(@Nonnull K key, @Nonnull V value);
62     }
63
64     protected final NamespaceBehaviour<K, V, N> delegate;
65     private final List<VirtualNamespaceContext<?, V, ?, K>> derivedNamespaces = new ArrayList<>();
66
67     protected NamespaceBehaviourWithListeners(final NamespaceBehaviour<K, V, N> delegate) {
68         super(delegate.getIdentifier());
69         this.delegate = delegate;
70     }
71
72     abstract void addListener(KeyedValueAddedListener<K> listener);
73
74     abstract void addListener(PredicateValueAddedListener<K, V> listener);
75
76     @Override
77     public abstract void addTo(NamespaceStorageNode storage, K key, V value);
78
79     protected void notifyListeners(final NamespaceStorageNode storage,
80             final Iterator<? extends KeyedValueAddedListener<K>> keyListeners, final V value) {
81         List<KeyedValueAddedListener<K>> toNotify = new ArrayList<>();
82         while (keyListeners.hasNext()) {
83             final KeyedValueAddedListener<K> listener = keyListeners.next();
84             if (listener.isRequestedValue(this, storage, value)) {
85                 keyListeners.remove();
86                 toNotify.add(listener);
87             }
88         }
89         for (KeyedValueAddedListener<K> listener : toNotify) {
90             listener.onValueAdded(value);
91         }
92     }
93
94     protected void notifyDerivedNamespaces(final NamespaceStorageNode storage, final K key, final V value) {
95         for (VirtualNamespaceContext<?, V, ?, K> derived : derivedNamespaces) {
96             derived.addedToSourceNamespace(storage, key, value);
97         }
98     }
99
100     final void addDerivedNamespace(final VirtualNamespaceContext<?, V, ?, K> namespace) {
101         derivedNamespaces.add(namespace);
102     }
103
104     @Override
105     public V getFrom(final NamespaceStorageNode storage, final K key) {
106         return delegate.getFrom(storage, key);
107     }
108
109     @Override
110     public Map<K, V> getAllFrom(final NamespaceStorageNode storage) {
111         return delegate.getAllFrom(storage);
112     }
113 }