Introduce TypeDefinitionAware
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / stmt / rfc6020 / effective / type / Decimal64SpecificationEffectiveStatementImpl.java
index 73d6d34ad09686cad14f4d0b29c12e46c717c8ca..d18c0b3ddef1df7f5109a24266e26b82603693b8 100644 (file)
@@ -7,31 +7,35 @@
  */
 package org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.type;
 
-import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.EffectiveStatementBase;
-
-import org.opendaylight.yangtools.yang.model.util.Decimal64;
-import org.opendaylight.yangtools.yang.model.api.stmt.TypeStatement;
 import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableList;
 import java.math.BigDecimal;
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.YangConstants;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 import org.opendaylight.yangtools.yang.model.api.Status;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.TypeEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.TypeStatement.Decimal64Specification;
 import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
+import org.opendaylight.yangtools.yang.model.util.Decimal64;
+import org.opendaylight.yangtools.yang.model.util.ExtendedType;
+import org.opendaylight.yangtools.yang.model.util.ExtendedType.Builder;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.TypeUtils;
 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.Utils;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.EffectiveStatementBase;
 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.FractionDigitsEffectiveStatementImpl;
 
 public class Decimal64SpecificationEffectiveStatementImpl extends
-        EffectiveStatementBase<String, TypeStatement.Decimal64Specification> implements DecimalTypeDefinition, TypeDefinitionEffectiveBuilder {
+        EffectiveStatementBase<String, Decimal64Specification>
+        implements DecimalTypeDefinition, TypeEffectiveStatement<Decimal64Specification> {
 
     private static final String UNITS = "";
     private static final BigDecimal DEFAULT_VALUE = null;
@@ -45,35 +49,73 @@ public class Decimal64SpecificationEffectiveStatementImpl extends
     private static final String REFERENCE = "https://tools.ietf.org/html/rfc6020#section-9.3";
     private static final BigDecimal MIN_VALUE = new BigDecimal("-922337203685477580.8");
     private static final BigDecimal MAX_VALUE = new BigDecimal("922337203685477580.7");
+    private static final List<RangeConstraint> DEFAULT_RANGE_STATEMENTS;
+    static {
+        final String rangeDescription = "Integer values between " + MIN_VALUE
+                + " and " + MAX_VALUE + ", inclusively.";
+        final String rangeReference = RangeConstraintEffectiveImpl.DEFAULT_REFERENCE;
+
+        DEFAULT_RANGE_STATEMENTS = ImmutableList.<RangeConstraint>of(
+                new RangeConstraintEffectiveImpl(MIN_VALUE, MAX_VALUE, Optional.of(rangeDescription),
+                Optional.of(rangeReference)));
+    }
 
     private List<RangeConstraint> rangeConstraints;
     private Integer fractionDigits;
     private SchemaPath path;
+    private QName extendedTypeQName;
 
-    public Decimal64SpecificationEffectiveStatementImpl(StmtContext<String, TypeStatement.Decimal64Specification, EffectiveStatement<String, TypeStatement.Decimal64Specification>> ctx) {
-        super(ctx);
+    private ExtendedType extendedType;
+    private final boolean isExtended;
+    private Decimal64 decimal64Instance = null;
 
-        path = Utils.getSchemaPath(ctx.getParentContext()).createChild(QNAME);
+    public Decimal64SpecificationEffectiveStatementImpl(
+            final StmtContext<String, Decimal64Specification, EffectiveStatement<String, Decimal64Specification>> ctx) {
+        super(ctx);
 
         for (final EffectiveStatement<?, ?> effectiveStatement : effectiveSubstatements()) {
             if (effectiveStatement instanceof FractionDigitsEffectiveStatementImpl) {
-                fractionDigits = ((FractionDigitsEffectiveStatementImpl) effectiveStatement).argument();
+                fractionDigits = ((FractionDigitsEffectiveStatementImpl) effectiveStatement)
+                        .argument();
             }
         }
-        
-        rangeConstraints = defaultRangeStatements();
+
+        List<RangeConstraint> initRanges = initRanges();
+
+        if (!initRanges.isEmpty() && validateRanges(initRanges)) {
+            isExtended = true;
+            rangeConstraints = ImmutableList.copyOf(initRanges);
+            SchemaPath parentPath = Utils.getSchemaPath(ctx.getParentContext());
+            extendedTypeQName = QName.create(parentPath.getLastComponent().getModule(), QNAME.getLocalName());
+            path = parentPath.createChild(extendedTypeQName);
+        } else {
+            isExtended = false;
+            rangeConstraints = DEFAULT_RANGE_STATEMENTS;
+            path = Utils.getSchemaPath(ctx.getParentContext()).createChild(QNAME);
+        }
     }
 
-    private List<RangeConstraint> defaultRangeStatements() {
+    private static boolean validateRanges(final List<RangeConstraint> initRanges) {
+        for (RangeConstraint rangeConstraint : initRanges) {
 
-        final List<RangeConstraint> rangeStmts = new ArrayList<>();
-        final String rangeDescription = "Integer values between " + MIN_VALUE + " and " + MAX_VALUE + ", inclusively.";
-        final String rangeReference = RangeConstraintEffectiveImpl.DEFAULT_REFERENCE;
+            String maxValueString = rangeConstraint.getMax().toString();
+            String minValueString = rangeConstraint.getMin().toString();
+
+            if ((!"max".equals(maxValueString) && MAX_VALUE.compareTo(new BigDecimal(maxValueString)) < 0)
+                    || (!"min".equals(minValueString) && MIN_VALUE.compareTo(new BigDecimal(minValueString)) > 0)) {
+                return false;
+            }
+        }
+        return true;
+    }
 
-        rangeStmts.add(new RangeConstraintEffectiveImpl(MIN_VALUE, MAX_VALUE, Optional.of(rangeDescription), Optional
-                .of(rangeReference)));
+    private List<RangeConstraint> initRanges() {
+        final RangeEffectiveStatementImpl rangeConstraintsStmt = firstEffective(RangeEffectiveStatementImpl.class);
+        return rangeConstraintsStmt != null ? rangeConstraintsStmt.argument() : Collections.<RangeConstraint> emptyList();
+    }
 
-        return ImmutableList.copyOf(rangeStmts);
+    public boolean isExtended() {
+        return isExtended;
     }
 
     @Override
@@ -88,7 +130,14 @@ public class Decimal64SpecificationEffectiveStatementImpl extends
 
     @Override
     public DecimalTypeDefinition getBaseType() {
-        return null;
+        if (isExtended) {
+            if (decimal64Instance == null) {
+                decimal64Instance = Decimal64.create(path, fractionDigits);
+            }
+            return decimal64Instance;
+        } else {
+            return null;
+        }
     }
 
     @Override
@@ -135,8 +184,8 @@ public class Decimal64SpecificationEffectiveStatementImpl extends
     public int hashCode() {
         final int prime = 31;
         int result = 1;
-        result = prime * result + ((QNAME == null) ? 0 : QNAME.hashCode());
-        result = prime * result + ((path == null) ? 0 : path.hashCode());
+        result = prime * result + Objects.hashCode(QNAME);
+        result = prime * result + Objects.hashCode(path);
         return result;
     }
 
@@ -152,32 +201,38 @@ public class Decimal64SpecificationEffectiveStatementImpl extends
             return false;
         }
         Decimal64SpecificationEffectiveStatementImpl other = (Decimal64SpecificationEffectiveStatementImpl) obj;
-        if (path == null) {
-            if (other.path != null) {
-                return false;
-            }
-        } else if (!path.equals(other.path)) {
-            return false;
-        }
-        return true;
+        return Objects.equals(path, other.path);
     }
 
     @Override
     public String toString() {
-        return Decimal64SpecificationEffectiveStatementImpl.class.getSimpleName() + "[qName=" + QNAME
-                + ", fractionDigits=" + fractionDigits + "]";
+        return Decimal64SpecificationEffectiveStatementImpl.class.getSimpleName()
+                + "[qName=" + QNAME + ", fractionDigits=" + fractionDigits + "]";
     }
 
-    private Decimal64 decimal64Instance = null;
-
     @Override
-    public Decimal64 buildType() {
+    public TypeDefinition<?> getTypeDefinition() {
 
-        if (decimal64Instance != null) {
+        if (decimal64Instance == null) {
+            decimal64Instance = Decimal64.create(path, fractionDigits);
+        }
+
+        if (!isExtended) {
             return decimal64Instance;
         }
-        decimal64Instance = Decimal64.create(path, fractionDigits);
 
-        return decimal64Instance;
+        if (extendedType != null) {
+            return extendedType;
+        }
+
+        Builder extendedTypeBuilder = ExtendedType.builder(path.getLastComponent(), decimal64Instance,
+            Optional.<String>absent(), Optional.<String>absent(), path);
+
+        extendedTypeBuilder.fractionDigits(fractionDigits);
+        extendedTypeBuilder.ranges(rangeConstraints);
+
+        extendedType = extendedTypeBuilder.build();
+
+        return extendedType;
     }
 }