Bug 2366 - new parser API - implementation of declared statements
[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         SOURCE_LOCAL_SPECIAL,
34         STATEMENT_LOCAL,
35     }
36
37     public interface Registry {
38         <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> getNamespaceBehaviour(Class<N> type);
39     }
40
41     public interface NamespaceStorageNode {
42
43         StorageNodeType getStorageNodeType();
44
45         @Nullable NamespaceStorageNode getParentNamespaceStorage();
46
47         @Nullable  <K, V, N extends IdentifierNamespace<K, V>> V getFromLocalStorage(Class<N> type, K key);
48
49         //<K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAllFromLocalStorage(Class<N> type);
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     protected NamespaceBehaviour(Class<N> identifier) {
58         this.identifier = Preconditions.checkNotNull(identifier);
59     }
60
61     /**
62      *
63      * Creates global namespace behaviour for supplied namespace type.
64      *
65      * Global behaviour stores and loads all values from root {@link NamespaceStorageNode}
66      * with type of {@link StorageNodeType#GLOBAL}.
67      *
68      * @param identifier Namespace identifier.
69      * @return global namespace behaviour for supplied namespace type.
70      */
71     public static @Nonnull <K,V, N extends IdentifierNamespace<K, V>>  NamespaceBehaviour<K,V,N> global(Class<N> identifier) {
72         return new StorageSpecific<>(identifier, StorageNodeType.GLOBAL);
73     }
74
75     /**
76      *
77      * Creates source-local namespace behaviour for supplied namespace type.
78      *
79      * Source-local namespace behaviour stores and loads all values from closest
80      * {@link NamespaceStorageNode} ancestor with type of
81      * {@link StorageNodeType#SOURCE_LOCAL_SPECIAL}.
82      *
83      * @param identifier Namespace identifier.
84      * @return source-local namespace behaviour for supplied namespace type.
85      */
86     public static <K,V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K,V,N> sourceLocal(Class<N> identifier) {
87         return new StorageSpecific<>(identifier, StorageNodeType.SOURCE_LOCAL_SPECIAL);
88     }
89
90     /**
91     *
92     * Creates tree-scoped namespace behaviour for supplied namespace type.
93     *
94     * Tree-scoped namespace behaviour search for value in all storage nodes
95     * up to the root and stores values in supplied node.
96     *
97     * @param identifier Namespace identifier.
98     * @return tree-scoped namespace behaviour for supplied namespace type.
99     */
100     public static <K,V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K,V,N> treeScoped(Class<N> identifier) {
101         return new TreeScoped<>(identifier);
102     }
103
104     public abstract V getFrom(NamespaceStorageNode storage, K key);
105
106     //public abstract Map<K, V> getAllFrom(NamespaceStorageNode storage);
107
108     public abstract void addTo(NamespaceStorageNode storage,K key,V value);
109
110     @Override
111     public Class<N> getIdentifier() {
112         return identifier;
113     }
114
115     protected final V getFromLocalStorage(NamespaceStorageNode storage, K key) {
116         return storage.getFromLocalStorage(getIdentifier(), key);
117     }
118
119 //    protected final Map<K, V> getAllFromLocalStorage(NamespaceStorageNode storage) {
120 //        return storage.getAllFromLocalStorage(getIdentifier());
121 //    }
122
123     protected final void addToStorage(NamespaceStorageNode storage,K key,V value) {
124         storage.addToLocalStorage(getIdentifier(),key,value);
125     }
126
127     static class StorageSpecific<K,V, N extends IdentifierNamespace<K, V>> extends NamespaceBehaviour<K, V, N> {
128
129         StorageNodeType storageType;
130
131         public StorageSpecific(Class<N> identifier, StorageNodeType type) {
132             super(identifier);
133             storageType = Preconditions.checkNotNull(type);
134         }
135
136         @Override
137         public V getFrom(final NamespaceStorageNode storage, final K key) {
138             NamespaceStorageNode current = storage;
139             while(current.getStorageNodeType() != storageType) {
140                 current = current.getParentNamespaceStorage();
141             }
142             return getFromLocalStorage(current,key);
143         }
144
145 //        @Override
146 //        public Map<K, V> getAllFrom(final NamespaceStorageNode storage) {
147 //            NamespaceStorageNode current = storage;
148 //            while(current.getStorageNodeType() != storageType) {
149 //                current = current.getParentNamespaceStorage();
150 //            }
151 //            return getAllFromLocalStorage(current);
152 //        }
153
154         @Override
155         public void addTo(NamespaceBehaviour.NamespaceStorageNode storage, K key, V value) {
156             NamespaceStorageNode current = storage;
157             while(current.getStorageNodeType() != storageType) {
158                 current = current.getParentNamespaceStorage();
159             }
160             addToStorage(current, key, value);
161         }
162
163     }
164
165     static class TreeScoped<K,V, N extends IdentifierNamespace<K, V>> extends NamespaceBehaviour<K, V, N> {
166
167         public TreeScoped(Class<N> identifier) {
168             super(identifier);
169         }
170
171         @Override
172         public V getFrom(final NamespaceStorageNode storage, final K key) {
173             NamespaceStorageNode current = storage;
174             while(current != null) {
175                 final V val = getFromLocalStorage(current, key);
176                 if(val != null) {
177                     return val;
178                 }
179                 current = current.getParentNamespaceStorage();
180             }
181             return null;
182         }
183
184 //        @Override
185 //        public Map<K, V> getAllFrom(final NamespaceStorageNode storage) {
186 //            NamespaceStorageNode current = storage;
187 //            while(current != null) {
188 //                final Map<K, V> val = getAllFromLocalStorage(current);
189 //                if(val != null) {
190 //                    return val;
191 //                }
192 //                current = current.getParentNamespaceStorage();
193 //            }
194 //            return null;
195 //        }
196
197         @Override
198         public void addTo(NamespaceStorageNode storage,K key, V value) {
199             addToStorage(storage, key, value);
200         }
201
202     }
203 }