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 static java.util.Objects.requireNonNull;
13 import javax.annotation.Nonnull;
14 import javax.annotation.Nullable;
15 import org.opendaylight.yangtools.concepts.Identifiable;
16 import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
19 * Definition / implementation of specific Identifier Namespace behaviour. A namespace behaviour is built on top
20 * of a tree of {@link NamespaceStorageNode} which represents local context of one of types defined
21 * n {@link StorageNodeType}.
24 * For common behaviour models please use static factories {@link #global(Class)}, {@link #sourceLocal(Class)} and
25 * {@link #treeScoped(Class)}.
34 public abstract class NamespaceBehaviour<K, V, N extends IdentifierNamespace<K, V>> implements Identifiable<Class<N>> {
36 public enum StorageNodeType {
37 GLOBAL, SOURCE_LOCAL_SPECIAL, STATEMENT_LOCAL, ROOT_STATEMENT_LOCAL
40 public interface Registry {
41 <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> getNamespaceBehaviour(Class<N> type);
44 public interface NamespaceStorageNode {
46 * Return local namespace behaviour type.
48 * @return local namespace behaviour type {@link NamespaceBehaviour}
50 StorageNodeType getStorageNodeType();
53 NamespaceStorageNode getParentNamespaceStorage();
56 <K, V, N extends IdentifierNamespace<K, V>> V getFromLocalStorage(Class<N> type, K key);
59 <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAllFromLocalStorage(Class<N> type);
62 * Populate specified namespace with a key/value pair, overwriting previous contents. Similar to
63 * {@link Map#put(Object, Object)}.
65 * @param type Namespace identifier
68 * @return Previously-stored value, or null if the key was not present
71 <K, V, N extends IdentifierNamespace<K, V>> V putToLocalStorage(Class<N> type, K key, V value);
74 * Populate specified namespace with a key/value pair unless the key is already associated with a value. Similar
75 * to {@link Map#putIfAbsent(Object, Object)}.
77 * @param type Namespace identifier
80 * @return Preexisting value or null if there was no previous mapping
83 <K, V, N extends IdentifierNamespace<K, V>> V putToLocalStorageIfAbsent(Class<N> type, K key, V value);
86 private final Class<N> identifier;
88 protected NamespaceBehaviour(final Class<N> identifier) {
89 this.identifier = requireNonNull(identifier);
93 * Creates a global namespace behaviour for supplied namespace type. Global behaviour stores and loads all values
94 * from root {@link NamespaceStorageNode} with type of {@link StorageNodeType#GLOBAL}.
97 * Namespace identifier.
98 * @param <K> type parameter
99 * @param <V> type parameter
100 * @param <N> type parameter
101 * @return global namespace behaviour for supplied namespace type.
103 public static @Nonnull <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> global(
104 final Class<N> identifier) {
105 return new StorageSpecific<>(identifier, StorageNodeType.GLOBAL);
109 * Creates source-local namespace behaviour for supplied namespace type. Source-local namespace behaviour stores
110 * and loads all values from closest {@link NamespaceStorageNode} ancestor with type
111 * of {@link StorageNodeType#SOURCE_LOCAL_SPECIAL}.
114 * Namespace identifier.
115 * @param <K> type parameter
116 * @param <V> type parameter
117 * @param <N> type parameter
118 * @return source-local namespace behaviour for supplied namespace type.
120 public static <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> sourceLocal(
121 final Class<N> identifier) {
122 return new StorageSpecific<>(identifier, StorageNodeType.SOURCE_LOCAL_SPECIAL);
125 public static <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> statementLocal(
126 final Class<N> identifier) {
127 return new StorageSpecific<>(identifier, StorageNodeType.STATEMENT_LOCAL);
131 * Creates tree-scoped namespace behaviour for supplied namespace type. Tree-scoped namespace behaviour searches
132 * for value in all storage nodes up to the root and stores values in supplied node.
135 * Namespace identifier.
136 * @param <K> type parameter
137 * @param <V> type parameter
138 * @param <N> type parameter
139 * @return tree-scoped namespace behaviour for supplied namespace type.
141 public static <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> treeScoped(
142 final Class<N> identifier) {
143 return new TreeScoped<>(identifier);
147 * Returns a value from model namespace storage according to key param class.
149 * @param storage namespace storage
150 * @param key type parameter
151 * @return value from model namespace storage according to key param class
153 public abstract V getFrom(NamespaceStorageNode storage, K key);
156 * Returns all values of a keys of param class from model namespace storage.
158 * @param storage namespace storage
159 * @return all values of keys of param class from model namespace storage
161 public abstract Map<K, V> getAllFrom(NamespaceStorageNode storage);
164 * Adds a key/value to corresponding namespace storage according to param class.
166 * @param storage namespace storage
167 * @param key type parameter
168 * @param value type parameter
170 public abstract void addTo(NamespaceStorageNode storage, K key, V value);
173 public Class<N> getIdentifier() {
177 protected final V getFromLocalStorage(final NamespaceStorageNode storage, final K key) {
178 return storage.getFromLocalStorage(getIdentifier(), key);
181 protected final Map<K, V> getAllFromLocalStorage(final NamespaceStorageNode storage) {
182 return storage.getAllFromLocalStorage(getIdentifier());
185 protected final void addToStorage(final NamespaceStorageNode storage, final K key, final V value) {
186 storage.putToLocalStorage(getIdentifier(), key, value);
189 static final class StorageSpecific<K, V, N extends IdentifierNamespace<K, V>> extends NamespaceBehaviour<K, V, N> {
190 StorageNodeType storageType;
192 StorageSpecific(final Class<N> identifier, final StorageNodeType type) {
194 storageType = requireNonNull(type);
198 public V getFrom(final NamespaceStorageNode storage, final K key) {
199 NamespaceStorageNode current = findClosestTowardsRoot(storage, storageType);
200 return getFromLocalStorage(current, key);
204 public Map<K, V> getAllFrom(final NamespaceStorageNode storage) {
205 NamespaceStorageNode current = storage;
206 while (current.getStorageNodeType() != storageType) {
207 current = current.getParentNamespaceStorage();
210 return getAllFromLocalStorage(current);
214 public void addTo(final NamespaceBehaviour.NamespaceStorageNode storage, final K key, final V value) {
215 NamespaceStorageNode current = findClosestTowardsRoot(storage, storageType);
216 addToStorage(current, key, value);
220 static final class TreeScoped<K, V, N extends IdentifierNamespace<K, V>> extends NamespaceBehaviour<K, V, N> {
222 TreeScoped(final Class<N> identifier) {
227 public V getFrom(final NamespaceStorageNode storage, final K key) {
228 NamespaceStorageNode current = storage;
229 while (current != null) {
230 final V val = getFromLocalStorage(current, key);
234 current = current.getParentNamespaceStorage();
240 public Map<K, V> getAllFrom(final NamespaceStorageNode storage) {
241 NamespaceStorageNode current = storage;
242 while (current != null) {
243 final Map<K, V> val = getAllFromLocalStorage(current);
247 current = current.getParentNamespaceStorage();
253 public void addTo(final NamespaceStorageNode storage, final K key, final V value) {
254 addToStorage(storage, key, value);
259 protected static NamespaceStorageNode findClosestTowardsRoot(final NamespaceStorageNode storage,
260 final StorageNodeType type) {
261 NamespaceStorageNode current = storage;
262 while (current != null && current.getStorageNodeType() != type) {
263 current = current.getParentNamespaceStorage();