Make RangeRestrictedTypeDefinition type-aware
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / stmt / rfc6020 / effective / type / BitsTypeEffectiveStatementImpl.java
index a7fc6ec81fb37aea52ef6d8d764a6570798878b3..61c5da20ff5b0a64c392962690bf3fe2a39147f1 100644 (file)
@@ -8,17 +8,70 @@
 
 package org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type;
 
+import javax.annotation.Nonnull;
+import org.opendaylight.yangtools.yang.common.YangVersion;
 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.TypeEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.TypeStatement;
 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition.Bit;
+import org.opendaylight.yangtools.yang.model.util.type.BitsTypeBuilder;
 import org.opendaylight.yangtools.yang.model.util.type.RestrictedTypes;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
-import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.TypeUtils;
+import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.DeclaredEffectiveStatementBase;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.UnknownEffectiveStatementImpl;
+
+public final class BitsTypeEffectiveStatementImpl extends DeclaredEffectiveStatementBase<String, TypeStatement>
+        implements TypeEffectiveStatement<TypeStatement> {
+
+    private final BitsTypeDefinition typeDefinition;
 
-public final class BitsTypeEffectiveStatementImpl extends AbstractTypeEffectiveStatement<BitsTypeDefinition> {
     public BitsTypeEffectiveStatementImpl(
             final StmtContext<String, TypeStatement, EffectiveStatement<String, TypeStatement>> ctx,
             final BitsTypeDefinition baseType) {
-        super(ctx, RestrictedTypes.newBitsBuilder(baseType, TypeUtils.typeEffectiveSchemaPath(ctx)));
+        super(ctx);
+
+        final BitsTypeBuilder builder = RestrictedTypes.newBitsBuilder(baseType, ctx.getSchemaPath().get());
+
+        final YangVersion yangVersion = ctx.getRootVersion();
+        for (final EffectiveStatement<?, ?> stmt : effectiveSubstatements()) {
+            if (stmt instanceof BitEffectiveStatementImpl) {
+                SourceException.throwIf(yangVersion != YangVersion.VERSION_1_1, ctx.getStatementSourceReference(),
+                        "Restricted bits type is allowed only in YANG 1.1 version.");
+                final BitEffectiveStatementImpl bitSubStmt = (BitEffectiveStatementImpl) stmt;
+
+                final long effectivePos;
+                if (bitSubStmt.getDeclaredPosition() == null) {
+                    effectivePos = getBaseTypeBitPosition(bitSubStmt.getName(), baseType, ctx);
+                } else {
+                    effectivePos = bitSubStmt.getDeclaredPosition();
+                }
+
+                builder.addBit(EffectiveTypeUtil.buildBit(bitSubStmt, effectivePos));
+            } else if (stmt instanceof UnknownEffectiveStatementImpl) {
+                builder.addUnknownSchemaNode((UnknownEffectiveStatementImpl) stmt);
+            }
+        }
+
+        typeDefinition = builder.build();
+    }
+
+    private static long getBaseTypeBitPosition(final String bitName, final BitsTypeDefinition baseType,
+            final StmtContext<?, ?, ?> ctx) {
+        for (Bit baseTypeBit : baseType.getBits()) {
+            if (bitName.equals(baseTypeBit.getName())) {
+                return baseTypeBit.getPosition();
+            }
+        }
+
+        throw new SourceException(ctx.getStatementSourceReference(),
+                "Bit '%s' is not a subset of its base bits type %s.", bitName, baseType.getQName());
+    }
+
+    @Nonnull
+    @Override
+    public BitsTypeDefinition getTypeDefinition() {
+        return typeDefinition;
     }
 }