Migrate schema/data tree-related methods
[yangtools.git] / yang / yang-parser-rfc7950 / src / main / java / org / opendaylight / yangtools / yang / parser / rfc7950 / stmt / AbstractEffectiveModule.java
index 055188be4e45d478916d8e92689f99619d2fc2f8..8de6d290a63c8c20c64466efdd7e216d0b27e506 100644 (file)
@@ -7,17 +7,21 @@
  */
 package org.opendaylight.yangtools.yang.parser.rfc7950.stmt;
 
+import static com.google.common.base.Verify.verifyNotNull;
 import static java.util.Objects.requireNonNull;
 
 import com.google.common.annotations.Beta;
 import com.google.common.base.MoreObjects;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMap.Builder;
 import com.google.common.collect.ImmutableSet;
 import java.net.URI;
 import java.util.ArrayList;
-import java.util.HashSet;
+import java.util.Collection;
 import java.util.LinkedHashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
 import org.eclipse.jdt.annotation.NonNull;
@@ -41,20 +45,29 @@ import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.UsesNode;
 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.ContactEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.DataTreeAwareEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ImportEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ModuleEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.OrganizationEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.PrefixEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.PrefixStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeAwareEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.TypedefEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.YangVersionEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.compat.NotificationNodeContainerCompat;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
+import org.opendaylight.yangtools.yang.parser.spi.source.ImportPrefixToModuleCtx;
 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
 
 @Beta
-public abstract class AbstractEffectiveModule<D extends DeclaredStatement<String>> extends
+public abstract class AbstractEffectiveModule<D extends DeclaredStatement<String>,
+        E extends DataTreeAwareEffectiveStatement<String, D>> extends
         AbstractSchemaEffectiveDocumentedNode<String, D> implements Module,
