2 * Copyright (c) 2015 Cisco Systems, Inc. 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.stmt.rfc6020.effective;
10 import com.google.common.base.Optional;
11 import com.google.common.base.Splitter;
12 import com.google.common.collect.ImmutableList;
13 import java.util.ArrayList;
14 import java.util.Collections;
15 import java.util.List;
16 import org.opendaylight.yangtools.yang.common.QName;
17 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
18 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
19 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
20 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
21 import org.opendaylight.yangtools.yang.model.api.stmt.TypeEffectiveStatement;
22 import org.opendaylight.yangtools.yang.model.api.stmt.TypeStatement;
23 import org.opendaylight.yangtools.yang.model.api.stmt.TypedefEffectiveStatement;
24 import org.opendaylight.yangtools.yang.model.api.stmt.TypedefStatement;
25 import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition;
26 import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition;
27 import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
28 import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
29 import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
30 import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition;
31 import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition;
32 import org.opendaylight.yangtools.yang.model.util.ExtendedType;
33 import org.opendaylight.yangtools.yang.model.util.ExtendedType.Builder;
34 import org.opendaylight.yangtools.yang.parser.spi.TypeNamespace;
35 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
36 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.TypeUtils;
37 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.Utils;
38 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type.LengthEffectiveStatementImpl;
39 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type.PatternEffectiveStatementImpl;
40 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type.RangeEffectiveStatementImpl;
41 import org.opendaylight.yangtools.yang.parser.util.TypeConstraints;
43 public final class ExtendedTypeEffectiveStatementImpl extends AbstractEffectiveDocumentedNode<String, TypeStatement>
45 TypeDefinition<TypeDefinition<?>>, TypeEffectiveStatement<TypeStatement> {
47 private static final Splitter COLON_SPLITTER = Splitter.on(':').trimResults();
49 private final QName qName;
50 private final SchemaPath path;
51 private final TypeDefinition<?> baseType;
52 private final String defaultValue;
53 private final String units;
54 private final List<RangeConstraint> ranges;
55 private final List<LengthConstraint> lengths;
56 private final List<PatternConstraint> patterns;
57 private final Integer fractionDigits;
59 private ExtendedType extendedType = null;
60 private final boolean isExtended;
62 public ExtendedTypeEffectiveStatementImpl(
63 final StmtContext<String, TypeStatement, EffectiveStatement<String, TypeStatement>> ctx, final boolean isExtended) {
66 this.isExtended = isExtended;
67 qName = initQName(ctx, isExtended);
69 final StmtContext<?, TypedefStatement, TypedefEffectiveStatement> typeStmt =
70 ctx.getFromNamespace(TypeNamespace.class, qName);
71 if (typeStmt == null) {
72 path = Utils.getSchemaPath(ctx);
74 path = Utils.getSchemaPath(ctx.getFromNamespace(TypeNamespace.class, qName));
77 UnitsEffectiveStatementImpl unitsStmt = firstEffective(UnitsEffectiveStatementImpl.class);
78 this.units = (unitsStmt == null) ? null : unitsStmt.argument();
79 DefaultEffectiveStatementImpl defaultStmt = firstEffective(DefaultEffectiveStatementImpl.class);
80 this.defaultValue = (defaultStmt == null) ? null : defaultStmt.argument();
82 ranges = initRanges();
83 lengths = initLengths();
84 patterns = initPatterns();
85 fractionDigits = initFractionDigits();
87 baseType = parseBaseTypeFromCtx(ctx);
88 validateTypeConstraints(ctx);
91 private static QName initQName(final StmtContext<String, TypeStatement, EffectiveStatement<String, TypeStatement>> ctx,
92 final boolean isExtended) {
97 final List<String> nameTokens = COLON_SPLITTER.splitToList(ctx.getStatementArgument());
99 switch (nameTokens.size()) {
101 qName = QName.create(Utils.getRootModuleQName(ctx), nameTokens.get(0));
104 qName = QName.create(Utils.getRootModuleQName(ctx), nameTokens.get(1));
107 throw new IllegalArgumentException(String.format(
108 "Bad colon separated parts number (%d) of QName '%s'.", nameTokens.size(),
109 ctx.getStatementArgument()));
112 qName = Utils.qNameFromArgument(ctx, ctx.getStatementArgument());
117 private static TypeDefinition<?> parseBaseTypeFromCtx(
118 final StmtContext<String, TypeStatement, EffectiveStatement<String, TypeStatement>> ctx) {
120 TypeDefinition<?> baseType;
122 final QName baseTypeQName = Utils.qNameFromArgument(ctx, ctx.getStatementArgument());
123 if (TypeUtils.isYangPrimitiveTypeString(baseTypeQName.getLocalName())) {
124 baseType = TypeUtils.getYangPrimitiveTypeFromString(baseTypeQName.getLocalName());
126 StmtContext<?, TypedefStatement, TypedefEffectiveStatement> baseTypeCtx = ctx
127 .getParentContext().getFromNamespace(TypeNamespace.class, baseTypeQName);
129 if (baseTypeCtx == null) {
130 throw new IllegalStateException(String.format("Type '%s' was not found in %s.", baseTypeQName,
131 ctx.getStatementSourceReference()));
134 baseType = (TypeDefEffectiveStatementImpl) baseTypeCtx.buildEffective();
140 private void validateTypeConstraints(
141 final StmtContext<String, TypeStatement, EffectiveStatement<String, TypeStatement>> ctx) {
143 final List<String> sourceParts = COLON_SPLITTER.splitToList(ctx.getStatementSourceReference().toString());
144 TypeConstraints typeConstraints = new TypeConstraints(sourceParts.get(0), Integer.parseInt(sourceParts.get(1)));
146 typeConstraints.addRanges(ranges);
147 typeConstraints.addLengths(lengths);
148 typeConstraints.addPatterns(patterns);
149 typeConstraints.addFractionDigits(fractionDigits);
151 typeConstraints = addConstraintsFromBaseType(typeConstraints, baseType);
152 typeConstraints.validateConstraints();
155 private static TypeConstraints addConstraintsFromBaseType(final TypeConstraints typeConstraints,
156 final TypeDefinition<?> baseType) {
158 final String baseTypeName = baseType.getQName().getLocalName();
160 if (baseType instanceof IntegerTypeDefinition) {
161 final IntegerTypeDefinition intType = (IntegerTypeDefinition) TypeUtils
162 .getYangPrimitiveTypeFromString(baseTypeName);
163 typeConstraints.addRanges(intType.getRangeConstraints());
164 } else if (baseType instanceof UnsignedIntegerTypeDefinition) {
165 final UnsignedIntegerTypeDefinition uintType = (UnsignedIntegerTypeDefinition) TypeUtils
166 .getYangPrimitiveTypeFromString(baseTypeName);
167 typeConstraints.addRanges(uintType.getRangeConstraints());
168 } else if (baseType instanceof StringTypeDefinition) {
169 final StringTypeDefinition stringType = (StringTypeDefinition) TypeUtils
170 .getYangPrimitiveTypeFromString(baseTypeName);
171 typeConstraints.addLengths(stringType.getLengthConstraints());
172 typeConstraints.addPatterns(stringType.getPatternConstraints());
173 } else if (baseType instanceof BinaryTypeDefinition) {
174 final BinaryTypeDefinition binaryType = (BinaryTypeDefinition) TypeUtils
175 .getYangPrimitiveTypeFromString(baseTypeName);
176 typeConstraints.addLengths(binaryType.getLengthConstraints());
177 } else if (baseType instanceof TypeDefEffectiveStatementImpl) {
178 typeConstraints.addRanges(((TypeDefEffectiveStatementImpl) baseType).getRangeConstraints());
179 typeConstraints.addLengths(((TypeDefEffectiveStatementImpl) baseType).getLengthConstraints());
180 typeConstraints.addPatterns(((TypeDefEffectiveStatementImpl) baseType).getPatternConstraints());
181 typeConstraints.addFractionDigits(((TypeDefEffectiveStatementImpl) baseType).getFractionDigits());
184 return typeConstraints;
187 protected final Integer initFractionDigits() {
188 final FractionDigitsEffectiveStatementImpl fractionDigitsEffStmt = firstEffective(FractionDigitsEffectiveStatementImpl.class);
189 return fractionDigitsEffStmt != null ? fractionDigitsEffStmt.argument() : null;
192 protected final List<RangeConstraint> initRanges() {
193 final RangeEffectiveStatementImpl rangeConstraints = firstEffective(RangeEffectiveStatementImpl.class);
194 return rangeConstraints != null ? rangeConstraints.argument() : Collections.<RangeConstraint> emptyList();
197 protected final List<LengthConstraint> initLengths() {
198 final LengthEffectiveStatementImpl lengthConstraints = firstEffective(LengthEffectiveStatementImpl.class);
199 return lengthConstraints != null ? lengthConstraints.argument() : Collections.<LengthConstraint> emptyList();
202 protected final List<PatternConstraint> initPatterns() {
203 final List<PatternConstraint> patternConstraints = new ArrayList<>();
205 for (final EffectiveStatement<?, ?> effectiveStatement : effectiveSubstatements()) {
206 if (effectiveStatement instanceof PatternEffectiveStatementImpl) {
207 final PatternConstraint pattern = ((PatternEffectiveStatementImpl) effectiveStatement).argument();
209 if (pattern != null) {
210 patternConstraints.add(pattern);
215 return !patternConstraints.isEmpty() ? ImmutableList.copyOf(patternConstraints) : Collections
216 .<PatternConstraint> emptyList();
220 public TypeDefinition<?> getBaseType() {
225 public String getUnits() {
230 public Object getDefaultValue() {
235 public QName getQName() {
240 public SchemaPath getPath() {
245 public List<UnknownSchemaNode> getUnknownSchemaNodes() {
246 return Collections.emptyList();
249 public List<RangeConstraint> getRangeConstraints() {
253 public List<LengthConstraint> getLengthConstraints() {
257 public List<PatternConstraint> getPatternConstraints() {
261 public Integer getFractionDigits() {
262 return fractionDigits;
266 public TypeDefinition<?> getTypeDefinition() {
267 if (extendedType != null) {
271 if (!isExtended && baseType instanceof TypeDefEffectiveStatementImpl) {
272 TypeDefEffectiveStatementImpl originalTypeDef = (TypeDefEffectiveStatementImpl) baseType;
273 return originalTypeDef.getTypeDefinition();
276 Builder extendedTypeBuilder;
277 if (baseType instanceof TypeDefEffectiveStatementImpl) {
278 TypeDefEffectiveStatementImpl typeDefBaseType = (TypeDefEffectiveStatementImpl) baseType;
279 extendedTypeBuilder = ExtendedType.builder(qName, typeDefBaseType.getTypeDefinition(),
280 Optional.fromNullable(getDescription()), Optional.fromNullable(getReference()), path);
282 extendedTypeBuilder = ExtendedType.builder(qName, baseType, Optional.fromNullable(getDescription()),
283 Optional.fromNullable(getReference()), path);
286 extendedTypeBuilder.fractionDigits(fractionDigits);
287 extendedTypeBuilder.ranges(ranges);
288 extendedTypeBuilder.lengths(lengths);
289 extendedTypeBuilder.patterns(patterns);
291 extendedType = extendedTypeBuilder.build();