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.type;
10 import com.google.common.base.Optional;
11 import com.google.common.collect.ImmutableList;
12 import java.math.BigDecimal;
13 import java.util.Collections;
14 import java.util.List;
15 import java.util.Objects;
16 import org.opendaylight.yangtools.yang.common.QName;
17 import org.opendaylight.yangtools.yang.common.YangConstants;
18 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
19 import org.opendaylight.yangtools.yang.model.api.Status;
20 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
21 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
22 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
23 import org.opendaylight.yangtools.yang.model.api.stmt.TypeStatement;
24 import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition;
25 import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
26 import org.opendaylight.yangtools.yang.model.util.Decimal64;
27 import org.opendaylight.yangtools.yang.model.util.ExtendedType;
28 import org.opendaylight.yangtools.yang.model.util.ExtendedType.Builder;
29 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
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.EffectiveStatementBase;
33 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.FractionDigitsEffectiveStatementImpl;
35 public class Decimal64SpecificationEffectiveStatementImpl extends
36 EffectiveStatementBase<String, TypeStatement.Decimal64Specification>
37 implements DecimalTypeDefinition, TypeDefinitionEffectiveBuilder {
39 private static final String UNITS = "";
40 private static final BigDecimal DEFAULT_VALUE = null;
41 private static final QName QNAME = QName.create(YangConstants.RFC6020_YANG_MODULE, TypeUtils.DECIMAL64);
43 private static final String DESCRIPTION = "The decimal64 type represents a subset of the real numbers, which can "
44 + "be represented by decimal numerals. The value space of decimal64 is the set of numbers that can "
45 + "be obtained by multiplying a 64-bit signed integer by a negative power of ten, i.e., expressible as "
46 + "'i x 10^-n' where i is an integer64 and n is an integer between 1 and 18, inclusively.";
48 private static final String REFERENCE = "https://tools.ietf.org/html/rfc6020#section-9.3";
49 private static final BigDecimal MIN_VALUE = new BigDecimal("-922337203685477580.8");
50 private static final BigDecimal MAX_VALUE = new BigDecimal("922337203685477580.7");
51 private static final List<RangeConstraint> DEFAULT_RANGE_STATEMENTS;
53 final String rangeDescription = "Integer values between " + MIN_VALUE
54 + " and " + MAX_VALUE + ", inclusively.";
55 final String rangeReference = RangeConstraintEffectiveImpl.DEFAULT_REFERENCE;
57 DEFAULT_RANGE_STATEMENTS = ImmutableList.<RangeConstraint>of(
58 new RangeConstraintEffectiveImpl(MIN_VALUE, MAX_VALUE, Optional.of(rangeDescription),
59 Optional.of(rangeReference)));
62 private List<RangeConstraint> rangeConstraints;
63 private Integer fractionDigits;
64 private SchemaPath path;
65 private QName extendedTypeQName;
67 private ExtendedType extendedType;
68 private final boolean isExtended;
69 private Decimal64 decimal64Instance = null;
71 public Decimal64SpecificationEffectiveStatementImpl(
72 final StmtContext<String, TypeStatement.Decimal64Specification, EffectiveStatement<String, TypeStatement.Decimal64Specification>> ctx) {
75 for (final EffectiveStatement<?, ?> effectiveStatement : effectiveSubstatements()) {
76 if (effectiveStatement instanceof FractionDigitsEffectiveStatementImpl) {
77 fractionDigits = ((FractionDigitsEffectiveStatementImpl) effectiveStatement)
82 List<RangeConstraint> initRanges = initRanges();
84 if (!initRanges.isEmpty() && validateRanges(initRanges)) {
86 rangeConstraints = ImmutableList.copyOf(initRanges);
87 SchemaPath parentPath = Utils.getSchemaPath(ctx.getParentContext());
88 extendedTypeQName = QName.create(parentPath.getLastComponent().getModule(), QNAME.getLocalName());
89 path = parentPath.createChild(extendedTypeQName);
92 rangeConstraints = DEFAULT_RANGE_STATEMENTS;
93 path = Utils.getSchemaPath(ctx.getParentContext()).createChild(QNAME);
97 private static boolean validateRanges(final List<RangeConstraint> initRanges) {
98 for (RangeConstraint rangeConstraint : initRanges) {
100 String maxValueString = rangeConstraint.getMax().toString();
101 String minValueString = rangeConstraint.getMin().toString();
103 if ((!"max".equals(maxValueString) && MAX_VALUE.compareTo(new BigDecimal(maxValueString)) < 0)
104 || (!"min".equals(minValueString) && MIN_VALUE.compareTo(new BigDecimal(minValueString)) > 0)) {
111 private List<RangeConstraint> initRanges() {
112 final RangeEffectiveStatementImpl rangeConstraints = firstEffective(RangeEffectiveStatementImpl.class);
113 return rangeConstraints != null ? rangeConstraints.argument() : Collections.<RangeConstraint> emptyList();
116 public boolean isExtended() {
121 public List<RangeConstraint> getRangeConstraints() {
122 return rangeConstraints;
126 public Integer getFractionDigits() {
127 return fractionDigits;
131 public DecimalTypeDefinition getBaseType() {
133 if (decimal64Instance == null) {
134 decimal64Instance = Decimal64.create(path, fractionDigits);
136 return decimal64Instance;
143 public String getUnits() {
148 public Object getDefaultValue() {
149 return DEFAULT_VALUE;
153 public QName getQName() {
158 public SchemaPath getPath() {
163 public List<UnknownSchemaNode> getUnknownSchemaNodes() {
164 return Collections.emptyList();
168 public String getDescription() {
173 public String getReference() {
178 public Status getStatus() {
179 return Status.CURRENT;
183 public int hashCode() {
184 final int prime = 31;
186 result = prime * result + Objects.hashCode(QNAME);
187 result = prime * result + Objects.hashCode(path);
192 public boolean equals(final Object obj) {
199 if (getClass() != obj.getClass()) {
202 Decimal64SpecificationEffectiveStatementImpl other = (Decimal64SpecificationEffectiveStatementImpl) obj;
203 return Objects.equals(path, other.path);
207 public String toString() {
208 return Decimal64SpecificationEffectiveStatementImpl.class.getSimpleName()
209 + "[qName=" + QNAME + ", fractionDigits=" + fractionDigits + "]";
213 public TypeDefinition<?> buildType() {
215 if (decimal64Instance == null) {
216 decimal64Instance = Decimal64.create(path, fractionDigits);
220 return decimal64Instance;
223 if (extendedType != null) {
227 Builder extendedTypeBuilder = ExtendedType.builder(path.getLastComponent(), decimal64Instance,
228 Optional.<String>absent(), Optional.<String>absent(), path);
230 extendedTypeBuilder.fractionDigits(fractionDigits);
231 extendedTypeBuilder.ranges(rangeConstraints);
233 extendedType = extendedTypeBuilder.build();