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 org.opendaylight.yangtools.yang.model.util.ExtendedType;
11 import org.opendaylight.yangtools.yang.model.util.ExtendedType.Builder;
12 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
13 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.EffectiveStatementBase;
14 import org.opendaylight.yangtools.yang.model.util.Decimal64;
15 import org.opendaylight.yangtools.yang.model.api.stmt.TypeStatement;
16 import com.google.common.base.Optional;
17 import com.google.common.collect.ImmutableList;
18 import java.math.BigDecimal;
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.List;
22 import org.opendaylight.yangtools.yang.common.QName;
23 import org.opendaylight.yangtools.yang.common.YangConstants;
24 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
25 import org.opendaylight.yangtools.yang.model.api.Status;
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.type.DecimalTypeDefinition;
29 import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
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.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(
42 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(
51 "-922337203685477580.8");
52 private static final BigDecimal MAX_VALUE = new BigDecimal(
53 "922337203685477580.7");
55 private List<RangeConstraint> rangeConstraints;
56 private Integer fractionDigits;
57 private SchemaPath path;
58 private QName extendedTypeQName;
60 private ExtendedType extendedType;
61 private final boolean isExtended;
63 public Decimal64SpecificationEffectiveStatementImpl(
64 StmtContext<String, TypeStatement.Decimal64Specification, EffectiveStatement<String, TypeStatement.Decimal64Specification>> ctx) {
67 for (final EffectiveStatement<?, ?> effectiveStatement : effectiveSubstatements()) {
68 if (effectiveStatement instanceof FractionDigitsEffectiveStatementImpl) {
69 fractionDigits = ((FractionDigitsEffectiveStatementImpl) effectiveStatement)
74 List<RangeConstraint> initRanges = initRanges();
76 if (!initRanges.isEmpty() && validateRanges(initRanges)) {
78 rangeConstraints = ImmutableList.copyOf(initRanges);
79 SchemaPath parentPath = Utils.getSchemaPath(ctx.getParentContext());
80 extendedTypeQName = QName.create(parentPath.getLastComponent().getModule(), QNAME.getLocalName());
81 path = parentPath.createChild(extendedTypeQName);
84 rangeConstraints = defaultRangeStatements();
85 path = Utils.getSchemaPath(ctx.getParentContext()).createChild(QNAME);
89 private boolean validateRanges(List<RangeConstraint> initRanges) {
90 for (RangeConstraint rangeConstraint : initRanges) {
92 String maxValueString = rangeConstraint.getMax().toString();
93 String minValueString = rangeConstraint.getMin().toString();
95 if ((!maxValueString.equals("max") && new BigDecimal(maxValueString)
96 .compareTo(MAX_VALUE) > 0)
97 || (!minValueString.equals("min") && new BigDecimal(
98 minValueString).compareTo(MIN_VALUE) < 0)) {
105 protected List<RangeConstraint> initRanges() {
106 final RangeEffectiveStatementImpl rangeConstraints = firstEffective(RangeEffectiveStatementImpl.class);
107 return rangeConstraints != null ? rangeConstraints.argument()
108 : Collections.<RangeConstraint> emptyList();
111 private List<RangeConstraint> defaultRangeStatements() {
113 final List<RangeConstraint> rangeStmts = new ArrayList<>();
114 final String rangeDescription = "Integer values between " + MIN_VALUE
115 + " and " + MAX_VALUE + ", inclusively.";
116 final String rangeReference = RangeConstraintEffectiveImpl.DEFAULT_REFERENCE;
118 rangeStmts.add(new RangeConstraintEffectiveImpl(MIN_VALUE, MAX_VALUE,
119 Optional.of(rangeDescription), Optional.of(rangeReference)));
121 return ImmutableList.copyOf(rangeStmts);
124 public boolean isExtended() {
129 public List<RangeConstraint> getRangeConstraints() {
130 return rangeConstraints;
134 public Integer getFractionDigits() {
135 return fractionDigits;
139 public DecimalTypeDefinition getBaseType() {
141 if (decimal64Instance == null) {
142 decimal64Instance = Decimal64.create(path, fractionDigits);
144 return decimal64Instance;
151 public String getUnits() {
156 public Object getDefaultValue() {
157 return DEFAULT_VALUE;
161 public QName getQName() {
166 public SchemaPath getPath() {
171 public List<UnknownSchemaNode> getUnknownSchemaNodes() {
172 return Collections.emptyList();
176 public String getDescription() {
181 public String getReference() {
186 public Status getStatus() {
187 return Status.CURRENT;
191 public int hashCode() {
192 final int prime = 31;
194 result = prime * result + ((QNAME == null) ? 0 : QNAME.hashCode());
195 result = prime * result + ((path == null) ? 0 : path.hashCode());
200 public boolean equals(final Object obj) {
207 if (getClass() != obj.getClass()) {
210 Decimal64SpecificationEffectiveStatementImpl other = (Decimal64SpecificationEffectiveStatementImpl) obj;
212 if (other.path != null) {
215 } else if (!path.equals(other.path)) {
222 public String toString() {
223 return Decimal64SpecificationEffectiveStatementImpl.class
227 + ", fractionDigits="
228 + fractionDigits + "]";
231 private Decimal64 decimal64Instance = null;
234 public TypeDefinition<?> buildType() {
236 if (decimal64Instance == null) {
237 decimal64Instance = Decimal64.create(path, fractionDigits);
241 return decimal64Instance;
244 if (extendedType != null) {
248 Builder extendedTypeBuilder = ExtendedType.builder(path.getLastComponent(), decimal64Instance, Optional.<String>absent(),
249 Optional.<String>absent(), path);
251 extendedTypeBuilder.fractionDigits(fractionDigits);
252 extendedTypeBuilder.ranges(rangeConstraints);
254 extendedType = extendedTypeBuilder.build();