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) {
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(), new IdentityRefSpecificationRFC6020Support(config))
128 .put(TypeDefinitions.INSTANCE_IDENTIFIER.getLocalName(), new InstanceIdentifierSpecificationSupport(config))
129 .put(TypeDefinitions.LEAFREF.getLocalName(), new LeafrefSpecificationRFC6020Support(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 SubstatementValidator getSubstatementValidator() {
181 return SUBSTATEMENT_VALIDATOR;
185 protected final TypeStatement createDeclared(final StmtContext<QName, TypeStatement, ?> ctx,
186 final ImmutableList<? extends DeclaredStatement<?>> substatements) {
187 if (substatements.isEmpty()) {
188 final TypeStatement builtin = BuiltinTypeStatement.lookup(ctx.getRawArgument());
189 if (builtin != null) {
193 return DeclaredStatements.createType(ctx.getRawArgument(), ctx.getArgument(), substatements);
197 protected final TypeStatement attachDeclarationReference(final TypeStatement stmt,
198 final DeclarationReference reference) {
199 return DeclaredStatementDecorators.decorateType(stmt, reference);
203 protected EffectiveStatement<QName, TypeStatement> createEffective(final Current<QName, TypeStatement> stmt,
204 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
205 // First look up the proper base type
206 final TypeEffectiveStatement<TypeStatement> typeStmt = resolveType(stmt);
207 if (substatements.isEmpty()) {
211 // Now instantiate the proper effective statement for that type
212 final TypeDefinition<?> baseType = typeStmt.getTypeDefinition();
213 final TypeStatement declared = stmt.declared();
214 if (baseType instanceof BinaryTypeDefinition) {
215 return createBinary(stmt, (BinaryTypeDefinition) baseType, declared, substatements);
216 } else if (baseType instanceof BitsTypeDefinition) {
217 return createBits(stmt, (BitsTypeDefinition) baseType, declared, substatements);
218 } else if (baseType instanceof BooleanTypeDefinition) {
219 return createBoolean(stmt, (BooleanTypeDefinition) baseType, declared, substatements);
220 } else if (baseType instanceof DecimalTypeDefinition) {
221 return createDecimal(stmt, (DecimalTypeDefinition) baseType, declared, substatements);
222 } else if (baseType instanceof EmptyTypeDefinition) {
223 return createEmpty(stmt, (EmptyTypeDefinition) baseType, declared, substatements);
224 } else if (baseType instanceof EnumTypeDefinition) {
225 return createEnum(stmt, (EnumTypeDefinition) baseType, declared, substatements);
226 } else if (baseType instanceof IdentityrefTypeDefinition) {
227 return createIdentityref(stmt, (IdentityrefTypeDefinition) baseType, declared, substatements);
228 } else if (baseType instanceof InstanceIdentifierTypeDefinition) {
229 return createInstanceIdentifier(stmt, (InstanceIdentifierTypeDefinition) baseType, declared, substatements);
230 } else if (baseType instanceof Int8TypeDefinition) {
231 return createIntegral(stmt, declared, substatements,
232 RestrictedTypes.newInt8Builder((Int8TypeDefinition) baseType, typeEffectiveQName(stmt)));
233 } else if (baseType instanceof Int16TypeDefinition) {
234 return createIntegral(stmt, declared, substatements,
235 RestrictedTypes.newInt16Builder((Int16TypeDefinition) baseType, typeEffectiveQName(stmt)));
236 } else if (baseType instanceof Int32TypeDefinition) {
237 return createIntegral(stmt, declared, substatements,
238 RestrictedTypes.newInt32Builder((Int32TypeDefinition) baseType, typeEffectiveQName(stmt)));
239 } else if (baseType instanceof Int64TypeDefinition) {
240 return createIntegral(stmt, declared, substatements,
241 RestrictedTypes.newInt64Builder((Int64TypeDefinition) baseType, typeEffectiveQName(stmt)));
242 } else if (baseType instanceof LeafrefTypeDefinition) {
243 return createLeafref(stmt, (LeafrefTypeDefinition) baseType, declared, substatements);
244 } else if (baseType instanceof StringTypeDefinition) {
245 return createString(stmt, (StringTypeDefinition) baseType, declared, substatements);
246 } else if (baseType instanceof Uint8TypeDefinition) {
247 return createIntegral(stmt, declared, substatements,
248 RestrictedTypes.newUint8Builder((Uint8TypeDefinition) baseType, typeEffectiveQName(stmt)));
249 } else if (baseType instanceof Uint16TypeDefinition) {
250 return createIntegral(stmt, declared, substatements,
251 RestrictedTypes.newUint16Builder((Uint16TypeDefinition) baseType, typeEffectiveQName(stmt)));
252 } else if (baseType instanceof Uint32TypeDefinition) {
253 return createIntegral(stmt, declared, substatements,
254 RestrictedTypes.newUint32Builder((Uint32TypeDefinition) baseType, typeEffectiveQName(stmt)));
255 } else if (baseType instanceof Uint64TypeDefinition) {
256 return createIntegral(stmt, declared, substatements,
257 RestrictedTypes.newUint64Builder((Uint64TypeDefinition) baseType, typeEffectiveQName(stmt)));
258 } else if (baseType instanceof UnionTypeDefinition) {
259 return createUnion(stmt, (UnionTypeDefinition) baseType, declared, substatements);
261 throw new IllegalStateException("Unhandled base type " + baseType);
265 // FIXME: YANGTOOLS-1208: this needs to happen during onFullDefinitionDeclared() and stored (again) in a namespace
266 static final @NonNull QName typeEffectiveQName(final Current<QName, ?> stmt) {
267 return stmt.getArgument().bindTo(stmt.getEffectiveParent().effectiveNamespace()).intern();
271 * Resolve type reference, as pointed to by the context's argument.
273 * @param ctx Statement context
274 * @return Resolved type
275 * @throws SourceException if the target type cannot be found
277 private static @NonNull TypeEffectiveStatement<TypeStatement> resolveType(final Current<QName, ?> ctx) {
278 final Object obj = verifyNotNull(ctx.namespaceItem(BaseTypeNamespace.class, Empty.getInstance()));
279 if (obj instanceof BuiltinEffectiveStatement) {
280 return (BuiltinEffectiveStatement) obj;
281 } else if (obj instanceof StmtContext) {
282 return ((TypedefEffectiveStatement) ((StmtContext<?, ?, ?>) obj).buildEffective())
283 .asTypeEffectiveStatement();
285 throw new InferenceException(ctx, "Unexpected base object %s", obj);
289 private static @NonNull TypeEffectiveStatement<TypeStatement> createBinary(final Current<QName, ?> ctx,
290 final BinaryTypeDefinition baseType, final TypeStatement declared,
291 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
292 final LengthRestrictedTypeBuilder<BinaryTypeDefinition> builder =
293 RestrictedTypes.newBinaryBuilder(baseType, typeEffectiveQName(ctx));
295 for (EffectiveStatement<?, ?> stmt : substatements) {
296 if (stmt instanceof LengthEffectiveStatement) {
297 final LengthEffectiveStatement length = (LengthEffectiveStatement)stmt;
300 builder.setLengthConstraint(length, length.argument());
301 } catch (IllegalStateException e) {
302 throw new SourceException(ctx, e, "Multiple length constraints encountered");
303 } catch (InvalidLengthConstraintException e) {
304 throw new SourceException(ctx, e, "Invalid length constraint %s", length.argument());
309 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
312 private @NonNull TypeEffectiveStatement<TypeStatement> createBits(final Current<?, ?> ctx,
313 final BitsTypeDefinition baseType, final TypeStatement declared,
314 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
315 final BitsTypeBuilder builder = RestrictedTypes.newBitsBuilder(baseType, ctx.argumentAsTypeQName());
317 for (final EffectiveStatement<?, ?> stmt : substatements) {
318 if (stmt instanceof BitEffectiveStatement) {
319 builder.addBit(addRestrictedBit(ctx, baseType, (BitEffectiveStatement) stmt));
323 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
326 abstract @NonNull Bit addRestrictedBit(@NonNull EffectiveStmtCtx stmt, @NonNull BitsTypeDefinition base,
327 @NonNull BitEffectiveStatement bit);
329 private static @NonNull TypeEffectiveStatement<TypeStatement> createBoolean(final Current<QName, ?> ctx,
330 final BooleanTypeDefinition baseType, final TypeStatement declared,
331 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
332 return new TypeEffectiveStatementImpl<>(declared, substatements, RestrictedTypes.newBooleanBuilder(baseType,
333 typeEffectiveQName(ctx)));
336 private static @NonNull TypeEffectiveStatement<TypeStatement> createDecimal(final Current<QName, ?> ctx,
337 final DecimalTypeDefinition baseType, final TypeStatement declared,
338 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
339 final RangeRestrictedTypeBuilder<DecimalTypeDefinition, BigDecimal> builder =
340 RestrictedTypes.newDecima64Builder(baseType, typeEffectiveQName(ctx));
342 for (EffectiveStatement<?, ?> stmt : substatements) {
343 if (stmt instanceof RangeEffectiveStatement) {
344 final RangeEffectiveStatement range = (RangeEffectiveStatement) stmt;
345 builder.setRangeConstraint(range, range.argument());
347 if (stmt instanceof FractionDigitsEffectiveStatement) {
348 final Integer digits = ((FractionDigitsEffectiveStatement)stmt).argument();
349 SourceException.throwIf(baseType.getFractionDigits() != digits, ctx,
350 "Cannot override fraction-digits from base type %s to %s", baseType, digits);
354 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
357 private static @NonNull TypeEffectiveStatement<TypeStatement> createEmpty(final Current<QName, ?> ctx,
358 final EmptyTypeDefinition baseType, final TypeStatement declared,
359 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
360 return new TypeEffectiveStatementImpl<>(declared, substatements, RestrictedTypes.newEmptyBuilder(baseType,
361 typeEffectiveQName(ctx)));
364 private @NonNull TypeEffectiveStatement<TypeStatement> createEnum(final Current<?, ?> ctx,
365 final EnumTypeDefinition baseType, final TypeStatement declared,
366 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
367 final EnumerationTypeBuilder builder = RestrictedTypes.newEnumerationBuilder(baseType,
368 ctx.argumentAsTypeQName());
370 for (final EffectiveStatement<?, ?> stmt : substatements) {
371 if (stmt instanceof EnumEffectiveStatement) {
372 builder.addEnum(addRestrictedEnum(ctx, baseType, (EnumEffectiveStatement) stmt));
376 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
379 abstract @NonNull EnumPair addRestrictedEnum(@NonNull EffectiveStmtCtx stmt, @NonNull EnumTypeDefinition base,
380 @NonNull EnumEffectiveStatement enumStmt);
382 private static @NonNull TypeEffectiveStatement<TypeStatement> createIdentityref(final Current<QName, ?> ctx,
383 final IdentityrefTypeDefinition baseType, final TypeStatement declared,
384 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
385 return new TypeEffectiveStatementImpl<>(declared, substatements, RestrictedTypes.newIdentityrefBuilder(baseType,
386 typeEffectiveQName(ctx)));
389 private static @NonNull TypeEffectiveStatement<TypeStatement> createInstanceIdentifier(final Current<QName, ?> ctx,
390 final InstanceIdentifierTypeDefinition baseType, final TypeStatement declared,
391 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
392 final InstanceIdentifierTypeBuilder builder = RestrictedTypes.newInstanceIdentifierBuilder(baseType,
393 typeEffectiveQName(ctx));
395 for (EffectiveStatement<?, ?> stmt : substatements) {
396 if (stmt instanceof RequireInstanceEffectiveStatement) {
397 builder.setRequireInstance(((RequireInstanceEffectiveStatement)stmt).argument());
401 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
404 private static <T extends RangeRestrictedTypeDefinition<T, N>, N extends Number & Comparable<N>>
405 @NonNull TypeEffectiveStatement<TypeStatement> createIntegral(final Current<?, ?> ctx,
406 final TypeStatement declared, final ImmutableList<? extends EffectiveStatement<?, ?>> substatements,
407 final RangeRestrictedTypeBuilder<T, N> builder) {
408 for (EffectiveStatement<?, ?> stmt : substatements) {
409 if (stmt instanceof RangeEffectiveStatement) {
410 final RangeEffectiveStatement rangeStmt = (RangeEffectiveStatement)stmt;
411 builder.setRangeConstraint(rangeStmt, rangeStmt.argument());
416 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
417 } catch (InvalidRangeConstraintException e) {
418 throw new SourceException(ctx, e, "Invalid range constraint: %s", e.getOffendingRanges());
422 private static @NonNull TypeEffectiveStatement<TypeStatement> createLeafref(final Current<QName, ?> ctx,
423 final LeafrefTypeDefinition baseType, final TypeStatement declared,
424 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
425 final RequireInstanceRestrictedTypeBuilder<LeafrefTypeDefinition> builder =
426 RestrictedTypes.newLeafrefBuilder(baseType, AbstractTypeStatementSupport.typeEffectiveQName(ctx));
428 for (final EffectiveStatement<?, ?> stmt : substatements) {
429 if (stmt instanceof RequireInstanceEffectiveStatement) {
430 builder.setRequireInstance(((RequireInstanceEffectiveStatement) stmt).argument());
433 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
436 private static @NonNull TypeEffectiveStatement<TypeStatement> createString(final Current<QName, ?> ctx,
437 final StringTypeDefinition baseType, final TypeStatement declared,
438 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
439 final StringTypeBuilder builder = RestrictedTypes.newStringBuilder(baseType,
440 AbstractTypeStatementSupport.typeEffectiveQName(ctx));
442 for (EffectiveStatement<?, ?> stmt : substatements) {
443 if (stmt instanceof LengthEffectiveStatement) {
444 final LengthEffectiveStatement length = (LengthEffectiveStatement)stmt;
447 builder.setLengthConstraint(length, length.argument());
448 } catch (IllegalStateException e) {
449 throw new SourceException(ctx, e, "Multiple length constraints encountered");
450 } catch (InvalidLengthConstraintException e) {
451 throw new SourceException(ctx, e, "Invalid length constraint %s", length.argument());
454 if (stmt instanceof PatternEffectiveStatement) {
455 builder.addPatternConstraint((PatternEffectiveStatement) stmt);
459 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
462 private static @NonNull TypeEffectiveStatement<TypeStatement> createUnion(final Current<QName, ?> ctx,
463 final UnionTypeDefinition baseType, final TypeStatement declared,
464 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
465 return new TypeEffectiveStatementImpl<>(declared, substatements, RestrictedTypes.newUnionBuilder(baseType,
466 typeEffectiveQName(ctx)));