Bug 2361: Added meta-level SPI for building any statement-based models.
[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 javax.annotation.Nonnull;
12 import javax.annotation.Nullable;
13 import org.opendaylight.yangtools.concepts.Identifiable;
14 import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
15
16 /**
17  * Definition / implementation of specific Identifier Namespace behaviour.
18  *
19  * Namespace behaviour is build on top of tree of {@link NamespaceStorageNode}
20  * which represents local context of one of types defined in {@link StorageNodeType}.
21  *
22  * For common behaviour models please use static factories {@link #global(Class)},
23  * {@link #sourceLocal(Class)} and {@link #treeScoped(Class)}.
24  *
25  * @param <K> Key type
26  * @param <V> Value type
27  * @param <N> Namespace Type
28  */
29 public abstract class NamespaceBehaviour<K,V, N extends IdentifierNamespace<K, V>> implements Identifiable<Class<N>>{
30
31     public enum StorageNodeType {
32         Global,
33         SourceLocalSpecial,
34         StatementLocal
35     }
36
37     public interface Registry {
38
39         abstract <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> getNamespaceBehaviour(Class<N> type);
40
41     }
42
43     public interface NamespaceStorageNode {
44
45         StorageNodeType getStorageNodeType();
46
47         @Nullable NamespaceStorageNode getParentNamespaceStorage();
48
49         @Nullable  <K, V, N extends IdentifierNamespace<K, V>> V getFromLocalStorage(Class<N> type, K key);
50
51         @Nullable  <K, V, N extends IdentifierNamespace<K, V>> void addToLocalStorage(Class<N> type, K key, V value);
52
53     }
54
55     private final Class<N> identifier;
56
57
58     protected NamespaceBehaviour(Class<N> identifier) {
59         this.identifier = Preconditions.checkNotNull(identifier);
60     }
61
62     /**
63      *
64      * Creates global namespace behaviour for supplied namespace type.
65      *
66      * Global behaviour stores and loads all values from root {@link NamespaceStorageNode}
67      * with type of {@link StorageNodeType#Global}.
68      *
69      * @param identifier Namespace identifier.
70      * @return global namespace behaviour for supplied namespace type.
71      */
72     public static @Nonnull <K,V, N extends IdentifierNamespace<K, V>>  NamespaceBehaviour<K,V,N> global(Class<N> identifier) {
73         return new StorageSpecific<>(identifier, StorageNodeType.Global);
74     }
75
76     /**
77      *
78      * Creates source-local namespace behaviour for supplied namespace type.
79      *
80      * Source-local namespace behaviour stores and loads all values from closest
81      * {@link NamespaceStorageNode} ancestor with type of
82      * {@link StorageNodeType#SourceLocalSpecial}.
83      *
84      * @param identifier Namespace identifier.
85      * @return source-local namespace behaviour for supplied namespace type.
86      */
87     public static <K,V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K,V,N> sourceLocal(Class<N> identifier) {
88         return new StorageSpecific<>(identifier, StorageNodeType.SourceLocalSpecial);
89     }
90
91     /**
92     *
93     * Creates tree-scoped namespace behaviour for supplied namespace type.
94     *
95     * Tree-scoped namespace behaviour search for value in all storage nodes
96     * up to the root and stores values in supplied node.
97     *
98     * @param identifier Namespace identifier.
99     * @return tree-scoped namespace behaviour for supplied namespace type.
100     */
101     public static <K,V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K,V,N> treeScoped(Class<N> identifier) {
102         return new TreeScoped<>(identifier);
103     }
104
105     public abstract V getFrom(NamespaceStorageNode storage, K key);
106     public abstract void addTo(NamespaceStorageNode storage,K key,V value);
107
108
109     @Override
110     public Class<N> getIdentifier() {
111         return identifier;
112     }
113
114     protected final V getFromLocalStorage(NamespaceStorageNode storage, K key) {
115         return storage.getFromLocalStorage(getIdentifier(), key);
116     }
117
118     protected final void addToStorage(NamespaceStorageNode storage,K key,V value) {
119         storage.addToLocalStorage(getIdentifier(),key,value);
120     }
121
122     static class StorageSpecific<K,V, N extends IdentifierNamespace<K, V>> extends NamespaceBehaviour<K, V, N> {
123
124         StorageNodeType storageType;
125
126         public StorageSpecific(Class<N> identifier, StorageNodeType type) {
127             super(identifier);
128             storageType = Preconditions.checkNotNull(type);
129         }
130
131         @Override
132         public V getFrom(final NamespaceStorageNode storage, final K key) {
133             NamespaceStorageNode current = storage;
134             while(current.getParentNamespaceStorage() != null) {
135                 current = current.getParentNamespaceStorage();
136             }
137             return getFromLocalStorage(current,key);
138         }
139
140         @Override
141         public void addTo(NamespaceBehaviour.NamespaceStorageNode storage, K key, V value) {
142             NamespaceStorageNode current = storage;
143             while(current.getStorageNodeType() != storageType) {
144                 current = current.getParentNamespaceStorage();
145             }
146             addToStorage(current, key, value);
147         }
148
149     }
150
151     static class TreeScoped<K,V, N extends IdentifierNamespace<K, V>> extends NamespaceBehaviour<K, V, N> {
152
153         public TreeScoped(Class<N> identifier) {
154             super(identifier);
155         }
156
157         @Override
158         public V getFrom(final NamespaceStorageNode storage, final K key) {
159             NamespaceStorageNode current = storage;
160             while(current != null) {
161                 final V val = getFromLocalStorage(current, key);
162                 if(val != null) {
163                     return val;
164                 }
165                 current = current.getParentNamespaceStorage();
166             }
167             return null;
168         }
169
170         @Override
171         public void addTo(NamespaceStorageNode storage,K key, V value) {
172             addToStorage(storage, key, value);
173         }
174
175     }
176
177 }