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.Status;
19 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
20 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
21 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
22 import org.opendaylight.yangtools.yang.model.api.stmt.TypeStatement;
23 import org.opendaylight.yangtools.yang.model.api.stmt.TypedefStatement;
24 import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition;
25 import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition;
26 import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
27 import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
28 import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
29 import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition;
30 import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition;
31 import org.opendaylight.yangtools.yang.model.util.ExtendedType;
32 import org.opendaylight.yangtools.yang.model.util.ExtendedType.Builder;
33 import org.opendaylight.yangtools.yang.parser.spi.TypeNamespace;
34 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
35 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.TypeUtils;
36 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.Utils;
37 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type.LengthEffectiveStatementImpl;
38 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type.PatternEffectiveStatementImpl;
39 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type.RangeEffectiveStatementImpl;
40 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type.TypeDefinitionEffectiveBuilder;
41 import org.opendaylight.yangtools.yang.parser.util.TypeConstraints;
43 public class ExtendedTypeEffectiveStatementImpl extends EffectiveStatementBase<String, TypeStatement> implements
44 TypeDefinition<TypeDefinition<?>>, TypeDefinitionEffectiveBuilder {
46 private static final Splitter COLON_SPLITTER = Splitter.on(':').trimResults();
48 private final QName qName;
49 private final SchemaPath path;
51 private final TypeDefinition<?> baseType;
53 private final String defaultValue = null;
54 private final String units = null;
56 private final String description = null;
57 private final String reference = null;
59 private final Status status = null;
61 private final List<RangeConstraint> ranges;
62 private final List<LengthConstraint> lengths;
63 private final List<PatternConstraint> patterns;
64 private final Integer fractionDigits;
66 private ExtendedType extendedType = null;
67 private final boolean isExtended;
69 public ExtendedTypeEffectiveStatementImpl(
70 final StmtContext<String, TypeStatement, EffectiveStatement<String, TypeStatement>> ctx, final boolean isExtended) {
73 this.isExtended = isExtended;
74 qName = initQName(ctx, isExtended);
76 final StmtContext<?, TypedefStatement, EffectiveStatement<QName, TypedefStatement>> typeStmt = ctx
77 .getFromNamespace(TypeNamespace.class, qName);
78 if (typeStmt == null) {
79 path = Utils.getSchemaPath(ctx);
81 path = Utils.getSchemaPath(ctx.getFromNamespace(TypeNamespace.class, qName));
84 ranges = initRanges();
85 lengths = initLengths();
86 patterns = initPatterns();
87 fractionDigits = initFractionDigits();
89 baseType = parseBaseTypeFromCtx(ctx);
90 validateTypeConstraints(ctx);
93 private static QName initQName(final StmtContext<String, TypeStatement, EffectiveStatement<String, TypeStatement>> ctx,
94 final boolean isExtended) {
99 final Splitter colonSplitter = Splitter.on(":").trimResults();
100 final List<String> nameTokens = colonSplitter.splitToList(ctx.getStatementArgument());
102 switch (nameTokens.size()) {
104 qName = QName.create(Utils.getRootModuleQName(ctx), nameTokens.get(0));
107 qName = QName.create(Utils.getRootModuleQName(ctx), nameTokens.get(1));
110 throw new IllegalArgumentException(String.format(
111 "Bad colon separated parts number (%d) of QName '%s'.", nameTokens.size(),
112 ctx.getStatementArgument()));
115 qName = Utils.qNameFromArgument(ctx, ctx.getStatementArgument());
120 private static TypeDefinition<?> parseBaseTypeFromCtx(
121 final StmtContext<String, TypeStatement, EffectiveStatement<String, TypeStatement>> ctx) {
123 TypeDefinition<?> baseType;
125 final QName baseTypeQName = Utils.qNameFromArgument(ctx, ctx.getStatementArgument());
126 if (TypeUtils.isYangPrimitiveTypeString(baseTypeQName.getLocalName())) {
127 baseType = TypeUtils.getYangPrimitiveTypeFromString(baseTypeQName.getLocalName());
129 StmtContext<?, TypedefStatement, EffectiveStatement<QName, TypedefStatement>> baseTypeCtx = ctx
130 .getParentContext().getFromNamespace(TypeNamespace.class, baseTypeQName);
132 if (baseTypeCtx == null) {
133 throw new IllegalStateException(String.format("Type '%s' was not found in %s.", baseTypeQName,
134 ctx.getStatementSourceReference()));
137 baseType = (TypeDefEffectiveStatementImpl) baseTypeCtx.buildEffective();
143 private void validateTypeConstraints(
144 final StmtContext<String, TypeStatement, EffectiveStatement<String, TypeStatement>> ctx) {
146 final List<String> sourceParts = COLON_SPLITTER.splitToList(ctx.getStatementSourceReference().toString());
147 TypeConstraints typeConstraints = new TypeConstraints(sourceParts.get(0), Integer.parseInt(sourceParts.get(1)));
149 typeConstraints.addRanges(ranges);
150 typeConstraints.addLengths(lengths);
151 typeConstraints.addPatterns(patterns);
152 typeConstraints.addFractionDigits(fractionDigits);
154 typeConstraints = addConstraintsFromBaseType(typeConstraints, baseType);
155 typeConstraints.validateConstraints();
158 private static TypeConstraints addConstraintsFromBaseType(final TypeConstraints typeConstraints,
159 final TypeDefinition<?> baseType) {
161 final String baseTypeName = baseType.getQName().getLocalName();
163 if (baseType instanceof IntegerTypeDefinition) {
164 final IntegerTypeDefinition intType = (IntegerTypeDefinition) TypeUtils
165 .getYangPrimitiveTypeFromString(baseTypeName);
166 typeConstraints.addRanges(intType.getRangeConstraints());
167 } else if (baseType instanceof UnsignedIntegerTypeDefinition) {
168 final UnsignedIntegerTypeDefinition uintType = (UnsignedIntegerTypeDefinition) TypeUtils
169 .getYangPrimitiveTypeFromString(baseTypeName);
170 typeConstraints.addRanges(uintType.getRangeConstraints());
171 } else if (baseType instanceof StringTypeDefinition) {
172 final StringTypeDefinition stringType = (StringTypeDefinition) TypeUtils
173 .getYangPrimitiveTypeFromString(baseTypeName);
174 typeConstraints.addLengths(stringType.getLengthConstraints());
175 typeConstraints.addPatterns(stringType.getPatternConstraints());
176 } else if (baseType instanceof BinaryTypeDefinition) {
177 final BinaryTypeDefinition binaryType = (BinaryTypeDefinition) TypeUtils
178 .getYangPrimitiveTypeFromString(baseTypeName);
179 typeConstraints.addLengths(binaryType.getLengthConstraints());
180 } else if (baseType instanceof TypeDefEffectiveStatementImpl) {
181 typeConstraints.addRanges(((TypeDefEffectiveStatementImpl) baseType).getRangeConstraints());
182 typeConstraints.addLengths(((TypeDefEffectiveStatementImpl) baseType).getLengthConstraints());
183 typeConstraints.addPatterns(((TypeDefEffectiveStatementImpl) baseType).getPatternConstraints());
184 typeConstraints.addFractionDigits(((TypeDefEffectiveStatementImpl) baseType).getFractionDigits());
186 // else if (baseType instanceof DecimalTypeDefinition) {
187 // final DecimalTypeDefinition decimalType = (DecimalTypeDefinition) TypeUtils
188 // .getYangBaseTypeFromString(baseTypeName);
189 // typeConstraints.addRanges(decimalType.getRangeConstraints());
190 // typeConstraints.addFractionDigits(decimalType.getFractionDigits());
192 // else if (baseType instanceof ExtendedTypeEffectiveStatementImpl) {
193 // typeConstraints.addRanges(((ExtendedTypeEffectiveStatementImpl) baseType).getRangeConstraints());
194 // typeConstraints.addLengths(((ExtendedTypeEffectiveStatementImpl) baseType).getLengthConstraints());
195 // typeConstraints.addPatterns(((ExtendedTypeEffectiveStatementImpl) baseType).getPatternConstraints());
196 // typeConstraints.addFractionDigits(((ExtendedTypeEffectiveStatementImpl) baseType).getFractionDigits());
199 return typeConstraints;
202 protected Integer initFractionDigits() {
203 final FractionDigitsEffectiveStatementImpl fractionDigitsEffStmt = firstEffective(FractionDigitsEffectiveStatementImpl.class);
204 return fractionDigitsEffStmt != null ? fractionDigitsEffStmt.argument() : null;
207 protected List<RangeConstraint> initRanges() {
208 final RangeEffectiveStatementImpl rangeConstraints = firstEffective(RangeEffectiveStatementImpl.class);
209 return rangeConstraints != null ? rangeConstraints.argument() : Collections.<RangeConstraint> emptyList();
212 protected List<LengthConstraint> initLengths() {
213 final LengthEffectiveStatementImpl lengthConstraints = firstEffective(LengthEffectiveStatementImpl.class);
214 return lengthConstraints != null ? lengthConstraints.argument() : Collections.<LengthConstraint> emptyList();
217 protected List<PatternConstraint> initPatterns() {
218 final List<PatternConstraint> patternConstraints = new ArrayList<>();
220 for (final EffectiveStatement<?, ?> effectiveStatement : effectiveSubstatements()) {
221 if (effectiveStatement instanceof PatternEffectiveStatementImpl) {
222 final PatternConstraint pattern = ((PatternEffectiveStatementImpl) effectiveStatement).argument();
224 if (pattern != null) {
225 patternConstraints.add(pattern);
230 return !patternConstraints.isEmpty() ? ImmutableList.copyOf(patternConstraints) : Collections
231 .<PatternConstraint> emptyList();
235 public TypeDefinition<?> getBaseType() {
240 public String getUnits() {
245 public Object getDefaultValue() {
250 public QName getQName() {
255 public SchemaPath getPath() {
260 public List<UnknownSchemaNode> getUnknownSchemaNodes() {
261 return Collections.emptyList();
265 public String getDescription() {
270 public String getReference() {
275 public Status getStatus() {
279 public List<RangeConstraint> getRangeConstraints() {
283 public List<LengthConstraint> getLengthConstraints() {
287 public List<PatternConstraint> getPatternConstraints() {
291 public Integer getFractionDigits() {
292 return fractionDigits;
296 public ExtendedType buildType() {
298 if (extendedType != null) {
302 if (!isExtended && baseType instanceof TypeDefEffectiveStatementImpl) {
303 TypeDefEffectiveStatementImpl originalTypeDef = (TypeDefEffectiveStatementImpl) baseType;
304 return originalTypeDef.buildType();
307 Builder extendedTypeBuilder;
308 if (baseType instanceof TypeDefEffectiveStatementImpl) {
309 TypeDefEffectiveStatementImpl typeDefBaseType = (TypeDefEffectiveStatementImpl) baseType;
310 extendedTypeBuilder = ExtendedType.builder(qName, typeDefBaseType.buildType(),
311 Optional.fromNullable(description), Optional.fromNullable(reference), path);
313 extendedTypeBuilder = ExtendedType.builder(qName, baseType, Optional.fromNullable(description),
314 Optional.fromNullable(reference), path);
317 extendedTypeBuilder.fractionDigits(fractionDigits);
318 extendedTypeBuilder.ranges(ranges);
319 extendedTypeBuilder.lengths(lengths);
320 extendedTypeBuilder.patterns(patterns);
322 extendedType = extendedTypeBuilder.build();