From 77f6226c747f91122527fd68736a6d921df57d5e Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Mon, 23 Nov 2015 18:39:25 +0100 Subject: [PATCH] BUG-4638: introduce CompatUtils Create a CompatUtils class for dealing with downstream users, who rely on the parser not generating a type encapsulation for leaf types which also define the default value. Change-Id: Ifabf6dc5415e8598727b5e0ab86b7127efd96beb Signed-off-by: Robert Varga --- .../yang/model/util/type/CompatUtils.java | 199 ++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/CompatUtils.java diff --git a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/CompatUtils.java b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/CompatUtils.java new file mode 100644 index 0000000000..08bff3b637 --- /dev/null +++ b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/type/CompatUtils.java @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.yangtools.yang.model.util.type; + +import com.google.common.base.Preconditions; +import java.util.List; +import javax.annotation.Nonnull; +import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode; +import org.opendaylight.yangtools.yang.model.api.TypeDefinition; +import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition; +import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition; +import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition; +import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition; +import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint; +import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint; +import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition; +import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition; +import org.opendaylight.yangtools.yang.model.util.ExtendedType; + +/** + * Compatibility utilities for dealing with differences between the {@link ExtendedType}-driven type representation + * versus the representation this package models. + * + * @deprecated This class is provided strictly for compatibility only. No new users should be introduced, as this class + * is scheduled for removal when its two OpenDaylight users, Java Binding v1 and YANG JMX Bindings are + * removed. + */ +@Deprecated +public final class CompatUtils { + private CompatUtils() { + throw new UnsupportedOperationException(); + } + + /** + * This package's type hierarchy model generates a type which encapsulates the default value and units for leaves. + * Java Binding specification is implemented in a way, where it needs to revert this process if the internal + * declaration has not restricted the type further -- which is not something available via + * {@link TypeDefinition#getBaseType()}. + * + * Here are the possible scenarios: + * + *
+     * leaf foo {
+     *     type uint8 {
+     *         range 1..2;
+     *     }
+     * }
+     * 
+ * The leaf type's schema path does not match the schema path of the leaf. We do NOT want to strip it, as + * we need to generate an inner class to hold the restrictions. + * + *
+     * leaf foo {
+     *     type uint8 {
+     *         range 1..2;
+     *     }
+     *     default 1;
+     * }
+     * 
+ * The leaf type's schema path will match the schema path of the leaf. We do NOT want to strip it, as we need + * to generate an inner class to hold the restrictions. + * + *
+     * leaf foo {
+     *     type uint8;
+     *     default 1;
+     * }
+     * 
+ * The leaf type's schema path will match the schema path of the leaf. We DO want to strip it, as we will deal + * with the default value ourselves. + * + *
+     * leaf foo {
+     *     type uint8;
+     * }
+     * 
+ * The leaf type's schema path will not match the schema path of the leaf. We do NOT want to strip it. + * + * The situation is different for types which do not have a default instantiation in YANG: leafref, enumeration, + * identityref, decimal64, bits and union. If these types are defined within this leaf's statement, a base type + * will be instantiated. If the leaf defines a default statement, this base type will be visible via getBaseType(). + * + *
+     * leaf foo {
+     *     type decimal64 {
+     *         fraction-digits 2;
+     *     }
+     * }
+     * 
+ * The leaf type's schema path will not match the schema path of the leaf, and we do not want to strip it, as it + * needs to be generated. + * + *
+     * leaf foo {
+     *     type decimal64 {
+     *         fraction-digits 2;
+     *     }
+     *     default 1;
+     * }
+     * 
+ * The leaf type's schema path will match the schema path of the leaf, and we DO want to strip it. + * + * @param leaf Leaf for which we are acquiring the type + * @return Potentially base type of the leaf type. + */ + @Nonnull public static TypeDefinition compatLeafType(@Nonnull final LeafSchemaNode leaf) { + final TypeDefinition leafType = leaf.getType(); + Preconditions.checkNotNull(leafType); + + if (leafType instanceof ExtendedType) { + // Old parser referring to a typedef + return leafType; + } + + if (!leaf.getPath().equals(leafType.getPath())) { + // Old parser semantics, or no new default/units defined for this leaf + return leafType; + } + + // We are dealing with a type generated for the leaf itself + final TypeDefinition baseType = leafType.getBaseType(); + Preconditions.checkArgument(baseType != null, "Leaf %s has type for leaf, but no base type", leaf); + + if (leaf.getPath().equals(baseType.getPath().getParent())) { + // Internal instantiation of a base YANG type (decimal64 and similar) + return baseType; + } + + // At this point we have dealt with the easy cases. Now we need to perform per-type checking if there are no + // new constraints introduced by this type. If there were not, we will return the base type. + if (leafType instanceof BinaryTypeDefinition) { + return baseTypeIfNotConstrained((BinaryTypeDefinition) leafType); + } else if (leafType instanceof DecimalTypeDefinition) { + return baseTypeIfNotConstrained((DecimalTypeDefinition) leafType); + } else if (leafType instanceof InstanceIdentifierTypeDefinition) { + return baseTypeIfNotConstrained((InstanceIdentifierTypeDefinition) leafType); + } else if (leafType instanceof IntegerTypeDefinition) { + return baseTypeIfNotConstrained((IntegerTypeDefinition) leafType); + } else if (leafType instanceof StringTypeDefinition) { + return baseTypeIfNotConstrained((StringTypeDefinition) leafType); + } else if (leafType instanceof UnsignedIntegerTypeDefinition) { + return baseTypeIfNotConstrained((UnsignedIntegerTypeDefinition) leafType); + } else { + // Other types cannot be constrained, return the base type + return baseType; + } + } + + private static TypeDefinition baseTypeIfNotConstrained(final BinaryTypeDefinition type) { + final BinaryTypeDefinition base = type.getBaseType(); + return baseTypeIfNotConstrained(type, type.getLengthConstraints(), base, base.getLengthConstraints()); + } + + private static TypeDefinition baseTypeIfNotConstrained(final DecimalTypeDefinition type) { + final DecimalTypeDefinition base = type.getBaseType(); + return baseTypeIfNotConstrained(type, type.getRangeConstraints(), base, base.getRangeConstraints()); + } + + private static TypeDefinition baseTypeIfNotConstrained(final InstanceIdentifierTypeDefinition type) { + final InstanceIdentifierTypeDefinition base = type.getBaseType(); + return type.requireInstance() == base.requireInstance() ? base : type; + } + + private static TypeDefinition baseTypeIfNotConstrained(final IntegerTypeDefinition type) { + final IntegerTypeDefinition base = type.getBaseType(); + return baseTypeIfNotConstrained(type, type.getRangeConstraints(), base, base.getRangeConstraints()); + } + + private static TypeDefinition baseTypeIfNotConstrained(final StringTypeDefinition type) { + final StringTypeDefinition base = type.getBaseType(); + final List patterns = type.getPatternConstraints(); + final List lengths = type.getLengthConstraints(); + + if ((patterns.isEmpty() || patterns.equals(base.getPatternConstraints())) && + (lengths.isEmpty() || lengths.equals(base.getLengthConstraints()))) { + return base; + } + + return type; + } + + private static TypeDefinition baseTypeIfNotConstrained(final UnsignedIntegerTypeDefinition type) { + final UnsignedIntegerTypeDefinition base = type.getBaseType(); + return baseTypeIfNotConstrained(type, type.getRangeConstraints(), base, base.getRangeConstraints()); + } + + private static TypeDefinition baseTypeIfNotConstrained(final TypeDefinition type, + final List typeConstraints, final TypeDefinition base, final List baseConstraints) { + if (typeConstraints.isEmpty() || typeConstraints.equals(baseConstraints)) { + return base; + } + return type; + } +} -- 2.36.6