Enforce namespace listener compatibility
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / stmt / reactor / NamespaceStorageSupport.java
index 0fe03bec79a97db2aa2a59bbd6da39dcc8fa292d..ba55707b374bb0fce7785c8916c1d5db3c29a2ea 100644 (file)
@@ -8,11 +8,13 @@
 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;
@@ -20,7 +22,7 @@ import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.Namesp
 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;
-import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.Utils;
+import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
 
 abstract class NamespaceStorageSupport implements NamespaceStorageNode {
 
@@ -29,19 +31,28 @@ abstract class NamespaceStorageSupport implements NamespaceStorageNode {
     @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) {
+    /**
+     * Occurs when an item is added to model namespace.
+     *
+     * @throws SourceException instance of SourceException
+     */
+    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 {
+    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);
     }
 
@@ -50,38 +61,48 @@ abstract class NamespaceStorageSupport implements NamespaceStorageNode {
     }
 
     @SuppressWarnings("unchecked")
-    public final <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAllFromCurrentStmtCtxNamespace(final Class<N> type){
+    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 {
+    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 {
+    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) {
-        Map<K, V> localNamespace = (Map<K,V>) namespaces.get(type);
+        final Map<K, V> localNamespace = (Map<K,V>) namespaces.get(type);
 
         V potential = null;
         if (localNamespace != null) {
             potential = localNamespace.get(key);
         }
 
-        if (potential == null && Utils.isModuleIdentifierWithoutSpecifiedRevision(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) {
 
@@ -89,9 +110,9 @@ abstract class NamespaceStorageSupport implements NamespaceStorageNode {
             return null;
         }
 
-        Set<Entry<ModuleIdentifier, V>> entrySet = localNamespace.entrySet();
-        for (Entry<ModuleIdentifier, V> entry : entrySet) {
-            ModuleIdentifier moduleIdentifierInMap = entry.getKey();
+        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();
             }
@@ -103,25 +124,41 @@ abstract class NamespaceStorageSupport implements NamespaceStorageNode {
     @Override
     public <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAllFromLocalStorage(final Class<N> type) {
         @SuppressWarnings("unchecked")
-        Map<K, V> localNamespace = (Map<K, V>) namespaces.get(type);
+        final Map<K, V> localNamespace = (Map<K, V>) namespaces.get(type);
         return localNamespace;
     }
 
-    @Override
-    public <K, V, N extends IdentifierNamespace<K, V>> void addToLocalStorage(final Class<N> type, final K key, final V value) {
+    private <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> ensureLocalNamespace(final Class<N> type) {
         @SuppressWarnings("unchecked")
-        Map<K, V> localNamespace = (Map<K,V>) namespaces.get(type);
-        if (localNamespace == null) {
+        Map<K, V> ret = (Map<K,V>) namespaces.get(type);
+        if (ret == null) {
             checkLocalNamespaceAllowed(type);
-            localNamespace = new HashMap<>(1);
+            ret = new HashMap<>(1);
 
             if (namespaces.isEmpty()) {
                 namespaces = new HashMap<>(1);
             }
-            namespaces.put(type, localNamespace);
+            namespaces.put(type, ret);
         }
-        localNamespace.put(key,value);
-        onNamespaceElementAdded(type,key,value);
+
+        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;
+    }
 }