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.math.BigDecimal;
15 import java.util.Collection;
16 import org.eclipse.jdt.annotation.NonNull;
17 import org.opendaylight.yangtools.yang.common.Empty;
18 import org.opendaylight.yangtools.yang.common.QName;
19 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
20 import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
21 import org.opendaylight.yangtools.yang.model.api.meta.DeclarationReference;
22 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
23 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
24 import org.opendaylight.yangtools.yang.model.api.stmt.BitEffectiveStatement;
25 import org.opendaylight.yangtools.yang.model.api.stmt.EnumEffectiveStatement;
26 import org.opendaylight.yangtools.yang.model.api.stmt.FractionDigitsEffectiveStatement;
27 import org.opendaylight.yangtools.yang.model.api.stmt.LengthEffectiveStatement;
28 import org.opendaylight.yangtools.yang.model.api.stmt.PatternEffectiveStatement;
29 import org.opendaylight.yangtools.yang.model.api.stmt.RangeEffectiveStatement;
30 import org.opendaylight.yangtools.yang.model.api.stmt.RequireInstanceEffectiveStatement;
31 import org.opendaylight.yangtools.yang.model.api.stmt.TypeEffectiveStatement;
32 import org.opendaylight.yangtools.yang.model.api.stmt.TypeStatement;
33 import org.opendaylight.yangtools.yang.model.api.stmt.TypedefEffectiveStatement;
34 import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition;
35 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
36 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition.Bit;
37 import org.opendaylight.yangtools.yang.model.api.type.BooleanTypeDefinition;
38 import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition;
39 import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition;
40 import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
41 import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition.EnumPair;
42 import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
43 import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition;
44 import org.opendaylight.yangtools.yang.model.api.type.Int16TypeDefinition;
45 import org.opendaylight.yangtools.yang.model.api.type.Int32TypeDefinition;
46 import org.opendaylight.yangtools.yang.model.api.type.Int64TypeDefinition;
47 import org.opendaylight.yangtools.yang.model.api.type.Int8TypeDefinition;
48 import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
49 import org.opendaylight.yangtools.yang.model.api.type.RangeRestrictedTypeDefinition;
50 import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition;
51 import org.opendaylight.yangtools.yang.model.api.type.TypeDefinitions;
52 import org.opendaylight.yangtools.yang.model.api.type.Uint16TypeDefinition;
53 import org.opendaylight.yangtools.yang.model.api.type.Uint32TypeDefinition;
54 import org.opendaylight.yangtools.yang.model.api.type.Uint64TypeDefinition;
55 import org.opendaylight.yangtools.yang.model.api.type.Uint8TypeDefinition;
56 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
57 import org.opendaylight.yangtools.yang.model.ri.stmt.DeclaredStatementDecorators;
58 import org.opendaylight.yangtools.yang.model.ri.stmt.DeclaredStatements;
59 import org.opendaylight.yangtools.yang.model.ri.type.BitsTypeBuilder;
60 import org.opendaylight.yangtools.yang.model.ri.type.EnumerationTypeBuilder;
61 import org.opendaylight.yangtools.yang.model.ri.type.InstanceIdentifierTypeBuilder;
62 import org.opendaylight.yangtools.yang.model.ri.type.InvalidLengthConstraintException;
63 import org.opendaylight.yangtools.yang.model.ri.type.InvalidRangeConstraintException;
64 import org.opendaylight.yangtools.yang.model.ri.type.LengthRestrictedTypeBuilder;
65 import org.opendaylight.yangtools.yang.model.ri.type.RangeRestrictedTypeBuilder;
66 import org.opendaylight.yangtools.yang.model.ri.type.RequireInstanceRestrictedTypeBuilder;
67 import org.opendaylight.yangtools.yang.model.ri.type.RestrictedTypes;
68 import org.opendaylight.yangtools.yang.model.ri.type.StringTypeBuilder;
69 import org.opendaylight.yangtools.yang.parser.api.YangParserConfiguration;
70 import org.opendaylight.yangtools.yang.parser.spi.TypeNamespace;
71 import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx;
72 import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.Current;
73 import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
74 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder;
75 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.InferenceAction;
76 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.InferenceContext;
77 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.Prerequisite;
78 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
79 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport;
80 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
81 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
82 import org.opendaylight.yangtools.yang.parser.spi.meta.SubstatementValidator;
83 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
85 abstract class AbstractTypeStatementSupport extends AbstractTypeSupport<TypeStatement> {
86 private static final SubstatementValidator SUBSTATEMENT_VALIDATOR =
87 SubstatementValidator.builder(YangStmtMapping.TYPE)
88 .addOptional(YangStmtMapping.BASE)
89 .addAny(YangStmtMapping.BIT)
90 .addAny(YangStmtMapping.ENUM)
91 .addOptional(YangStmtMapping.FRACTION_DIGITS)
92 .addOptional(YangStmtMapping.LENGTH)
93 .addOptional(YangStmtMapping.PATH)
94 .addAny(YangStmtMapping.PATTERN)
95 .addOptional(YangStmtMapping.RANGE)
96 .addOptional(YangStmtMapping.REQUIRE_INSTANCE)
97 .addAny(YangStmtMapping.TYPE)
100 private static final ImmutableMap<String, BuiltinEffectiveStatement> STATIC_BUILT_IN_TYPES =
101 ImmutableMap.<String, BuiltinEffectiveStatement>builder()
102 .put(TypeDefinitions.BINARY.getLocalName(), BuiltinEffectiveStatement.BINARY)
103 .put(TypeDefinitions.BOOLEAN.getLocalName(), BuiltinEffectiveStatement.BOOLEAN)
104 .put(TypeDefinitions.EMPTY.getLocalName(), BuiltinEffectiveStatement.EMPTY)
105 // FIXME: this overlaps with DYNAMIC_BUILT_IN_TYPES. One of these is not needed, but we need to decide
106 // what to do. I think we should gradually use per-statement validators, hence go towards dynamic?
107 .put(TypeDefinitions.INSTANCE_IDENTIFIER.getLocalName(), BuiltinEffectiveStatement.INSTANCE_IDENTIFIER)
108 .put(TypeDefinitions.INT8.getLocalName(), BuiltinEffectiveStatement.INT8)
109 .put(TypeDefinitions.INT16.getLocalName(), BuiltinEffectiveStatement.INT16)
110 .put(TypeDefinitions.INT32.getLocalName(), BuiltinEffectiveStatement.INT32)
111 .put(TypeDefinitions.INT64.getLocalName(), BuiltinEffectiveStatement.INT64)
112 .put(TypeDefinitions.STRING.getLocalName(), BuiltinEffectiveStatement.STRING)
113 .put(TypeDefinitions.UINT8.getLocalName(), BuiltinEffectiveStatement.UINT8)
114 .put(TypeDefinitions.UINT16.getLocalName(), BuiltinEffectiveStatement.UINT16)
115 .put(TypeDefinitions.UINT32.getLocalName(), BuiltinEffectiveStatement.UINT32)
116 .put(TypeDefinitions.UINT64.getLocalName(), BuiltinEffectiveStatement.UINT64)
119 private final ImmutableMap<String, StatementSupport<?, ?, ?>> dynamicBuiltInTypes;
121 AbstractTypeStatementSupport(final YangParserConfiguration config) {
122 super(config, SUBSTATEMENT_VALIDATOR);
123 dynamicBuiltInTypes = ImmutableMap.<String, StatementSupport<?, ?, ?>>builder()
124 .put(TypeDefinitions.BITS.getLocalName(), new BitsSpecificationSupport(config))
125 .put(TypeDefinitions.DECIMAL64.getLocalName(), new Decimal64SpecificationSupport(config))
126 .put(TypeDefinitions.ENUMERATION.getLocalName(), new EnumSpecificationSupport(config))
127 .put(TypeDefinitions.IDENTITYREF.getLocalName(), IdentityRefSpecificationSupport.rfc6020Instance(config))
128 .put(TypeDefinitions.INSTANCE_IDENTIFIER.getLocalName(), new InstanceIdentifierSpecificationSupport(config))
129 .put(TypeDefinitions.LEAFREF.getLocalName(), LeafrefSpecificationSupport.rfc6020Instance(config))
130 .put(TypeDefinitions.UNION.getLocalName(), new UnionSpecificationSupport(config))
135 public final void onFullDefinitionDeclared(
136 final Mutable<QName, TypeStatement, EffectiveStatement<QName, TypeStatement>> stmt) {
137 super.onFullDefinitionDeclared(stmt);
139 final BuiltinEffectiveStatement builtin = STATIC_BUILT_IN_TYPES.get(stmt.getRawArgument());
140 if (builtin != null) {
141 stmt.addToNs(BaseTypeNamespace.class, Empty.getInstance(), builtin);
145 final QName typeQName = stmt.getArgument();
146 final ModelActionBuilder typeAction = stmt.newInferenceAction(ModelProcessingPhase.EFFECTIVE_MODEL);
147 final Prerequisite<StmtContext<?, ?, ?>> typePrereq = typeAction.requiresCtx(stmt, TypeNamespace.class,
148 typeQName, ModelProcessingPhase.EFFECTIVE_MODEL);
149 typeAction.mutatesEffectiveCtx(stmt.getParentContext());
152 * If the type does not exist, throw an InferenceException.
153 * If the type exists, store a reference to it in BaseTypeNamespace.
155 typeAction.apply(new InferenceAction() {
157 public void apply(final InferenceContext ctx) {
158 // Note: do not attempt to call buildEffective() here
159 stmt.addToNs(BaseTypeNamespace.class, Empty.getInstance(), typePrereq.resolve(ctx));
163 public void prerequisiteFailed(final Collection<? extends Prerequisite<?>> failed) {
164 InferenceException.throwIf(failed.contains(typePrereq), stmt, "Type [%s] was not found.", typeQName);
170 public boolean hasArgumentSpecificSupports() {
171 return !dynamicBuiltInTypes.isEmpty();
175 public StatementSupport<?, ?, ?> getSupportSpecificForArgument(final String argument) {
176 return dynamicBuiltInTypes.get(argument);
180 protected final TypeStatement createDeclared(final StmtContext<QName, TypeStatement, ?> ctx,
181 final ImmutableList<? extends DeclaredStatement<?>> substatements) {
182 if (substatements.isEmpty()) {
183 final TypeStatement builtin = BuiltinTypeStatement.lookup(ctx.getRawArgument());
184 if (builtin != null) {
188 return DeclaredStatements.createType(ctx.getRawArgument(), ctx.getArgument(), substatements);
192 protected final TypeStatement attachDeclarationReference(final TypeStatement stmt,
193 final DeclarationReference reference) {
194 return DeclaredStatementDecorators.decorateType(stmt, reference);
198 protected EffectiveStatement<QName, TypeStatement> createEffective(final Current<QName, TypeStatement> stmt,
199 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
200 // First look up the proper base type
201 final TypeEffectiveStatement<TypeStatement> typeStmt = resolveType(stmt);
202 if (substatements.isEmpty()) {
206 // Now instantiate the proper effective statement for that type
207 final TypeDefinition<?> baseType = typeStmt.getTypeDefinition();
208 final TypeStatement declared = stmt.declared();
209 if (baseType instanceof BinaryTypeDefinition) {
210 return createBinary(stmt, (BinaryTypeDefinition) baseType, declared, substatements);
211 } else if (baseType instanceof BitsTypeDefinition) {
212 return createBits(stmt, (BitsTypeDefinition) baseType, declared, substatements);
213 } else if (baseType instanceof BooleanTypeDefinition) {
214 return createBoolean(stmt, (BooleanTypeDefinition) baseType, declared, substatements);
215 } else if (baseType instanceof DecimalTypeDefinition) {
216 return createDecimal(stmt, (DecimalTypeDefinition) baseType, declared, substatements);
217 } else if (baseType instanceof EmptyTypeDefinition) {
218 return createEmpty(stmt, (EmptyTypeDefinition) baseType, declared, substatements);
219 } else if (baseType instanceof EnumTypeDefinition) {
220 return createEnum(stmt, (EnumTypeDefinition) baseType, declared, substatements);
221 } else if (baseType instanceof IdentityrefTypeDefinition) {
222 return createIdentityref(stmt, (IdentityrefTypeDefinition) baseType, declared, substatements);
223 } else if (baseType instanceof InstanceIdentifierTypeDefinition) {
224 return createInstanceIdentifier(stmt, (InstanceIdentifierTypeDefinition) baseType, declared, substatements);
225 } else if (baseType instanceof Int8TypeDefinition) {
226 return createIntegral(stmt, declared, substatements,
227 RestrictedTypes.newInt8Builder((Int8TypeDefinition) baseType, typeEffectiveQName(stmt)));
228 } else if (baseType instanceof Int16TypeDefinition) {
229 return createIntegral(stmt, declared, substatements,
230 RestrictedTypes.newInt16Builder((Int16TypeDefinition) baseType, typeEffectiveQName(stmt)));
231 } else if (baseType instanceof Int32TypeDefinition) {
232 return createIntegral(stmt, declared, substatements,
233 RestrictedTypes.newInt32Builder((Int32TypeDefinition) baseType, typeEffectiveQName(stmt)));
234 } else if (baseType instanceof Int64TypeDefinition) {
235 return createIntegral(stmt, declared, substatements,
236 RestrictedTypes.newInt64Builder((Int64TypeDefinition) baseType, typeEffectiveQName(stmt)));
237 } else if (baseType instanceof LeafrefTypeDefinition) {
238 return createLeafref(stmt, (LeafrefTypeDefinition) baseType, declared, substatements);
239 } else if (baseType instanceof StringTypeDefinition) {
240 return createString(stmt, (StringTypeDefinition) baseType, declared, substatements);
241 } else if (baseType instanceof Uint8TypeDefinition) {
242 return createIntegral(stmt, declared, substatements,
243 RestrictedTypes.newUint8Builder((Uint8TypeDefinition) baseType, typeEffectiveQName(stmt)));
244 } else if (baseType instanceof Uint16TypeDefinition) {
245 return createIntegral(stmt, declared, substatements,
246 RestrictedTypes.newUint16Builder((Uint16TypeDefinition) baseType, typeEffectiveQName(stmt)));
247 } else if (baseType instanceof Uint32TypeDefinition) {
248 return createIntegral(stmt, declared, substatements,
249 RestrictedTypes.newUint32Builder((Uint32TypeDefinition) baseType, typeEffectiveQName(stmt)));
250 } else if (baseType instanceof Uint64TypeDefinition) {
251 return createIntegral(stmt, declared, substatements,
252 RestrictedTypes.newUint64Builder((Uint64TypeDefinition) baseType, typeEffectiveQName(stmt)));
253 } else if (baseType instanceof UnionTypeDefinition) {
254 return createUnion(stmt, (UnionTypeDefinition) baseType, declared, substatements);
256 throw new IllegalStateException("Unhandled base type " + baseType);
260 // FIXME: YANGTOOLS-1208: this needs to happen during onFullDefinitionDeclared() and stored (again) in a namespace
261 static final @NonNull QName typeEffectiveQName(final Current<QName, ?> stmt) {
262 return stmt.getArgument().bindTo(stmt.getEffectiveParent().effectiveNamespace()).intern();
266 * Resolve type reference, as pointed to by the context's argument.
268 * @param ctx Statement context
269 * @return Resolved type
270 * @throws SourceException if the target type cannot be found
272 private static @NonNull TypeEffectiveStatement<TypeStatement> resolveType(final Current<QName, ?> ctx) {
273 final Object obj = verifyNotNull(ctx.namespaceItem(BaseTypeNamespace.class, Empty.getInstance()));
274 if (obj instanceof BuiltinEffectiveStatement) {
275 return (BuiltinEffectiveStatement) obj;
276 } else if (obj instanceof StmtContext) {
277 return ((TypedefEffectiveStatement) ((StmtContext<?, ?, ?>) obj).buildEffective())
278 .asTypeEffectiveStatement();
280 throw new InferenceException(ctx, "Unexpected base object %s", obj);
284 private static @NonNull TypeEffectiveStatement<TypeStatement> createBinary(final Current<QName, ?> ctx,
285 final BinaryTypeDefinition baseType, final TypeStatement declared,
286 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
287 final LengthRestrictedTypeBuilder<BinaryTypeDefinition> builder =
288 RestrictedTypes.newBinaryBuilder(baseType, typeEffectiveQName(ctx));
290 for (EffectiveStatement<?, ?> stmt : substatements) {
291 if (stmt instanceof LengthEffectiveStatement) {
292 final LengthEffectiveStatement length = (LengthEffectiveStatement)stmt;
295 builder.setLengthConstraint(length, length.argument());
296 } catch (IllegalStateException e) {
297 throw new SourceException(ctx, e, "Multiple length constraints encountered");
298 } catch (InvalidLengthConstraintException e) {
299 throw new SourceException(ctx, e, "Invalid length constraint %s", length.argument());
304 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
307 private @NonNull TypeEffectiveStatement<TypeStatement> createBits(final Current<?, ?> ctx,
308 final BitsTypeDefinition baseType, final TypeStatement declared,
309 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
310 final BitsTypeBuilder builder = RestrictedTypes.newBitsBuilder(baseType, ctx.argumentAsTypeQName());
312 for (final EffectiveStatement<?, ?> stmt : substatements) {
313 if (stmt instanceof BitEffectiveStatement) {
314 builder.addBit(addRestrictedBit(ctx, baseType, (BitEffectiveStatement) stmt));
318 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
321 abstract @NonNull Bit addRestrictedBit(@NonNull EffectiveStmtCtx stmt, @NonNull BitsTypeDefinition base,
322 @NonNull BitEffectiveStatement bit);
324 private static @NonNull TypeEffectiveStatement<TypeStatement> createBoolean(final Current<QName, ?> ctx,
325 final BooleanTypeDefinition baseType, final TypeStatement declared,
326 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
327 return new TypeEffectiveStatementImpl<>(declared, substatements, RestrictedTypes.newBooleanBuilder(baseType,
328 typeEffectiveQName(ctx)));
331 private static @NonNull TypeEffectiveStatement<TypeStatement> createDecimal(final Current<QName, ?> ctx,
332 final DecimalTypeDefinition baseType, final TypeStatement declared,
333 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
334 final RangeRestrictedTypeBuilder<DecimalTypeDefinition, BigDecimal> builder =
335 RestrictedTypes.newDecima64Builder(baseType, typeEffectiveQName(ctx));
337 for (EffectiveStatement<?, ?> stmt : substatements) {
338 if (stmt instanceof RangeEffectiveStatement) {
339 final RangeEffectiveStatement range = (RangeEffectiveStatement) stmt;
340 builder.setRangeConstraint(range, range.argument());
342 if (stmt instanceof FractionDigitsEffectiveStatement) {
343 final Integer digits = ((FractionDigitsEffectiveStatement)stmt).argument();
344 SourceException.throwIf(baseType.getFractionDigits() != digits, ctx,
345 "Cannot override fraction-digits from base type %s to %s", baseType, digits);
349 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
352 private static @NonNull TypeEffectiveStatement<TypeStatement> createEmpty(final Current<QName, ?> ctx,
353 final EmptyTypeDefinition baseType, final TypeStatement declared,
354 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
355 return new TypeEffectiveStatementImpl<>(declared, substatements, RestrictedTypes.newEmptyBuilder(baseType,
356 typeEffectiveQName(ctx)));
359 private @NonNull TypeEffectiveStatement<TypeStatement> createEnum(final Current<?, ?> ctx,
360 final EnumTypeDefinition baseType, final TypeStatement declared,
361 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
362 final EnumerationTypeBuilder builder = RestrictedTypes.newEnumerationBuilder(baseType,
363 ctx.argumentAsTypeQName());
365 for (final EffectiveStatement<?, ?> stmt : substatements) {
366 if (stmt instanceof EnumEffectiveStatement) {
367 builder.addEnum(addRestrictedEnum(ctx, baseType, (EnumEffectiveStatement) stmt));
371 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
374 abstract @NonNull EnumPair addRestrictedEnum(@NonNull EffectiveStmtCtx stmt, @NonNull EnumTypeDefinition base,
375 @NonNull EnumEffectiveStatement enumStmt);
377 private static @NonNull TypeEffectiveStatement<TypeStatement> createIdentityref(final Current<QName, ?> ctx,
378 final IdentityrefTypeDefinition baseType, final TypeStatement declared,
379 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
380 return new TypeEffectiveStatementImpl<>(declared, substatements, RestrictedTypes.newIdentityrefBuilder(baseType,
381 typeEffectiveQName(ctx)));
384 private static @NonNull TypeEffectiveStatement<TypeStatement> createInstanceIdentifier(final Current<QName, ?> ctx,
385 final InstanceIdentifierTypeDefinition baseType, final TypeStatement declared,
386 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
387 final InstanceIdentifierTypeBuilder builder = RestrictedTypes.newInstanceIdentifierBuilder(baseType,
388 typeEffectiveQName(ctx));
390 for (EffectiveStatement<?, ?> stmt : substatements) {
391 if (stmt instanceof RequireInstanceEffectiveStatement) {
392 builder.setRequireInstance(((RequireInstanceEffectiveStatement)stmt).argument());
396 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
399 private static <T extends RangeRestrictedTypeDefinition<T, N>, N extends Number & Comparable<N>>
400 @NonNull TypeEffectiveStatement<TypeStatement> createIntegral(final Current<?, ?> ctx,
401 final TypeStatement declared, final ImmutableList<? extends EffectiveStatement<?, ?>> substatements,
402 final RangeRestrictedTypeBuilder<T, N> builder) {
403 for (EffectiveStatement<?, ?> stmt : substatements) {
404 if (stmt instanceof RangeEffectiveStatement) {
405 final RangeEffectiveStatement rangeStmt = (RangeEffectiveStatement)stmt;
406 builder.setRangeConstraint(rangeStmt, rangeStmt.argument());
411 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
412 } catch (InvalidRangeConstraintException e) {
413 throw new SourceException(ctx, e, "Invalid range constraint: %s", e.getOffendingRanges());
417 private static @NonNull TypeEffectiveStatement<TypeStatement> createLeafref(final Current<QName, ?> ctx,
418 final LeafrefTypeDefinition baseType, final TypeStatement declared,
419 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
420 final RequireInstanceRestrictedTypeBuilder<LeafrefTypeDefinition> builder =
421 RestrictedTypes.newLeafrefBuilder(baseType, AbstractTypeStatementSupport.typeEffectiveQName(ctx));
423 for (final EffectiveStatement<?, ?> stmt : substatements) {
424 if (stmt instanceof RequireInstanceEffectiveStatement) {
425 builder.setRequireInstance(((RequireInstanceEffectiveStatement) stmt).argument());
428 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
431 private static @NonNull TypeEffectiveStatement<TypeStatement> createString(final Current<QName, ?> ctx,
432 final StringTypeDefinition baseType, final TypeStatement declared,
433 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
434 final StringTypeBuilder builder = RestrictedTypes.newStringBuilder(baseType,
435 AbstractTypeStatementSupport.typeEffectiveQName(ctx));
437 for (EffectiveStatement<?, ?> stmt : substatements) {
438 if (stmt instanceof LengthEffectiveStatement) {
439 final LengthEffectiveStatement length = (LengthEffectiveStatement)stmt;
442 builder.setLengthConstraint(length, length.argument());
443 } catch (IllegalStateException e) {
444 throw new SourceException(ctx, e, "Multiple length constraints encountered");
445 } catch (InvalidLengthConstraintException e) {
446 throw new SourceException(ctx, e, "Invalid length constraint %s", length.argument());
449 if (stmt instanceof PatternEffectiveStatement) {
450 builder.addPatternConstraint((PatternEffectiveStatement) stmt);
454 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
457 private static @NonNull TypeEffectiveStatement<TypeStatement> createUnion(final Current<QName, ?> ctx,
458 final UnionTypeDefinition baseType, final TypeStatement declared,
459 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
460 return new TypeEffectiveStatementImpl<>(declared, substatements, RestrictedTypes.newUnionBuilder(baseType,
461 typeEffectiveQName(ctx)));