2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.yangtools.yang.parser.spi.meta;
10 import com.google.common.base.Preconditions;
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;
18 * Definition / implementation of specific Identifier Namespace behaviour.
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}.
23 * For common behaviour models please use static factories {@link #global(Class)}, {@link #sourceLocal(Class)} and
24 * {@link #treeScoped(Class)}.
33 public abstract class NamespaceBehaviour<K, V, N extends IdentifierNamespace<K, V>> implements Identifiable<Class<N>> {
35 public enum StorageNodeType {
36 GLOBAL, SOURCE_LOCAL_SPECIAL, STATEMENT_LOCAL, ROOT_STATEMENT_LOCAL
39 public interface Registry {
40 <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> getNamespaceBehaviour(Class<N> type);
43 public interface NamespaceStorageNode {
45 StorageNodeType getStorageNodeType();
48 NamespaceStorageNode getParentNamespaceStorage();
51 <K, V, N extends IdentifierNamespace<K, V>> V getFromLocalStorage(Class<N> type, K key);
54 <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAllFromLocalStorage(Class<N> type);
57 <K, V, N extends IdentifierNamespace<K, V>> void addToLocalStorage(Class<N> type, K key, V value);
61 private final Class<N> identifier;
63 protected NamespaceBehaviour(Class<N> identifier) {
64 this.identifier = Preconditions.checkNotNull(identifier);
69 * Creates global namespace behaviour for supplied namespace type.
71 * Global behaviour stores and loads all values from root {@link NamespaceStorageNode} with type of
72 * {@link StorageNodeType#GLOBAL}.
75 * Namespace identifier.
76 * @param <K> type parameter
77 * @param <V> type parameter
78 * @param <N> type parameter
80 * @return global namespace behaviour for supplied namespace type.
82 public static @Nonnull <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> global(
83 Class<N> identifier) {
84 return new StorageSpecific<>(identifier, StorageNodeType.GLOBAL);
89 * Creates source-local namespace behaviour for supplied namespace type.
91 * Source-local namespace behaviour stores and loads all values from closest {@link NamespaceStorageNode} ancestor
92 * with type of {@link StorageNodeType#SOURCE_LOCAL_SPECIAL}.
95 * Namespace identifier.
96 * @param <K> type parameter
97 * @param <V> type parameter
98 * @param <N> type parameter
100 * @return source-local namespace behaviour for supplied namespace type.
102 public static <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> sourceLocal(
103 Class<N> identifier) {
104 return new StorageSpecific<>(identifier, StorageNodeType.SOURCE_LOCAL_SPECIAL);
107 public static <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> statementLocal(
108 Class<N> identifier) {
109 return new StorageSpecific<>(identifier, StorageNodeType.STATEMENT_LOCAL);
114 * Creates tree-scoped namespace behaviour for supplied namespace type.
116 * Tree-scoped namespace behaviour search for value in all storage nodes up to the root and stores values in
120 * Namespace identifier. *
121 * @param <K> type parameter
122 * @param <V> type parameter
123 * @param <N> type parameter
125 * @return tree-scoped namespace behaviour for supplied namespace type.
127 public static <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> treeScoped(Class<N> identifier) {
128 return new TreeScoped<>(identifier);
132 * returns value from model namespace storage according to key param class
134 * @param storage namespace storage
135 * @param key type parameter
137 * @return value from model namespace storage according to key param class
139 public abstract V getFrom(NamespaceStorageNode storage, K key);
142 * returns all values of a keys of param class from model namespace storage
144 * @param storage namespace storage
146 * @return all values of keys of param class from model namespace storage
148 public abstract Map<K, V> getAllFrom(NamespaceStorageNode storage);
151 * adds key and value to corresponding namespace storage according to param class
153 * @param storage namespace storage
154 * @param key type parameter
155 * @param value type parameter
157 public abstract void addTo(NamespaceStorageNode storage, K key, V value);
160 public Class<N> getIdentifier() {
164 protected final V getFromLocalStorage(NamespaceStorageNode storage, K key) {
165 return storage.getFromLocalStorage(getIdentifier(), key);
168 protected final Map<K, V> getAllFromLocalStorage(NamespaceStorageNode storage) {
169 return storage.getAllFromLocalStorage(getIdentifier());
172 protected final void addToStorage(NamespaceStorageNode storage, K key, V value) {
173 storage.addToLocalStorage(getIdentifier(), key, value);
176 static class StorageSpecific<K, V, N extends IdentifierNamespace<K, V>> extends NamespaceBehaviour<K, V, N> {
178 StorageNodeType storageType;
180 public StorageSpecific(Class<N> identifier, StorageNodeType type) {
182 storageType = Preconditions.checkNotNull(type);
186 public V getFrom(final NamespaceStorageNode storage, final K key) {
187 NamespaceStorageNode current = findClosestTowardsRoot(storage, storageType);
188 return getFromLocalStorage(current, key);
192 public Map<K, V> getAllFrom(final NamespaceStorageNode storage) {
193 NamespaceStorageNode current = storage;
194 while (current.getStorageNodeType() != storageType) {
195 current = current.getParentNamespaceStorage();
198 return getAllFromLocalStorage(current);
202 public void addTo(NamespaceBehaviour.NamespaceStorageNode storage, K key, V value) {
203 NamespaceStorageNode current = findClosestTowardsRoot(storage, storageType);
204 addToStorage(current, key, value);
209 static class TreeScoped<K, V, N extends IdentifierNamespace<K, V>> extends NamespaceBehaviour<K, V, N> {
211 public TreeScoped(Class<N> identifier) {
216 public V getFrom(final NamespaceStorageNode storage, final K key) {
217 NamespaceStorageNode current = storage;
218 while (current != null) {
219 final V val = getFromLocalStorage(current, key);
223 current = current.getParentNamespaceStorage();
229 public Map<K, V> getAllFrom(final NamespaceStorageNode storage) {
230 NamespaceStorageNode current = storage;
231 while (current != null) {
232 final Map<K, V> val = getAllFromLocalStorage(current);
236 current = current.getParentNamespaceStorage();
242 public void addTo(NamespaceStorageNode storage, K key, V value) {
243 addToStorage(storage, key, value);
248 protected static NamespaceStorageNode findClosestTowardsRoot(NamespaceStorageNode storage, StorageNodeType type) {
249 NamespaceStorageNode current = storage;
250 while(current != null && current.getStorageNodeType() != type) {
251 current = current.getParentNamespaceStorage();