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.TypeEffectiveStatement;
24 import org.opendaylight.yangtools.yang.model.api.stmt.TypeStatement.Decimal64Specification;
25 import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition;
26 import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
27 import org.opendaylight.yangtools.yang.model.util.Decimal64;
28 import org.opendaylight.yangtools.yang.model.util.ExtendedType;
29 import org.opendaylight.yangtools.yang.model.util.ExtendedType.Builder;
30 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
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.EffectiveStatementBase;
34 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.FractionDigitsEffectiveStatementImpl;
36 public class Decimal64SpecificationEffectiveStatementImpl extends
37 EffectiveStatementBase<String, Decimal64Specification>
38 implements DecimalTypeDefinition, TypeEffectiveStatement<Decimal64Specification> {
40 private static final String UNITS = "";
41 private static final BigDecimal DEFAULT_VALUE = null;
42 private static final QName QNAME = QName.create(YangConstants.RFC6020_YANG_MODULE, TypeUtils.DECIMAL64);
44 private static final String DESCRIPTION = "The decimal64 type represents a subset of the real numbers, which can "
45 + "be represented by decimal numerals. The value space of decimal64 is the set of numbers that can "
46 + "be obtained by multiplying a 64-bit signed integer by a negative power of ten, i.e., expressible as "
47 + "'i x 10^-n' where i is an integer64 and n is an integer between 1 and 18, inclusively.";
49 private static final String REFERENCE = "https://tools.ietf.org/html/rfc6020#section-9.3";
50 private static final BigDecimal MIN_VALUE = new BigDecimal("-922337203685477580.8");
51 private static final BigDecimal MAX_VALUE = new BigDecimal("922337203685477580.7");
52 private static final List<RangeConstraint> DEFAULT_RANGE_STATEMENTS;
54 final String rangeDescription = "Integer values between " + MIN_VALUE
55 + " and " + MAX_VALUE + ", inclusively.";
56 final String rangeReference = RangeConstraintEffectiveImpl.DEFAULT_REFERENCE;
58 DEFAULT_RANGE_STATEMENTS = ImmutableList.<RangeConstraint>of(
59 new RangeConstraintEffectiveImpl(MIN_VALUE, MAX_VALUE, Optional.of(rangeDescription),
60 Optional.of(rangeReference)));
63 private List<RangeConstraint> rangeConstraints;
64 private Integer fractionDigits;
65 private SchemaPath path;
66 private QName extendedTypeQName;
68 private ExtendedType extendedType;
69 private final boolean isExtended;
70 private Decimal64 decimal64Instance = null;
72 public Decimal64SpecificationEffectiveStatementImpl(
73 final StmtContext<String, Decimal64Specification, EffectiveStatement<String, Decimal64Specification>> ctx) {
76 for (final EffectiveStatement<?, ?> effectiveStatement : effectiveSubstatements()) {
77 if (effectiveStatement instanceof FractionDigitsEffectiveStatementImpl) {
78 fractionDigits = ((FractionDigitsEffectiveStatementImpl) effectiveStatement)
83 List<RangeConstraint> initRanges = initRanges();
85 if (!initRanges.isEmpty() && validateRanges(initRanges)) {
87 rangeConstraints = ImmutableList.copyOf(initRanges);
88 SchemaPath parentPath = Utils.getSchemaPath(ctx.getParentContext());
89 extendedTypeQName = QName.create(parentPath.getLastComponent().getModule(), QNAME.getLocalName());
90 path = parentPath.createChild(extendedTypeQName);
93 rangeConstraints = DEFAULT_RANGE_STATEMENTS;
94 path = Utils.getSchemaPath(ctx.getParentContext()).createChild(QNAME);
98 private static boolean validateRanges(final List<RangeConstraint> initRanges) {
99 for (RangeConstraint rangeConstraint : initRanges) {
101 String maxValueString = rangeConstraint.getMax().toString();
102 String minValueString = rangeConstraint.getMin().toString();
104 if ((!"max".equals(maxValueString) && MAX_VALUE.compareTo(new BigDecimal(maxValueString)) < 0)
105 || (!"min".equals(minValueString) && MIN_VALUE.compareTo(new BigDecimal(minValueString)) > 0)) {
112 private List<RangeConstraint> initRanges() {
113 final RangeEffectiveStatementImpl rangeConstraintsStmt = firstEffective(RangeEffectiveStatementImpl.class);
114 return rangeConstraintsStmt != null ? rangeConstraintsStmt.argument() : Collections.<RangeConstraint> emptyList();
117 public boolean isExtended() {
122 public List<RangeConstraint> getRangeConstraints() {
123 return rangeConstraints;
127 public Integer getFractionDigits() {
128 return fractionDigits;
132 public DecimalTypeDefinition getBaseType() {
134 if (decimal64Instance == null) {
135 decimal64Instance = Decimal64.create(path, fractionDigits);
137 return decimal64Instance;
144 public String getUnits() {
149 public Object getDefaultValue() {
150 return DEFAULT_VALUE;
154 public QName getQName() {
159 public SchemaPath getPath() {
164 public List<UnknownSchemaNode> getUnknownSchemaNodes() {
165 return Collections.emptyList();
169 public String getDescription() {
174 public String getReference() {
179 public Status getStatus() {
180 return Status.CURRENT;
184 public int hashCode() {
185 final int prime = 31;
187 result = prime * result + Objects.hashCode(QNAME);
188 result = prime * result + Objects.hashCode(path);
193 public boolean equals(final Object obj) {
200 if (getClass() != obj.getClass()) {
203 Decimal64SpecificationEffectiveStatementImpl other = (Decimal64SpecificationEffectiveStatementImpl) obj;
204 return Objects.equals(path, other.path);
208 public String toString() {
209 return Decimal64SpecificationEffectiveStatementImpl.class.getSimpleName()
210 + "[qName=" + QNAME + ", fractionDigits=" + fractionDigits + "]";
214 public TypeDefinition<?> getTypeDefinition() {
216 if (decimal64Instance == null) {
217 decimal64Instance = Decimal64.create(path, fractionDigits);
221 return decimal64Instance;
224 if (extendedType != null) {
228 Builder extendedTypeBuilder = ExtendedType.builder(path.getLastComponent(), decimal64Instance,
229 Optional.<String>absent(), Optional.<String>absent(), path);
231 extendedTypeBuilder.fractionDigits(fractionDigits);
232 extendedTypeBuilder.ranges(rangeConstraints);
234 extendedType = extendedTypeBuilder.build();