From: Robert Varga Date: Sat, 30 Jan 2021 12:50:32 +0000 (+0100) Subject: Rework base type lookup X-Git-Tag: v7.0.0~246 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=refs%2Fchanges%2F95%2F94895%2F7;p=yangtools.git Rework base type lookup Rather than performing two string-based lookups, populate BaseTypeNamespace with BuiltinEffectiveStatement. This allows for better expressiveness, as inference-based logic is done before we build effective statement. JIRA: YANGTOOLS-1208 Change-Id: I49ff3383da93a7469172bc4ebbb0e7c62b09bb5e Signed-off-by: Robert Varga --- diff --git a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/type/AbstractTypeStatementSupport.java b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/type/AbstractTypeStatementSupport.java index 1d7c6e9f59..a05b18a35c 100644 --- a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/type/AbstractTypeStatementSupport.java +++ b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/type/AbstractTypeStatementSupport.java @@ -7,8 +7,13 @@ */ package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.type; +import static com.google.common.base.Verify.verifyNotNull; + import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import com.google.common.collect.Maps; import java.math.BigDecimal; import java.util.Collection; import org.eclipse.jdt.annotation.NonNull; @@ -113,29 +118,26 @@ abstract class AbstractTypeStatementSupport static final String UINT64 = "uint64"; static final String UNION = "union"; - private static final ImmutableMap BUILT_IN_TYPES = ImmutableMap.builder() - .put(BINARY, BINARY) - .put(BITS, BITS) - .put(BOOLEAN, BOOLEAN) - .put(DECIMAL64, DECIMAL64) - .put(EMPTY, EMPTY) - .put(ENUMERATION, ENUMERATION) - .put(IDENTITY_REF,IDENTITY_REF) - .put(INSTANCE_IDENTIFIER, INSTANCE_IDENTIFIER) - .put(INT8, INT8) - .put(INT16, INT16) - .put(INT32, INT32) - .put(INT64, INT64) - .put(LEAF_REF, LEAF_REF) - .put(STRING, STRING) - .put(UINT8, UINT8) - .put(UINT16, UINT16) - .put(UINT32, UINT32) - .put(UINT64, UINT64) - .put(UNION, UNION) - .build(); + private static final ImmutableMap STATIC_BUILT_IN_TYPES = + ImmutableMap.builder() + .put(BINARY, BuiltinEffectiveStatement.BINARY) + .put(BOOLEAN, BuiltinEffectiveStatement.BOOLEAN) + .put(EMPTY, BuiltinEffectiveStatement.EMPTY) + // FIXME: this overlaps with DYNAMIC_BUILT_IN_TYPES. One of these is not needed, but we need to decide + // what to do. I think we should gradually use per-statement validators, hence go towards dynamic? + .put(INSTANCE_IDENTIFIER, BuiltinEffectiveStatement.INSTANCE_IDENTIFIER) + .put(INT8, BuiltinEffectiveStatement.INT8) + .put(INT16, BuiltinEffectiveStatement.INT16) + .put(INT32, BuiltinEffectiveStatement.INT32) + .put(INT64, BuiltinEffectiveStatement.INT64) + .put(STRING, BuiltinEffectiveStatement.STRING) + .put(UINT8, BuiltinEffectiveStatement.UINT8) + .put(UINT16, BuiltinEffectiveStatement.UINT16) + .put(UINT32, BuiltinEffectiveStatement.UINT32) + .put(UINT64, BuiltinEffectiveStatement.UINT64) + .build(); - private static final ImmutableMap> ARGUMENT_SPECIFIC_SUPPORTS = + private static final ImmutableMap> DYNAMIC_BUILT_IN_TYPES = ImmutableMap.>builder() .put(BITS, new BitsSpecificationSupport()) .put(DECIMAL64, new Decimal64SpecificationSupport()) @@ -146,6 +148,9 @@ abstract class AbstractTypeStatementSupport .put(UNION, new UnionSpecificationSupport()) .build(); + private static final ImmutableMap BUILT_IN_TYPES = Maps.uniqueIndex(ImmutableSet.copyOf( + Iterables.concat(STATIC_BUILT_IN_TYPES.keySet(), DYNAMIC_BUILT_IN_TYPES.keySet())), key -> key); + AbstractTypeStatementSupport() { super(YangStmtMapping.TYPE, StatementPolicy.contextIndependent()); } @@ -155,14 +160,14 @@ abstract class AbstractTypeStatementSupport final Mutable> stmt) { super.onFullDefinitionDeclared(stmt); - // if it is yang built-in type, no prerequisite is needed, so simply return - if (BUILT_IN_TYPES.containsKey(stmt.argument())) { - // FIXME: consider populating BaseTypeNamespace here, which could be done quite efficiently, moving the - // logic from resolveType() + final String argument = stmt.getArgument(); + final BuiltinEffectiveStatement builtin = STATIC_BUILT_IN_TYPES.get(argument); + if (builtin != null) { + stmt.addToNs(BaseTypeNamespace.class, Empty.getInstance(), builtin); return; } - final QName typeQName = StmtContextUtils.parseNodeIdentifier(stmt, stmt.argument()); + final QName typeQName = StmtContextUtils.parseNodeIdentifier(stmt, argument); final ModelActionBuilder typeAction = stmt.newInferenceAction(ModelProcessingPhase.EFFECTIVE_MODEL); final Prerequisite> typePrereq = typeAction.requiresCtx(stmt, TypeNamespace.class, typeQName, ModelProcessingPhase.EFFECTIVE_MODEL); @@ -175,6 +180,7 @@ abstract class AbstractTypeStatementSupport typeAction.apply(new InferenceAction() { @Override public void apply(final InferenceContext ctx) { + // Note: do not attempt to call buildEffective() here stmt.addToNs(BaseTypeNamespace.class, Empty.getInstance(), typePrereq.resolve(ctx)); } @@ -193,12 +199,12 @@ abstract class AbstractTypeStatementSupport @Override public boolean hasArgumentSpecificSupports() { - return !ARGUMENT_SPECIFIC_SUPPORTS.isEmpty(); + return !DYNAMIC_BUILT_IN_TYPES.isEmpty(); } @Override public StatementSupport getSupportSpecificForArgument(final String argument) { - return ARGUMENT_SPECIFIC_SUPPORTS.get(argument); + return DYNAMIC_BUILT_IN_TYPES.get(argument); } @Override @@ -302,41 +308,14 @@ abstract class AbstractTypeStatementSupport * @throws SourceException if the target type cannot be found */ private static @NonNull TypeEffectiveStatement resolveType(final Current ctx) { - final StmtContext baseType = ctx.namespaceItem(BaseTypeNamespace.class, Empty.getInstance()); - if (baseType != null) { - return ((TypedefEffectiveStatement) baseType.buildEffective()).asTypeEffectiveStatement(); - } - - final String argument = ctx.getArgument(); - switch (argument) { - case BINARY: - return BuiltinEffectiveStatement.BINARY; - case BOOLEAN: - return BuiltinEffectiveStatement.BOOLEAN; - case EMPTY: - return BuiltinEffectiveStatement.EMPTY; - case INSTANCE_IDENTIFIER: - return BuiltinEffectiveStatement.INSTANCE_IDENTIFIER; - case INT8: - return BuiltinEffectiveStatement.INT8; - case INT16: - return BuiltinEffectiveStatement.INT16; - case INT32: - return BuiltinEffectiveStatement.INT32; - case INT64: - return BuiltinEffectiveStatement.INT64; - case STRING: - return BuiltinEffectiveStatement.STRING; - case UINT8: - return BuiltinEffectiveStatement.UINT8; - case UINT16: - return BuiltinEffectiveStatement.UINT16; - case UINT32: - return BuiltinEffectiveStatement.UINT32; - case UINT64: - return BuiltinEffectiveStatement.UINT64; - default: - throw new IllegalStateException("Unhandled type argument " + argument); + final Object obj = verifyNotNull(ctx.namespaceItem(BaseTypeNamespace.class, Empty.getInstance())); + if (obj instanceof BuiltinEffectiveStatement) { + return (BuiltinEffectiveStatement) obj; + } else if (obj instanceof StmtContext) { + return ((TypedefEffectiveStatement) ((StmtContext) obj).buildEffective()) + .asTypeEffectiveStatement(); + } else { + throw new InferenceException(ctx, "Unexpected base object %s", obj); } } diff --git a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/type/BaseTypeNamespace.java b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/type/BaseTypeNamespace.java index 59dbd37fe1..ecb04ab2b7 100644 --- a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/type/BaseTypeNamespace.java +++ b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/type/BaseTypeNamespace.java @@ -12,10 +12,9 @@ import org.eclipse.jdt.annotation.NonNull; import org.opendaylight.yangtools.yang.common.Empty; import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour; import org.opendaylight.yangtools.yang.parser.spi.meta.ParserNamespace; -import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext; @Beta -public interface BaseTypeNamespace extends ParserNamespace> { - NamespaceBehaviour, @NonNull BaseTypeNamespace> BEHAVIOUR = +public interface BaseTypeNamespace extends ParserNamespace { + NamespaceBehaviour BEHAVIOUR = NamespaceBehaviour.statementLocal(BaseTypeNamespace.class); }