*/
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;
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;
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)
.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<>();
}
@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;
}
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()
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());
+ });
+ }
}