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 org.eclipse.jdt.annotation.NonNull;
16 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceNotAvailableException;
17 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceStorage;
18 import org.opendaylight.yangtools.yang.parser.spi.meta.ParserNamespace;
19 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
20 import org.slf4j.Logger;
21 import org.slf4j.LoggerFactory;
23 abstract class AbstractNamespaceStorage implements NamespaceStorage {
24 private static final Logger LOG = LoggerFactory.getLogger(AbstractNamespaceStorage.class);
26 private Map<ParserNamespace<?, ?>, Map<?, ?>> namespaces = ImmutableMap.of();
29 * Get access to a {@link ParserNamespace}.
32 * @param <V> value type
33 * @param namespace Namespace type
34 * @return Namespace behaviour
35 * @throws NamespaceNotAvailableException when the namespace is not available
36 * @throws NullPointerException if {@code namespace} is {@code null}
38 abstract <K, V> @NonNull NamespaceAccess<K, V> accessNamespace(ParserNamespace<K, V> namespace);
40 // FIXME: 8.0.0: do we really need this method?
41 final void checkLocalNamespaceAllowed(final ParserNamespace<?, ?> type) {
42 // Always no-op. We used to route this towards StatementDefinitionContext, but this method remained
43 // unimplemented even there.
47 * Occurs when an item is added to model namespace.
49 * @throws SourceException instance of SourceException
51 <K, V> void onNamespaceElementAdded(final ParserNamespace<K, V> type, final K key, final V value) {
55 final <K, V> Map<K, V> getNamespace(final ParserNamespace<K, V> type) {
56 return accessNamespace(type).allFrom(this);
59 @SuppressWarnings("unchecked")
60 final <K, V> Map<K, V> getLocalNamespace(final ParserNamespace<K, V> type) {
61 final var local = verifyNotNull(namespaces, "Attempted to access swept namespaces of %s", this);
62 return (Map<K, V>) local.get(type);
65 final <K, V> void addToNamespace(final ParserNamespace<K, V> type, final K key, final V value) {
66 accessNamespace(type).valueTo(this, key, value);
70 public <K, V> V getFromLocalStorage(final ParserNamespace<K, V> type, final K key) {
71 final var localNamespace = getLocalNamespace(type);
72 return localNamespace == null ? null : localNamespace.get(key);
76 public <K, V> Map<K, V> getAllFromLocalStorage(final ParserNamespace<K, V> type) {
77 return getLocalNamespace(type);
81 public <K, V> V putToLocalStorage(final ParserNamespace<K, V> type, final K key, final V value) {
82 final V ret = ensureLocalNamespace(type).put(key, value);
83 onNamespaceElementAdded(type, key, value);
88 public final <K, V> V putToLocalStorageIfAbsent(final ParserNamespace<K, V> type, final K key, final V value) {
89 final V ret = ensureLocalNamespace(type).putIfAbsent(key, value);
91 onNamespaceElementAdded(type, key, value);
96 void sweepNamespaces() {
98 LOG.trace("Swept namespace storages of {}", this);
101 void sweepNamespaces(final Map<ParserNamespace<?, ?>, SweptNamespace> toWipe) {
102 switch (namespaces.size()) {
104 namespaces = ImmutableMap.copyOf(toWipe);
107 namespaces = new HashMap<>(namespaces);
110 // No-op, we are ready
113 namespaces.putAll(toWipe);
114 LOG.trace("Trimmed namespace storages of {} to {}", this, namespaces.keySet());
117 private <K, V> Map<K, V> ensureLocalNamespace(final ParserNamespace<K, V> type) {
118 var ret = getLocalNamespace(type);
120 checkLocalNamespaceAllowed(type);
121 ret = new HashMap<>(1);
123 switch (namespaces.size()) {
125 // We typically have small population of namespaces, use a singleton map
126 namespaces = ImmutableMap.of(type, ret);
129 // Alright, time to grow to a full HashMap
130 final var newNamespaces = new HashMap<ParserNamespace<?, ?>, Map<?, ?>>(4);
131 final var entry = namespaces.entrySet().iterator().next();
132 newNamespaces.put(entry.getKey(), entry.getValue());
133 namespaces = newNamespaces;
136 // Already expanded, just put the new namespace
137 namespaces.put(type, ret);