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 com.google.common.collect.ImmutableMap;
11 import java.util.HashMap;
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;
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;
25 abstract class NamespaceStorageSupport implements NamespaceStorageNode {
27 private Map<Class<?>, Map<?,?>> namespaces = ImmutableMap.of();
33 * This method override provides bimorphic invocation on this method invocation between
34 * {@link SourceSpecificContext} and the more general {@link NamespaceStorageSupport}. We typically do not expect
35 * the two accesses to overlap.
38 public abstract NamespaceStorageNode getParentNamespaceStorage();
41 * Return the registry of a source context.
43 * @return registry of source context
45 public abstract Registry getBehaviourRegistry();
47 protected void checkLocalNamespaceAllowed(final Class<? extends IdentifierNamespace<?, ?>> type) {
52 * Occurs when an item is added to model namespace.
54 * @throws SourceException instance of SourceException
56 protected <K, V, N extends IdentifierNamespace<K, V>> void onNamespaceElementAdded(final Class<N> type, final K key,
61 public final <K, V, N extends IdentifierNamespace<K, V>> Optional<Entry<K, V>> getFromNamespace(
62 final Class<N> type, final NamespaceKeyCriterion<K> criterion) {
63 return getBehaviourRegistry().getNamespaceBehaviour(type).getFrom(this, criterion);
66 public final <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getNamespace(final Class<N> type) {
67 return getBehaviourRegistry().getNamespaceBehaviour(type).getAllFrom(this);
70 @SuppressWarnings("unchecked")
71 final <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getLocalNamespace(final Class<N> type) {
72 return (Map<K, V>) namespaces.get(type);
75 final <K, V, T extends K, U extends V, N extends IdentifierNamespace<K, V>> void addToNamespace(
76 final Class<N> type, final T key, final U value) {
77 getBehaviourRegistry().getNamespaceBehaviour(type).addTo(this, key, value);
80 final <K, V, T extends K, U extends V, N extends IdentifierNamespace<K, V>> void addToNamespace(
81 final Class<N> type, final Map<T, U> map) {
82 final NamespaceBehaviour<K, V, N> behavior = getBehaviourRegistry().getNamespaceBehaviour(type);
83 for (final Entry<T, U> validationBundle : map.entrySet()) {
84 behavior.addTo(this, validationBundle.getKey(), validationBundle.getValue());
89 * Associate a context with a key within a namespace.
91 * @param type Namespace type
93 * @param value Context value
94 * @param <K> namespace key type
95 * @param <N> namespace type
96 * @throws NamespaceNotAvailableException when the namespace is not available.
98 @SuppressWarnings({ "unchecked", "rawtypes" })
99 public final <K, N extends StatementNamespace<K, ?,?>> void addContextToNamespace(final Class<N> type, final K key,
100 final StmtContext<?, ?, ?> value) {
101 getBehaviourRegistry().getNamespaceBehaviour((Class)type).addTo(this, key, value);
104 @SuppressWarnings("unchecked")
106 public <K, V, N extends IdentifierNamespace<K, V>> V getFromLocalStorage(final Class<N> type, final K key) {
107 final Map<K, V> localNamespace = (Map<K, V>) namespaces.get(type);
108 return localNamespace == null ? null : localNamespace.get(key);
112 public <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAllFromLocalStorage(final Class<N> type) {
113 @SuppressWarnings("unchecked")
114 final Map<K, V> localNamespace = (Map<K, V>) namespaces.get(type);
115 return localNamespace;
118 private <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> ensureLocalNamespace(final Class<N> type) {
119 @SuppressWarnings("unchecked")
120 Map<K, V> ret = (Map<K,V>) namespaces.get(type);
122 checkLocalNamespaceAllowed(type);
123 ret = new HashMap<>(1);
125 switch (namespaces.size()) {
127 // We typically have small population of namespaces, use a singleton map
128 namespaces = ImmutableMap.of(type, ret);
131 // Alright, time to grow to a full HashMap
132 final Map<Class<?>, Map<?,?>> newNamespaces = new HashMap<>(4);
133 final Entry<Class<?>, Map<?, ?>> entry = namespaces.entrySet().iterator().next();
134 newNamespaces.put(entry.getKey(), entry.getValue());
135 namespaces = newNamespaces;
138 // Already expanded, just put the new namespace
139 namespaces.put(type, ret);
147 public <K, V, N extends IdentifierNamespace<K, V>> V putToLocalStorage(final Class<N> type, final K key,
149 final V ret = ensureLocalNamespace(type).put(key, value);
150 onNamespaceElementAdded(type, key, value);
155 public <K, V, N extends IdentifierNamespace<K, V>> V putToLocalStorageIfAbsent(final Class<N> type, final K key,
157 final V ret = ensureLocalNamespace(type).putIfAbsent(key, value);
159 onNamespaceElementAdded(type, key, value);