Move StatementContextBase.getStorageNodeType()
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / spi / meta / NamespaceBehaviour.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.spi.meta;
9
10 import com.google.common.base.Preconditions;
11 import java.util.Map;
12 import javax.annotation.Nonnull;
13 import javax.annotation.Nullable;
14 import org.opendaylight.yangtools.concepts.Identifiable;
15 import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
16
17 /**
18  * Definition / implementation of specific Identifier Namespace behaviour.
19  *
20  * Namespace behaviour is build on top of tree of {@link NamespaceStorageNode} which represents local context of one of
21  * types defined in {@link StorageNodeType}.
22  *
23  * For common behaviour models please use static factories {@link #global(Class)}, {@link #sourceLocal(Class)} and
24  * {@link #treeScoped(Class)}.
25  *
26  * @param <K>
27  *            Key type
28  * @param <V>
29  *            Value type
30  * @param <N>
31  *            Namespace Type
32  */
33 public abstract class NamespaceBehaviour<K, V, N extends IdentifierNamespace<K, V>> implements Identifiable<Class<N>> {
34
35     public enum StorageNodeType {
36         GLOBAL, SOURCE_LOCAL_SPECIAL, STATEMENT_LOCAL, ROOT_STATEMENT_LOCAL
37     }
38
39     public interface Registry {
40         <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> getNamespaceBehaviour(Class<N> type);
41     }
42
43     public interface NamespaceStorageNode {
44         /**
45          * @return local namespace behaviour type {@link NamespaceBehaviour}
46          */
47         StorageNodeType getStorageNodeType();
48
49         @Nullable
50         NamespaceStorageNode getParentNamespaceStorage();
51
52         @Nullable
53         <K, V, N extends IdentifierNamespace<K, V>> V getFromLocalStorage(Class<N> type, K key);
54
55         @Nullable
56         <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAllFromLocalStorage(Class<N> type);
57
58         <K, V, N extends IdentifierNamespace<K, V>> void addToLocalStorage(Class<N> type, K key, V value);
59
60     }
61
62     private final Class<N> identifier;
63
64     protected NamespaceBehaviour(final Class<N> identifier) {
65         this.identifier = Preconditions.checkNotNull(identifier);
66     }
67
68     /**
69      *
70      * Creates global namespace behaviour for supplied namespace type.
71      *
72      * Global behaviour stores and loads all values from root {@link NamespaceStorageNode} with type of
73      * {@link StorageNodeType#GLOBAL}.
74      *
75      * @param identifier
76      *            Namespace identifier.
77      * @param <K> type parameter
78      * @param <V> type parameter
79      * @param <N> type parameter
80      *
81      * @return global namespace behaviour for supplied namespace type.
82      */
83     public static @Nonnull <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> global(
84             final Class<N> identifier) {
85         return new StorageSpecific<>(identifier, StorageNodeType.GLOBAL);
86     }
87
88     /**
89      *
90      * Creates source-local namespace behaviour for supplied namespace type.
91      *
92      * Source-local namespace behaviour stores and loads all values from closest {@link NamespaceStorageNode} ancestor
93      * with type of {@link StorageNodeType#SOURCE_LOCAL_SPECIAL}.
94      *
95      * @param identifier
96      *            Namespace identifier.
97      * @param <K> type parameter
98      * @param <V> type parameter
99      * @param <N> type parameter
100      *
101      * @return source-local namespace behaviour for supplied namespace type.
102      */
103     public static <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> sourceLocal(
104             final Class<N> identifier) {
105         return new StorageSpecific<>(identifier, StorageNodeType.SOURCE_LOCAL_SPECIAL);
106     }
107
108     public static <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> statementLocal(
109            final Class<N> identifier) {
110        return new StorageSpecific<>(identifier, StorageNodeType.STATEMENT_LOCAL);
111    }
112
113     /**
114      *
115      * Creates tree-scoped namespace behaviour for supplied namespace type.
116      *
117      * Tree-scoped namespace behaviour search for value in all storage nodes up to the root and stores values in
118      * supplied node.
119      *
120      * @param identifier
121      *            Namespace identifier.     *
122      * @param <K> type parameter
123      * @param <V> type parameter
124      * @param <N> type parameter
125      *
126      * @return tree-scoped namespace behaviour for supplied namespace type.
127      */
128     public static <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> treeScoped(final Class<N> identifier) {
129         return new TreeScoped<>(identifier);
130     }
131
132     /**
133      * returns value from model namespace storage according to key param class
134      *
135      * @param storage namespace storage
136      * @param key type parameter
137      *
138      * @return value from model namespace storage according to key param class
139      */
140     public abstract V getFrom(NamespaceStorageNode storage, K key);
141
142     /**
143      * returns all values of a keys of param class from model namespace storage
144      *
145      * @param storage namespace storage
146      *
147      * @return all values of keys of param class from model namespace storage
148      */
149     public abstract Map<K, V> getAllFrom(NamespaceStorageNode storage);
150
151     /**
152      * adds key and value to corresponding namespace storage according to param class
153      *
154      * @param storage namespace storage
155      * @param key type parameter
156      * @param value type parameter
157      */
158     public abstract void addTo(NamespaceStorageNode storage, K key, V value);
159
160     @Override
161     public Class<N> getIdentifier() {
162         return identifier;
163     }
164
165     protected final V getFromLocalStorage(final NamespaceStorageNode storage, final K key) {
166         return storage.getFromLocalStorage(getIdentifier(), key);
167     }
168
169     protected final Map<K, V> getAllFromLocalStorage(final NamespaceStorageNode storage) {
170         return storage.getAllFromLocalStorage(getIdentifier());
171     }
172
173     protected final void addToStorage(final NamespaceStorageNode storage, final K key, final V value) {
174         storage.addToLocalStorage(getIdentifier(), key, value);
175     }
176
177     static class StorageSpecific<K, V, N extends IdentifierNamespace<K, V>> extends NamespaceBehaviour<K, V, N> {
178
179         StorageNodeType storageType;
180
181         public StorageSpecific(final Class<N> identifier, final StorageNodeType type) {
182             super(identifier);
183             storageType = Preconditions.checkNotNull(type);
184         }
185
186         @Override
187         public V getFrom(final NamespaceStorageNode storage, final K key) {
188             NamespaceStorageNode current = findClosestTowardsRoot(storage, storageType);
189             return getFromLocalStorage(current, key);
190         }
191
192         @Override
193         public Map<K, V> getAllFrom(final NamespaceStorageNode storage) {
194             NamespaceStorageNode current = storage;
195             while (current.getStorageNodeType() != storageType) {
196                 current = current.getParentNamespaceStorage();
197             }
198
199             return getAllFromLocalStorage(current);
200         }
201
202         @Override
203         public void addTo(final NamespaceBehaviour.NamespaceStorageNode storage, final K key, final V value) {
204             NamespaceStorageNode current = findClosestTowardsRoot(storage, storageType);
205             addToStorage(current, key, value);
206         }
207
208     }
209
210     static class TreeScoped<K, V, N extends IdentifierNamespace<K, V>> extends NamespaceBehaviour<K, V, N> {
211
212         public TreeScoped(final Class<N> identifier) {
213             super(identifier);
214         }
215
216         @Override
217         public V getFrom(final NamespaceStorageNode storage, final K key) {
218             NamespaceStorageNode current = storage;
219             while (current != null) {
220                 final V val = getFromLocalStorage(current, key);
221                 if (val != null) {
222                     return val;
223                 }
224                 current = current.getParentNamespaceStorage();
225             }
226             return null;
227         }
228
229         @Override
230         public Map<K, V> getAllFrom(final NamespaceStorageNode storage) {
231             NamespaceStorageNode current = storage;
232             while (current != null) {
233                 final Map<K, V> val = getAllFromLocalStorage(current);
234                 if (val != null) {
235                     return val;
236                 }
237                 current = current.getParentNamespaceStorage();
238             }
239             return null;
240         }
241
242         @Override
243         public void addTo(final NamespaceStorageNode storage, final K key, final V value) {
244             addToStorage(storage, key, value);
245         }
246
247     }
248
249     protected static NamespaceStorageNode findClosestTowardsRoot(final NamespaceStorageNode storage, final StorageNodeType type) {
250         NamespaceStorageNode current = storage;
251         while (current != null && current.getStorageNodeType() != type) {
252             current = current.getParentNamespaceStorage();
253         }
254         return current;
255     }
256 }