/* * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.yangtools.yang.parser.stmt.reactor; import com.google.common.collect.ImmutableMap; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import javax.annotation.Nonnull; import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil; import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier; 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.NamespaceNotAvailableException; import org.opendaylight.yangtools.yang.parser.spi.meta.StatementNamespace; import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext; abstract class NamespaceStorageSupport implements NamespaceStorageNode { private Map<Class<?>, Map<?,?>> namespaces = ImmutableMap.of(); @Override public abstract NamespaceStorageNode getParentNamespaceStorage(); /** * @return registry of source context */ public abstract NamespaceBehaviour.Registry getBehaviourRegistry(); protected void checkLocalNamespaceAllowed(final Class<? extends IdentifierNamespace<?, ?>> type) { // NOOP } protected <K, V, N extends IdentifierNamespace<K, V>> void onNamespaceElementAdded(final Class<N> type, final K key, final V value) { // NOOP } @Nonnull public final <K,V, KT extends K, N extends IdentifierNamespace<K, V>> V getFromNamespace(final Class<N> type, final KT key) throws NamespaceNotAvailableException { return getBehaviourRegistry().getNamespaceBehaviour(type).getFrom(this,key); } public final <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAllFromNamespace(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); } public final <K,V, KT extends K, VT extends V,N extends IdentifierNamespace<K, V>> void addToNs(final Class<N> type, final KT key, final VT value) throws NamespaceNotAvailableException { getBehaviourRegistry().getNamespaceBehaviour(type).addTo(this,key,value); } @SuppressWarnings({ "unchecked", "rawtypes" }) public final <K, N extends StatementNamespace<K, ?,?>> void addContextToNamespace(final Class<N> type, final K key, final StmtContext<?, ?, ?> value) throws NamespaceNotAvailableException { getBehaviourRegistry().getNamespaceBehaviour((Class)type).addTo(this, key, value); } @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); V potential = null; if (localNamespace != null) { potential = localNamespace.get(key); } if (potential == null && isModuleIdentifierWithoutSpecifiedRevision(key)) { potential = getRegardlessOfRevision((ModuleIdentifier)key,(Map<ModuleIdentifier,V>)localNamespace); } return potential; } private static boolean isModuleIdentifierWithoutSpecifiedRevision(final Object obj) { if (!(obj instanceof ModuleIdentifier)) { return false; } final Date rev = ((ModuleIdentifier) obj).getRevision(); return rev == SimpleDateFormatUtil.DEFAULT_DATE_IMP || rev == SimpleDateFormatUtil.DEFAULT_BELONGS_TO_DATE; } private static <K, V, N extends IdentifierNamespace<K, V>> V getRegardlessOfRevision(final ModuleIdentifier key, final Map<ModuleIdentifier, V> localNamespace) { if (localNamespace == null) { return null; } final Set<Entry<ModuleIdentifier, V>> entrySet = localNamespace.entrySet(); for (final Entry<ModuleIdentifier, V> entry : entrySet) { final ModuleIdentifier moduleIdentifierInMap = entry.getKey(); if (moduleIdentifierInMap.getName().equals(key.getName())) { return entry.getValue(); } } return null; } @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); 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) { final V ret = ensureLocalNamespace(type).put(key, value); onNamespaceElementAdded(type, key, value); return ret; } @Override public <K, V, N extends IdentifierNamespace<K, V>> V putToLocalStorageIfAbsent(final Class<N> type, final K key, final V value) { final V ret = ensureLocalNamespace(type).putIfAbsent(key, value); if (ret == null) { onNamespaceElementAdded(type, key, value); } return ret; } }