Bug 3670 (part 1/5): Use of new statement parser in yang-maven-plugin
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / stmt / rfc6020 / effective / TypeDefEffectiveStatementImpl.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective;
9
10 import org.opendaylight.yangtools.yang.model.api.stmt.TypeStatement;
11
12 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
13 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type.Decimal64SpecificationEffectiveStatementImpl;
14 import java.util.ArrayList;
15 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type.LengthEffectiveStatementImpl;
16 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type.PatternEffectiveStatementImpl;
17 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type.RangeEffectiveStatementImpl;
18 import com.google.common.base.Optional;
19 import com.google.common.collect.ImmutableList;
20 import java.util.Collections;
21 import java.util.List;
22 import org.opendaylight.yangtools.yang.common.QName;
23 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
24 import org.opendaylight.yangtools.yang.model.api.Status;
25 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
26 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
27 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
28 import org.opendaylight.yangtools.yang.model.api.stmt.TypedefStatement;
29 import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
30 import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
31 import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
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.TypeDefinitionEffectiveBuilder;
39
40 public class TypeDefEffectiveStatementImpl extends
41         EffectiveStatementBase<QName, TypedefStatement> implements
42         TypeDefinition<TypeDefinition<?>>, TypeDefinitionEffectiveBuilder {
43
44     private final QName qName;
45     private final SchemaPath path;
46
47     private final TypeDefinition<?> baseType;
48
49     private String defaultValue;
50     private String units;
51
52     private String description;
53     private String reference;
54
55     private Status status;
56
57     private final List<RangeConstraint> ranges;
58     private final List<LengthConstraint> lengths;
59     private final List<PatternConstraint> patterns;
60     private final Integer fractionDigits;
61
62     private ExtendedType extendedType = null;
63
64     public TypeDefEffectiveStatementImpl(
65             StmtContext<QName, TypedefStatement, ?> ctx) {
66         super(ctx);
67
68         qName = ctx.getStatementArgument();
69         path = Utils.getSchemaPath(ctx);
70         baseType = parseBaseTypeFromCtx(ctx);
71
72         EffectiveStatementBase<?, ?> typeEffectiveStmt = firstSubstatementOfType(
73                 TypeDefinition.class, EffectiveStatementBase.class);
74
75         ranges = initRanges(typeEffectiveStmt);
76         lengths = initLengths(typeEffectiveStmt);
77         patterns = initPatterns(typeEffectiveStmt);
78
79         //due to compatibility problems with original yang parser
80         //:FIXME try to find out better solution
81         if (typeEffectiveStmt.argument().equals(TypeUtils.DECIMAL64)
82                 && ranges.isEmpty()) {
83             fractionDigits = null;
84         } else {
85             fractionDigits = initFractionDigits(typeEffectiveStmt);
86         }
87
88         for (final EffectiveStatement<?, ?> effectiveStatement : effectiveSubstatements()) {
89             if (effectiveStatement instanceof DefaultEffectiveStatementImpl) {
90                 defaultValue = ((DefaultEffectiveStatementImpl) effectiveStatement)
91                         .argument();
92             }
93             if (effectiveStatement instanceof UnitsEffectiveStatementImpl) {
94                 units = ((UnitsEffectiveStatementImpl) effectiveStatement)
95                         .argument();
96             }
97             if (effectiveStatement instanceof DescriptionEffectiveStatementImpl) {
98                 description = ((DescriptionEffectiveStatementImpl) effectiveStatement)
99                         .argument();
100             }
101             if (effectiveStatement instanceof ReferenceEffectiveStatementImpl) {
102                 reference = ((ReferenceEffectiveStatementImpl) effectiveStatement)
103                         .argument();
104             }
105             if (effectiveStatement instanceof StatusEffectiveStatementImpl) {
106                 status = ((StatusEffectiveStatementImpl) effectiveStatement)
107                         .argument();
108             }
109         }
110     }
111
112     private TypeDefinition<?> parseBaseTypeFromCtx(
113             final StmtContext<QName, TypedefStatement, ?> ctx) {
114
115         TypeDefinition<?> baseType;
116
117         QName baseTypeQName = Utils.qNameFromArgument(ctx, StmtContextUtils
118                 .firstAttributeOf(ctx.declaredSubstatements(),
119                         TypeStatement.class));
120
121         if (TypeUtils.isYangBuiltInTypeString(baseTypeQName.getLocalName())) {
122             baseType = TypeUtils.getYangPrimitiveTypeFromString(baseTypeQName
123                     .getLocalName());
124             if (baseType == null) {
125                 baseType = firstSubstatementOfType(TypeDefinition.class);
126
127                 //due to compatibility problems with original yang parser
128                 //:FIXME try to find out better solution
129                 if(baseType instanceof Decimal64SpecificationEffectiveStatementImpl) {
130                     Decimal64SpecificationEffectiveStatementImpl decimal64 = (Decimal64SpecificationEffectiveStatementImpl) baseType;
131                     if(decimal64.isExtended()) {
132                         baseType = decimal64.getBaseType();
133                     }
134                 }
135             }
136         } else {
137             StmtContext<?, TypedefStatement, EffectiveStatement<QName, TypedefStatement>> baseTypeCtx = ctx
138                     .getParentContext().getFromNamespace(TypeNamespace.class,
139                             baseTypeQName);
140             baseType = (TypeDefEffectiveStatementImpl) baseTypeCtx
141                     .buildEffective();
142         }
143
144         return baseType;
145     }
146
147     protected Integer initFractionDigits(
148             EffectiveStatementBase<?, ?> typeEffectiveStmt) {
149         final FractionDigitsEffectiveStatementImpl fractionDigitsEffStmt = typeEffectiveStmt
150                 .firstEffective(FractionDigitsEffectiveStatementImpl.class);
151         return fractionDigitsEffStmt != null ? fractionDigitsEffStmt.argument()
152                 : null;
153     }
154
155     protected List<RangeConstraint> initRanges(
156             EffectiveStatementBase<?, ?> typeEffectiveStmt) {
157         final RangeEffectiveStatementImpl rangeConstraints = typeEffectiveStmt
158                 .firstEffective(RangeEffectiveStatementImpl.class);
159         return rangeConstraints != null ? rangeConstraints.argument()
160                 : Collections.<RangeConstraint> emptyList();
161     }
162
163     protected List<LengthConstraint> initLengths(
164             EffectiveStatementBase<?, ?> typeEffectiveStmt) {
165         final LengthEffectiveStatementImpl lengthConstraints = typeEffectiveStmt
166                 .firstEffective(LengthEffectiveStatementImpl.class);
167         return lengthConstraints != null ? lengthConstraints.argument()
168                 : Collections.<LengthConstraint> emptyList();
169     }
170
171     protected List<PatternConstraint> initPatterns(
172             EffectiveStatementBase<?, ?> typeEffectiveStmt) {
173         final List<PatternConstraint> patternConstraints = new ArrayList<>();
174
175         for (final EffectiveStatement<?, ?> effectiveStatement : typeEffectiveStmt
176                 .effectiveSubstatements()) {
177             if (effectiveStatement instanceof PatternEffectiveStatementImpl) {
178                 final PatternConstraint pattern = ((PatternEffectiveStatementImpl) effectiveStatement)
179                         .argument();
180
181                 if (pattern != null) {
182                     patternConstraints.add(pattern);
183                 }
184             }
185         }
186
187         return !patternConstraints.isEmpty() ? ImmutableList
188                 .copyOf(patternConstraints) : Collections
189                 .<PatternConstraint> emptyList();
190     }
191
192     @Override
193     public TypeDefinition<?> getBaseType() {
194         return baseType;
195     }
196
197     @Override
198     public String getUnits() {
199         return units;
200     }
201
202     @Override
203     public Object getDefaultValue() {
204         return defaultValue;
205     }
206
207     @Override
208     public QName getQName() {
209         return qName;
210     }
211
212     @Override
213     public SchemaPath getPath() {
214         return path;
215     }
216
217     @Override
218     public List<UnknownSchemaNode> getUnknownSchemaNodes() {
219         return Collections.emptyList();
220     }
221
222     @Override
223     public String getDescription() {
224         return description;
225     }
226
227     @Override
228     public String getReference() {
229         return reference;
230     }
231
232     @Override
233     public Status getStatus() {
234         return status;
235     }
236
237     public List<RangeConstraint> getRangeConstraints() {
238         return ranges;
239     }
240
241     public List<LengthConstraint> getLengthConstraints() {
242         return lengths;
243     }
244
245     public List<PatternConstraint> getPatternConstraints() {
246         return patterns;
247     }
248
249     public Integer getFractionDigits() {
250         return fractionDigits;
251     }
252
253     @Override
254     public ExtendedType buildType() {
255
256         if (extendedType != null) {
257             return extendedType;
258         }
259
260         Builder extendedTypeBuilder;
261         if (baseType instanceof TypeDefinitionEffectiveBuilder) {
262             TypeDefinitionEffectiveBuilder typeDefBaseType = (TypeDefinitionEffectiveBuilder) baseType;
263             extendedTypeBuilder = ExtendedType.builder(qName,
264                     typeDefBaseType.buildType(),
265                     Optional.fromNullable(description),
266                     Optional.fromNullable(reference), path);
267         } else {
268             extendedTypeBuilder = ExtendedType.builder(qName, baseType,
269                     Optional.fromNullable(description),
270                     Optional.fromNullable(reference), path);
271         }
272
273         extendedTypeBuilder.defaultValue(defaultValue);
274         extendedTypeBuilder.units(units);
275
276         extendedTypeBuilder.fractionDigits(fractionDigits);
277         extendedTypeBuilder.ranges(ranges);
278         extendedTypeBuilder.lengths(lengths);
279         extendedTypeBuilder.patterns(patterns);
280
281         extendedType = extendedTypeBuilder.build();
282
283         return extendedType;
284     }
285 }