Graduate ChildSchemaNodeNamespace as SchemaTreeNamespace
[yangtools.git] / yang / yang-parser-spi / src / main / java / org / opendaylight / yangtools / yang / parser / spi / meta / NamespaceBehaviour.java
index 54c3e0ccb858c881551b3cd920aac16ec910be1d..25d440954780cc5cd9b2f7105718d9ea7d6f62ac 100644 (file)
@@ -9,16 +9,21 @@ package org.opendaylight.yangtools.yang.parser.spi.meta;
 
 import static java.util.Objects.requireNonNull;
 
-import com.google.common.base.MoreObjects;
+import com.google.common.annotations.Beta;
 import com.google.common.base.MoreObjects.ToStringHelper;
 import com.google.common.base.Verify;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Optional;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import org.opendaylight.yangtools.concepts.Identifiable;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.yangtools.concepts.AbstractIdentifiable;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeAwareEffectiveStatement;
+import org.opendaylight.yangtools.yang.parser.spi.SchemaTreeNamespace;
 
 /**
  * Definition / implementation of specific Identifier Namespace behaviour. A namespace behaviour is built on top
@@ -29,14 +34,12 @@ import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
  * For common behaviour models please use static factories {@link #global(Class)}, {@link #sourceLocal(Class)} and
  * {@link #treeScoped(Class)}.
  *
- * @param <K>
- *            Key type
- * @param <V>
- *            Value type
- * @param <N>
- *            Namespace Type
+ * @param <K> Key type
+ * @param <V> Value type
+ * @param <N> Namespace Type
  */
