X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=yang%2Fyang-parser-rfc7950%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fyangtools%2Fyang%2Fparser%2Frfc7950%2Fstmt%2Ftype%2FAbstractTypeStatementSupport.java;h=2637518739f31c850c7704a52817af207ef626b6;hb=e83f373de212e0fb3771191866ebe259f1a974e7;hp=bf17401ba6a1ec17eaee6182edcd816b6eb79887;hpb=914ae3e8d065887390269b910e9deb6a0397b866;p=yangtools.git 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 bf17401ba6..2637518739 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 @@ -11,25 +11,34 @@ import static com.google.common.base.Preconditions.checkArgument; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import java.math.BigDecimal; import java.util.Collection; import org.eclipse.jdt.annotation.NonNull; +import org.opendaylight.yangtools.yang.common.Empty; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.model.api.SchemaPath; import org.opendaylight.yangtools.yang.model.api.TypeDefinition; import org.opendaylight.yangtools.yang.model.api.YangStmtMapping; 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.stmt.BitEffectiveStatement; +import org.opendaylight.yangtools.yang.model.api.stmt.EnumEffectiveStatement; +import org.opendaylight.yangtools.yang.model.api.stmt.FractionDigitsEffectiveStatement; import org.opendaylight.yangtools.yang.model.api.stmt.LengthEffectiveStatement; +import org.opendaylight.yangtools.yang.model.api.stmt.PatternEffectiveStatement; +import org.opendaylight.yangtools.yang.model.api.stmt.RangeEffectiveStatement; +import org.opendaylight.yangtools.yang.model.api.stmt.RequireInstanceEffectiveStatement; 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.stmt.TypedefEffectiveStatement; -import org.opendaylight.yangtools.yang.model.api.stmt.TypedefStatement; import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition; 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.api.type.BooleanTypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition; +import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition.EnumPair; import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.Int16TypeDefinition; @@ -37,17 +46,27 @@ import org.opendaylight.yangtools.yang.model.api.type.Int32TypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.Int64TypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.Int8TypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition; +import org.opendaylight.yangtools.yang.model.api.type.RangeRestrictedTypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.Uint16TypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.Uint32TypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.Uint64TypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.Uint8TypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition; +import org.opendaylight.yangtools.yang.model.util.type.BitsTypeBuilder; +import org.opendaylight.yangtools.yang.model.util.type.EnumerationTypeBuilder; +import org.opendaylight.yangtools.yang.model.util.type.InstanceIdentifierTypeBuilder; import org.opendaylight.yangtools.yang.model.util.type.InvalidLengthConstraintException; +import org.opendaylight.yangtools.yang.model.util.type.InvalidRangeConstraintException; import org.opendaylight.yangtools.yang.model.util.type.LengthRestrictedTypeBuilder; +import org.opendaylight.yangtools.yang.model.util.type.RangeRestrictedTypeBuilder; +import org.opendaylight.yangtools.yang.model.util.type.RequireInstanceRestrictedTypeBuilder; import org.opendaylight.yangtools.yang.model.util.type.RestrictedTypes; +import org.opendaylight.yangtools.yang.model.util.type.StringTypeBuilder; import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.BaseStatementSupport; import org.opendaylight.yangtools.yang.parser.spi.TypeNamespace; +import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx; +import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.Current; import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException; import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder; import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.InferenceAction; @@ -60,9 +79,13 @@ import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable; import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils; import org.opendaylight.yangtools.yang.parser.spi.meta.SubstatementValidator; import org.opendaylight.yangtools.yang.parser.spi.source.SourceException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; abstract class AbstractTypeStatementSupport extends BaseStatementSupport> { + private static final Logger LOG = LoggerFactory.getLogger(AbstractTypeStatementSupport.class); + private static final SubstatementValidator SUBSTATEMENT_VALIDATOR = SubstatementValidator.builder( YangStmtMapping.TYPE) .addOptional(YangStmtMapping.BASE) @@ -145,30 +168,31 @@ abstract class AbstractTypeStatementSupport super.onFullDefinitionDeclared(stmt); // if it is yang built-in type, no prerequisite is needed, so simply return - if (BUILT_IN_TYPES.containsKey(stmt.getStatementArgument())) { + if (BUILT_IN_TYPES.containsKey(stmt.argument())) { + // FIXME: consider populating BaseTypeNamespace here, which could be done quite efficiently, moving the + // logic from resolveType() return; } - final QName typeQName = StmtContextUtils.parseNodeIdentifier(stmt, stmt.getStatementArgument()); + final QName typeQName = StmtContextUtils.parseNodeIdentifier(stmt, stmt.argument()); final ModelActionBuilder typeAction = stmt.newInferenceAction(ModelProcessingPhase.EFFECTIVE_MODEL); final Prerequisite> typePrereq = typeAction.requiresCtx(stmt, TypeNamespace.class, typeQName, ModelProcessingPhase.EFFECTIVE_MODEL); typeAction.mutatesEffectiveCtx(stmt.getParentContext()); /* - * If the type does not exist, throw new InferenceException. - * Otherwise perform no operation. + * If the type does not exist, throw an InferenceException. + * If the type exists, store a reference to it in BaseTypeNamespace. */ typeAction.apply(new InferenceAction() { @Override public void apply(final InferenceContext ctx) { - // Intentional NOOP + stmt.addToNs(BaseTypeNamespace.class, Empty.getInstance(), typePrereq.resolve(ctx)); } @Override public void prerequisiteFailed(final Collection> failed) { - InferenceException.throwIf(failed.contains(typePrereq), stmt.getStatementSourceReference(), - "Type [%s] was not found.", typeQName); + InferenceException.throwIf(failed.contains(typePrereq), stmt, "Type [%s] was not found.", typeQName); } }); } @@ -197,84 +221,81 @@ abstract class AbstractTypeStatementSupport @Override protected final TypeStatement createDeclared(final StmtContext ctx, final ImmutableList> substatements) { - return new RegularTypeStatement(ctx, substatements); + return new RegularTypeStatement(ctx.getRawArgument(), substatements); } @Override protected final TypeStatement createEmptyDeclared(final StmtContext ctx) { final TypeStatement builtin; - return (builtin = BuiltinTypeStatement.lookup(ctx)) != null ? builtin : new EmptyTypeStatement(ctx); + return (builtin = BuiltinTypeStatement.lookup(ctx)) != null ? builtin + : new EmptyTypeStatement(ctx.getRawArgument()); } @Override - protected final TypeEffectiveStatement createEffective( - final StmtContext> ctx, - final TypeStatement declared, final ImmutableList> substatements) { + protected EffectiveStatement createEffective(final Current stmt, + final ImmutableList> substatements) { // First look up the proper base type - final TypeEffectiveStatement typeStmt = resolveType(ctx); + final TypeEffectiveStatement typeStmt = resolveType(stmt); + if (substatements.isEmpty()) { + return typeStmt; + } + // Now instantiate the proper effective statement for that type final TypeDefinition baseType = typeStmt.getTypeDefinition(); + final TypeStatement declared = stmt.declared(); if (baseType instanceof BinaryTypeDefinition) { - return createBinary(ctx, (BinaryTypeDefinition) baseType, declared, substatements); + return createBinary(stmt, (BinaryTypeDefinition) baseType, declared, substatements); } else if (baseType instanceof BitsTypeDefinition) { - return new BitsTypeEffectiveStatementImpl(ctx, (BitsTypeDefinition) baseType); + return createBits(stmt, (BitsTypeDefinition) baseType, declared, substatements); } else if (baseType instanceof BooleanTypeDefinition) { - return createBoolean(ctx, (BooleanTypeDefinition) baseType, declared, substatements); + return createBoolean(stmt, (BooleanTypeDefinition) baseType, declared, substatements); } else if (baseType instanceof DecimalTypeDefinition) { - return new DecimalTypeEffectiveStatementImpl(ctx, (DecimalTypeDefinition) baseType); + return createDecimal(stmt, (DecimalTypeDefinition) baseType, declared, substatements); } else if (baseType instanceof EmptyTypeDefinition) { - return new EmptyTypeEffectiveStatementImpl(ctx, (EmptyTypeDefinition) baseType); + return createEmpty(stmt, (EmptyTypeDefinition) baseType, declared, substatements); } else if (baseType instanceof EnumTypeDefinition) { - return new EnumTypeEffectiveStatementImpl(ctx, (EnumTypeDefinition) baseType); + return createEnum(stmt, (EnumTypeDefinition) baseType, declared, substatements); } else if (baseType instanceof IdentityrefTypeDefinition) { - return new IdentityrefTypeEffectiveStatementImpl(ctx, (IdentityrefTypeDefinition) baseType); + return createIdentityref(stmt, (IdentityrefTypeDefinition) baseType, declared, substatements); } else if (baseType instanceof InstanceIdentifierTypeDefinition) { - return new InstanceIdentifierTypeEffectiveStatementImpl(ctx, - (InstanceIdentifierTypeDefinition) baseType); + return createInstanceIdentifier(stmt, (InstanceIdentifierTypeDefinition) baseType, declared, substatements); } else if (baseType instanceof Int8TypeDefinition) { - return new IntegralTypeEffectiveStatementImpl<>(ctx, - RestrictedTypes.newInt8Builder((Int8TypeDefinition) baseType, typeEffectiveSchemaPath(ctx))); + return createIntegral(stmt, declared, substatements, + RestrictedTypes.newInt8Builder((Int8TypeDefinition) baseType, typeEffectiveSchemaPath(stmt))); } else if (baseType instanceof Int16TypeDefinition) { - return new IntegralTypeEffectiveStatementImpl<>(ctx, - RestrictedTypes.newInt16Builder((Int16TypeDefinition) baseType, typeEffectiveSchemaPath(ctx))); + return createIntegral(stmt, declared, substatements, + RestrictedTypes.newInt16Builder((Int16TypeDefinition) baseType, typeEffectiveSchemaPath(stmt))); } else if (baseType instanceof Int32TypeDefinition) { - return new IntegralTypeEffectiveStatementImpl<>(ctx, - RestrictedTypes.newInt32Builder((Int32TypeDefinition) baseType, typeEffectiveSchemaPath(ctx))); + return createIntegral(stmt, declared, substatements, + RestrictedTypes.newInt32Builder((Int32TypeDefinition) baseType, typeEffectiveSchemaPath(stmt))); } else if (baseType instanceof Int64TypeDefinition) { - return new IntegralTypeEffectiveStatementImpl<>(ctx, - RestrictedTypes.newInt64Builder((Int64TypeDefinition) baseType, typeEffectiveSchemaPath(ctx))); + return createIntegral(stmt, declared, substatements, + RestrictedTypes.newInt64Builder((Int64TypeDefinition) baseType, typeEffectiveSchemaPath(stmt))); } else if (baseType instanceof LeafrefTypeDefinition) { - return new LeafrefTypeEffectiveStatementImpl(ctx, (LeafrefTypeDefinition) baseType); + return createLeafref(stmt, (LeafrefTypeDefinition) baseType, declared, substatements); } else if (baseType instanceof StringTypeDefinition) { - return new StringTypeEffectiveStatementImpl(ctx, (StringTypeDefinition) baseType); + return createString(stmt, (StringTypeDefinition) baseType, declared, substatements); } else if (baseType instanceof Uint8TypeDefinition) { - return new IntegralTypeEffectiveStatementImpl<>(ctx, - RestrictedTypes.newUint8Builder((Uint8TypeDefinition) baseType, typeEffectiveSchemaPath(ctx))); + return createIntegral(stmt, declared, substatements, + RestrictedTypes.newUint8Builder((Uint8TypeDefinition) baseType, typeEffectiveSchemaPath(stmt))); } else if (baseType instanceof Uint16TypeDefinition) { - return new IntegralTypeEffectiveStatementImpl<>(ctx, - RestrictedTypes.newUint16Builder((Uint16TypeDefinition) baseType, typeEffectiveSchemaPath(ctx))); + return createIntegral(stmt, declared, substatements, + RestrictedTypes.newUint16Builder((Uint16TypeDefinition) baseType, typeEffectiveSchemaPath(stmt))); } else if (baseType instanceof Uint32TypeDefinition) { - return new IntegralTypeEffectiveStatementImpl<>(ctx, - RestrictedTypes.newUint32Builder((Uint32TypeDefinition) baseType, typeEffectiveSchemaPath(ctx))); + return createIntegral(stmt, declared, substatements, + RestrictedTypes.newUint32Builder((Uint32TypeDefinition) baseType, typeEffectiveSchemaPath(stmt))); } else if (baseType instanceof Uint64TypeDefinition) { - return new IntegralTypeEffectiveStatementImpl<>(ctx, - RestrictedTypes.newUint64Builder((Uint64TypeDefinition) baseType, typeEffectiveSchemaPath(ctx))); + return createIntegral(stmt, declared, substatements, + RestrictedTypes.newUint64Builder((Uint64TypeDefinition) baseType, typeEffectiveSchemaPath(stmt))); } else if (baseType instanceof UnionTypeDefinition) { - return new UnionTypeEffectiveStatementImpl(ctx, (UnionTypeDefinition) baseType); + return createUnion(stmt, (UnionTypeDefinition) baseType, declared, substatements); } else { throw new IllegalStateException("Unhandled base type " + baseType); } } - @Override - protected final EffectiveStatement createEmptyEffective( - final StmtContext> ctx, - final TypeStatement declared) { - return resolveType(ctx); - } - - static final SchemaPath typeEffectiveSchemaPath(final StmtContext stmtCtx) { - final SchemaPath path = stmtCtx.getSchemaPath().get(); + static final SchemaPath typeEffectiveSchemaPath(final Current stmt) { + final SchemaPath path = stmt.getSchemaPath(); final SchemaPath parent = path.getParent(); final QName parentQName = parent.getLastComponent(); checkArgument(parentQName != null, "Path %s has an empty parent", path); @@ -290,8 +311,13 @@ abstract class AbstractTypeStatementSupport * @return Resolved type * @throws SourceException if the target type cannot be found */ - private static @NonNull TypeEffectiveStatement resolveType(final StmtContext ctx) { - final String argument = ctx.coerceStatementArgument(); + 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; @@ -320,15 +346,11 @@ abstract class AbstractTypeStatementSupport case UINT64: return BuiltinEffectiveStatement.UINT64; default: - final QName qname = StmtContextUtils.parseNodeIdentifier(ctx, argument); - final StmtContext typedef = - SourceException.throwIfNull(ctx.getFromNamespace(TypeNamespace.class, qname), - ctx.getStatementSourceReference(), "Type '%s' not found", qname); - return typedef.buildEffective().asTypeEffectiveStatement(); + throw new IllegalStateException("Unhandled type argument " + argument); } } - private static @NonNull TypeEffectiveStatement createBinary(final StmtContext ctx, + private static @NonNull TypeEffectiveStatement createBinary(final Current ctx, final BinaryTypeDefinition baseType, final TypeStatement declared, final ImmutableList> substatements) { final LengthRestrictedTypeBuilder builder = @@ -341,11 +363,9 @@ abstract class AbstractTypeStatementSupport try { builder.setLengthConstraint(length, length.argument()); } catch (IllegalStateException e) { - throw new SourceException(ctx.getStatementSourceReference(), e, - "Multiple length constraints encountered"); + throw new SourceException(ctx, e, "Multiple length constraints encountered"); } catch (InvalidLengthConstraintException e) { - throw new SourceException(ctx.getStatementSourceReference(), e, "Invalid length constraint %s", - length.argument()); + throw new SourceException(ctx, e, "Invalid length constraint %s", length.argument()); } } } @@ -353,10 +373,159 @@ abstract class AbstractTypeStatementSupport return new TypeEffectiveStatementImpl<>(declared, substatements, builder); } - private static @NonNull TypeEffectiveStatement createBoolean(final StmtContext ctx, + private @NonNull TypeEffectiveStatement createBits(final Current ctx, + final BitsTypeDefinition baseType, final TypeStatement declared, + final ImmutableList> substatements) { + final BitsTypeBuilder builder = RestrictedTypes.newBitsBuilder(baseType, ctx.getSchemaPath()); + + for (final EffectiveStatement stmt : substatements) { + if (stmt instanceof BitEffectiveStatement) { + builder.addBit(addRestrictedBit(ctx, baseType, (BitEffectiveStatement) stmt)); + } + } + + return new TypeEffectiveStatementImpl<>(declared, substatements, builder); + } + + abstract @NonNull Bit addRestrictedBit(@NonNull EffectiveStmtCtx stmt, @NonNull BitsTypeDefinition base, + @NonNull BitEffectiveStatement bit); + + private static @NonNull TypeEffectiveStatement createBoolean(final Current ctx, final BooleanTypeDefinition baseType, final TypeStatement declared, final ImmutableList> substatements) { return new TypeEffectiveStatementImpl<>(declared, substatements, RestrictedTypes.newBooleanBuilder(baseType, typeEffectiveSchemaPath(ctx))); } + + private static @NonNull TypeEffectiveStatement createDecimal(final Current ctx, + final DecimalTypeDefinition baseType, final TypeStatement declared, + final ImmutableList> substatements) { + final RangeRestrictedTypeBuilder builder = + RestrictedTypes.newDecima64Builder(baseType, typeEffectiveSchemaPath(ctx)); + + for (EffectiveStatement stmt : substatements) { + if (stmt instanceof RangeEffectiveStatement) { + final RangeEffectiveStatement range = (RangeEffectiveStatement) stmt; + builder.setRangeConstraint(range, range.argument()); + } + if (stmt instanceof FractionDigitsEffectiveStatement) { + final Integer digits = ((FractionDigitsEffectiveStatement)stmt).argument(); + SourceException.throwIf(baseType.getFractionDigits() != digits, ctx, + "Cannot override fraction-digits from base type %s to %s", baseType, digits); + } + } + + return new TypeEffectiveStatementImpl<>(declared, substatements, builder); + } + + private static @NonNull TypeEffectiveStatement createEmpty(final Current ctx, + final EmptyTypeDefinition baseType, final TypeStatement declared, + final ImmutableList> substatements) { + return new TypeEffectiveStatementImpl<>(declared, substatements, RestrictedTypes.newEmptyBuilder(baseType, + typeEffectiveSchemaPath(ctx))); + } + + private @NonNull TypeEffectiveStatement createEnum(final Current ctx, + final EnumTypeDefinition baseType, final TypeStatement declared, + final ImmutableList> substatements) { + final EnumerationTypeBuilder builder = RestrictedTypes.newEnumerationBuilder(baseType, ctx.getSchemaPath()); + + for (final EffectiveStatement stmt : substatements) { + if (stmt instanceof EnumEffectiveStatement) { + builder.addEnum(addRestrictedEnum(ctx, baseType, (EnumEffectiveStatement) stmt)); + } + } + + return new TypeEffectiveStatementImpl<>(declared, substatements, builder); + } + + abstract @NonNull EnumPair addRestrictedEnum(@NonNull EffectiveStmtCtx stmt, @NonNull EnumTypeDefinition base, + @NonNull EnumEffectiveStatement enumStmt); + + private static @NonNull TypeEffectiveStatement createIdentityref(final Current ctx, + final IdentityrefTypeDefinition baseType, final TypeStatement declared, + final ImmutableList> substatements) { + return new TypeEffectiveStatementImpl<>(declared, substatements, RestrictedTypes.newIdentityrefBuilder(baseType, + typeEffectiveSchemaPath(ctx))); + } + + private static @NonNull TypeEffectiveStatement createInstanceIdentifier( + final Current ctx, final InstanceIdentifierTypeDefinition baseType, final TypeStatement declared, + final ImmutableList> substatements) { + final InstanceIdentifierTypeBuilder builder = RestrictedTypes.newInstanceIdentifierBuilder(baseType, + typeEffectiveSchemaPath(ctx)); + + for (EffectiveStatement stmt : substatements) { + if (stmt instanceof RequireInstanceEffectiveStatement) { + builder.setRequireInstance(((RequireInstanceEffectiveStatement)stmt).argument()); + } + } + + return new TypeEffectiveStatementImpl<>(declared, substatements, builder); + } + + private static , N extends Number & Comparable> + @NonNull TypeEffectiveStatement createIntegral(final Current ctx, + final TypeStatement declared, final ImmutableList> substatements, + final RangeRestrictedTypeBuilder builder) { + for (EffectiveStatement stmt : substatements) { + if (stmt instanceof RangeEffectiveStatement) { + final RangeEffectiveStatement rangeStmt = (RangeEffectiveStatement)stmt; + builder.setRangeConstraint(rangeStmt, rangeStmt.argument()); + } + } + + try { + return new TypeEffectiveStatementImpl<>(declared, substatements, builder); + } catch (InvalidRangeConstraintException e) { + throw new SourceException(ctx, e, "Invalid range constraint: %s", e.getOffendingRanges()); + } + } + + private static @NonNull TypeEffectiveStatement createLeafref(final Current ctx, + final LeafrefTypeDefinition baseType, final TypeStatement declared, + final ImmutableList> substatements) { + final RequireInstanceRestrictedTypeBuilder builder = + RestrictedTypes.newLeafrefBuilder(baseType, AbstractTypeStatementSupport.typeEffectiveSchemaPath(ctx)); + + for (final EffectiveStatement stmt : substatements) { + if (stmt instanceof RequireInstanceEffectiveStatement) { + builder.setRequireInstance(((RequireInstanceEffectiveStatement) stmt).argument()); + } + } + return new TypeEffectiveStatementImpl<>(declared, substatements, builder); + } + + private static @NonNull TypeEffectiveStatement createString(final Current ctx, + final StringTypeDefinition baseType, final TypeStatement declared, + final ImmutableList> substatements) { + final StringTypeBuilder builder = RestrictedTypes.newStringBuilder(baseType, + AbstractTypeStatementSupport.typeEffectiveSchemaPath(ctx)); + + for (EffectiveStatement stmt : substatements) { + if (stmt instanceof LengthEffectiveStatement) { + final LengthEffectiveStatement length = (LengthEffectiveStatement)stmt; + + try { + builder.setLengthConstraint(length, length.argument()); + } catch (IllegalStateException e) { + throw new SourceException(ctx, e, "Multiple length constraints encountered"); + } catch (InvalidLengthConstraintException e) { + throw new SourceException(ctx, e, "Invalid length constraint %s", length.argument()); + } + } + if (stmt instanceof PatternEffectiveStatement) { + builder.addPatternConstraint((PatternEffectiveStatement) stmt); + } + } + + return new TypeEffectiveStatementImpl<>(declared, substatements, builder); + } + + private static @NonNull TypeEffectiveStatement createUnion(final Current ctx, + final UnionTypeDefinition baseType, final TypeStatement declared, + final ImmutableList> substatements) { + return new TypeEffectiveStatementImpl<>(declared, substatements, RestrictedTypes.newUnionBuilder(baseType, + typeEffectiveSchemaPath(ctx))); + } } \ No newline at end of file