/* * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.yangtools.yang.parser.spi.meta; import com.google.common.base.Preconditions; import javax.annotation.Nonnull; import javax.annotation.Nullable; import org.opendaylight.yangtools.concepts.Identifiable; import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace; /** * Definition / implementation of specific Identifier Namespace behaviour. * * Namespace behaviour is build on top of tree of {@link NamespaceStorageNode} * which represents local context of one of types defined in {@link StorageNodeType}. * * For common behaviour models please use static factories {@link #global(Class)}, * {@link #sourceLocal(Class)} and {@link #treeScoped(Class)}. * * @param Key type * @param Value type * @param Namespace Type */ public abstract class NamespaceBehaviour> implements Identifiable>{ public enum StorageNodeType { GLOBAL, SOURCE_LOCAL_SPECIAL, STATEMENT_LOCAL, } public interface Registry { > NamespaceBehaviour getNamespaceBehaviour(Class type); } public interface NamespaceStorageNode { StorageNodeType getStorageNodeType(); @Nullable NamespaceStorageNode getParentNamespaceStorage(); @Nullable > V getFromLocalStorage(Class type, K key); //> Map getAllFromLocalStorage(Class type); @Nullable > void addToLocalStorage(Class type, K key, V value); } private final Class identifier; protected NamespaceBehaviour(Class identifier) { this.identifier = Preconditions.checkNotNull(identifier); } /** * * Creates global namespace behaviour for supplied namespace type. * * Global behaviour stores and loads all values from root {@link NamespaceStorageNode} * with type of {@link StorageNodeType#GLOBAL}. * * @param identifier Namespace identifier. * @return global namespace behaviour for supplied namespace type. */ public static @Nonnull > NamespaceBehaviour global(Class identifier) { return new StorageSpecific<>(identifier, StorageNodeType.GLOBAL); } /** * * Creates source-local namespace behaviour for supplied namespace type. * * Source-local namespace behaviour stores and loads all values from closest * {@link NamespaceStorageNode} ancestor with type of * {@link StorageNodeType#SOURCE_LOCAL_SPECIAL}. * * @param identifier Namespace identifier. * @return source-local namespace behaviour for supplied namespace type. */ public static > NamespaceBehaviour sourceLocal(Class identifier) { return new StorageSpecific<>(identifier, StorageNodeType.SOURCE_LOCAL_SPECIAL); } /** * * Creates tree-scoped namespace behaviour for supplied namespace type. * * Tree-scoped namespace behaviour search for value in all storage nodes * up to the root and stores values in supplied node. * * @param identifier Namespace identifier. * @return tree-scoped namespace behaviour for supplied namespace type. */ public static > NamespaceBehaviour treeScoped(Class identifier) { return new TreeScoped<>(identifier); } public abstract V getFrom(NamespaceStorageNode storage, K key); //public abstract Map getAllFrom(NamespaceStorageNode storage); public abstract void addTo(NamespaceStorageNode storage,K key,V value); @Override public Class getIdentifier() { return identifier; } protected final V getFromLocalStorage(NamespaceStorageNode storage, K key) { return storage.getFromLocalStorage(getIdentifier(), key); } // protected final Map getAllFromLocalStorage(NamespaceStorageNode storage) { // return storage.getAllFromLocalStorage(getIdentifier()); // } protected final void addToStorage(NamespaceStorageNode storage,K key,V value) { storage.addToLocalStorage(getIdentifier(),key,value); } static class StorageSpecific> extends NamespaceBehaviour { StorageNodeType storageType; public StorageSpecific(Class identifier, StorageNodeType type) { super(identifier); storageType = Preconditions.checkNotNull(type); } @Override public V getFrom(final NamespaceStorageNode storage, final K key) { NamespaceStorageNode current = storage; while(current.getStorageNodeType() != storageType) { current = current.getParentNamespaceStorage(); } return getFromLocalStorage(current,key); } // @Override // public Map getAllFrom(final NamespaceStorageNode storage) { // NamespaceStorageNode current = storage; // while(current.getStorageNodeType() != storageType) { // current = current.getParentNamespaceStorage(); // } // return getAllFromLocalStorage(current); // } @Override public void addTo(NamespaceBehaviour.NamespaceStorageNode storage, K key, V value) { NamespaceStorageNode current = storage; while(current.getStorageNodeType() != storageType) { current = current.getParentNamespaceStorage(); } addToStorage(current, key, value); } } static class TreeScoped> extends NamespaceBehaviour { public TreeScoped(Class identifier) { super(identifier); } @Override public V getFrom(final NamespaceStorageNode storage, final K key) { NamespaceStorageNode current = storage; while(current != null) { final V val = getFromLocalStorage(current, key); if(val != null) { return val; } current = current.getParentNamespaceStorage(); } return null; } // @Override // public Map getAllFrom(final NamespaceStorageNode storage) { // NamespaceStorageNode current = storage; // while(current != null) { // final Map val = getAllFromLocalStorage(current); // if(val != null) { // return val; // } // current = current.getParentNamespaceStorage(); // } // return null; // } @Override public void addTo(NamespaceStorageNode storage,K key, V value) { addToStorage(storage, key, value); } } }