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