Bug 2366 - Effective statments impl merge, retest & bugfix
[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.Collections;
13 import java.util.List;
14 import org.opendaylight.yangtools.yang.common.QName;
15 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
16 import org.opendaylight.yangtools.yang.model.api.Status;
17 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
18 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
19 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
20 import org.opendaylight.yangtools.yang.model.api.stmt.TypeStatement;
21 import org.opendaylight.yangtools.yang.model.api.stmt.TypedefStatement;
22 import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
23 import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
24 import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
25 import org.opendaylight.yangtools.yang.model.util.ExtendedType;
26 import org.opendaylight.yangtools.yang.model.util.ExtendedType.Builder;
27 import org.opendaylight.yangtools.yang.parser.spi.TypeNamespace;
28 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
29 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
30 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.TypeUtils;
31 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.Utils;
32 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type.TypeDefinitionEffectiveBuilder;
33
34 public class TypeDefEffectiveStatementImpl extends EffectiveStatementBase<QName, TypedefStatement> implements
35         TypeDefinition<TypeDefinition<?>>, TypeDefinitionEffectiveBuilder {
36
37     private final QName qName;
38     private final SchemaPath path;
39
40     private final TypeDefinition<?> baseType;
41
42     private String defaultValue;
43     private String units;
44
45     private String description;
46     private String reference;
47
48     private Status status;
49
50     private final List<RangeConstraint> ranges;
51     private final List<LengthConstraint> lengths;
52     private final List<PatternConstraint> patterns;
53     private final Integer fractionDigits;
54
55     private ExtendedType extendedType = null;
56
57     public TypeDefEffectiveStatementImpl(StmtContext<QName, TypedefStatement, ?> ctx) {
58         super(ctx);
59
60         qName = ctx.getStatementArgument();
61         path = Utils.getSchemaPath(ctx);
62
63         ExtendedTypeEffectiveStatementImpl type = null;
64
65         for (final EffectiveStatement<?, ?> effectiveStatement : effectiveSubstatements()) {
66             if (effectiveStatement instanceof ExtendedTypeEffectiveStatementImpl) {
67                 type = ((ExtendedTypeEffectiveStatementImpl) effectiveStatement);
68             }
69             if (effectiveStatement instanceof DefaultEffectiveStatementImpl) {
70                 defaultValue = ((DefaultEffectiveStatementImpl) effectiveStatement).argument();
71             }
72             if (effectiveStatement instanceof UnitsEffectiveStatementImpl) {
73                 units = ((UnitsEffectiveStatementImpl) effectiveStatement).argument();
74             }
75             if (effectiveStatement instanceof DescriptionEffectiveStatementImpl) {
76                 description = ((DescriptionEffectiveStatementImpl) effectiveStatement).argument();
77             }
78             if (effectiveStatement instanceof ReferenceEffectiveStatementImpl) {
79                 reference = ((ReferenceEffectiveStatementImpl) effectiveStatement).argument();
80             }
81             if (effectiveStatement instanceof StatusEffectiveStatementImpl) {
82                 status = ((StatusEffectiveStatementImpl) effectiveStatement).argument();
83             }
84         }
85
86         if (type != null) {
87
88             ranges = ImmutableList.copyOf(type.getRangeConstraints());
89             lengths = ImmutableList.copyOf(type.getLengthConstraints());
90             patterns = ImmutableList.copyOf(type.getPatternConstraints());
91             fractionDigits = type.getFractionDigits();
92         } else {
93
94             ranges = Collections.emptyList();
95             lengths = Collections.emptyList();
96             patterns = Collections.emptyList();
97             fractionDigits = null;
98         }
99
100         baseType = parseBaseTypeFromCtx(ctx);
101     }
102
103     private TypeDefinition<?> parseBaseTypeFromCtx(final StmtContext<QName, TypedefStatement, ?> ctx) {
104
105         TypeDefinition<?> baseType;
106
107         QName baseTypeQName = Utils.qNameFromArgument(ctx,
108                 StmtContextUtils.firstAttributeOf(ctx.declaredSubstatements(), TypeStatement.class));
109
110         if (TypeUtils.isYangBaseTypeString(baseTypeQName.getLocalName())) {
111             baseType = TypeUtils.getYangBaseTypeFromString(baseTypeQName.getLocalName());
112         } else {
113             StmtContext<?, TypedefStatement, EffectiveStatement<QName, TypedefStatement>> baseTypeCtx = ctx
114                     .getParentContext().getFromNamespace(TypeNamespace.class, baseTypeQName);
115             baseType = (TypeDefEffectiveStatementImpl) baseTypeCtx.buildEffective();
116         }
117
118         if (baseType == null) {
119             baseType = firstSubstatementOfType(TypeDefinition.class);
120         }
121
122         return baseType;
123     }
124
125     @Override
126     public TypeDefinition<?> getBaseType() {
127         return baseType;
128     }
129
130     @Override
131     public String getUnits() {
132         return units;
133     }
134
135     @Override
136     public Object getDefaultValue() {
137         return defaultValue;
138     }
139
140     @Override
141     public QName getQName() {
142         return qName;
143     }
144
145     @Override
146     public SchemaPath getPath() {
147         return path;
148     }
149
150     @Override
151     public List<UnknownSchemaNode> getUnknownSchemaNodes() {
152         return Collections.emptyList();
153     }
154
155     @Override
156     public String getDescription() {
157         return description;
158     }
159
160     @Override
161     public String getReference() {
162         return reference;
163     }
164
165     @Override
166     public Status getStatus() {
167         return status;
168     }
169
170     public List<RangeConstraint> getRangeConstraints() {
171         return ranges;
172     }
173
174     public List<LengthConstraint> getLengthConstraints() {
175         return lengths;
176     }
177
178     public List<PatternConstraint> getPatternConstraints() {
179         return patterns;
180     }
181
182     public Integer getFractionDigits() {
183         return fractionDigits;
184     }
185
186     @Override
187     public ExtendedType buildType() {
188
189         if (extendedType != null) {
190             return extendedType;
191         }
192
193         Builder extendedTypeBuilder;
194         if (baseType instanceof TypeDefinitionEffectiveBuilder) {
195             TypeDefinitionEffectiveBuilder typeDefBaseType = (TypeDefinitionEffectiveBuilder) baseType;
196             extendedTypeBuilder = ExtendedType.builder(qName, typeDefBaseType.buildType(),
197                     Optional.fromNullable(description), Optional.fromNullable(reference), path);
198         } else {
199             extendedTypeBuilder = ExtendedType.builder(qName, baseType, Optional.fromNullable(description),
200                     Optional.fromNullable(reference), path);
201         }
202
203         extendedTypeBuilder.defaultValue(defaultValue);
204         extendedTypeBuilder.units(units);
205
206         extendedTypeBuilder.fractionDigits(fractionDigits);
207         extendedTypeBuilder.ranges(ranges);
208         extendedTypeBuilder.lengths(lengths);
209         extendedTypeBuilder.patterns(patterns);
210
211         extendedType = extendedTypeBuilder.build();
212
213         return extendedType;
214     }
215 }