-        NotificationNodeContainerCompat<String, D> {
+        NotificationNodeContainerCompat<String, D, E> {
     private final String name;
     private final String prefix;
     private final YangVersion yangVersion;
@@ -73,12 +86,23 @@ public abstract class AbstractEffectiveModule<D extends DeclaredStatement<String
     private final ImmutableSet<TypeDefinition<?>> typeDefinitions;
     private final ImmutableSet<DataSchemaNode> publicChildNodes;
     private final SemVer semanticVersion;
+    private final ImmutableMap<QName, SchemaTreeEffectiveStatement<?>> schemaTreeNamespace;
 
     protected AbstractEffectiveModule(
             final @NonNull StmtContext<String, D, ? extends EffectiveStatement<String, ?>> ctx,
             final @NonNull String prefix) {
         super(ctx);
 
+        // This check is rather weird, but comes from our desire to lower memory footprint while providing both
+        // EffectiveStatements and SchemaNode interfaces -- which do not overlap completely where child lookups are
+        // concerned. This ensures that we have SchemaTree index available for use with child lookups.
+        final Map<QName, SchemaTreeEffectiveStatement<?>> schemaTree =
+                createSchemaTreeNamespace(ctx.getStatementSourceReference(), effectiveSubstatements());
+        schemaTreeNamespace = ImmutableMap.copyOf(schemaTree);
+
+        // Data tree check, not currently used
+        createDataTreeNamespace(ctx.getStatementSourceReference(), schemaTree.values(), schemaTreeNamespace);
+
         this.name = argument();
         this.prefix = requireNonNull(prefix);
         this.yangVersion = findFirstEffectiveSubstatementArgument(YangVersionEffectiveStatement.class)
@@ -91,16 +115,16 @@ public abstract class AbstractEffectiveModule<D extends DeclaredStatement<String
                 .orElse(null);
 
         final Set<AugmentationSchemaNode> augmentationsInit = new LinkedHashSet<>();
-        final Set<ModuleImport> importsInit = new HashSet<>();
-        final Set<NotificationDefinition> notificationsInit = new HashSet<>();
-        final Set<RpcDefinition> rpcsInit = new HashSet<>();
-        final Set<Deviation> deviationsInit = new HashSet<>();
-        final Set<IdentitySchemaNode> identitiesInit = new HashSet<>();
-        final Set<FeatureDefinition> featuresInit = new HashSet<>();
+        final Set<ModuleImport> importsInit = new LinkedHashSet<>();
+        final Set<NotificationDefinition> notificationsInit = new LinkedHashSet<>();
+        final Set<RpcDefinition> rpcsInit = new LinkedHashSet<>();
+        final Set<Deviation> deviationsInit = new LinkedHashSet<>();
+        final Set<IdentitySchemaNode> identitiesInit = new LinkedHashSet<>();
+        final Set<FeatureDefinition> featuresInit = new LinkedHashSet<>();
         final List<ExtensionDefinition> extensionNodesInit = new ArrayList<>();
 
-        final Set<GroupingDefinition> mutableGroupings = new HashSet<>();
-        final Set<UsesNode> mutableUses = new HashSet<>();
+        final Set<GroupingDefinition> mutableGroupings = new LinkedHashSet<>();
+        final Set<UsesNode> mutableUses = new LinkedHashSet<>();
         final Set<TypeDefinition<?>> mutableTypeDefinitions = new LinkedHashSet<>();
         final Set<DataSchemaNode> mutablePublicChildNodes = new LinkedHashSet<>();
 
@@ -198,68 +222,69 @@ public abstract class AbstractEffectiveModule<D extends DeclaredStatement<String
     }
 
     @Override
-    public Set<ModuleImport> getImports() {
+    public Collection<? extends ModuleImport> getImports() {
         return imports;
     }
 
     @Override
-    public Set<FeatureDefinition> getFeatures() {
+    public Collection<? extends FeatureDefinition> getFeatures() {
         return features;
     }
 
     @Override
-    public Set<NotificationDefinition> getNotifications() {
+    public Collection<? extends NotificationDefinition> getNotifications() {
         return notifications;
     }
 
     @Override
-    public Set<AugmentationSchemaNode> getAugmentations() {
+    public Collection<? extends AugmentationSchemaNode> getAugmentations() {
         return augmentations;
     }
 
     @Override
-    public Set<RpcDefinition> getRpcs() {
+    public Collection<? extends RpcDefinition> getRpcs() {
         return rpcs;
     }
 
     @Override
-    public Set<Deviation> getDeviations() {
+    public Collection<? extends Deviation> getDeviations() {
         return deviations;
     }
 
     @Override
-    public List<ExtensionDefinition> getExtensionSchemaNodes() {
+    public Collection<? extends ExtensionDefinition> getExtensionSchemaNodes() {
         return extensionNodes;
     }
 
     @Override
-    public Set<IdentitySchemaNode> getIdentities() {
+    public Collection<? extends IdentitySchemaNode> getIdentities() {
         return identities;
     }
 
     @Override
-    public final Set<TypeDefinition<?>> getTypeDefinitions() {
+    public final Collection<? extends TypeDefinition<?>> getTypeDefinitions() {
         return typeDefinitions;
     }
 
     @Override
-    public final Set<DataSchemaNode> getChildNodes() {
+    public final Collection<? extends DataSchemaNode> getChildNodes() {
         return publicChildNodes;
     }
 
     @Override
-    public final Set<GroupingDefinition> getGroupings() {
+    public final Collection<? extends GroupingDefinition> getGroupings() {
         return groupings;
     }
 
     @Override
     @SuppressWarnings("checkstyle:hiddenField")
     public final Optional<DataSchemaNode> findDataChildByName(final QName name) {
-        return findDataSchemaNode(name);
+        final SchemaTreeEffectiveStatement<?> child = schemaTreeNamespace.get(requireNonNull(name));
+        return child instanceof DataSchemaNode ? Optional.of((DataSchemaNode) child) : Optional.empty();
     }
 
     @Override
-    public Set<UsesNode> getUses() {
+    public Collection<? extends UsesNode> getUses() {
         return uses;
     }
 
@@ -268,6 +293,16 @@ public abstract class AbstractEffectiveModule<D extends DeclaredStatement<String
         return Optional.ofNullable(semanticVersion);
     }
 
+    @Override
+    @SuppressWarnings("unchecked")
+    protected <K, V, N extends IdentifierNamespace<K, V>> Optional<? extends Map<K, V>> getNamespaceContents(
+            final Class<N> namespace) {
+        if (SchemaTreeAwareEffectiveStatement.Namespace.class.equals(namespace)) {
+            return Optional.of((Map<K, V>) schemaTreeNamespace);
+        }
+        return super.getNamespaceContents(namespace);
+    }
+
     @Override
     public String toString() {
         return MoreObjects.toStringHelper(this).omitNullValues()
@@ -285,4 +320,17 @@ public abstract class AbstractEffectiveModule<D extends DeclaredStatement<String
             StmtContextUtils.firstAttributeOf(ctx.declaredSubstatements(), PrefixStatement.class),
             ctx.getStatementSourceReference(), "Unable to resolve prefix for %s %s.", type, name);
     }
+
+    // Alright. this is quite ugly
+    protected final void appendPrefixes(final StmtContext<?, ?, ?> ctx,
+            final Builder<String, ModuleEffectiveStatement> builder) {
+        streamEffectiveSubstatements(ImportEffectiveStatement.class)
+            .map(imp -> imp.findFirstEffectiveSubstatementArgument(PrefixEffectiveStatement.class).get())
+            .forEach(pfx -> {
+                final StmtContext<?, ?, ?> importedCtx =
+                        verifyNotNull(ctx.getFromNamespace(ImportPrefixToModuleCtx.class, pfx),
+                            "Failed to resolve prefix %s", pfx);
+                builder.put(pfx, (ModuleEffectiveStatement) importedCtx.buildEffective());
+            });
+    }
 }