Merge branch 'master' of ../controller
[yangtools.git] / yang / yang-parser-reactor / src / main / java / org / opendaylight / yangtools / yang / parser / stmt / reactor / NamespaceStorageSupport.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 com.google.common.collect.ImmutableMap;
11 import java.util.HashMap;
12 import java.util.Map;
13 import java.util.Map.Entry;
14 import java.util.Optional;
15 import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
16 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.NamespaceStorageNode;
17 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.Registry;
18 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceKeyCriterion;
19 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceNotAvailableException;
20 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementNamespace;
21 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
22 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
23
24 abstract class NamespaceStorageSupport implements NamespaceStorageNode {
25
26     private Map<Class<?>, Map<?,?>> namespaces = ImmutableMap.of();
27
28     @Override
29     public abstract NamespaceStorageNode getParentNamespaceStorage();
30
31     /**
32      * Return the registry of a source context.
33      *
34      * @return registry of source context
35      */
36     public abstract Registry getBehaviourRegistry();
37
38     protected void checkLocalNamespaceAllowed(final Class<? extends IdentifierNamespace<?, ?>> type) {
39         // NOOP
40     }
41
42     /**
43      * Occurs when an item is added to model namespace.
44      *
45      * @throws SourceException instance of SourceException
46      */
47     protected <K, V, N extends IdentifierNamespace<K, V>> void onNamespaceElementAdded(final Class<N> type, final K key,
48             final V value) {
49         // NOOP
50     }
51
52     /**
53      * Return a value associated with specified key within a namespace.
54      *
55      * @param type Namespace type
56      * @param key Key
57      * @param <K> namespace key type
58      * @param <V> namespace value type
59      * @param <N> namespace type
60      * @param <T> key type
61      * @return Value, or null if there is no element
62      * @throws NamespaceNotAvailableException when the namespace is not available.
63      */
64     public final <K, V, T extends K, N extends IdentifierNamespace<K, V>> V getFromNamespace(final Class<N> type,
65             final T key) {
66         return getBehaviourRegistry().getNamespaceBehaviour(type).getFrom(this, key);
67     }
68
69     public final <K, V, N extends IdentifierNamespace<K, V>> Optional<Entry<K, V>> getFromNamespace(
70             final Class<N> type, final NamespaceKeyCriterion<K> criterion) {
71         return getBehaviourRegistry().getNamespaceBehaviour(type).getFrom(this, criterion);
72     }
73
74     public final <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAllFromNamespace(final Class<N> type) {
75         return getBehaviourRegistry().getNamespaceBehaviour(type).getAllFrom(this);
76     }
77
78     @SuppressWarnings("unchecked")
79     public final <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAllFromCurrentStmtCtxNamespace(
80             final Class<N> type) {
81         return (Map<K, V>) namespaces.get(type);
82     }
83
84     /**
85      * Associate a value with a key within a namespace.
86      *
87      * @param type Namespace type
88      * @param key Key
89      * @param value value
90      * @param <K> namespace key type
91      * @param <V> namespace value type
92      * @param <N> namespace type
93      * @param <T> key type
94      * @param <U> value type
95      * @throws NamespaceNotAvailableException when the namespace is not available.
96      */
97     public final <K, V, T extends K, U extends V, N extends IdentifierNamespace<K, V>> void addToNs(
98             final Class<N> type, final T key, final U value) {
99         getBehaviourRegistry().getNamespaceBehaviour(type).addTo(this,key,value);
100     }
101
102     /**
103      * Associate a context with a key within a namespace.
104      *
105      * @param type Namespace type
106      * @param key Key
107      * @param value Context value
108      * @param <K> namespace key type
109      * @param <N> namespace type
110      * @throws NamespaceNotAvailableException when the namespace is not available.
111      */
112     @SuppressWarnings({ "unchecked", "rawtypes" })
113     public final <K, N extends StatementNamespace<K, ?,?>> void addContextToNamespace(final Class<N> type, final K key,
114             final StmtContext<?, ?, ?> value) {
115         getBehaviourRegistry().getNamespaceBehaviour((Class)type).addTo(this, key, value);
116     }
117
118     @SuppressWarnings("unchecked")
119     @Override
120     public <K, V, N extends IdentifierNamespace<K, V>> V getFromLocalStorage(final Class<N> type, final K key) {
121         final Map<K, V> localNamespace = (Map<K, V>) namespaces.get(type);
122         return localNamespace == null ? null : localNamespace.get(key);
123     }
124
125     @Override
126     public <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAllFromLocalStorage(final Class<N> type) {
127         @SuppressWarnings("unchecked")
128         final Map<K, V> localNamespace = (Map<K, V>) namespaces.get(type);
129         return localNamespace;
130     }
131
132     private <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> ensureLocalNamespace(final Class<N> type) {
133         @SuppressWarnings("unchecked")
134         Map<K, V> ret = (Map<K,V>) namespaces.get(type);
135         if (ret == null) {
136             checkLocalNamespaceAllowed(type);
137             ret = new HashMap<>(1);
138
139             if (namespaces.isEmpty()) {
140                 namespaces = new HashMap<>(1);
141             }
142             namespaces.put(type, ret);
143         }
144
145         return ret;
146     }
147
148     @Override
149     public <K, V, N extends IdentifierNamespace<K, V>> V putToLocalStorage(final Class<N> type, final K key,
150             final V value) {
151         final V ret = ensureLocalNamespace(type).put(key, value);
152         onNamespaceElementAdded(type, key, value);
153         return ret;
154     }
155
156     @Override
157     public <K, V, N extends IdentifierNamespace<K, V>> V putToLocalStorageIfAbsent(final Class<N> type, final K key,
158             final V value) {
159         final V ret = ensureLocalNamespace(type).putIfAbsent(key, value);
160         if (ret == null) {
161             onNamespaceElementAdded(type, key, value);
162         }
163         return ret;
164     }
165 }