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