2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.yangtools.yang.parser.stmt.reactor;
10 import static com.google.common.base.Verify.verifyNotNull;
12 import com.google.common.collect.ImmutableMap;
13 import java.util.HashMap;
15 import java.util.Map.Entry;
16 import java.util.Optional;
17 import org.eclipse.jdt.annotation.NonNull;
18 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour;
19 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.NamespaceStorageNode;
20 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.Registry;
21 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceKeyCriterion;
22 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceNotAvailableException;
23 import org.opendaylight.yangtools.yang.parser.spi.meta.ParserNamespace;
24 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementNamespace;
25 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
26 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
30 abstract class NamespaceStorageSupport implements NamespaceStorageNode {
31 private static final Logger LOG = LoggerFactory.getLogger(NamespaceStorageSupport.class);
33 private Map<Class<?>, Map<?, ?>> namespaces = ImmutableMap.of();
39 * This method override provides bimorphic invocation on this method invocation between
40 * {@link SourceSpecificContext} and the more general {@link NamespaceStorageSupport}. We typically do not expect
41 * the two accesses to overlap.
44 public abstract NamespaceStorageNode getParentNamespaceStorage();
47 * Return the registry of a source context.
49 * @return registry of source context
51 public abstract @NonNull Registry getBehaviourRegistry();
53 // FIXME: 8.0.0: do we really need this method?
54 final void checkLocalNamespaceAllowed(final Class<? extends ParserNamespace<?, ?>> type) {
55 // Always no-op. We used to route this towards StatementDefinitionContext, but this method remained
56 // unimplemented even there.
60 * Occurs when an item is added to model namespace.
62 * @throws SourceException instance of SourceException
64 protected <K, V, N extends ParserNamespace<K, V>> void onNamespaceElementAdded(final Class<N> type, final K key,
69 public final <K, V, N extends ParserNamespace<K, V>> Optional<Entry<K, V>> getFromNamespace(
70 final Class<N> type, final NamespaceKeyCriterion<K> criterion) {
71 return getBehaviourRegistry().getNamespaceBehaviour(type).getFrom(this, criterion);
74 public final <K, V, N extends ParserNamespace<K, V>> Map<K, V> getNamespace(final Class<N> type) {
75 return getBehaviourRegistry().getNamespaceBehaviour(type).getAllFrom(this);
78 @SuppressWarnings("unchecked")
79 final <K, V, N extends ParserNamespace<K, V>> Map<K, V> getLocalNamespace(final Class<N> type) {
80 return (Map<K, V>) accessNamespaces().get(type);
83 final <K, V, T extends K, U extends V, N extends ParserNamespace<K, V>> void addToNamespace(
84 final Class<N> type, final T key, final U value) {
85 getBehaviourRegistry().getNamespaceBehaviour(type).addTo(this, key, value);
88 final <K, V, T extends K, U extends V, N extends ParserNamespace<K, V>> void addToNamespace(
89 final Class<N> type, final Map<T, U> map) {
90 final NamespaceBehaviour<K, V, N> behavior = getBehaviourRegistry().getNamespaceBehaviour(type);
91 for (final Entry<T, U> validationBundle : map.entrySet()) {
92 behavior.addTo(this, validationBundle.getKey(), validationBundle.getValue());
97 * Associate a context with a key within a namespace.
99 * @param type Namespace type
101 * @param value Context value
102 * @param <K> namespace key type
103 * @param <N> namespace type
104 * @throws NamespaceNotAvailableException when the namespace is not available.
106 @SuppressWarnings({ "unchecked", "rawtypes" })
107 public final <K, N extends StatementNamespace<K, ?,?>> void addContextToNamespace(final Class<N> type, final K key,
108 final StmtContext<?, ?, ?> value) {
109 getBehaviourRegistry().getNamespaceBehaviour((Class)type).addTo(this, key, value);
112 @SuppressWarnings("unchecked")
114 public <K, V, N extends ParserNamespace<K, V>> V getFromLocalStorage(final Class<N> type, final K key) {
115 final Map<K, V> localNamespace = (Map<K, V>) accessNamespaces().get(type);
116 return localNamespace == null ? null : localNamespace.get(key);
120 public <K, V, N extends ParserNamespace<K, V>> Map<K, V> getAllFromLocalStorage(final Class<N> type) {
121 @SuppressWarnings("unchecked")
122 final Map<K, V> localNamespace = (Map<K, V>) accessNamespaces().get(type);
123 return localNamespace;
127 public <K, V, N extends ParserNamespace<K, V>> V putToLocalStorage(final Class<N> type, final K key,
129 final V ret = ensureLocalNamespace(type).put(key, value);
130 onNamespaceElementAdded(type, key, value);
135 public <K, V, N extends ParserNamespace<K, V>> V putToLocalStorageIfAbsent(final Class<N> type, final K key,
137 final V ret = ensureLocalNamespace(type).putIfAbsent(key, value);
139 onNamespaceElementAdded(type, key, value);
144 void sweepNamespaces() {
146 LOG.trace("Swept namespace storages of {}", this);
149 void sweepNamespaces(final Map<Class<?>, SweptNamespace> toWipe) {
150 switch (namespaces.size()) {
152 namespaces = ImmutableMap.copyOf(toWipe);
155 namespaces = new HashMap<>(namespaces);
158 // No-op, we are ready
161 namespaces.putAll(toWipe);
162 LOG.trace("Trimmed namespace storages of {} to {}", this, namespaces.keySet());
165 private Map<Class<?>, Map<?, ?>> accessNamespaces() {
166 return verifyNotNull(namespaces, "Attempted to access swept namespaces of %s", this);
169 private <K, V, N extends ParserNamespace<K, V>> Map<K, V> ensureLocalNamespace(final Class<N> type) {
170 @SuppressWarnings("unchecked")
171 Map<K, V> ret = (Map<K,V>) accessNamespaces().get(type);
173 checkLocalNamespaceAllowed(type);
174 ret = new HashMap<>(1);
176 switch (namespaces.size()) {
178 // We typically have small population of namespaces, use a singleton map
179 namespaces = ImmutableMap.of(type, ret);
182 // Alright, time to grow to a full HashMap
183 final Map<Class<?>, Map<?,?>> newNamespaces = new HashMap<>(4);
184 final Entry<Class<?>, Map<?, ?>> entry = namespaces.entrySet().iterator().next();
185 newNamespaces.put(entry.getKey(), entry.getValue());
186 namespaces = newNamespaces;
189 // Already expanded, just put the new namespace
190 namespaces.put(type, ret);