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.TypeNamespace;
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.class, Empty.value(), builtin);
153 final ModelActionBuilder typeAction = stmt.newInferenceAction(ModelProcessingPhase.EFFECTIVE_MODEL);
154 final Prerequisite<StmtContext<?, ?, ?>> typePrereq = typeAction.requiresCtx(stmt, TypeNamespace.class,
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.class, 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.class, 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) {
318 final LengthEffectiveStatement length = (LengthEffectiveStatement)stmt;
321 builder.setLengthConstraint(length, length.argument());
322 } catch (IllegalStateException e) {
323 throw new SourceException(ctx, e, "Multiple length constraints encountered");
324 } catch (InvalidLengthConstraintException e) {
325 throw new SourceException(ctx, e, "Invalid length constraint %s", length.argument());
330 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
333 private @NonNull TypeEffectiveStatement<TypeStatement> createBits(final Current<?, ?> ctx,
334 final BitsTypeDefinition baseType, final TypeStatement declared,
335 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
336 final BitsTypeBuilder builder = RestrictedTypes.newBitsBuilder(baseType, ctx.argumentAsTypeQName());
338 for (final EffectiveStatement<?, ?> stmt : substatements) {
339 if (stmt instanceof BitEffectiveStatement) {
340 builder.addBit(addRestrictedBit(ctx, baseType, (BitEffectiveStatement) stmt));
344 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
347 abstract @NonNull Bit addRestrictedBit(@NonNull EffectiveStmtCtx stmt, @NonNull BitsTypeDefinition base,
348 @NonNull BitEffectiveStatement bit);
350 private static @NonNull TypeEffectiveStatement<TypeStatement> createBoolean(final Current<QName, ?> ctx,
351 final BooleanTypeDefinition baseType, final TypeStatement declared,
352 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
353 return new TypeEffectiveStatementImpl<>(declared, substatements, RestrictedTypes.newBooleanBuilder(baseType,
354 typeEffectiveQName(ctx)));
357 private static @NonNull TypeEffectiveStatement<TypeStatement> createDecimal(final Current<QName, ?> ctx,
358 final DecimalTypeDefinition baseType, final TypeStatement declared,
359 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
360 final RangeRestrictedTypeBuilder<DecimalTypeDefinition, Decimal64> builder =
361 RestrictedTypes.newDecima64Builder(baseType, typeEffectiveQName(ctx));
363 for (EffectiveStatement<?, ?> stmt : substatements) {
364 if (stmt instanceof RangeEffectiveStatement) {
365 final RangeEffectiveStatement range = (RangeEffectiveStatement) stmt;
366 builder.setRangeConstraint(range, range.argument());
368 if (stmt instanceof FractionDigitsEffectiveStatement) {
369 final Integer digits = ((FractionDigitsEffectiveStatement)stmt).argument();
370 SourceException.throwIf(baseType.getFractionDigits() != digits, ctx,
371 "Cannot override fraction-digits from base type %s to %s", baseType, digits);
375 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
378 private static @NonNull TypeEffectiveStatement<TypeStatement> createEmpty(final Current<QName, ?> ctx,
379 final EmptyTypeDefinition baseType, final TypeStatement declared,
380 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
381 return new TypeEffectiveStatementImpl<>(declared, substatements, RestrictedTypes.newEmptyBuilder(baseType,
382 typeEffectiveQName(ctx)));
385 private @NonNull TypeEffectiveStatement<TypeStatement> createEnum(final Current<?, ?> ctx,
386 final EnumTypeDefinition baseType, final TypeStatement declared,
387 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
388 final EnumerationTypeBuilder builder = RestrictedTypes.newEnumerationBuilder(baseType,
389 ctx.argumentAsTypeQName());
391 for (final EffectiveStatement<?, ?> stmt : substatements) {
392 if (stmt instanceof EnumEffectiveStatement) {
393 builder.addEnum(addRestrictedEnum(ctx, baseType, (EnumEffectiveStatement) stmt));
397 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
400 abstract @NonNull EnumPair addRestrictedEnum(@NonNull EffectiveStmtCtx stmt, @NonNull EnumTypeDefinition base,
401 @NonNull EnumEffectiveStatement enumStmt);
403 private static @NonNull TypeEffectiveStatement<TypeStatement> createIdentityref(final Current<QName, ?> ctx,
404 final IdentityrefTypeDefinition baseType, final TypeStatement declared,
405 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
406 return new TypeEffectiveStatementImpl<>(declared, substatements, RestrictedTypes.newIdentityrefBuilder(baseType,
407 typeEffectiveQName(ctx)));
410 private static @NonNull TypeEffectiveStatement<TypeStatement> createInstanceIdentifier(final Current<QName, ?> ctx,
411 final InstanceIdentifierTypeDefinition baseType, final TypeStatement declared,
412 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
413 final InstanceIdentifierTypeBuilder builder = RestrictedTypes.newInstanceIdentifierBuilder(baseType,
414 typeEffectiveQName(ctx));
416 for (EffectiveStatement<?, ?> stmt : substatements) {
417 if (stmt instanceof RequireInstanceEffectiveStatement) {
418 builder.setRequireInstance(((RequireInstanceEffectiveStatement)stmt).argument());
422 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
425 private static <T extends RangeRestrictedTypeDefinition<T, N>, N extends Number & Comparable<N>>
426 @NonNull TypeEffectiveStatement<TypeStatement> createIntegral(final Current<?, ?> ctx,
427 final TypeStatement declared, final ImmutableList<? extends EffectiveStatement<?, ?>> substatements,
428 final RangeRestrictedTypeBuilder<T, N> builder) {
429 for (EffectiveStatement<?, ?> stmt : substatements) {
430 if (stmt instanceof RangeEffectiveStatement) {
431 final RangeEffectiveStatement rangeStmt = (RangeEffectiveStatement)stmt;
432 builder.setRangeConstraint(rangeStmt, rangeStmt.argument());
437 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
438 } catch (InvalidRangeConstraintException e) {
439 throw new SourceException(ctx, e, "Invalid range constraint: %s", e.getOffendingRanges());
443 private static @NonNull TypeEffectiveStatement<TypeStatement> createLeafref(final Current<QName, ?> ctx,
444 final LeafrefTypeDefinition baseType, final TypeStatement declared,
445 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
446 final RequireInstanceRestrictedTypeBuilder<LeafrefTypeDefinition> builder =
447 RestrictedTypes.newLeafrefBuilder(baseType, AbstractTypeStatementSupport.typeEffectiveQName(ctx));
449 for (final EffectiveStatement<?, ?> stmt : substatements) {
450 if (stmt instanceof RequireInstanceEffectiveStatement) {
451 builder.setRequireInstance(((RequireInstanceEffectiveStatement) stmt).argument());
454 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
457 private static @NonNull TypeEffectiveStatement<TypeStatement> createString(final Current<QName, ?> ctx,
458 final StringTypeDefinition baseType, final TypeStatement declared,
459 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
460 final StringTypeBuilder builder = RestrictedTypes.newStringBuilder(baseType,
461 AbstractTypeStatementSupport.typeEffectiveQName(ctx));
463 for (EffectiveStatement<?, ?> stmt : substatements) {
464 if (stmt instanceof LengthEffectiveStatement) {
465 final LengthEffectiveStatement length = (LengthEffectiveStatement)stmt;
468 builder.setLengthConstraint(length, length.argument());
469 } catch (IllegalStateException e) {
470 throw new SourceException(ctx, e, "Multiple length constraints encountered");
471 } catch (InvalidLengthConstraintException e) {
472 throw new SourceException(ctx, e, "Invalid length constraint %s", length.argument());
475 if (stmt instanceof PatternEffectiveStatement) {
476 builder.addPatternConstraint((PatternEffectiveStatement) stmt);
480 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
483 private static @NonNull TypeEffectiveStatement<TypeStatement> createUnion(final Current<QName, ?> ctx,
484 final UnionTypeDefinition baseType, final TypeStatement declared,
485 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
486 return new TypeEffectiveStatementImpl<>(declared, substatements, RestrictedTypes.newUnionBuilder(baseType,
487 typeEffectiveQName(ctx)));