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 * @return local namespace behaviour type {@link NamespaceBehaviour}
47 StorageNodeType getStorageNodeType();
50 NamespaceStorageNode getParentNamespaceStorage();
53 <K, V, N extends IdentifierNamespace<K, V>> V getFromLocalStorage(Class<N> type, K key);
56 <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAllFromLocalStorage(Class<N> type);
59 * Populate specified namespace with a key/value pair, overwriting previous contents. Similar to
60 * {@link Map#put(Object, Object)}.
62 * @param type Namespace identifier
65 * @return Previously-stored value, or null if the key was not present
68 <K, V, N extends IdentifierNamespace<K, V>> V putToLocalStorage(Class<N> type, K key, V value);
71 * Populate specified namespace with a key/value pair unless the key is already associated with a value. Similar
72 * to {@link Map#putIfAbsent(Object, Object)}.
74 * @param type Namespace identifier
77 * @return Preexisting value or null if there was no previous mapping
80 <K, V, N extends IdentifierNamespace<K, V>> V putToLocalStorageIfAbsent(Class<N> type, K key, V value);
83 private final Class<N> identifier;
85 protected NamespaceBehaviour(final Class<N> identifier) {
86 this.identifier = Preconditions.checkNotNull(identifier);
91 * Creates global namespace behaviour for supplied namespace type.
93 * Global behaviour stores and loads all values from root {@link NamespaceStorageNode} with type of
94 * {@link StorageNodeType#GLOBAL}.
97 * Namespace identifier.
98 * @param <K> type parameter
99 * @param <V> type parameter
100 * @param <N> type parameter
102 * @return global namespace behaviour for supplied namespace type.
104 public static @Nonnull <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> global(
105 final Class<N> identifier) {
106 return new StorageSpecific<>(identifier, StorageNodeType.GLOBAL);
111 * Creates source-local namespace behaviour for supplied namespace type.
113 * Source-local namespace behaviour stores and loads all values from closest {@link NamespaceStorageNode} ancestor
114 * with type of {@link StorageNodeType#SOURCE_LOCAL_SPECIAL}.
117 * Namespace identifier.
118 * @param <K> type parameter
119 * @param <V> type parameter
120 * @param <N> type parameter
122 * @return source-local namespace behaviour for supplied namespace type.
124 public static <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> sourceLocal(
125 final Class<N> identifier) {
126 return new StorageSpecific<>(identifier, StorageNodeType.SOURCE_LOCAL_SPECIAL);
129 public static <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> statementLocal(
130 final Class<N> identifier) {
131 return new StorageSpecific<>(identifier, StorageNodeType.STATEMENT_LOCAL);
136 * Creates tree-scoped namespace behaviour for supplied namespace type.
138 * Tree-scoped namespace behaviour search for value in all storage nodes up to the root and stores values in
142 * Namespace identifier. *
143 * @param <K> type parameter
144 * @param <V> type parameter
145 * @param <N> type parameter
147 * @return tree-scoped namespace behaviour for supplied namespace type.
149 public static <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> treeScoped(final Class<N> identifier) {
150 return new TreeScoped<>(identifier);
154 * returns value from model namespace storage according to key param class
156 * @param storage namespace storage
157 * @param key type parameter
159 * @return value from model namespace storage according to key param class
161 public abstract V getFrom(NamespaceStorageNode storage, K key);
164 * returns all values of a keys of param class from model namespace storage
166 * @param storage namespace storage
168 * @return all values of keys of param class from model namespace storage
170 public abstract Map<K, V> getAllFrom(NamespaceStorageNode storage);
173 * adds key and value to corresponding namespace storage according to param class
175 * @param storage namespace storage
176 * @param key type parameter
177 * @param value type parameter
179 public abstract void addTo(NamespaceStorageNode storage, K key, V value);
182 public Class<N> getIdentifier() {
186 protected final V getFromLocalStorage(final NamespaceStorageNode storage, final K key) {
187 return storage.getFromLocalStorage(getIdentifier(), key);
190 protected final Map<K, V> getAllFromLocalStorage(final NamespaceStorageNode storage) {
191 return storage.getAllFromLocalStorage(getIdentifier());
194 protected final void addToStorage(final NamespaceStorageNode storage, final K key, final V value) {
195 storage.putToLocalStorage(getIdentifier(), key, value);
198 static class StorageSpecific<K, V, N extends IdentifierNamespace<K, V>> extends NamespaceBehaviour<K, V, N> {
200 StorageNodeType storageType;
202 public StorageSpecific(final Class<N> identifier, final StorageNodeType type) {
204 storageType = Preconditions.checkNotNull(type);
208 public V getFrom(final NamespaceStorageNode storage, final K key) {
209 NamespaceStorageNode current = findClosestTowardsRoot(storage, storageType);
210 return getFromLocalStorage(current, key);
214 public Map<K, V> getAllFrom(final NamespaceStorageNode storage) {
215 NamespaceStorageNode current = storage;
216 while (current.getStorageNodeType() != storageType) {
217 current = current.getParentNamespaceStorage();
220 return getAllFromLocalStorage(current);
224 public void addTo(final NamespaceBehaviour.NamespaceStorageNode storage, final K key, final V value) {
225 NamespaceStorageNode current = findClosestTowardsRoot(storage, storageType);
226 addToStorage(current, key, value);
231 static class TreeScoped<K, V, N extends IdentifierNamespace<K, V>> extends NamespaceBehaviour<K, V, N> {
233 public TreeScoped(final Class<N> identifier) {
238 public V getFrom(final NamespaceStorageNode storage, final K key) {
239 NamespaceStorageNode current = storage;
240 while (current != null) {
241 final V val = getFromLocalStorage(current, key);
245 current = current.getParentNamespaceStorage();
251 public Map<K, V> getAllFrom(final NamespaceStorageNode storage) {
252 NamespaceStorageNode current = storage;
253 while (current != null) {
254 final Map<K, V> val = getAllFromLocalStorage(current);
258 current = current.getParentNamespaceStorage();
264 public void addTo(final NamespaceStorageNode storage, final K key, final V value) {
265 addToStorage(storage, key, value);
270 protected static NamespaceStorageNode findClosestTowardsRoot(final NamespaceStorageNode storage, final StorageNodeType type) {
271 NamespaceStorageNode current = storage;
272 while (current != null && current.getStorageNodeType() != type) {
273 current = current.getParentNamespaceStorage();