Update DataTreeFactory
[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     abstract static class KeyedValueAddedListener<K> extends ValueAddedListener<K> {
36         private final K key;
37
38         KeyedValueAddedListener(final NamespaceStorageNode contextNode, final K key) {
39             super(contextNode);
40             this.key = requireNonNull(key);
41         }
42
43         final K getKey() {
44             return key;
45         }
46
47         final <V> boolean isRequestedValue(final NamespaceBehaviour<K, ? , ?> behavior,
48                 final NamespaceStorageNode storage, final V value) {
49             return value == behavior.getFrom(getCtxNode(), key);
50         }
51
52         abstract void onValueAdded(Object value);
53     }
54
55     abstract static class PredicateValueAddedListener<K, V> extends ValueAddedListener<K> {
56         PredicateValueAddedListener(final NamespaceStorageNode contextNode) {
57             super(contextNode);
58         }
59
60         abstract boolean onValueAdded(@Nonnull K key, @Nonnull V value);
61     }
62
63     protected final NamespaceBehaviour<K, V, N> delegate;
64
65     private List<VirtualNamespaceContext<?, V, ?, K>> derivedNamespaces;
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         if (derivedNamespaces != null) {
96             for (VirtualNamespaceContext<?, V, ?, K> derived : derivedNamespaces) {
97                 derived.addedToSourceNamespace(storage, key, value);
98             }
99         }
100     }
101
102     final void addDerivedNamespace(final VirtualNamespaceContext<?, V, ?, K> namespace) {
103         if (derivedNamespaces == null) {
104             derivedNamespaces = new ArrayList<>();
105         }
106         derivedNamespaces.add(namespace);
107     }
108
109     @Override
110     public V getFrom(final NamespaceStorageNode storage, final K key) {
111         return delegate.getFrom(storage, key);
112     }
113
114     @Override
115     public Map<K, V> getAllFrom(final NamespaceStorageNode storage) {
116         return delegate.getAllFrom(storage);
117     }
118 }