*/
package org.opendaylight.yangtools.yang.parser.stmt.reactor;
+import static com.google.common.base.Verify.verifyNotNull;
+
import com.google.common.collect.ImmutableMap;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
-import javax.annotation.Nonnull;
+import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
+import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour;
import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.NamespaceStorageNode;
import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.Registry;
import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceKeyCriterion;
import org.opendaylight.yangtools.yang.parser.spi.meta.StatementNamespace;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
abstract class NamespaceStorageSupport implements NamespaceStorageNode {
+ private static final Logger LOG = LoggerFactory.getLogger(NamespaceStorageSupport.class);
- private Map<Class<?>, Map<?,?>> namespaces = ImmutableMap.of();
+ private Map<Class<?>, Map<?, ?>> namespaces = ImmutableMap.of();
+ /**
+ * {@inheritDoc}
+ *
+ * <p>
+ * This method override provides bimorphic invocation on this method invocation between
+ * {@link SourceSpecificContext} and the more general {@link NamespaceStorageSupport}. We typically do not expect
+ * the two accesses to overlap.
+ */
@Override
public abstract NamespaceStorageNode getParentNamespaceStorage();
*
* @return registry of source context
*/
- public abstract Registry getBehaviourRegistry();
+ public abstract @NonNull Registry getBehaviourRegistry();
protected void checkLocalNamespaceAllowed(final Class<? extends IdentifierNamespace<?, ?>> type) {
// NOOP
// NOOP
}
- /**
- * Return a value associated with specified key within a namespace.
- *
- * @param type Namespace type
- * @param key Key
- * @param <K> namespace key type
- * @param <V> namespace value type
- * @param <N> namespace type
- * @param <T> key type
- * @return Value, or null if there is no element
- * @throws NamespaceNotAvailableException when the namespace is not available.
- */
- @Nonnull
- public final <K, V, T extends K, N extends IdentifierNamespace<K, V>> V getFromNamespace(final Class<N> type,
- final T key) {
- return getBehaviourRegistry().getNamespaceBehaviour(type).getFrom(this, key);
- }
-
public final <K, V, N extends IdentifierNamespace<K, V>> Optional<Entry<K, V>> getFromNamespace(
final Class<N> type, final NamespaceKeyCriterion<K> criterion) {
return getBehaviourRegistry().getNamespaceBehaviour(type).getFrom(this, criterion);
}
- public final <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAllFromNamespace(final Class<N> type) {
+ public final <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getNamespace(final Class<N> type) {
return getBehaviourRegistry().getNamespaceBehaviour(type).getAllFrom(this);
}
@SuppressWarnings("unchecked")
- public final <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAllFromCurrentStmtCtxNamespace(
- final Class<N> type) {
- return (Map<K, V>) namespaces.get(type);
+ final <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getLocalNamespace(final Class<N> type) {
+ return (Map<K, V>) accessNamespaces().get(type);
}
- /**
- * Associate a value with a key within a namespace.
- *
- * @param type Namespace type
- * @param key Key
- * @param value value
- * @param <K> namespace key type
- * @param <V> namespace value type
- * @param <N> namespace type
- * @param <T> key type
- * @param <U> key type
- * @throws NamespaceNotAvailableException when the namespace is not available.
- */
- public final <K, V, T extends K, U extends V, N extends IdentifierNamespace<K, V>> void addToNs(
+ final <K, V, T extends K, U extends V, N extends IdentifierNamespace<K, V>> void addToNamespace(
final Class<N> type, final T key, final U value) {
- getBehaviourRegistry().getNamespaceBehaviour(type).addTo(this,key,value);
+ getBehaviourRegistry().getNamespaceBehaviour(type).addTo(this, key, value);
+ }
+
+ final <K, V, T extends K, U extends V, N extends IdentifierNamespace<K, V>> void addToNamespace(
+ final Class<N> type, final Map<T, U> map) {
+ final NamespaceBehaviour<K, V, N> behavior = getBehaviourRegistry().getNamespaceBehaviour(type);
+ for (final Entry<T, U> validationBundle : map.entrySet()) {
+ behavior.addTo(this, validationBundle.getKey(), validationBundle.getValue());
+ }
}
/**
@SuppressWarnings("unchecked")
@Override
public <K, V, N extends IdentifierNamespace<K, V>> V getFromLocalStorage(final Class<N> type, final K key) {
- final Map<K, V> localNamespace = (Map<K, V>) namespaces.get(type);
+ final Map<K, V> localNamespace = (Map<K, V>) accessNamespaces().get(type);
return localNamespace == null ? null : localNamespace.get(key);
}
@Override
public <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAllFromLocalStorage(final Class<N> type) {
@SuppressWarnings("unchecked")
- final Map<K, V> localNamespace = (Map<K, V>) namespaces.get(type);
+ final Map<K, V> localNamespace = (Map<K, V>) accessNamespaces().get(type);
return localNamespace;
}
- private <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> ensureLocalNamespace(final Class<N> type) {
- @SuppressWarnings("unchecked")
- Map<K, V> ret = (Map<K,V>) namespaces.get(type);
- if (ret == null) {
- checkLocalNamespaceAllowed(type);
- ret = new HashMap<>(1);
-
- if (namespaces.isEmpty()) {
- namespaces = new HashMap<>(1);
- }
- namespaces.put(type, ret);
- }
-
- return ret;
- }
-
@Override
public <K, V, N extends IdentifierNamespace<K, V>> V putToLocalStorage(final Class<N> type, final K key,
final V value) {
}
return ret;
}
+
+ void sweepNamespaces() {
+ namespaces = null;
+ LOG.trace("Swept namespace storages of {}", this);
+ }
+
+ void sweepNamespaces(final Map<Class<?>, SweptNamespace> toWipe) {
+ switch (namespaces.size()) {
+ case 0:
+ namespaces = ImmutableMap.copyOf(toWipe);
+ return;
+ case 1:
+ namespaces = new HashMap<>(namespaces);
+ break;
+ default:
+ // No-op, we are ready
+ }
+
+ namespaces.putAll(toWipe);
+ LOG.trace("Trimmed namespace storages of {} to {}", this, namespaces.keySet());
+ }
+
+ private Map<Class<?>, Map<?, ?>> accessNamespaces() {
+ return verifyNotNull(namespaces, "Attempted to access swept namespaces of %s", this);
+ }
+
+ private <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> ensureLocalNamespace(final Class<N> type) {
+ @SuppressWarnings("unchecked")
+ Map<K, V> ret = (Map<K,V>) accessNamespaces().get(type);
+ if (ret == null) {
+ checkLocalNamespaceAllowed(type);
+ ret = new HashMap<>(1);
+
+ switch (namespaces.size()) {
+ case 0:
+ // We typically have small population of namespaces, use a singleton map
+ namespaces = ImmutableMap.of(type, ret);
+ break;
+ case 1:
+ // Alright, time to grow to a full HashMap
+ final Map<Class<?>, Map<?,?>> newNamespaces = new HashMap<>(4);
+ final Entry<Class<?>, Map<?, ?>> entry = namespaces.entrySet().iterator().next();
+ newNamespaces.put(entry.getKey(), entry.getValue());
+ namespaces = newNamespaces;
+ // fall through
+ default:
+ // Already expanded, just put the new namespace
+ namespaces.put(type, ret);
+ }
+ }
+
+ return ret;
+ }
}