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.util.type.BitsTypeBuilder;
59 import org.opendaylight.yangtools.yang.model.util.type.EnumerationTypeBuilder;
60 import org.opendaylight.yangtools.yang.model.util.type.InstanceIdentifierTypeBuilder;
61 import org.opendaylight.yangtools.yang.model.util.type.InvalidLengthConstraintException;
62 import org.opendaylight.yangtools.yang.model.util.type.InvalidRangeConstraintException;
63 import org.opendaylight.yangtools.yang.model.util.type.LengthRestrictedTypeBuilder;
64 import org.opendaylight.yangtools.yang.model.util.type.RangeRestrictedTypeBuilder;
65 import org.opendaylight.yangtools.yang.model.util.type.RequireInstanceRestrictedTypeBuilder;
66 import org.opendaylight.yangtools.yang.model.util.type.RestrictedTypes;
67 import org.opendaylight.yangtools.yang.model.util.type.StringTypeBuilder;
68 import org.opendaylight.yangtools.yang.parser.spi.TypeNamespace;
69 import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractStringStatementSupport;
70 import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx;
71 import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.Current;
72 import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
73 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder;
74 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.InferenceAction;
75 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.InferenceContext;
76 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.Prerequisite;
77 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
78 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport;
79 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
80 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
81 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
82 import org.opendaylight.yangtools.yang.parser.spi.meta.SubstatementValidator;
83 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
85 abstract class AbstractTypeStatementSupport
86 extends AbstractStringStatementSupport<TypeStatement, EffectiveStatement<String, TypeStatement>> {
87 private static final SubstatementValidator SUBSTATEMENT_VALIDATOR = SubstatementValidator.builder(
89 .addOptional(YangStmtMapping.BASE)
90 .addAny(YangStmtMapping.BIT)
91 .addAny(YangStmtMapping.ENUM)
92 .addOptional(YangStmtMapping.FRACTION_DIGITS)
93 .addOptional(YangStmtMapping.LENGTH)
94 .addOptional(YangStmtMapping.PATH)
95 .addAny(YangStmtMapping.PATTERN)
96 .addOptional(YangStmtMapping.RANGE)
97 .addOptional(YangStmtMapping.REQUIRE_INSTANCE)
98 .addAny(YangStmtMapping.TYPE)
101 static final String BINARY = "binary";
102 static final String BITS = "bits";
103 static final String BOOLEAN = "boolean";
104 static final String DECIMAL64 = "decimal64";
105 static final String EMPTY = "empty";
106 static final String ENUMERATION = "enumeration";
107 static final String IDENTITY_REF = "identityref";
108 static final String INSTANCE_IDENTIFIER = "instance-identifier";
109 static final String INT8 = "int8";
110 static final String INT16 = "int16";
111 static final String INT32 = "int32";
112 static final String INT64 = "int64";
113 static final String LEAF_REF = "leafref";
114 static final String STRING = "string";
115 static final String UINT8 = "uint8";
116 static final String UINT16 = "uint16";
117 static final String UINT32 = "uint32";
118 static final String UINT64 = "uint64";
119 static final String UNION = "union";
121 private static final ImmutableMap<String, BuiltinEffectiveStatement> STATIC_BUILT_IN_TYPES =
122 ImmutableMap.<String, BuiltinEffectiveStatement>builder()
123 .put(BINARY, BuiltinEffectiveStatement.BINARY)
124 .put(BOOLEAN, BuiltinEffectiveStatement.BOOLEAN)
125 .put(EMPTY, BuiltinEffectiveStatement.EMPTY)
126 // FIXME: this overlaps with DYNAMIC_BUILT_IN_TYPES. One of these is not needed, but we need to decide
127 // what to do. I think we should gradually use per-statement validators, hence go towards dynamic?
128 .put(INSTANCE_IDENTIFIER, BuiltinEffectiveStatement.INSTANCE_IDENTIFIER)
129 .put(INT8, BuiltinEffectiveStatement.INT8)
130 .put(INT16, BuiltinEffectiveStatement.INT16)
131 .put(INT32, BuiltinEffectiveStatement.INT32)
132 .put(INT64, BuiltinEffectiveStatement.INT64)
133 .put(STRING, BuiltinEffectiveStatement.STRING)
134 .put(UINT8, BuiltinEffectiveStatement.UINT8)
135 .put(UINT16, BuiltinEffectiveStatement.UINT16)
136 .put(UINT32, BuiltinEffectiveStatement.UINT32)
137 .put(UINT64, BuiltinEffectiveStatement.UINT64)
140 private static final ImmutableMap<String, StatementSupport<?, ?, ?>> DYNAMIC_BUILT_IN_TYPES =
141 ImmutableMap.<String, StatementSupport<?, ?, ?>>builder()
142 .put(BITS, new BitsSpecificationSupport())
143 .put(DECIMAL64, new Decimal64SpecificationSupport())
144 .put(ENUMERATION, new EnumSpecificationSupport())
145 .put(IDENTITY_REF, new IdentityRefSpecificationRFC6020Support())
146 .put(INSTANCE_IDENTIFIER, new InstanceIdentifierSpecificationSupport())
147 .put(LEAF_REF, new LeafrefSpecificationRFC6020Support())
148 .put(UNION, new UnionSpecificationSupport())
151 private static final ImmutableMap<String, String> BUILT_IN_TYPES = Maps.uniqueIndex(ImmutableSet.copyOf(
152 Iterables.<String>concat(STATIC_BUILT_IN_TYPES.keySet(), DYNAMIC_BUILT_IN_TYPES.keySet())), key -> key);
154 AbstractTypeStatementSupport() {
155 super(YangStmtMapping.TYPE, StatementPolicy.contextIndependent());
159 public final void onFullDefinitionDeclared(
160 final Mutable<String, TypeStatement, EffectiveStatement<String, TypeStatement>> stmt) {
161 super.onFullDefinitionDeclared(stmt);
163 final String argument = stmt.getArgument();
164 final BuiltinEffectiveStatement builtin = STATIC_BUILT_IN_TYPES.get(argument);
165 if (builtin != null) {
166 stmt.addToNs(BaseTypeNamespace.class, Empty.getInstance(), builtin);
170 final QName typeQName = StmtContextUtils.parseNodeIdentifier(stmt, argument);
171 final ModelActionBuilder typeAction = stmt.newInferenceAction(ModelProcessingPhase.EFFECTIVE_MODEL);
172 final Prerequisite<StmtContext<?, ?, ?>> typePrereq = typeAction.requiresCtx(stmt, TypeNamespace.class,
173 typeQName, ModelProcessingPhase.EFFECTIVE_MODEL);
174 typeAction.mutatesEffectiveCtx(stmt.getParentContext());
177 * If the type does not exist, throw an InferenceException.
178 * If the type exists, store a reference to it in BaseTypeNamespace.
180 typeAction.apply(new InferenceAction() {
182 public void apply(final InferenceContext ctx) {
183 // Note: do not attempt to call buildEffective() here
184 stmt.addToNs(BaseTypeNamespace.class, Empty.getInstance(), typePrereq.resolve(ctx));
188 public void prerequisiteFailed(final Collection<? extends Prerequisite<?>> failed) {
189 InferenceException.throwIf(failed.contains(typePrereq), stmt, "Type [%s] was not found.", typeQName);
195 public final String internArgument(final String rawArgument) {
197 return (found = BUILT_IN_TYPES.get(rawArgument)) != null ? found : rawArgument;
201 public boolean hasArgumentSpecificSupports() {
202 return !DYNAMIC_BUILT_IN_TYPES.isEmpty();
206 public StatementSupport<?, ?, ?> getSupportSpecificForArgument(final String argument) {
207 return DYNAMIC_BUILT_IN_TYPES.get(argument);
211 protected final SubstatementValidator getSubstatementValidator() {
212 return SUBSTATEMENT_VALIDATOR;
216 protected final TypeStatement createDeclared(final StmtContext<String, TypeStatement, ?> ctx,
217 final ImmutableList<? extends DeclaredStatement<?>> substatements) {
218 return new RegularTypeStatement(ctx.getRawArgument(), substatements);
222 protected final TypeStatement createEmptyDeclared(final StmtContext<String, TypeStatement, ?> ctx) {
223 final TypeStatement builtin;
224 return (builtin = BuiltinTypeStatement.lookup(ctx)) != null ? builtin
225 : new EmptyTypeStatement(ctx.getRawArgument());
229 protected EffectiveStatement<String, TypeStatement> createEffective(final Current<String, TypeStatement> stmt,
230 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
231 // First look up the proper base type
232 final TypeEffectiveStatement<TypeStatement> typeStmt = resolveType(stmt);
233 if (substatements.isEmpty()) {
237 // Now instantiate the proper effective statement for that type
238 final TypeDefinition<?> baseType = typeStmt.getTypeDefinition();
239 final TypeStatement declared = stmt.declared();
240 if (baseType instanceof BinaryTypeDefinition) {
241 return createBinary(stmt, (BinaryTypeDefinition) baseType, declared, substatements);
242 } else if (baseType instanceof BitsTypeDefinition) {
243 return createBits(stmt, (BitsTypeDefinition) baseType, declared, substatements);
244 } else if (baseType instanceof BooleanTypeDefinition) {
245 return createBoolean(stmt, (BooleanTypeDefinition) baseType, declared, substatements);
246 } else if (baseType instanceof DecimalTypeDefinition) {
247 return createDecimal(stmt, (DecimalTypeDefinition) baseType, declared, substatements);
248 } else if (baseType instanceof EmptyTypeDefinition) {
249 return createEmpty(stmt, (EmptyTypeDefinition) baseType, declared, substatements);
250 } else if (baseType instanceof EnumTypeDefinition) {
251 return createEnum(stmt, (EnumTypeDefinition) baseType, declared, substatements);
252 } else if (baseType instanceof IdentityrefTypeDefinition) {
253 return createIdentityref(stmt, (IdentityrefTypeDefinition) baseType, declared, substatements);
254 } else if (baseType instanceof InstanceIdentifierTypeDefinition) {
255 return createInstanceIdentifier(stmt, (InstanceIdentifierTypeDefinition) baseType, declared, substatements);
256 } else if (baseType instanceof Int8TypeDefinition) {
257 return createIntegral(stmt, declared, substatements,
258 RestrictedTypes.newInt8Builder((Int8TypeDefinition) baseType, typeEffectiveQName(stmt)));
259 } else if (baseType instanceof Int16TypeDefinition) {
260 return createIntegral(stmt, declared, substatements,
261 RestrictedTypes.newInt16Builder((Int16TypeDefinition) baseType, typeEffectiveQName(stmt)));
262 } else if (baseType instanceof Int32TypeDefinition) {
263 return createIntegral(stmt, declared, substatements,
264 RestrictedTypes.newInt32Builder((Int32TypeDefinition) baseType, typeEffectiveQName(stmt)));
265 } else if (baseType instanceof Int64TypeDefinition) {
266 return createIntegral(stmt, declared, substatements,
267 RestrictedTypes.newInt64Builder((Int64TypeDefinition) baseType, typeEffectiveQName(stmt)));
268 } else if (baseType instanceof LeafrefTypeDefinition) {
269 return createLeafref(stmt, (LeafrefTypeDefinition) baseType, declared, substatements);
270 } else if (baseType instanceof StringTypeDefinition) {
271 return createString(stmt, (StringTypeDefinition) baseType, declared, substatements);
272 } else if (baseType instanceof Uint8TypeDefinition) {
273 return createIntegral(stmt, declared, substatements,
274 RestrictedTypes.newUint8Builder((Uint8TypeDefinition) baseType, typeEffectiveQName(stmt)));
275 } else if (baseType instanceof Uint16TypeDefinition) {
276 return createIntegral(stmt, declared, substatements,
277 RestrictedTypes.newUint16Builder((Uint16TypeDefinition) baseType, typeEffectiveQName(stmt)));
278 } else if (baseType instanceof Uint32TypeDefinition) {
279 return createIntegral(stmt, declared, substatements,
280 RestrictedTypes.newUint32Builder((Uint32TypeDefinition) baseType, typeEffectiveQName(stmt)));
281 } else if (baseType instanceof Uint64TypeDefinition) {
282 return createIntegral(stmt, declared, substatements,
283 RestrictedTypes.newUint64Builder((Uint64TypeDefinition) baseType, typeEffectiveQName(stmt)));
284 } else if (baseType instanceof UnionTypeDefinition) {
285 return createUnion(stmt, (UnionTypeDefinition) baseType, declared, substatements);
287 throw new IllegalStateException("Unhandled base type " + baseType);
291 // FIXME: YANGTOOLS-1208: this needs to happen during onFullDefinitionDeclared() and stored (again) in a namespace
292 static final @NonNull QName typeEffectiveQName(final Current<String, ?> stmt) {
293 // FIXME: YANGTOOLS-1117: this really should be handled through A=AbstractQName, with two values coming out of
294 // parseArgument(): either UnqualifiedQName or QualifiedQName. Each of those can easily be bound to
296 // stmt.getArgument().bindTo(parentNamespace).
297 final String argument = stmt.getArgument();
298 return QName.create(stmt.getEffectiveParent().effectiveNamespace(),
299 // Split out localName event if it is prefixed. This should really be in parseArgument()
300 argument.substring(argument.indexOf(':') + 1)).intern();
304 * Resolve type reference, as pointed to by the context's argument.
306 * @param ctx Statement context
307 * @return Resolved type
308 * @throws SourceException if the target type cannot be found
310 private static @NonNull TypeEffectiveStatement<TypeStatement> resolveType(final Current<String, ?> ctx) {
311 final Object obj = verifyNotNull(ctx.namespaceItem(BaseTypeNamespace.class, Empty.getInstance()));
312 if (obj instanceof BuiltinEffectiveStatement) {
313 return (BuiltinEffectiveStatement) obj;
314 } else if (obj instanceof StmtContext) {
315 return ((TypedefEffectiveStatement) ((StmtContext<?, ?, ?>) obj).buildEffective())
316 .asTypeEffectiveStatement();
318 throw new InferenceException(ctx, "Unexpected base object %s", obj);
322 private static @NonNull TypeEffectiveStatement<TypeStatement> createBinary(final Current<String, ?> ctx,
323 final BinaryTypeDefinition baseType, final TypeStatement declared,
324 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
325 final LengthRestrictedTypeBuilder<BinaryTypeDefinition> builder =
326 RestrictedTypes.newBinaryBuilder(baseType, typeEffectiveQName(ctx));
328 for (EffectiveStatement<?, ?> stmt : substatements) {
329 if (stmt instanceof LengthEffectiveStatement) {
330 final LengthEffectiveStatement length = (LengthEffectiveStatement)stmt;
333 builder.setLengthConstraint(length, length.argument());
334 } catch (IllegalStateException e) {
335 throw new SourceException(ctx, e, "Multiple length constraints encountered");
336 } catch (InvalidLengthConstraintException e) {
337 throw new SourceException(ctx, e, "Invalid length constraint %s", length.argument());
342 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
345 private @NonNull TypeEffectiveStatement<TypeStatement> createBits(final Current<?, ?> ctx,
346 final BitsTypeDefinition baseType, final TypeStatement declared,
347 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
348 final BitsTypeBuilder builder = RestrictedTypes.newBitsBuilder(baseType, ctx.argumentAsTypeQName());
350 for (final EffectiveStatement<?, ?> stmt : substatements) {
351 if (stmt instanceof BitEffectiveStatement) {
352 builder.addBit(addRestrictedBit(ctx, baseType, (BitEffectiveStatement) stmt));
356 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
359 abstract @NonNull Bit addRestrictedBit(@NonNull EffectiveStmtCtx stmt, @NonNull BitsTypeDefinition base,
360 @NonNull BitEffectiveStatement bit);
362 private static @NonNull TypeEffectiveStatement<TypeStatement> createBoolean(final Current<String, ?> ctx,
363 final BooleanTypeDefinition baseType, final TypeStatement declared,
364 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
365 return new TypeEffectiveStatementImpl<>(declared, substatements, RestrictedTypes.newBooleanBuilder(baseType,
366 typeEffectiveQName(ctx)));
369 private static @NonNull TypeEffectiveStatement<TypeStatement> createDecimal(final Current<String, ?> ctx,
370 final DecimalTypeDefinition baseType, final TypeStatement declared,
371 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
372 final RangeRestrictedTypeBuilder<DecimalTypeDefinition, BigDecimal> builder =
373 RestrictedTypes.newDecima64Builder(baseType, typeEffectiveQName(ctx));
375 for (EffectiveStatement<?, ?> stmt : substatements) {
376 if (stmt instanceof RangeEffectiveStatement) {
377 final RangeEffectiveStatement range = (RangeEffectiveStatement) stmt;
378 builder.setRangeConstraint(range, range.argument());
380 if (stmt instanceof FractionDigitsEffectiveStatement) {
381 final Integer digits = ((FractionDigitsEffectiveStatement)stmt).argument();
382 SourceException.throwIf(baseType.getFractionDigits() != digits, ctx,
383 "Cannot override fraction-digits from base type %s to %s", baseType, digits);
387 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
390 private static @NonNull TypeEffectiveStatement<TypeStatement> createEmpty(final Current<String, ?> ctx,
391 final EmptyTypeDefinition baseType, final TypeStatement declared,
392 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
393 return new TypeEffectiveStatementImpl<>(declared, substatements, RestrictedTypes.newEmptyBuilder(baseType,
394 typeEffectiveQName(ctx)));
397 private @NonNull TypeEffectiveStatement<TypeStatement> createEnum(final Current<?, ?> ctx,
398 final EnumTypeDefinition baseType, final TypeStatement declared,
399 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
400 final EnumerationTypeBuilder builder = RestrictedTypes.newEnumerationBuilder(baseType,
401 ctx.argumentAsTypeQName());
403 for (final EffectiveStatement<?, ?> stmt : substatements) {
404 if (stmt instanceof EnumEffectiveStatement) {
405 builder.addEnum(addRestrictedEnum(ctx, baseType, (EnumEffectiveStatement) stmt));
409 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
412 abstract @NonNull EnumPair addRestrictedEnum(@NonNull EffectiveStmtCtx stmt, @NonNull EnumTypeDefinition base,
413 @NonNull EnumEffectiveStatement enumStmt);
415 private static @NonNull TypeEffectiveStatement<TypeStatement> createIdentityref(final Current<String, ?> ctx,
416 final IdentityrefTypeDefinition baseType, final TypeStatement declared,
417 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
418 return new TypeEffectiveStatementImpl<>(declared, substatements, RestrictedTypes.newIdentityrefBuilder(baseType,
419 typeEffectiveQName(ctx)));
422 private static @NonNull TypeEffectiveStatement<TypeStatement> createInstanceIdentifier(final Current<String, ?> ctx,
423 final InstanceIdentifierTypeDefinition baseType, final TypeStatement declared,
424 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
425 final InstanceIdentifierTypeBuilder builder = RestrictedTypes.newInstanceIdentifierBuilder(baseType,
426 typeEffectiveQName(ctx));
428 for (EffectiveStatement<?, ?> stmt : substatements) {
429 if (stmt instanceof RequireInstanceEffectiveStatement) {
430 builder.setRequireInstance(((RequireInstanceEffectiveStatement)stmt).argument());
434 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
437 private static <T extends RangeRestrictedTypeDefinition<T, N>, N extends Number & Comparable<N>>
438 @NonNull TypeEffectiveStatement<TypeStatement> createIntegral(final Current<?, ?> ctx,
439 final TypeStatement declared, final ImmutableList<? extends EffectiveStatement<?, ?>> substatements,
440 final RangeRestrictedTypeBuilder<T, N> builder) {
441 for (EffectiveStatement<?, ?> stmt : substatements) {
442 if (stmt instanceof RangeEffectiveStatement) {
443 final RangeEffectiveStatement rangeStmt = (RangeEffectiveStatement)stmt;
444 builder.setRangeConstraint(rangeStmt, rangeStmt.argument());
449 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
450 } catch (InvalidRangeConstraintException e) {
451 throw new SourceException(ctx, e, "Invalid range constraint: %s", e.getOffendingRanges());
455 private static @NonNull TypeEffectiveStatement<TypeStatement> createLeafref(final Current<String, ?> ctx,
456 final LeafrefTypeDefinition baseType, final TypeStatement declared,
457 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
458 final RequireInstanceRestrictedTypeBuilder<LeafrefTypeDefinition> builder =
459 RestrictedTypes.newLeafrefBuilder(baseType, AbstractTypeStatementSupport.typeEffectiveQName(ctx));
461 for (final EffectiveStatement<?, ?> stmt : substatements) {
462 if (stmt instanceof RequireInstanceEffectiveStatement) {
463 builder.setRequireInstance(((RequireInstanceEffectiveStatement) stmt).argument());
466 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
469 private static @NonNull TypeEffectiveStatement<TypeStatement> createString(final Current<String, ?> ctx,
470 final StringTypeDefinition baseType, final TypeStatement declared,
471 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
472 final StringTypeBuilder builder = RestrictedTypes.newStringBuilder(baseType,
473 AbstractTypeStatementSupport.typeEffectiveQName(ctx));
475 for (EffectiveStatement<?, ?> stmt : substatements) {
476 if (stmt instanceof LengthEffectiveStatement) {
477 final LengthEffectiveStatement length = (LengthEffectiveStatement)stmt;
480 builder.setLengthConstraint(length, length.argument());
481 } catch (IllegalStateException e) {
482 throw new SourceException(ctx, e, "Multiple length constraints encountered");
483 } catch (InvalidLengthConstraintException e) {
484 throw new SourceException(ctx, e, "Invalid length constraint %s", length.argument());
487 if (stmt instanceof PatternEffectiveStatement) {
488 builder.addPatternConstraint((PatternEffectiveStatement) stmt);
492 return new TypeEffectiveStatementImpl<>(declared, substatements, builder);
495 private static @NonNull TypeEffectiveStatement<TypeStatement> createUnion(final Current<String, ?> ctx,
496 final UnionTypeDefinition baseType, final TypeStatement declared,
497 final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
498 return new TypeEffectiveStatementImpl<>(declared, substatements, RestrictedTypes.newUnionBuilder(baseType,
499 typeEffectiveQName(ctx)));