-public abstract class NamespaceBehaviour<K, V, N extends IdentifierNamespace<K, V>> implements Identifiable<Class<N>> {
+public abstract class NamespaceBehaviour<K, V, N extends IdentifierNamespace<K, V>>
+        extends AbstractIdentifiable<Class<N>> {
 
     public enum StorageNodeType {
         /**
@@ -46,7 +49,7 @@ public abstract class NamespaceBehaviour<K, V, N extends IdentifierNamespace<K,
         /**
          * Storage of the root statement of a particular source and any sources it is importing.
          */
-        // FIXME: 3.0.0: this is a misnomer and should be renamed
+        // FIXME: 7.0.0: this is a misnomer and should be renamed
         SOURCE_LOCAL_SPECIAL,
         /**
          * Storage of a single statement.
@@ -80,14 +83,11 @@ public abstract class NamespaceBehaviour<K, V, N extends IdentifierNamespace<K,
          */
         StorageNodeType getStorageNodeType();
 
-        @Nullable
-        NamespaceStorageNode getParentNamespaceStorage();
+        @Nullable NamespaceStorageNode getParentNamespaceStorage();
 
-        @Nullable
-        <K, V, N extends IdentifierNamespace<K, V>> V getFromLocalStorage(Class<N> type, K key);
+        <K, V, N extends IdentifierNamespace<K, V>> @Nullable V getFromLocalStorage(Class<N> type, K key);
 
-        @Nullable
-        <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAllFromLocalStorage(Class<N> type);
+        <K, V, N extends IdentifierNamespace<K, V>> @Nullable Map<K, V> getAllFromLocalStorage(Class<N> type);
 
         /**
          * Populate specified namespace with a key/value pair, overwriting previous contents. Similar to
@@ -98,8 +98,7 @@ public abstract class NamespaceBehaviour<K, V, N extends IdentifierNamespace<K,
          * @param value Value
          * @return Previously-stored value, or null if the key was not present
          */
-        @Nullable
-        <K, V, N extends IdentifierNamespace<K, V>> V putToLocalStorage(Class<N> type, K key, V value);
+        <K, V, N extends IdentifierNamespace<K, V>> @Nullable V putToLocalStorage(Class<N> type, K key, V value);
 
         /**
          * Populate specified namespace with a key/value pair unless the key is already associated with a value. Similar
@@ -110,28 +109,55 @@ public abstract class NamespaceBehaviour<K, V, N extends IdentifierNamespace<K,
          * @param value Value
          * @return Preexisting value or null if there was no previous mapping
          */
-        @Nullable
-        <K, V, N extends IdentifierNamespace<K, V>> V putToLocalStorageIfAbsent(Class<N> type, K key, V value);
+        <K, V, N extends IdentifierNamespace<K, V>> @Nullable V putToLocalStorageIfAbsent(Class<N> type, K key,
+                V value);
     }
 
-    private final Class<N> identifier;
+    /**
+     * Interface implemented by {@link NamespaceStorageNode}s which support dynamic addition of child elements as they
+     * are requested. This means that such a node can, defer creation of child namespace storage nodes, in effect lazily
+     * expanding this namespace on an if-needed basis.
+     */
+    @Beta
+    public interface OnDemandSchemaTreeStorageNode extends NamespaceStorageNode {
+        /**
+         * Request that a new member of this node's schema tree statement be added. Implementations are required to
+         * perform lookup in their internal structure and create a child if tracktable. Resulting node is expected to
+         * have been registered with local storage, so that it is accessible through
+         * {@link #getFromLocalStorage(Class, Object)}.
+         *
+         * <p>
+         * This method must not change its mind about a child's presence -- once it returns non-present, it has to be
+         * always returning non-present.
+         *
+         * <p>
+         * The results produced by this method are expected to be consistent with
+         * {@link SchemaTreeAwareEffectiveStatement#findSchemaTreeNode(QName)} and
+         * {@link SchemaTreeNamespace#getFrom(NamespaceStorageNode, QName)}.
+         *
+         * @param qname node identifier of the child being requested
+         * @return Requested child, if it is present.
+         * @throws NullPointerException in {@code qname} is null
+         */
+        <D extends DeclaredStatement<QName>, E extends EffectiveStatement<QName, D>>
+            @Nullable StmtContext<QName, D, E> requestSchemaTreeChild(QName qname);
+    }
 
     protected NamespaceBehaviour(final Class<N> identifier) {
-        this.identifier = requireNonNull(identifier);
+        super(identifier);
     }
 
     /**
      * Creates a 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.
+     * @param identifier Namespace identifier.
      * @param <K> type parameter
      * @param <V> type parameter
      * @param <N> type parameter
      * @return global namespace behaviour for supplied namespace type.
      */
-    public static @Nonnull <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> global(
+    public static <K, V, N extends IdentifierNamespace<K, V>> @NonNull NamespaceBehaviour<K, V, N> global(
             final Class<N> identifier) {
         return new StorageSpecific<>(identifier, StorageNodeType.GLOBAL);
     }
@@ -141,19 +167,18 @@ public abstract class NamespaceBehaviour<K, V, N extends IdentifierNamespace<K,
      * and loads all values from closest {@link NamespaceStorageNode} ancestor with type
      * of {@link StorageNodeType#SOURCE_LOCAL_SPECIAL}.
      *
-     * @param identifier
-     *            Namespace identifier.
+     * @param identifier Namespace identifier.
      * @param <K> type parameter
      * @param <V> type parameter
      * @param <N> type parameter
      * @return source-local namespace behaviour for supplied namespace type.
      */
-    public static <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> sourceLocal(
+    public static <K, V, N extends IdentifierNamespace<K, V>> @NonNull NamespaceBehaviour<K, V, N> sourceLocal(
             final Class<N> identifier) {
         return new StorageSpecific<>(identifier, StorageNodeType.SOURCE_LOCAL_SPECIAL);
     }
 
-    public static <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> statementLocal(
+    public static <K, V, N extends IdentifierNamespace<K, V>> @NonNull NamespaceBehaviour<K, V, N> statementLocal(
            final Class<N> identifier) {
         return new StorageSpecific<>(identifier, StorageNodeType.STATEMENT_LOCAL);
     }
@@ -163,14 +188,13 @@ public abstract class NamespaceBehaviour<K, V, N extends IdentifierNamespace<K,
      * behaviour stores and loads all values from closest {@link NamespaceStorageNode} ancestor with type
      * of {@link StorageNodeType#ROOT_STATEMENT_LOCAL}.
      *
-     * @param identifier
-     *            Namespace identifier.
+     * @param identifier Namespace identifier.
      * @param <K> type parameter
      * @param <V> type parameter
      * @param <N> type parameter
      * @return root-statement-local namespace behaviour for supplied namespace type.
      */
-    public static <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> rootStatementLocal(
+    public static <K, V, N extends IdentifierNamespace<K, V>> @NonNull NamespaceBehaviour<K, V, N> rootStatementLocal(
             final Class<N> identifier) {
         return new StorageSpecific<>(identifier, StorageNodeType.ROOT_STATEMENT_LOCAL);
     }
@@ -186,7 +210,7 @@ public abstract class NamespaceBehaviour<K, V, N extends IdentifierNamespace<K,
      * @param <N> type parameter
      * @return tree-scoped namespace behaviour for supplied namespace type.
      */
-    public static <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> treeScoped(
+    public static <K, V, N extends IdentifierNamespace<K, V>> @NonNull NamespaceBehaviour<K, V, N> treeScoped(
             final Class<N> identifier) {
         return new TreeScoped<>(identifier);
     }
@@ -252,11 +276,6 @@ public abstract class NamespaceBehaviour<K, V, N extends IdentifierNamespace<K,
      */
     public abstract void addTo(NamespaceStorageNode storage, K key, V value);
 
-    @Override
-    public Class<N> getIdentifier() {
-        return identifier;
-    }
-
     protected final V getFromLocalStorage(final NamespaceStorageNode storage, final K key) {
         return storage.getFromLocalStorage(getIdentifier(), key);
     }
@@ -270,7 +289,7 @@ public abstract class NamespaceBehaviour<K, V, N extends IdentifierNamespace<K,
     }
 
     static final class StorageSpecific<K, V, N extends IdentifierNamespace<K, V>> extends NamespaceBehaviour<K, V, N> {
-        StorageNodeType storageType;
+        private final StorageNodeType storageType;
 
         StorageSpecific(final Class<N> identifier, final StorageNodeType type) {
             super(identifier);
@@ -354,12 +373,7 @@ public abstract class NamespaceBehaviour<K, V, N extends IdentifierNamespace<K,
     }
 
     @Override
-    // FIXME: 3.0.0: make this final
-    public String toString() {
-        return addToStringAttributes(MoreObjects.toStringHelper(this)).toString();
-    }
-
     protected ToStringHelper addToStringAttributes(final ToStringHelper helper) {
-        return helper.add("identifier", identifier.getName());
+        return helper.add("identifier", getIdentifier().getName());
     }
 }