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 com.google.common.collect.ImmutableSet;
15 import com.google.common.collect.Iterables;
16 import com.google.common.collect.Maps;
17 import java.math.BigDecimal;
18 import java.util.Collection;
19 import org.eclipse.jdt.annotation.NonNull;
20 import org.opendaylight.yangtools.yang.common.Empty;
21 import org.opendaylight.yangtools.yang.common.QName;
22 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
23 import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
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.Uint16TypeDefinition;
54 import org.opendaylight.yangtools.yang.model.api.type.Uint32TypeDefinition;
55 import org.opendaylight.yangtools.yang.model.api.type.Uint64TypeDefinition;
56 import org.opendaylight.yangtools.yang.model.api.type.Uint8TypeDefinition;
57 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
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.spi.TypeNamespace;
70 import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractStringStatementSupport;
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.StmtContextUtils;
83 import org.opendaylight.yangtools.yang.parser.spi.meta.SubstatementValidator;
84 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
86 abstract class AbstractTypeStatementSupport
87 extends AbstractStringStatementSupport<TypeStatement, EffectiveStatement<String, TypeStatement>> {
88 private static final SubstatementValidator SUBSTATEMENT_VALIDATOR = SubstatementValidator.builder(
90 .addOptional(YangStmtMapping.BASE)
91 .addAny(YangStmtMapping.BIT)
92 .addAny(YangStmtMapping.ENUM)
93 .addOptional(YangStmtMapping.FRACTION_DIGITS)
94 .addOptional(YangStmtMapping.LENGTH)
95 .addOptional(YangStmtMapping.PATH)
96 .addAny(YangStmtMapping.PATTERN)
97 .addOptional(YangStmtMapping.RANGE)
98 .addOptional(YangStmtMapping.REQUIRE_INSTANCE)
99 .addAny(YangStmtMapping.TYPE)
102 static final String BINARY = "binary";
103 static final String BITS = "bits";
104 static final String BOOLEAN = "boolean";
105 static final String DECIMAL64 = "decimal64";
106 static final String EMPTY = "empty";
107 static final String ENUMERATION = "enumeration";
108 static final String IDENTITY_REF = "identityref";
109 static final String INSTANCE_IDENTIFIER = "instance-identifier";
110 static final String INT8 = "int8";
111 static final String INT16 = "int16";
112 static final String INT32 = "int32";
113 static final String INT64 = "int64";
114 static final String LEAF_REF = "leafref";
115 static final String STRING = "string";
116 static final String UINT8 = "uint8";
117 static final String UINT16 = "uint16";
118 static final String UINT32 = "uint32";
119 static final String UINT64 = "uint64";
120 static final String UNION = "union";
122 private static final ImmutableMap<String, BuiltinEffectiveStatement> STATIC_BUILT_IN_TYPES =
123 ImmutableMap.<String, BuiltinEffectiveStatement>builder()
124 .put(BINARY, BuiltinEffectiveStatement.BINARY)
125 .put(BOOLEAN, BuiltinEffectiveStatement.BOOLEAN)
126 .put(EMPTY, BuiltinEffectiveStatement.EMPTY)
127 // FIXME: this overlaps with DYNAMIC_BUILT_IN_TYPES. One of these is not needed, but we need to decide
128 // what to do. I think we should gradually use per-statement validators, hence go towards dynamic?
129 .put(INSTANCE_IDENTIFIER, BuiltinEffectiveStatement.INSTANCE_IDENTIFIER)
130 .put(INT8, BuiltinEffectiveStatement.INT8)
131 .put(INT16, BuiltinEffectiveStatement.INT16)
132 .put(INT32, BuiltinEffectiveStatement.INT32)
133 .put(INT64, BuiltinEffectiveStatement.INT64)
134 .put(STRING, BuiltinEffectiveStatement.STRING)
135 .put(UINT8, BuiltinEffectiveStatement.UINT8)
136 .put(UINT16, BuiltinEffectiveStatement.UINT16)
137 .put(UINT32, BuiltinEffectiveStatement.UINT32)
138 .put(UINT64, BuiltinEffectiveStatement.UINT64)
141 private static final ImmutableMap<String, StatementSupport<?, ?, ?>> DYNAMIC_BUILT_IN_TYPES =
142 ImmutableMap.<String, StatementSupport<?, ?, ?>>builder()
143 .put(BITS, new BitsSpecificationSupport())
144 .put(DECIMAL64, new Decimal64SpecificationSupport())
145 .put(ENUMERATION, new EnumSpecificationSupport())
146 .put(IDENTITY_REF, new IdentityRefSpecificationRFC6020Support())
147 .put(INSTANCE_IDENTIFIER, new InstanceIdentifierSpecificationSupport())
148 .put(LEAF_REF, new LeafrefSpecificationRFC6020Support())
149 .put(UNION, new UnionSpecificationSupport())
152 private static final ImmutableMap<String, String> BUILT_IN_TYPES = Maps.uniqueIndex(ImmutableSet.copyOf(
153 Iterables.<String>concat(STATIC_BUILT_IN_TYPES.keySet(), DYNAMIC_BUILT_IN_TYPES.keySet())), key -> key);
155 AbstractTypeStatementSupport() {
156 super(YangStmtMapping.TYPE, StatementPolicy.exactReplica());
160 public final void onFullDefinitionDeclared(
161 final Mutable<String, TypeStatement, EffectiveStatement<String, TypeStatement>> stmt) {
162 super.onFullDefinitionDeclared(stmt);
164 final String argument = stmt.getArgument();
165 final BuiltinEffectiveStatement builtin = STATIC_BUILT_IN_TYPES.get(argument);
166 if (builtin != null) {
167 stmt.addToNs(BaseTypeNamespace.class, Empty.getInstance(), builtin);
171 final QName typeQName = StmtContextUtils.parseNodeIdentifier(stmt, argument);
172 final ModelActionBuilder typeAction = stmt.newInferenceAction(ModelProcessingPhase.EFFECTIVE_MODEL);
173 final Prerequisite<StmtContext<?, ?, ?>> typePrereq = typeAction.requiresCtx(stmt, TypeNamespace.class,
174 typeQName, ModelProcessingPhase.EFFECTIVE_MODEL);
175 typeAction.mutatesEffectiveCtx(stmt.getParentContext());
178 * If the type does not exist, throw an InferenceException.
179 * If the type exists, store a reference to it in BaseTypeNamespace.
181 typeAction.apply(new InferenceAction() {
183 public void apply(final InferenceContext ctx) {
184 // Note: do not attempt to call buildEffective() here
185 stmt.addToNs(BaseTypeNamespace.class, Empty.getInstance(), typePrereq.resolve(ctx));
189 public void prerequisiteFailed(final Collection<? extends Prerequisite<?>> failed) {
190 InferenceException.throwIf(failed.contains(typePrereq), stmt, "Type [%s] was not found.", typeQName);
196 public final String internArgument(final String rawArgument) {
198 return (found = BUILT_IN_TYPES.get(rawArgument)) != null ? found : rawArgument;
202 public boolean hasArgumentSpecificSupports() {
203 return !DYNAMIC_BUILT_IN_TYPES.isEmpty();
207 public StatementSupport<?, ?, ?> getSupportSpecificForArgument(final String argument) {
208 return DYNAMIC_BUILT_IN_TYPES.get(argument);
212 protected final SubstatementValidator getSubstatementValidator() {
213 return SUBSTATEMENT_VALIDATOR;
217 protected final TypeStatement createDeclared(final StmtContext<String, TypeStatement, ?> ctx,
218 final ImmutableList<? extends DeclaredStatement<?>> substatements) {
219 return DeclaredStatements.createType(ctx.getRawArgument(), substatements);
223 protected final TypeStatement createEmptyDeclared(final StmtContext<String, TypeStatement, ?> ctx) {
224 final TypeStatement builtin;
225 return (builtin = BuiltinTypeStatement.lookup(ctx)) != null ? builtin
226 : DeclaredStatements.createType(ctx.getRawArgument());
230 protected EffectiveStatement<String, TypeStatement> createEffective(final Current<String, TypeStatement> stmt,
231 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
232 // First look up the proper base type
233 final TypeEffectiveStatement<TypeStatement> typeStmt = resolveType(stmt);
234 if (substatements.isEmpty()) {
238 // Now instantiate the proper effective statement for that type
239 final TypeDefinition<?> baseType = typeStmt.getTypeDefinition();
240 final TypeStatement declared = stmt.declared();
241 if (baseType instanceof BinaryTypeDefinition) {
242 return createBinary(stmt, (BinaryTypeDefinition) baseType, declared, substatements);
243 } else if (baseType instanceof BitsTypeDefinition) {
244 return createBits(stmt, (BitsTypeDefinition) baseType, declared, substatements);
245 } else if (baseType instanceof BooleanTypeDefinition) {
246 return createBoolean(stmt, (BooleanTypeDefinition) baseType, declared, substatements);
247 } else if (baseType instanceof DecimalTypeDefinition) {
248 return createDecimal(stmt, (DecimalTypeDefinition) baseType, declared, substatements);
249 } else if (baseType instanceof EmptyTypeDefinition) {
250 return createEmpty(stmt, (EmptyTypeDefinition) baseType, declared, substatements);
251 } else if (baseType instanceof EnumTypeDefinition) {
252 return createEnum(stmt, (EnumTypeDefinition) baseType, declared, substatements);
253 } else if (baseType instanceof IdentityrefTypeDefinition) {
254 return createIdentityref(stmt, (IdentityrefTypeDefinition) baseType, declared, substatements);
255 } else if (baseType instanceof InstanceIdentifierTypeDefinition) {
256 return createInstanceIdentifier(stmt, (InstanceIdentifierTypeDefinition) baseType, declared, substatements);
257 } else if (baseType instanceof Int8TypeDefinition) {
258 return createIntegral(stmt, declared, substatements,
259 RestrictedTypes.newInt8Builder((Int8TypeDefinition) baseType, typeEffectiveQName(stmt)));
260 } else if (baseType instanceof Int16TypeDefinition) {
261 return createIntegral(stmt, declared, substatements,
262 RestrictedTypes.newInt16Builder((Int16TypeDefinition) baseType, typeEffectiveQName(stmt)));
263 } else if (baseType instanceof Int32TypeDefinition) {
264 return createIntegral(stmt, declared, substatements,
265 RestrictedTypes.newInt32Builder((Int32TypeDefinition) baseType, typeEffectiveQName(stmt)));
266 } else if (baseType instanceof Int64TypeDefinition) {
267 return createIntegral(stmt, declared, substatements,
268 RestrictedTypes.newInt64Builder((Int64TypeDefinition) baseType, typeEffectiveQName(stmt)));
269 } else if (baseType instanceof LeafrefTypeDefinition) {
270 return createLeafref(stmt, (LeafrefTypeDefinition) baseType, declared, substatements);
271 } else if (baseType instanceof StringTypeDefinition) {
272 return createString(stmt, (StringTypeDefinition) baseType, declared, substatements);
273 } else if (baseType instanceof Uint8TypeDefinition) {
274 return createIntegral(stmt, declared, substatements,
275 RestrictedTypes.newUint8Builder((Uint8TypeDefinition) baseType, typeEffectiveQName(stmt)));
276 } else if (baseType instanceof Uint16TypeDefinition) {
277 return createIntegral(stmt, declared, substatements,
278 RestrictedTypes.newUint16Builder((Uint16TypeDefinition) baseType, typeEffectiveQName(stmt)));
279 } else if (baseType instanceof Uint32TypeDefinition) {
280 return createIntegral(stmt, declared, substatements,
281 RestrictedTypes.newUint32Builder((Uint32TypeDefinition) baseType, typeEffectiveQName(stmt)));
282 } else if (baseType instanceof Uint64TypeDefinition) {
283 return createIntegral(stmt, declared, substatements,
284 RestrictedTypes.newUint64Builder((Uint64TypeDefinition) baseType, typeEffectiveQName(stmt)));
285 } else if (baseType instanceof UnionTypeDefinition) {
286 return createUnion(stmt, (UnionTypeDefinition) baseType, declared, substatements);
288 throw new IllegalStateException("Unhandled base type " + baseType);
292 // FIXME: YANGTOOLS-1208: this needs to happen during onFullDefinitionDeclared() and stored (again) in a namespace
293 static final @NonNull QName typeEffectiveQName(final Current<String, ?> stmt) {
294 // FIXME: YANGTOOLS-1117: this really should be handled through A=AbstractQName, with two values coming out of
295 // parseArgument(): either UnqualifiedQName or QualifiedQName. Each of those can easily be bound to
297 // stmt.getArgument().bindTo(parentNamespace).
298 final String argument = stmt.getArgument();
299 return QName.create(stmt.getEffectiveParent().effectiveNamespace(),
300 // Split out localName event if it is prefixed. This should really be in parseArgument()
301 argument.substring(argument.indexOf(':') + 1)).intern();
305 * Resolve type reference, as pointed to by the context's argument.
307 * @param ctx Statement context
308 * @return Resolved type
309 * @throws SourceException if the target type cannot be found
311 private static @NonNull TypeEffectiveStatement<TypeStatement> resolveType(final Current<String, ?> ctx) {
312 final Object obj = verifyNotNull(ctx.namespaceItem(BaseTypeNamespace.class, Empty.getInstance()));
313 if (obj instanceof BuiltinEffectiveStatement) {
314 return (BuiltinEffectiveStatement) obj;
315 } else if (obj instanceof StmtContext) {
316 return ((TypedefEffectiveStatement) ((StmtContext<?, ?, ?>) obj).buildEffective())
317 .asTypeEffectiveStatement();
319 throw new InferenceException(ctx, "Unexpected base object %s", obj);
323 private static @NonNull TypeEffectiveStatement<TypeStatement> createBinary(final Current<String, ?> ctx,
324 final BinaryTypeDefinition baseType, final TypeStatement declared,
325 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
326 final LengthRestrictedTypeBuilder<BinaryTypeDefinition> builder =
327 RestrictedTypes.newBinaryBuilder(baseType, typeEffectiveQName(ctx));
329 for (EffectiveStatement<?, ?> stmt : substatements) {
330 if (stmt instanceof LengthEffectiveStatement) {
331 final LengthEffectiveStatement length = (LengthEffectiveStatement)stmt;
334 builder.setLengthConstraint(length, length.argument());
335 } catch (IllegalStateException e) {
336 throw new SourceException(ctx, e, "Multiple length constraints encountered");
337 } catch (InvalidLengthConstraintException e) {
338 throw new SourceException(ctx, e, "Invalid length constraint %s", length.argument());
343 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
346 private @NonNull TypeEffectiveStatement<TypeStatement> createBits(final Current<?, ?> ctx,
347 final BitsTypeDefinition baseType, final TypeStatement declared,
348 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
349 final BitsTypeBuilder builder = RestrictedTypes.newBitsBuilder(baseType, ctx.argumentAsTypeQName());
351 for (final EffectiveStatement<?, ?> stmt : substatements) {
352 if (stmt instanceof BitEffectiveStatement) {
353 builder.addBit(addRestrictedBit(ctx, baseType, (BitEffectiveStatement) stmt));
357 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
360 abstract @NonNull Bit addRestrictedBit(@NonNull EffectiveStmtCtx stmt, @NonNull BitsTypeDefinition base,
361 @NonNull BitEffectiveStatement bit);
363 private static @NonNull TypeEffectiveStatement<TypeStatement> createBoolean(final Current<String, ?> ctx,
364 final BooleanTypeDefinition baseType, final TypeStatement declared,
365 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
366 return new TypeEffectiveStatementImpl<>(declared, substatements, RestrictedTypes.newBooleanBuilder(baseType,
367 typeEffectiveQName(ctx)));
370 private static @NonNull TypeEffectiveStatement<TypeStatement> createDecimal(final Current<String, ?> ctx,
371 final DecimalTypeDefinition baseType, final TypeStatement declared,
372 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
373 final RangeRestrictedTypeBuilder<DecimalTypeDefinition, BigDecimal> builder =
374 RestrictedTypes.newDecima64Builder(baseType, typeEffectiveQName(ctx));
376 for (EffectiveStatement<?, ?> stmt : substatements) {
377 if (stmt instanceof RangeEffectiveStatement) {
378 final RangeEffectiveStatement range = (RangeEffectiveStatement) stmt;
379 builder.setRangeConstraint(range, range.argument());
381 if (stmt instanceof FractionDigitsEffectiveStatement) {
382 final Integer digits = ((FractionDigitsEffectiveStatement)stmt).argument();
383 SourceException.throwIf(baseType.getFractionDigits() != digits, ctx,
384 "Cannot override fraction-digits from base type %s to %s", baseType, digits);
388 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
391 private static @NonNull TypeEffectiveStatement<TypeStatement> createEmpty(final Current<String, ?> ctx,
392 final EmptyTypeDefinition baseType, final TypeStatement declared,
393 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
394 return new TypeEffectiveStatementImpl<>(declared, substatements, RestrictedTypes.newEmptyBuilder(baseType,
395 typeEffectiveQName(ctx)));
398 private @NonNull TypeEffectiveStatement<TypeStatement> createEnum(final Current<?, ?> ctx,
399 final EnumTypeDefinition baseType, final TypeStatement declared,
400 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
401 final EnumerationTypeBuilder builder = RestrictedTypes.newEnumerationBuilder(baseType,
402 ctx.argumentAsTypeQName());
404 for (final EffectiveStatement<?, ?> stmt : substatements) {
405 if (stmt instanceof EnumEffectiveStatement) {
406 builder.addEnum(addRestrictedEnum(ctx, baseType, (EnumEffectiveStatement) stmt));
410 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
413 abstract @NonNull EnumPair addRestrictedEnum(@NonNull EffectiveStmtCtx stmt, @NonNull EnumTypeDefinition base,
414 @NonNull EnumEffectiveStatement enumStmt);
416 private static @NonNull TypeEffectiveStatement<TypeStatement> createIdentityref(final Current<String, ?> ctx,
417 final IdentityrefTypeDefinition baseType, final TypeStatement declared,
418 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
419 return new TypeEffectiveStatementImpl<>(declared, substatements, RestrictedTypes.newIdentityrefBuilder(baseType,
420 typeEffectiveQName(ctx)));
423 private static @NonNull TypeEffectiveStatement<TypeStatement> createInstanceIdentifier(final Current<String, ?> ctx,
424 final InstanceIdentifierTypeDefinition baseType, final TypeStatement declared,
425 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
426 final InstanceIdentifierTypeBuilder builder = RestrictedTypes.newInstanceIdentifierBuilder(baseType,
427 typeEffectiveQName(ctx));
429 for (EffectiveStatement<?, ?> stmt : substatements) {
430 if (stmt instanceof RequireInstanceEffectiveStatement) {
431 builder.setRequireInstance(((RequireInstanceEffectiveStatement)stmt).argument());
435 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
438 private static <T extends RangeRestrictedTypeDefinition<T, N>, N extends Number & Comparable<N>>
439 @NonNull TypeEffectiveStatement<TypeStatement> createIntegral(final Current<?, ?> ctx,
440 final TypeStatement declared, final ImmutableList<? extends EffectiveStatement<?, ?>> substatements,
441 final RangeRestrictedTypeBuilder<T, N> builder) {
442 for (EffectiveStatement<?, ?> stmt : substatements) {
443 if (stmt instanceof RangeEffectiveStatement) {
444 final RangeEffectiveStatement rangeStmt = (RangeEffectiveStatement)stmt;
445 builder.setRangeConstraint(rangeStmt, rangeStmt.argument());
450 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
451 } catch (InvalidRangeConstraintException e) {
452 throw new SourceException(ctx, e, "Invalid range constraint: %s", e.getOffendingRanges());
456 private static @NonNull TypeEffectiveStatement<TypeStatement> createLeafref(final Current<String, ?> ctx,
457 final LeafrefTypeDefinition baseType, final TypeStatement declared,
458 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
459 final RequireInstanceRestrictedTypeBuilder<LeafrefTypeDefinition> builder =
460 RestrictedTypes.newLeafrefBuilder(baseType, AbstractTypeStatementSupport.typeEffectiveQName(ctx));
462 for (final EffectiveStatement<?, ?> stmt : substatements) {
463 if (stmt instanceof RequireInstanceEffectiveStatement) {
464 builder.setRequireInstance(((RequireInstanceEffectiveStatement) stmt).argument());
467 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
470 private static @NonNull TypeEffectiveStatement<TypeStatement> createString(final Current<String, ?> ctx,
471 final StringTypeDefinition baseType, final TypeStatement declared,
472 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
473 final StringTypeBuilder builder = RestrictedTypes.newStringBuilder(baseType,
474 AbstractTypeStatementSupport.typeEffectiveQName(ctx));
476 for (EffectiveStatement<?, ?> stmt : substatements) {
477 if (stmt instanceof LengthEffectiveStatement) {
478 final LengthEffectiveStatement length = (LengthEffectiveStatement)stmt;
481 builder.setLengthConstraint(length, length.argument());
482 } catch (IllegalStateException e) {
483 throw new SourceException(ctx, e, "Multiple length constraints encountered");
484 } catch (InvalidLengthConstraintException e) {
485 throw new SourceException(ctx, e, "Invalid length constraint %s", length.argument());
488 if (stmt instanceof PatternEffectiveStatement) {
489 builder.addPatternConstraint((PatternEffectiveStatement) stmt);
493 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
496 private static @NonNull TypeEffectiveStatement<TypeStatement> createUnion(final Current<String, ?> ctx,
497 final UnionTypeDefinition baseType, final TypeStatement declared,
498 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
499 return new TypeEffectiveStatementImpl<>(declared, substatements, RestrictedTypes.newUnionBuilder(baseType,
500 typeEffectiveQName(ctx)));