82dd703048ae43cb4825ea82682acd6ca5c9f569
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / stmt / reactor / NamespaceStorageSupport.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.yangtools.yang.parser.stmt.reactor;
9
10 import com.google.common.collect.ImmutableMap;
11 import java.util.Date;
12 import java.util.HashMap;
13 import java.util.Map;
14 import java.util.Map.Entry;
15 import java.util.Set;
16 import javax.annotation.Nonnull;
17 import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
18 import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier;
19 import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
20 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour;
21 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.NamespaceStorageNode;
22 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceNotAvailableException;
23 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementNamespace;
24 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
25
26 abstract class NamespaceStorageSupport implements NamespaceStorageNode {
27
28     private Map<Class<?>, Map<?,?>> namespaces = ImmutableMap.of();
29
30     @Override
31     public abstract NamespaceStorageNode getParentNamespaceStorage();
32
33     /**
34      * @return registry of source context
35      */
36     public abstract NamespaceBehaviour.Registry getBehaviourRegistry();
37
38     protected void checkLocalNamespaceAllowed(final Class<? extends IdentifierNamespace<?, ?>> type) {
39         // NOOP
40     }
41
42     protected <K, V, N extends IdentifierNamespace<K, V>> void onNamespaceElementAdded(final Class<N> type, final K key,
43             final V value) {
44         // NOOP
45     }
46
47     @Nonnull
48     public final <K,V, KT extends K, N extends IdentifierNamespace<K, V>> V getFromNamespace(final Class<N> type,
49             final KT key) throws NamespaceNotAvailableException {
50         return getBehaviourRegistry().getNamespaceBehaviour(type).getFrom(this,key);
51     }
52
53     public final <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAllFromNamespace(final Class<N> type){
54         return getBehaviourRegistry().getNamespaceBehaviour(type).getAllFrom(this);
55     }
56
57     @SuppressWarnings("unchecked")
58     public final <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAllFromCurrentStmtCtxNamespace(
59             final Class<N> type) {
60         return (Map<K, V>) namespaces.get(type);
61     }
62
63     public final <K,V, KT extends K, VT extends V,N extends IdentifierNamespace<K, V>> void addToNs(final Class<N> type,
64             final KT key, final VT value) throws NamespaceNotAvailableException {
65         getBehaviourRegistry().getNamespaceBehaviour(type).addTo(this,key,value);
66     }
67
68     @SuppressWarnings({ "unchecked", "rawtypes" })
69     public final <K, N extends StatementNamespace<K, ?,?>> void addContextToNamespace(final Class<N> type, final K key,
70             final StmtContext<?, ?, ?> value) throws NamespaceNotAvailableException {
71         getBehaviourRegistry().getNamespaceBehaviour((Class)type).addTo(this, key, value);
72     }
73
74     @SuppressWarnings("unchecked")
75     @Override
76     public <K, V, N extends IdentifierNamespace<K, V>> V getFromLocalStorage(final Class<N> type, final K key) {
77         final Map<K, V> localNamespace = (Map<K,V>) namespaces.get(type);
78
79         V potential = null;
80         if (localNamespace != null) {
81             potential = localNamespace.get(key);
82         }
83
84         if (potential == null && isModuleIdentifierWithoutSpecifiedRevision(key)) {
85             potential = getRegardlessOfRevision((ModuleIdentifier)key,(Map<ModuleIdentifier,V>)localNamespace);
86         }
87
88         return potential;
89     }
90
91     private static boolean isModuleIdentifierWithoutSpecifiedRevision(final Object obj) {
92         if (!(obj instanceof ModuleIdentifier)) {
93             return false;
94         }
95
96         final Date rev = ((ModuleIdentifier) obj).getRevision();
97         return rev == SimpleDateFormatUtil.DEFAULT_DATE_IMP || rev == SimpleDateFormatUtil.DEFAULT_BELONGS_TO_DATE;
98     }
99
100     private static <K, V, N extends IdentifierNamespace<K, V>> V getRegardlessOfRevision(final ModuleIdentifier key,
101             final Map<ModuleIdentifier, V> localNamespace) {
102
103         if (localNamespace == null) {
104             return null;
105         }
106
107         final Set<Entry<ModuleIdentifier, V>> entrySet = localNamespace.entrySet();
108         for (final Entry<ModuleIdentifier, V> entry : entrySet) {
109             final ModuleIdentifier moduleIdentifierInMap = entry.getKey();
110             if (moduleIdentifierInMap.getName().equals(key.getName())) {
111                 return entry.getValue();
112             }
113         }
114
115         return null;
116     }
117
118     @Override
119     public <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAllFromLocalStorage(final Class<N> type) {
120         @SuppressWarnings("unchecked")
121         final Map<K, V> localNamespace = (Map<K, V>) namespaces.get(type);
122         return localNamespace;
123     }
124
125     private <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> ensureLocalNamespace(final Class<N> type) {
126         @SuppressWarnings("unchecked")
127         Map<K, V> ret = (Map<K,V>) namespaces.get(type);
128         if (ret == null) {
129             checkLocalNamespaceAllowed(type);
130             ret = new HashMap<>(1);
131
132             if (namespaces.isEmpty()) {
133                 namespaces = new HashMap<>(1);
134             }
135             namespaces.put(type, ret);
136         }
137
138         return ret;
139     }
140
141     @Override
142     public <K, V, N extends IdentifierNamespace<K, V>> V putToLocalStorage(final Class<N> type, final K key,
143             final V value) {
144         final V ret = ensureLocalNamespace(type).put(key, value);
145         onNamespaceElementAdded(type, key, value);
146         return ret;
147     }
148
149     @Override
150     public <K, V, N extends IdentifierNamespace<K, V>> V putToLocalStorageIfAbsent(final Class<N> type, final K key,
151             final V value) {
152         final V ret = ensureLocalNamespace(type).putIfAbsent(key, value);
153         if (ret == null) {
154             onNamespaceElementAdded(type, key, value);
155         }
156         return ret;
157     }
158 }