2 * Copyright (c) 2017 Pantheon Technologies, s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.type;
10 import static com.google.common.base.Verify.verifyNotNull;
12 import com.google.common.collect.ImmutableList;
13 import com.google.common.collect.ImmutableMap;
14 import java.util.Collection;
15 import java.util.stream.Collectors;
16 import java.util.stream.Stream;
17 import org.eclipse.jdt.annotation.NonNull;
18 import org.opendaylight.yangtools.yang.common.Decimal64;
19 import org.opendaylight.yangtools.yang.common.Empty;
20 import org.opendaylight.yangtools.yang.common.QName;
21 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
22 import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
23 import org.opendaylight.yangtools.yang.model.api.meta.DeclarationReference;
24 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
25 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
26 import org.opendaylight.yangtools.yang.model.api.stmt.BitEffectiveStatement;
27 import org.opendaylight.yangtools.yang.model.api.stmt.EnumEffectiveStatement;
28 import org.opendaylight.yangtools.yang.model.api.stmt.FractionDigitsEffectiveStatement;
29 import org.opendaylight.yangtools.yang.model.api.stmt.LengthEffectiveStatement;
30 import org.opendaylight.yangtools.yang.model.api.stmt.PatternEffectiveStatement;
31 import org.opendaylight.yangtools.yang.model.api.stmt.RangeEffectiveStatement;
32 import org.opendaylight.yangtools.yang.model.api.stmt.RequireInstanceEffectiveStatement;
33 import org.opendaylight.yangtools.yang.model.api.stmt.TypeEffectiveStatement;
34 import org.opendaylight.yangtools.yang.model.api.stmt.TypeStatement;
35 import org.opendaylight.yangtools.yang.model.api.stmt.TypedefEffectiveStatement;
36 import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition;
37 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
38 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition.Bit;
39 import org.opendaylight.yangtools.yang.model.api.type.BooleanTypeDefinition;
40 import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition;
41 import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition;
42 import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
43 import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition.EnumPair;
44 import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
45 import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition;
46 import org.opendaylight.yangtools.yang.model.api.type.Int16TypeDefinition;
47 import org.opendaylight.yangtools.yang.model.api.type.Int32TypeDefinition;
48 import org.opendaylight.yangtools.yang.model.api.type.Int64TypeDefinition;
49 import org.opendaylight.yangtools.yang.model.api.type.Int8TypeDefinition;
50 import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
51 import org.opendaylight.yangtools.yang.model.api.type.RangeRestrictedTypeDefinition;
52 import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition;
53 import org.opendaylight.yangtools.yang.model.api.type.TypeDefinitions;
54 import org.opendaylight.yangtools.yang.model.api.type.Uint16TypeDefinition;
55 import org.opendaylight.yangtools.yang.model.api.type.Uint32TypeDefinition;
56 import org.opendaylight.yangtools.yang.model.api.type.Uint64TypeDefinition;
57 import org.opendaylight.yangtools.yang.model.api.type.Uint8TypeDefinition;
58 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
59 import org.opendaylight.yangtools.yang.model.ri.stmt.DeclaredStatementDecorators;
60 import org.opendaylight.yangtools.yang.model.ri.stmt.DeclaredStatements;
61 import org.opendaylight.yangtools.yang.model.ri.type.BitsTypeBuilder;
62 import org.opendaylight.yangtools.yang.model.ri.type.EnumerationTypeBuilder;
63 import org.opendaylight.yangtools.yang.model.ri.type.InstanceIdentifierTypeBuilder;
64 import org.opendaylight.yangtools.yang.model.ri.type.InvalidLengthConstraintException;
65 import org.opendaylight.yangtools.yang.model.ri.type.InvalidRangeConstraintException;
66 import org.opendaylight.yangtools.yang.model.ri.type.LengthRestrictedTypeBuilder;
67 import org.opendaylight.yangtools.yang.model.ri.type.RangeRestrictedTypeBuilder;
68 import org.opendaylight.yangtools.yang.model.ri.type.RequireInstanceRestrictedTypeBuilder;
69 import org.opendaylight.yangtools.yang.model.ri.type.RestrictedTypes;
70 import org.opendaylight.yangtools.yang.model.ri.type.StringTypeBuilder;
71 import org.opendaylight.yangtools.yang.parser.api.YangParserConfiguration;
72 import org.opendaylight.yangtools.yang.parser.spi.ParserNamespaces;
73 import org.opendaylight.yangtools.yang.parser.spi.meta.BoundStmtCtx;
74 import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx;
75 import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.Current;
76 import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.UndeclaredCurrent;
77 import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
78 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder;
79 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.InferenceAction;
80 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.InferenceContext;
81 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.Prerequisite;
82 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
83 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceStmtCtx;
84 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport;
85 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
86 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
87 import org.opendaylight.yangtools.yang.parser.spi.meta.SubstatementValidator;
88 import org.opendaylight.yangtools.yang.parser.spi.meta.UndeclaredStatementFactory;
89 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
91 abstract class AbstractTypeStatementSupport extends AbstractTypeSupport<TypeStatement>
92 implements UndeclaredStatementFactory<QName, TypeStatement, TypeEffectiveStatement<TypeStatement>> {
93 private static final SubstatementValidator SUBSTATEMENT_VALIDATOR =
94 SubstatementValidator.builder(YangStmtMapping.TYPE)
95 .addOptional(YangStmtMapping.BASE)
96 .addAny(YangStmtMapping.BIT)
97 .addAny(YangStmtMapping.ENUM)
98 .addOptional(YangStmtMapping.FRACTION_DIGITS)
99 .addOptional(YangStmtMapping.LENGTH)
100 .addOptional(YangStmtMapping.PATH)
101 .addAny(YangStmtMapping.PATTERN)
102 .addOptional(YangStmtMapping.RANGE)
103 .addOptional(YangStmtMapping.REQUIRE_INSTANCE)
104 .addAny(YangStmtMapping.TYPE)
107 private static final ImmutableMap<QName, BuiltinEffectiveStatement> STATIC_BUILT_IN_TYPES =
108 ImmutableMap.<QName, BuiltinEffectiveStatement>builder()
109 .put(TypeDefinitions.BINARY, BuiltinEffectiveStatement.BINARY)
110 .put(TypeDefinitions.BOOLEAN, BuiltinEffectiveStatement.BOOLEAN)
111 .put(TypeDefinitions.EMPTY, BuiltinEffectiveStatement.EMPTY)
112 // FIXME: this overlaps with DYNAMIC_BUILT_IN_TYPES. One of these is not needed, but we need to decide
113 // what to do. I think we should gradually use per-statement validators, hence go towards dynamic?
114 .put(TypeDefinitions.INSTANCE_IDENTIFIER, BuiltinEffectiveStatement.INSTANCE_IDENTIFIER)
115 .put(TypeDefinitions.INT8, BuiltinEffectiveStatement.INT8)
116 .put(TypeDefinitions.INT16, BuiltinEffectiveStatement.INT16)
117 .put(TypeDefinitions.INT32, BuiltinEffectiveStatement.INT32)
118 .put(TypeDefinitions.INT64, BuiltinEffectiveStatement.INT64)
119 .put(TypeDefinitions.STRING, BuiltinEffectiveStatement.STRING)
120 .put(TypeDefinitions.UINT8, BuiltinEffectiveStatement.UINT8)
121 .put(TypeDefinitions.UINT16, BuiltinEffectiveStatement.UINT16)
122 .put(TypeDefinitions.UINT32, BuiltinEffectiveStatement.UINT32)
123 .put(TypeDefinitions.UINT64, BuiltinEffectiveStatement.UINT64)
126 private final ImmutableMap<String, StatementSupport<?, ?, ?>> dynamicBuiltInTypes;
128 AbstractTypeStatementSupport(final YangParserConfiguration config) {
129 super(config, SUBSTATEMENT_VALIDATOR);
130 dynamicBuiltInTypes = ImmutableMap.<String, StatementSupport<?, ?, ?>>builder()
131 .put(TypeDefinitions.BITS.getLocalName(), new BitsSpecificationSupport(config))
132 .put(TypeDefinitions.DECIMAL64.getLocalName(), new Decimal64SpecificationSupport(config))
133 .put(TypeDefinitions.ENUMERATION.getLocalName(), new EnumSpecificationSupport(config))
134 .put(TypeDefinitions.IDENTITYREF.getLocalName(), IdentityRefSpecificationSupport.rfc6020Instance(config))
135 .put(TypeDefinitions.INSTANCE_IDENTIFIER.getLocalName(), new InstanceIdentifierSpecificationSupport(config))
136 .put(TypeDefinitions.LEAFREF.getLocalName(), LeafrefSpecificationSupport.rfc6020Instance(config))
137 .put(TypeDefinitions.UNION.getLocalName(), new UnionSpecificationSupport(config))
142 public final void onFullDefinitionDeclared(
143 final Mutable<QName, TypeStatement, EffectiveStatement<QName, TypeStatement>> stmt) {
144 super.onFullDefinitionDeclared(stmt);
146 final QName typeQName = stmt.getArgument();
147 final BuiltinEffectiveStatement builtin = STATIC_BUILT_IN_TYPES.get(typeQName);
148 if (builtin != null) {
149 stmt.addToNs(BaseTypeNamespace.INSTANCE, Empty.value(), builtin);
153 final ModelActionBuilder typeAction = stmt.newInferenceAction(ModelProcessingPhase.EFFECTIVE_MODEL);
154 final Prerequisite<StmtContext<?, ?, ?>> typePrereq = typeAction.requiresCtx(stmt, ParserNamespaces.TYPE,
155 typeQName, ModelProcessingPhase.EFFECTIVE_MODEL);
156 typeAction.mutatesEffectiveCtx(stmt.getParentContext());
159 * If the type does not exist, throw an InferenceException.
160 * If the type exists, store a reference to it in BaseTypeNamespace.
162 typeAction.apply(new InferenceAction() {
164 public void apply(final InferenceContext ctx) {
165 // Note: do not attempt to call buildEffective() here
166 stmt.addToNs(BaseTypeNamespace.INSTANCE, Empty.value(), typePrereq.resolve(ctx));
170 public void prerequisiteFailed(final Collection<? extends Prerequisite<?>> failed) {
171 InferenceException.throwIf(failed.contains(typePrereq), stmt, "Type [%s] was not found.", typeQName);
177 public boolean hasArgumentSpecificSupports() {
178 return !dynamicBuiltInTypes.isEmpty();
182 public StatementSupport<?, ?, ?> getSupportSpecificForArgument(final String argument) {
183 return dynamicBuiltInTypes.get(argument);
187 public final TypeEffectiveStatement<TypeStatement> createUndeclaredEffective(
188 final UndeclaredCurrent<QName, TypeStatement> stmt,
189 final Stream<? extends StmtContext<?, ?, ?>> effectiveSubstatements) {
190 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements = buildEffectiveSubstatements(stmt,
191 statementsToBuild(stmt, effectiveSubstatements
192 .filter(StmtContext::isSupportedToBuildEffective)
193 .collect(Collectors.toUnmodifiableList())));
195 // First look up the proper base type
196 final TypeEffectiveStatement<TypeStatement> typeStmt = resolveType(stmt);
197 if (substatements.isEmpty()) {
201 // TODO: mirror the logic below
202 throw new UnsupportedOperationException("Non-empty undeclared type statements are not implemented yet");
206 protected final TypeStatement createDeclared(final BoundStmtCtx<QName> ctx,
207 final ImmutableList<DeclaredStatement<?>> substatements) {
208 if (substatements.isEmpty()) {
209 final TypeStatement builtin = BuiltinTypeStatement.lookup(ctx.getRawArgument());
210 if (builtin != null) {
214 return DeclaredStatements.createType(ctx.getRawArgument(), ctx.getArgument(), substatements);
218 protected final TypeStatement attachDeclarationReference(final TypeStatement stmt,
219 final DeclarationReference reference) {
220 return DeclaredStatementDecorators.decorateType(stmt, reference);
224 protected EffectiveStatement<QName, TypeStatement> createEffective(final Current<QName, TypeStatement> stmt,
225 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
226 // First look up the proper base type
227 final TypeEffectiveStatement<TypeStatement> typeStmt = resolveType(stmt);
228 if (substatements.isEmpty()) {
232 // Now instantiate the proper effective statement for that type
233 final TypeDefinition<?> baseType = typeStmt.getTypeDefinition();
234 final TypeStatement declared = stmt.declared();
235 if (baseType instanceof BinaryTypeDefinition) {
236 return createBinary(stmt, (BinaryTypeDefinition) baseType, declared, substatements);
237 } else if (baseType instanceof BitsTypeDefinition) {
238 return createBits(stmt, (BitsTypeDefinition) baseType, declared, substatements);
239 } else if (baseType instanceof BooleanTypeDefinition) {
240 return createBoolean(stmt, (BooleanTypeDefinition) baseType, declared, substatements);
241 } else if (baseType instanceof DecimalTypeDefinition) {
242 return createDecimal(stmt, (DecimalTypeDefinition) baseType, declared, substatements);
243 } else if (baseType instanceof EmptyTypeDefinition) {
244 return createEmpty(stmt, (EmptyTypeDefinition) baseType, declared, substatements);
245 } else if (baseType instanceof EnumTypeDefinition) {
246 return createEnum(stmt, (EnumTypeDefinition) baseType, declared, substatements);
247 } else if (baseType instanceof IdentityrefTypeDefinition) {
248 return createIdentityref(stmt, (IdentityrefTypeDefinition) baseType, declared, substatements);
249 } else if (baseType instanceof InstanceIdentifierTypeDefinition) {
250 return createInstanceIdentifier(stmt, (InstanceIdentifierTypeDefinition) baseType, declared, substatements);
251 } else if (baseType instanceof Int8TypeDefinition) {
252 return createIntegral(stmt, declared, substatements,
253 RestrictedTypes.newInt8Builder((Int8TypeDefinition) baseType, typeEffectiveQName(stmt)));
254 } else if (baseType instanceof Int16TypeDefinition) {
255 return createIntegral(stmt, declared, substatements,
256 RestrictedTypes.newInt16Builder((Int16TypeDefinition) baseType, typeEffectiveQName(stmt)));
257 } else if (baseType instanceof Int32TypeDefinition) {
258 return createIntegral(stmt, declared, substatements,
259 RestrictedTypes.newInt32Builder((Int32TypeDefinition) baseType, typeEffectiveQName(stmt)));
260 } else if (baseType instanceof Int64TypeDefinition) {
261 return createIntegral(stmt, declared, substatements,
262 RestrictedTypes.newInt64Builder((Int64TypeDefinition) baseType, typeEffectiveQName(stmt)));
263 } else if (baseType instanceof LeafrefTypeDefinition) {
264 return createLeafref(stmt, (LeafrefTypeDefinition) baseType, declared, substatements);
265 } else if (baseType instanceof StringTypeDefinition) {
266 return createString(stmt, (StringTypeDefinition) baseType, declared, substatements);
267 } else if (baseType instanceof Uint8TypeDefinition) {
268 return createIntegral(stmt, declared, substatements,
269 RestrictedTypes.newUint8Builder((Uint8TypeDefinition) baseType, typeEffectiveQName(stmt)));
270 } else if (baseType instanceof Uint16TypeDefinition) {
271 return createIntegral(stmt, declared, substatements,
272 RestrictedTypes.newUint16Builder((Uint16TypeDefinition) baseType, typeEffectiveQName(stmt)));
273 } else if (baseType instanceof Uint32TypeDefinition) {
274 return createIntegral(stmt, declared, substatements,
275 RestrictedTypes.newUint32Builder((Uint32TypeDefinition) baseType, typeEffectiveQName(stmt)));
276 } else if (baseType instanceof Uint64TypeDefinition) {
277 return createIntegral(stmt, declared, substatements,
278 RestrictedTypes.newUint64Builder((Uint64TypeDefinition) baseType, typeEffectiveQName(stmt)));
279 } else if (baseType instanceof UnionTypeDefinition) {
280 return createUnion(stmt, (UnionTypeDefinition) baseType, declared, substatements);
282 throw new IllegalStateException("Unhandled base type " + baseType);
286 // FIXME: YANGTOOLS-1208: this needs to happen during onFullDefinitionDeclared() and stored (again) in a namespace
287 static final @NonNull QName typeEffectiveQName(final Current<QName, ?> stmt) {
288 return stmt.getArgument().bindTo(stmt.getEffectiveParent().effectiveNamespace()).intern();
292 * Resolve type reference, as pointed to by the context's argument.
294 * @param ctx Statement context
295 * @return Resolved type
296 * @throws SourceException if the target type cannot be found
298 private static @NonNull TypeEffectiveStatement<TypeStatement> resolveType(final NamespaceStmtCtx ctx) {
299 final Object obj = verifyNotNull(ctx.namespaceItem(BaseTypeNamespace.INSTANCE, Empty.value()));
300 if (obj instanceof BuiltinEffectiveStatement) {
301 return (BuiltinEffectiveStatement) obj;
302 } else if (obj instanceof StmtContext) {
303 return ((TypedefEffectiveStatement) ((StmtContext<?, ?, ?>) obj).buildEffective())
304 .asTypeEffectiveStatement();
306 throw new InferenceException(ctx, "Unexpected base object %s", obj);
310 private static @NonNull TypeEffectiveStatement<TypeStatement> createBinary(final Current<QName, ?> ctx,
311 final BinaryTypeDefinition baseType, final TypeStatement declared,
312 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
313 final LengthRestrictedTypeBuilder<BinaryTypeDefinition> builder =
314 RestrictedTypes.newBinaryBuilder(baseType, typeEffectiveQName(ctx));
316 for (EffectiveStatement<?, ?> stmt : substatements) {
317 if (stmt instanceof LengthEffectiveStatement length) {
319 builder.setLengthConstraint(length, length.argument());
320 } catch (IllegalStateException e) {
321 throw new SourceException(ctx, e, "Multiple length constraints encountered");
322 } catch (InvalidLengthConstraintException e) {
323 throw new SourceException(ctx, e, "Invalid length constraint %s", length.argument());
328 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
331 private @NonNull TypeEffectiveStatement<TypeStatement> createBits(final Current<?, ?> ctx,
332 final BitsTypeDefinition baseType, final TypeStatement declared,
333 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
334 final BitsTypeBuilder builder = RestrictedTypes.newBitsBuilder(baseType, ctx.argumentAsTypeQName());
336 for (final EffectiveStatement<?, ?> stmt : substatements) {
337 if (stmt instanceof BitEffectiveStatement) {
338 builder.addBit(addRestrictedBit(ctx, baseType, (BitEffectiveStatement) stmt));
342 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
345 abstract @NonNull Bit addRestrictedBit(@NonNull EffectiveStmtCtx stmt, @NonNull BitsTypeDefinition base,
346 @NonNull BitEffectiveStatement bit);
348 private static @NonNull TypeEffectiveStatement<TypeStatement> createBoolean(final Current<QName, ?> ctx,
349 final BooleanTypeDefinition baseType, final TypeStatement declared,
350 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
351 return new TypeEffectiveStatementImpl<>(declared, substatements, RestrictedTypes.newBooleanBuilder(baseType,
352 typeEffectiveQName(ctx)));
355 private static @NonNull TypeEffectiveStatement<TypeStatement> createDecimal(final Current<QName, ?> ctx,
356 final DecimalTypeDefinition baseType, final TypeStatement declared,
357 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
358 final RangeRestrictedTypeBuilder<DecimalTypeDefinition, Decimal64> builder =
359 RestrictedTypes.newDecima64Builder(baseType, typeEffectiveQName(ctx));
361 for (EffectiveStatement<?, ?> stmt : substatements) {
362 if (stmt instanceof RangeEffectiveStatement range) {
363 builder.setRangeConstraint(range, range.argument());
365 if (stmt instanceof FractionDigitsEffectiveStatement) {
366 final Integer digits = ((FractionDigitsEffectiveStatement)stmt).argument();
367 SourceException.throwIf(baseType.getFractionDigits() != digits, ctx,
368 "Cannot override fraction-digits from base type %s to %s", baseType, digits);
372 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
375 private static @NonNull TypeEffectiveStatement<TypeStatement> createEmpty(final Current<QName, ?> ctx,
376 final EmptyTypeDefinition baseType, final TypeStatement declared,
377 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
378 return new TypeEffectiveStatementImpl<>(declared, substatements, RestrictedTypes.newEmptyBuilder(baseType,
379 typeEffectiveQName(ctx)));
382 private @NonNull TypeEffectiveStatement<TypeStatement> createEnum(final Current<?, ?> ctx,
383 final EnumTypeDefinition baseType, final TypeStatement declared,
384 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
385 final EnumerationTypeBuilder builder = RestrictedTypes.newEnumerationBuilder(baseType,
386 ctx.argumentAsTypeQName());
388 for (final EffectiveStatement<?, ?> stmt : substatements) {
389 if (stmt instanceof EnumEffectiveStatement) {
390 builder.addEnum(addRestrictedEnum(ctx, baseType, (EnumEffectiveStatement) stmt));
394 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
397 abstract @NonNull EnumPair addRestrictedEnum(@NonNull EffectiveStmtCtx stmt, @NonNull EnumTypeDefinition base,
398 @NonNull EnumEffectiveStatement enumStmt);
400 private static @NonNull TypeEffectiveStatement<TypeStatement> createIdentityref(final Current<QName, ?> ctx,
401 final IdentityrefTypeDefinition baseType, final TypeStatement declared,
402 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
403 return new TypeEffectiveStatementImpl<>(declared, substatements, RestrictedTypes.newIdentityrefBuilder(baseType,
404 typeEffectiveQName(ctx)));
407 private static @NonNull TypeEffectiveStatement<TypeStatement> createInstanceIdentifier(final Current<QName, ?> ctx,
408 final InstanceIdentifierTypeDefinition baseType, final TypeStatement declared,
409 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
410 final InstanceIdentifierTypeBuilder builder = RestrictedTypes.newInstanceIdentifierBuilder(baseType,
411 typeEffectiveQName(ctx));
413 for (EffectiveStatement<?, ?> stmt : substatements) {
414 if (stmt instanceof RequireInstanceEffectiveStatement) {
415 builder.setRequireInstance(((RequireInstanceEffectiveStatement)stmt).argument());
419 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
422 private static <T extends RangeRestrictedTypeDefinition<T, N>, N extends Number & Comparable<N>>
423 @NonNull TypeEffectiveStatement<TypeStatement> createIntegral(final Current<?, ?> ctx,
424 final TypeStatement declared, final ImmutableList<? extends EffectiveStatement<?, ?>> substatements,
425 final RangeRestrictedTypeBuilder<T, N> builder) {
426 for (EffectiveStatement<?, ?> stmt : substatements) {
427 if (stmt instanceof RangeEffectiveStatement rangeStmt) {
428 builder.setRangeConstraint(rangeStmt, rangeStmt.argument());
433 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
434 } catch (InvalidRangeConstraintException e) {
435 throw new SourceException(ctx, e, "Invalid range constraint: %s", e.getOffendingRanges());
439 private static @NonNull TypeEffectiveStatement<TypeStatement> createLeafref(final Current<QName, ?> ctx,
440 final LeafrefTypeDefinition baseType, final TypeStatement declared,
441 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
442 final RequireInstanceRestrictedTypeBuilder<LeafrefTypeDefinition> builder =
443 RestrictedTypes.newLeafrefBuilder(baseType, AbstractTypeStatementSupport.typeEffectiveQName(ctx));
445 for (final EffectiveStatement<?, ?> stmt : substatements) {
446 if (stmt instanceof RequireInstanceEffectiveStatement) {
447 builder.setRequireInstance(((RequireInstanceEffectiveStatement) stmt).argument());
450 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
453 private static @NonNull TypeEffectiveStatement<TypeStatement> createString(final Current<QName, ?> ctx,
454 final StringTypeDefinition baseType, final TypeStatement declared,
455 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
456 final StringTypeBuilder builder = RestrictedTypes.newStringBuilder(baseType,
457 AbstractTypeStatementSupport.typeEffectiveQName(ctx));
459 for (EffectiveStatement<?, ?> stmt : substatements) {
460 if (stmt instanceof LengthEffectiveStatement length) {
462 builder.setLengthConstraint(length, length.argument());
463 } catch (IllegalStateException e) {
464 throw new SourceException(ctx, e, "Multiple length constraints encountered");
465 } catch (InvalidLengthConstraintException e) {
466 throw new SourceException(ctx, e, "Invalid length constraint %s", length.argument());
469 if (stmt instanceof PatternEffectiveStatement) {
470 builder.addPatternConstraint((PatternEffectiveStatement) stmt);
474 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
477 private static @NonNull TypeEffectiveStatement<TypeStatement> createUnion(final Current<QName, ?> ctx,
478 final UnionTypeDefinition baseType, final TypeStatement declared,
479 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
480 return new TypeEffectiveStatementImpl<>(declared, substatements, RestrictedTypes.newUnionBuilder(baseType,
481 typeEffectiveQName(ctx)));