X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=binding%2Fmdsal-binding-generator-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fmdsal%2Fbinding%2Fyang%2Ftypes%2FAbstractTypeProvider.java;h=8786f15e6dbf8d25aa7c47e8f662cee235e2cb53;hb=74eef8e88d1c9bec36a7c0d45478a9884a012968;hp=8ece98b359855d10cef506e59905f8231e1d0f87;hpb=3035ac7215c3c66af829ece2903628415b77b6ad;p=mdsal.git diff --git a/binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/yang/types/AbstractTypeProvider.java b/binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/yang/types/AbstractTypeProvider.java index 8ece98b359..8786f15e6d 100644 --- a/binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/yang/types/AbstractTypeProvider.java +++ b/binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/yang/types/AbstractTypeProvider.java @@ -7,33 +7,34 @@ */ package org.opendaylight.mdsal.binding.yang.types; -import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataSchemaNode; +import static java.util.Objects.requireNonNull; +import static org.opendaylight.mdsal.binding.model.util.BindingTypes.TYPE_OBJECT; import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataSchemaNodeForRelativeXPath; +import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataTreeSchemaNode; import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findParentModule; import com.google.common.annotations.Beta; +import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; import com.google.common.base.Strings; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Sets; -import com.google.common.io.BaseEncoding; -import java.io.Serializable; import java.math.BigDecimal; -import java.math.BigInteger; import java.util.ArrayList; +import java.util.Base64; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.TreeMap; -import java.util.regex.Matcher; import java.util.regex.Pattern; import org.opendaylight.mdsal.binding.generator.spi.TypeProvider; +import org.opendaylight.mdsal.binding.generator.util.BaseYangTypesProvider; import org.opendaylight.mdsal.binding.model.api.AccessModifier; import org.opendaylight.mdsal.binding.model.api.ConcreteType; import org.opendaylight.mdsal.binding.model.api.Enumeration; @@ -48,21 +49,27 @@ import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTOBuilder; import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilder; import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase; import org.opendaylight.mdsal.binding.model.api.type.builder.MethodSignatureBuilder; +import org.opendaylight.mdsal.binding.model.util.BaseYangTypes; import org.opendaylight.mdsal.binding.model.util.BindingGeneratorUtil; +import org.opendaylight.mdsal.binding.model.util.BindingTypes; import org.opendaylight.mdsal.binding.model.util.TypeConstants; import org.opendaylight.mdsal.binding.model.util.Types; import org.opendaylight.mdsal.binding.model.util.generated.type.builder.AbstractEnumerationBuilder; import org.opendaylight.mdsal.binding.model.util.generated.type.builder.GeneratedPropertyBuilderImpl; -import org.opendaylight.yangtools.yang.binding.BindingMapping; +import org.opendaylight.mdsal.binding.spec.naming.BindingMapping; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.Revision; +import org.opendaylight.yangtools.yang.common.Uint16; +import org.opendaylight.yangtools.yang.common.Uint32; +import org.opendaylight.yangtools.yang.common.Uint64; +import org.opendaylight.yangtools.yang.common.Uint8; import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode; import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode; import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode; import org.opendaylight.yangtools.yang.model.api.Module; -import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath; +import org.opendaylight.yangtools.yang.model.api.PathExpression; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.model.api.SchemaNode; import org.opendaylight.yangtools.yang.model.api.SchemaPath; @@ -82,7 +89,7 @@ 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.UnionTypeDefinition; import org.opendaylight.yangtools.yang.model.util.ModuleDependencySort; -import org.opendaylight.yangtools.yang.model.util.RevisionAwareXPathImpl; +import org.opendaylight.yangtools.yang.model.util.PathExpressionImpl; import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil; import org.opendaylight.yangtools.yang.model.util.type.BaseTypes; import org.opendaylight.yangtools.yang.model.util.type.CompatUtils; @@ -93,7 +100,7 @@ import org.slf4j.LoggerFactory; public abstract class AbstractTypeProvider implements TypeProvider { private static final Logger LOG = LoggerFactory.getLogger(AbstractTypeProvider.class); private static final Pattern GROUPS_PATTERN = Pattern.compile("\\[(.*?)\\]"); - private static final Pattern NUMBERS_PATTERN = Pattern.compile("[0-9]+\\z"); + private static final JavaTypeName DEPRECATED_ANNOTATION = JavaTypeName.create(Deprecated.class); // Backwards compatibility: Union types used to be instantiated in YANG namespace, which is no longer // the case, as unions are emitted to their correct schema path. @@ -105,9 +112,6 @@ public abstract class AbstractTypeProvider implements TypeProvider { */ private final SchemaContext schemaContext; - /** - * Map>> - */ private final Map, Map>> genTypeDefsContextMap = new HashMap<>(); /** @@ -115,29 +119,27 @@ public abstract class AbstractTypeProvider implements TypeProvider { */ private final Map referencedTypes = new HashMap<>(); private final Map> additionalTypes = new HashMap<>(); + private final Map renames; /** * Creates new instance of class TypeProviderImpl. * - * @param schemaContext - * contains the schema data red from YANG files - * @throws IllegalArgumentException - * if schemaContext equal null. + * @param schemaContext contains the schema data red from YANG files + * @param renames renaming table + * @throws IllegalArgumentException if schemaContext equal null. */ - AbstractTypeProvider(final SchemaContext schemaContext) { + AbstractTypeProvider(final SchemaContext schemaContext, final Map renames) { Preconditions.checkArgument(schemaContext != null, "Schema Context cannot be null!"); - this.schemaContext = schemaContext; + this.renames = requireNonNull(renames); resolveTypeDefsFromContext(); } /** - * Puts refType to map with key refTypePath + * Puts refType to map with key refTypePath. * - * @param refTypePath - * schema path used as the map key - * @param refType - * type which represents the map value + * @param refTypePath schema path used as the map key + * @param refType type which represents the map value * @throws IllegalArgumentException *
    *
  • if refTypePath equal null
  • @@ -156,32 +158,16 @@ public abstract class AbstractTypeProvider implements TypeProvider { return additionalTypes; } - /** - * - * Converts basic YANG type type to JAVA Type. - * - * @param type - * string with YANG name of type - * @return JAVA Type for YANG type type - * @see TypeProvider#javaTypeForYangType(String) - */ - @Override - @Deprecated - public Type javaTypeForYangType(final String type) { - return BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForYangType(type); - } - @Override - public Type javaTypeForSchemaDefinitionType(final TypeDefinition typeDefinition, final SchemaNode parentNode) { - return javaTypeForSchemaDefinitionType(typeDefinition, parentNode, null); + public Type javaTypeForSchemaDefinitionType(final TypeDefinition typeDefinition, final SchemaNode parentNode, + final boolean lenientRelativeLeafrefs) { + return javaTypeForSchemaDefinitionType(typeDefinition, parentNode, null, lenientRelativeLeafrefs); } /** - * Converts schema definition type typeDefinition to JAVA - * Type + * Converts schema definition type typeDefinition to JAVA Type. * - * @param typeDefinition - * type definition which is converted to JAVA type + * @param typeDefinition type definition which is converted to JAVA type * @throws IllegalArgumentException *
      *
    • if typeDefinition equal null
    • @@ -191,7 +177,7 @@ public abstract class AbstractTypeProvider implements TypeProvider { */ @Override public Type javaTypeForSchemaDefinitionType(final TypeDefinition typeDefinition, final SchemaNode parentNode, - final Restrictions r) { + final Restrictions restrictions, final boolean lenientRelativeLeafrefs) { Preconditions.checkArgument(typeDefinition != null, "Type Definition cannot be NULL!"); Preconditions.checkArgument(typeDefinition.getQName() != null, "Type Definition cannot have non specified QName (QName cannot be NULL!)"); @@ -204,21 +190,21 @@ public abstract class AbstractTypeProvider implements TypeProvider { // and generated an enclosing ExtendedType to hold any range constraints. The new parser instantiates // a base type which holds these constraints. if (typeDefinition instanceof DecimalTypeDefinition) { - final Type ret = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(typeDefinition, - parentNode, r); + final Type ret = BaseYangTypesProvider.INSTANCE.javaTypeForSchemaDefinitionType(typeDefinition, + parentNode, restrictions, lenientRelativeLeafrefs); if (ret != null) { return ret; } } // Deal with leafrefs/identityrefs - Type ret = javaTypeForLeafrefOrIdentityRef(typeDefinition, parentNode); + Type ret = javaTypeForLeafrefOrIdentityRef(typeDefinition, parentNode, lenientRelativeLeafrefs); if (ret != null) { return ret; } // FIXME: it looks as though we could be using the same codepath as above... - ret = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForYangType(typeDefinition.getQName().getLocalName()); + ret = BaseYangTypes.javaTypeForYangType(typeDefinition.getQName().getLocalName()); if (ret == null) { LOG.debug("Failed to resolve Java type for {}", typeDefinition); } @@ -226,8 +212,8 @@ public abstract class AbstractTypeProvider implements TypeProvider { return ret; } - Type returnType = javaTypeForExtendedType(typeDefinition); - if (r != null && returnType instanceof GeneratedTransferObject) { + Type returnType = javaTypeForExtendedType(typeDefinition, lenientRelativeLeafrefs); + if (restrictions != null && returnType instanceof GeneratedTransferObject) { final GeneratedTransferObject gto = (GeneratedTransferObject) returnType; final Module module = findParentModule(schemaContext, parentNode); final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule()); @@ -236,19 +222,31 @@ public abstract class AbstractTypeProvider implements TypeProvider { final String genTOName = BindingMapping.getClassName(typedefName); final String name = packageName + "." + genTOName; if (!returnType.getFullyQualifiedName().equals(name)) { - returnType = shadedTOWithRestrictions(gto, r); + returnType = shadedTOWithRestrictions(gto, restrictions); } } return returnType; } - private GeneratedTransferObject shadedTOWithRestrictions(final GeneratedTransferObject gto, final Restrictions r) { + public SchemaNode getTargetForLeafref(final LeafrefTypeDefinition leafrefType, final SchemaNode parentNode) { + final PathExpression xpath = leafrefType.getPathStatement(); + Preconditions.checkArgument(xpath != null, "The Path Statement for Leafref Type Definition cannot be NULL!"); + + final Module module = findParentModule(schemaContext, parentNode); + Preconditions.checkArgument(module != null, "Failed to find module for parent %s", parentNode); + + return xpath.isAbsolute() ? findDataTreeSchemaNode(schemaContext, module.getQNameModule(), xpath) + : findDataSchemaNodeForRelativeXPath(schemaContext, module, parentNode, xpath); + } + + private GeneratedTransferObject shadedTOWithRestrictions(final GeneratedTransferObject gto, + final Restrictions restrictions) { final GeneratedTOBuilder gtob = newGeneratedTOBuilder(gto.getIdentifier()); final GeneratedTransferObject parent = gto.getSuperType(); if (parent != null) { gtob.setExtendsType(parent); } - gtob.setRestrictions(r); + gtob.setRestrictions(restrictions); for (GeneratedProperty gp : gto.getProperties()) { final GeneratedPropertyBuilder gpb = gtob.addProperty(gp.getName()); gpb.setValue(gp.getValue()); @@ -262,63 +260,59 @@ public abstract class AbstractTypeProvider implements TypeProvider { } private boolean isLeafRefSelfReference(final LeafrefTypeDefinition leafref, final SchemaNode parentNode) { - final SchemaNode leafRefValueNode; - final RevisionAwareXPath leafRefXPath = leafref.getPathStatement(); - final RevisionAwareXPath leafRefStrippedXPath = new RevisionAwareXPathImpl( - GROUPS_PATTERN.matcher(leafRefXPath.toString()).replaceAll(""), leafRefXPath.isAbsolute()); - - ///// skip leafrefs in augments - they're checked once augments are resolved - final Iterator iterator = parentNode.getPath().getPathFromRoot().iterator(); - boolean isAugmenting = false; + /* + * First check if the leafref is an augment. If that is the case, skip it as it will be checked once augments + * are resolved. + */ DataNodeContainer current = null; DataSchemaNode dataChildByName; - - while (iterator.hasNext() && !isAugmenting) { - final QName next = iterator.next(); + for (QName next : parentNode.getPath().getPathFromRoot()) { if (current == null) { dataChildByName = schemaContext.getDataChildByName(next); } else { dataChildByName = current.getDataChildByName(next); } - if (dataChildByName != null) { - isAugmenting = dataChildByName.isAugmenting(); - } else { + if (dataChildByName == null) { + return false; + } + if (dataChildByName.isAugmenting()) { return false; } if (dataChildByName instanceof DataNodeContainer) { current = (DataNodeContainer) dataChildByName; } } - if (isAugmenting) { - return false; - } - ///// + // Then try to look up the expression. + final PathExpression leafRefXPath = leafref.getPathStatement(); final Module parentModule = getParentModule(parentNode); - if (!leafRefStrippedXPath.isAbsolute()) { - leafRefValueNode = SchemaContextUtil.findDataSchemaNodeForRelativeXPath(schemaContext, parentModule, - parentNode, leafRefStrippedXPath); + final SchemaNode leafRefValueNode; + if (leafRefXPath.isAbsolute()) { + leafRefValueNode = SchemaContextUtil.findDataTreeSchemaNode(schemaContext, parentModule.getQNameModule(), + leafRefXPath); } else { - leafRefValueNode = SchemaContextUtil.findDataSchemaNode(schemaContext, parentModule, leafRefStrippedXPath); + leafRefValueNode = SchemaContextUtil.findDataSchemaNodeForRelativeXPath(schemaContext, parentModule, + parentNode, new PathExpressionImpl( + GROUPS_PATTERN.matcher(leafRefXPath.getOriginalString()).replaceAll(""), false)); } - return leafRefValueNode != null ? leafRefValueNode.equals(parentNode) : false; + + return leafRefValueNode != null && leafRefValueNode.equals(parentNode); } /** - * Returns JAVA Type for instances of the type - * LeafrefTypeDefinition or + * Returns JAVA Type for instances of the type LeafrefTypeDefinition or * IdentityrefTypeDefinition. * - * @param typeDefinition - * type definition which is converted to JAVA Type + * @param typeDefinition type definition which is converted to JAVA Type * @return JAVA Type instance for typeDefinition */ - private Type javaTypeForLeafrefOrIdentityRef(final TypeDefinition typeDefinition, final SchemaNode parentNode) { + private Type javaTypeForLeafrefOrIdentityRef(final TypeDefinition typeDefinition, final SchemaNode parentNode, + final boolean inGrouping) { if (typeDefinition instanceof LeafrefTypeDefinition) { final LeafrefTypeDefinition leafref = (LeafrefTypeDefinition) typeDefinition; Preconditions.checkArgument(!isLeafRefSelfReference(leafref, parentNode), "Leafref %s is referencing itself, incoming StackOverFlowError detected.", leafref); - return provideTypeForLeafref(leafref, parentNode); + return provideTypeForLeafref(leafref, parentNode, inGrouping); } else if (typeDefinition instanceof IdentityrefTypeDefinition) { return provideTypeForIdentityref((IdentityrefTypeDefinition) typeDefinition); } @@ -327,17 +321,15 @@ public abstract class AbstractTypeProvider implements TypeProvider { } /** - * Returns JAVA Type for instances of the type - * ExtendedType. + * Returns JAVA Type for instances of the type ExtendedType. * - * @param typeDefinition - * type definition which is converted to JAVA Type + * @param typeDefinition type definition which is converted to JAVA Type * @return JAVA Type instance for typeDefinition */ - private Type javaTypeForExtendedType(final TypeDefinition typeDefinition) { + private Type javaTypeForExtendedType(final TypeDefinition typeDefinition, final boolean lenient) { final String typedefName = typeDefinition.getQName().getLocalName(); final TypeDefinition baseTypeDef = baseTypeDefForExtendedType(typeDefinition); - Type returnType = javaTypeForLeafrefOrIdentityRef(baseTypeDef, typeDefinition); + Type returnType = javaTypeForLeafrefOrIdentityRef(baseTypeDef, typeDefinition, lenient); if (returnType == null) { if (baseTypeDef instanceof EnumTypeDefinition) { final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) baseTypeDef; @@ -353,8 +345,8 @@ public abstract class AbstractTypeProvider implements TypeProvider { returnType = genTOs.get(typedefName); } if (returnType == null) { - returnType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType( - baseTypeDef, typeDefinition, r); + returnType = BaseYangTypesProvider.INSTANCE.javaTypeForSchemaDefinitionType(baseTypeDef, + typeDefinition, r, lenient); } } } @@ -363,22 +355,18 @@ public abstract class AbstractTypeProvider implements TypeProvider { } /** - * Seeks for identity reference idref the JAVA - * type.
      - *
      + * Seeks for identity reference idref the JAVA type. * + *

      * Example:
      * If identy which is referenced via idref has name Idn * then returning type is {@code Class}
      * - * @param idref - * identityref type definition for which JAVA Type - * is sought - * @return JAVA Type of the identity which is referenced through - * idref + * @param idref identityref type definition for which JAVA Type is sought + * @return JAVA Type of the identity which is referenced through idref */ private Type provideTypeForIdentityref(final IdentityrefTypeDefinition idref) { - final Collection identities = idref.getIdentities(); + final Collection identities = idref.getIdentities(); if (identities.size() > 1) { LOG.warn("Identity reference {} has multiple identities, using only the first one", idref); } @@ -391,13 +379,12 @@ public abstract class AbstractTypeProvider implements TypeProvider { identity = id; } } - Preconditions.checkArgument(identity != null, "Target identity '" + baseIdQName + "' do not exists"); + Preconditions.checkArgument(identity != null, "Target identity '" + baseIdQName + "' do not exist"); final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule()); - final JavaTypeName identifier = JavaTypeName.create(BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, - identity.getPath()), BindingMapping.getClassName(identity.getQName())); - final Type paramType = Types.wildcardTypeFor(identifier); - return Types.parameterizedTypeFor(Types.typeForClass(Class.class), paramType); + final JavaTypeName identifier = JavaTypeName.create(BindingGeneratorUtil.packageNameForGeneratedType( + basePackageName, identity.getPath()), BindingMapping.getClassName(identity.getQName())); + return Types.classType(Types.wildcardTypeFor(identifier)); } /** @@ -415,11 +402,11 @@ public abstract class AbstractTypeProvider implements TypeProvider { *

    • if name of typeDefinition
    • *
    */ - public Type generatedTypeForExtendedDefinitionType(final TypeDefinition typeDefinition, final SchemaNode parentNode) { + public Type generatedTypeForExtendedDefinitionType(final TypeDefinition typeDefinition, + final SchemaNode parentNode) { Preconditions.checkArgument(typeDefinition != null, "Type Definition cannot be NULL!"); if (typeDefinition.getQName() == null) { - throw new IllegalArgumentException( - "Type Definition cannot have non specified QName (QName cannot be NULL!)"); + throw new IllegalArgumentException("Type Definition cannot have unspecified QName (QName cannot be NULL!)"); } Preconditions.checkArgument(typeDefinition.getQName().getLocalName() != null, "Type Definitions Local Name cannot be NULL!"); @@ -512,69 +499,94 @@ public abstract class AbstractTypeProvider implements TypeProvider { } /** - * Converts leafrefType to JAVA Type. + * Converts leafrefType to JAVA Type. The path of leafrefType is followed + * to find referenced node and its Type is returned. * - * The path of leafrefType is followed to find referenced node - * and its Type is returned. - * - * @param leafrefType - * leafref type definition for which is the type sought - * @return JAVA Type of data schema node which is referenced in - * leafrefType + * @param leafrefType leafref type definition for which is the type sought + * @param parentNode parent node of the leaf being resolved + * @param inGrouping true if we are resolving the type within a grouping. + * @return JAVA Type of data schema node which is referenced in leafrefType * @throws IllegalArgumentException *
      *
    • if leafrefType equal null
    • *
    • if path statement of leafrefType equal null
    • *
    - * */ - public Type provideTypeForLeafref(final LeafrefTypeDefinition leafrefType, final SchemaNode parentNode) { - Type returnType = null; + @VisibleForTesting + Type provideTypeForLeafref(final LeafrefTypeDefinition leafrefType, final SchemaNode parentNode, + final boolean inGrouping) { Preconditions.checkArgument(leafrefType != null, "Leafref Type Definition reference cannot be NULL!"); - Preconditions.checkArgument(leafrefType.getPathStatement() != null, - "The Path Statement for Leafref Type Definition cannot be NULL!"); + final PathExpression xpath = leafrefType.getPathStatement(); + Preconditions.checkArgument(xpath != null, "The Path Statement for Leafref Type Definition cannot be NULL!"); - final RevisionAwareXPath xpath = leafrefType.getPathStatement(); - final String strXPath = xpath.toString(); + final String strXPath = xpath.getOriginalString(); + if (strXPath.indexOf('[') != -1) { + // XXX: why are we special-casing this? + return Types.objectType(); + } - if (strXPath != null) { - if (strXPath.indexOf('[') == -1) { - final Module module = findParentModule(schemaContext, parentNode); - Preconditions.checkArgument(module != null, "Failed to find module for parent %s", parentNode); + final Module module = findParentModule(schemaContext, parentNode); + Preconditions.checkArgument(module != null, "Failed to find module for parent %s", parentNode); - final SchemaNode dataNode; - if (xpath.isAbsolute()) { - dataNode = findDataSchemaNode(schemaContext, module, xpath); - } else { - dataNode = findDataSchemaNodeForRelativeXPath(schemaContext, module, parentNode, xpath); - } - Preconditions.checkArgument(dataNode != null, "Failed to find leafref target: %s in module %s (%s)", - strXPath, this.getParentModule(parentNode).getName(), parentNode.getQName().getModule()); - - if (leafContainsEnumDefinition(dataNode)) { - returnType = referencedTypes.get(dataNode.getPath()); - } else if (leafListContainsEnumDefinition(dataNode)) { - returnType = Types.listTypeFor(referencedTypes.get(dataNode.getPath())); - } else { - returnType = resolveTypeFromDataSchemaNode(dataNode); - } - } else { - returnType = Types.typeForClass(Object.class); + final SchemaNode dataNode; + if (xpath.isAbsolute()) { + dataNode = findDataTreeSchemaNode(schemaContext, module.getQNameModule(), xpath); + } else { + dataNode = findDataSchemaNodeForRelativeXPath(schemaContext, module, parentNode, xpath); + if (dataNode == null && inGrouping) { + // Relative path within a grouping may end up being unresolvable because it may refer outside + // the grouping, in which case it is polymorphic based on instantiation, for example: + // + // grouping foo { + // leaf foo { + // type leafref { + // path "../../bar"; + // } + // } + // } + // + // container one { + // leaf bar { + // type string; + // } + // uses foo; + // } + // + // container two { + // leaf bar { + // type uint16; + // } + // uses foo; + // } + LOG.debug("Leafref type {} not found in parent {}, assuming polymorphic object", leafrefType, + parentNode); + return Types.objectType(); } } + Preconditions.checkArgument(dataNode != null, "Failed to find leafref target: %s in module %s (%s)", + strXPath, this.getParentModule(parentNode).getName(), parentNode.getQName().getModule()); + + // FIXME: this block seems to be some weird magic hack. Analyze and refactor it. + Type returnType = null; + if (leafContainsEnumDefinition(dataNode)) { + returnType = referencedTypes.get(dataNode.getPath()); + } else if (leafListContainsEnumDefinition(dataNode)) { + returnType = Types.listTypeFor(referencedTypes.get(dataNode.getPath())); + } + if (returnType == null) { + returnType = resolveTypeFromDataSchemaNode(dataNode, inGrouping); + } Preconditions.checkArgument(returnType != null, "Failed to find leafref target: %s in module %s (%s)", strXPath, this.getParentModule(parentNode).getName(), parentNode.getQName().getModule(), this); return returnType; } /** - * Checks if dataNode is LeafSchemaNode and if it - * so then checks if it is of type EnumTypeDefinition. + * Checks if dataNode is LeafSchemaNode and if it so then checks if it is of type + * EnumTypeDefinition. * - * @param dataNode - * data schema node for which is checked if it is leaf and if it - * is of enum type + * @param dataNode data schema node for which is checked if it is leaf and if it is of enum type * @return boolean value *
      *
    • true - if dataNode is leaf of type enumeration
    • @@ -584,20 +596,16 @@ public abstract class AbstractTypeProvider implements TypeProvider { private static boolean leafContainsEnumDefinition(final SchemaNode dataNode) { if (dataNode instanceof LeafSchemaNode) { final LeafSchemaNode leaf = (LeafSchemaNode) dataNode; - if (CompatUtils.compatLeafType(leaf) instanceof EnumTypeDefinition) { - return true; - } + return CompatUtils.compatType(leaf) instanceof EnumTypeDefinition; } return false; } /** - * Checks if dataNode is LeafListSchemaNode and if - * it so then checks if it is of type EnumTypeDefinition. + * Checks if dataNode is LeafListSchemaNode and if it so then checks if it is of type + * EnumTypeDefinition. * - * @param dataNode - * data schema node for which is checked if it is leaflist and if - * it is of enum type + * @param dataNode data schema node for which is checked if it is leaflist and if it is of enum type * @return boolean value *
        *
      • true - if dataNode is leaflist of type @@ -608,24 +616,17 @@ public abstract class AbstractTypeProvider implements TypeProvider { private static boolean leafListContainsEnumDefinition(final SchemaNode dataNode) { if (dataNode instanceof LeafListSchemaNode) { final LeafListSchemaNode leafList = (LeafListSchemaNode) dataNode; - if (leafList.getType() instanceof EnumTypeDefinition) { - return true; - } + return leafList.getType() instanceof EnumTypeDefinition; } return false; } /** - * Converts enumTypeDef to - * {@link Enumeration - * enumeration}. + * Converts enumTypeDef to {@link Enumeration enumeration}. * - * @param enumTypeDef - * enumeration type definition which is converted to enumeration - * @param enumName - * string with name which is used as the enumeration name - * @return enumeration type which is built with data (name, enum values) - * from enumTypeDef + * @param enumTypeDef enumeration type definition which is converted to enumeration + * @param enumName string with name which is used as the enumeration name + * @return enumeration type which is built with data (name, enum values) from enumTypeDef * @throws IllegalArgumentException *
          *
        • if enumTypeDef equals null
        • @@ -655,18 +656,12 @@ public abstract class AbstractTypeProvider implements TypeProvider { } /** - * Adds enumeration to typeBuilder. The enumeration data are - * taken from enumTypeDef. + * Adds enumeration to typeBuilder. The enumeration data are taken from enumTypeDef. * - * @param enumTypeDef - * enumeration type definition is source of enumeration data for - * typeBuilder - * @param enumName - * string with the name of enumeration - * @param typeBuilder - * generated type builder to which is enumeration added - * @return enumeration type which contains enumeration data form - * enumTypeDef + * @param enumTypeDef enumeration type definition is source of enumeration data for typeBuilder + * @param enumName string with the name of enumeration + * @param typeBuilder generated type builder to which is enumeration added + * @return enumeration type which contains enumeration data form enumTypeDef * @throws IllegalArgumentException *
            *
          • if enumTypeDef equals null
          • @@ -713,14 +708,12 @@ public abstract class AbstractTypeProvider implements TypeProvider { abstract void addCodegenInformation(GeneratedTypeBuilderBase genTOBuilder, TypeDefinition typeDef); /** - * Converts the pattern constraints from typedef to the list of - * the strings which represents these constraints. + * Converts the pattern constraints from typedef to the list of the strings which represents these + * constraints. * - * @param typedef - * extended type in which are the pattern constraints sought + * @param typedef extended type in which are the pattern constraints sought * @return list of strings which represents the constraint patterns - * @throws IllegalArgumentException - * if typedef equals null + * @throws IllegalArgumentException if typedef equals null * */ private Map resolveRegExpressionsFromTypedef(final TypeDefinition typedef) { @@ -735,48 +728,42 @@ public abstract class AbstractTypeProvider implements TypeProvider { /** * Converts dataNode to JAVA Type. * - * @param dataNode - * contains information about YANG type + * @param dataNode contains information about YANG type * @return JAVA Type representation of dataNode */ - private Type resolveTypeFromDataSchemaNode(final SchemaNode dataNode) { + private Type resolveTypeFromDataSchemaNode(final SchemaNode dataNode, final boolean inGrouping) { Type returnType = null; if (dataNode != null) { if (dataNode instanceof LeafSchemaNode) { final LeafSchemaNode leaf = (LeafSchemaNode) dataNode; - final TypeDefinition type = CompatUtils.compatLeafType(leaf); - returnType = javaTypeForSchemaDefinitionType(type, leaf); + final TypeDefinition type = CompatUtils.compatType(leaf); + returnType = javaTypeForSchemaDefinitionType(type, leaf, inGrouping); } else if (dataNode instanceof LeafListSchemaNode) { final LeafListSchemaNode leafList = (LeafListSchemaNode) dataNode; - returnType = javaTypeForSchemaDefinitionType(leafList.getType(), leafList); + returnType = javaTypeForSchemaDefinitionType(leafList.getType(), leafList, inGrouping); } } return returnType; } /** - * Passes through all modules and through all its type definitions and - * convert it to generated types. + * Passes through all modules and through all its type definitions and convert it to generated types. * - * The modules are firstly sorted by mutual dependencies. The modules are - * sequentially passed. All type definitions of a module are at the - * beginning sorted so that type definition with less amount of references - * to other type definition are processed first.
            + *

            + * The modules are first sorted by mutual dependencies. The modules are sequentially passed. All type definitions + * of a module are at the beginning sorted so that type definition with less amount of references to other type + * definition are processed first.
            * For each module is created mapping record in the map * {@link AbstractTypeProvider#genTypeDefsContextMap genTypeDefsContextMap} - * which map current module name to the map which maps type names to - * returned types (generated types). - * + * which map current module name to the map which maps type names to returned types (generated types). */ private void resolveTypeDefsFromContext() { - final Set modules = schemaContext.getModules(); - Preconditions.checkArgument(modules != null, "Set of Modules cannot be NULL!"); - final List modulesSortedByDependency = ModuleDependencySort.sort(modules); + final List modulesSortedByDependency = ModuleDependencySort.sort(schemaContext.getModules()); for (Module module : modulesSortedByDependency) { Map, Map> dateTypeMap = genTypeDefsContextMap.computeIfAbsent( module.getName(), key -> new HashMap<>()); - dateTypeMap.put(module.getRevision(), Collections.emptyMap()); + dateTypeMap.put(module.getRevision(), Collections.emptyMap()); genTypeDefsContextMap.put(module.getName(), dateTypeMap); } @@ -794,15 +781,12 @@ public abstract class AbstractTypeProvider implements TypeProvider { } /** + * Create Type for specified type definition. * - * @param basePackageName - * string with name of package to which the module belongs - * @param module - * string with the name of the module for to which the - * typedef belongs - * @param typedef - * type definition of the node for which should be creted JAVA - * Type (usually generated TO) + * @param basePackageName string with name of package to which the module belongs + * @param module string with the name of the module for to which the typedef belongs + * @param typedef type definition of the node for which should be created JAVA Type + * (usually generated TO) * @return JAVA Type representation of typedef or * null value if basePackageName or * modulName or typedef or Q name of @@ -810,23 +794,23 @@ public abstract class AbstractTypeProvider implements TypeProvider { */ private Type typedefToGeneratedType(final String basePackageName, final Module module, final TypeDefinition typedef) { - final TypeDefinition innerTypedef = typedef.getBaseType(); + final TypeDefinition baseTypedef = typedef.getBaseType(); // See generatedTypeForExtendedDefinitionType() above for rationale behind this special case. - if (innerTypedef instanceof LeafrefTypeDefinition || innerTypedef instanceof IdentityrefTypeDefinition) { + if (baseTypedef instanceof LeafrefTypeDefinition || baseTypedef instanceof IdentityrefTypeDefinition) { return null; } final String typedefName = typedef.getQName().getLocalName(); final Type returnType; - if (innerTypedef.getBaseType() != null) { - returnType = provideGeneratedTOFromExtendedType(typedef, innerTypedef, basePackageName, + if (baseTypedef.getBaseType() != null) { + returnType = provideGeneratedTOFromExtendedType(typedef, baseTypedef, basePackageName, module.getName()); - } else if (innerTypedef instanceof UnionTypeDefinition) { + } else if (baseTypedef instanceof UnionTypeDefinition) { final GeneratedTOBuilder genTOBuilder = provideGeneratedTOBuilderForUnionTypeDef( JavaTypeName.create(basePackageName, BindingMapping.getClassName(typedef.getQName())), - (UnionTypeDefinition) innerTypedef, typedef); + (UnionTypeDefinition) baseTypedef, typedef); genTOBuilder.setTypedef(true); genTOBuilder.setIsUnion(true); addUnitsToGenTO(genTOBuilder, typedef.getUnits().orElse(null)); @@ -843,28 +827,22 @@ public abstract class AbstractTypeProvider implements TypeProvider { method.addParameter(Types.STRING, "defaultValue"); method.setAccessModifier(AccessModifier.PUBLIC); method.setStatic(true); - Set types = additionalTypes.get(module); - if (types == null) { - types = Sets. newHashSet(unionBuilder.build()); - additionalTypes.put(module, types); - } else { - types.add(unionBuilder.build()); - } - } else if (innerTypedef instanceof EnumTypeDefinition) { + additionalTypes.computeIfAbsent(module, key -> new HashSet<>()).add(unionBuilder.build()); + } else if (baseTypedef instanceof EnumTypeDefinition) { // enums are automatically Serializable - final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) innerTypedef; + final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) baseTypedef; // TODO units for typedef enum returnType = provideTypeForEnum(enumTypeDef, typedefName, typedef); - } else if (innerTypedef instanceof BitsTypeDefinition) { + } else if (baseTypedef instanceof BitsTypeDefinition) { final GeneratedTOBuilder genTOBuilder = provideGeneratedTOBuilderForBitsTypeDefinition( JavaTypeName.create(basePackageName, BindingMapping.getClassName(typedef.getQName())), - (BitsTypeDefinition) innerTypedef, module.getName()); + (BitsTypeDefinition) baseTypedef, module.getName()); genTOBuilder.setTypedef(true); addUnitsToGenTO(genTOBuilder, typedef.getUnits().orElse(null)); makeSerializable(genTOBuilder); returnType = genTOBuilder.build(); } else { - final Type javaType = javaTypeForSchemaDefinitionType(innerTypedef, typedef); + final Type javaType = javaTypeForSchemaDefinitionType(baseTypedef, typedef); returnType = wrapJavaTypeIntoTO(basePackageName, typedef, javaType, module.getName()); } if (returnType != null) { @@ -887,28 +865,26 @@ public abstract class AbstractTypeProvider implements TypeProvider { /** * Wraps base YANG type to generated TO. * - * @param basePackageName - * string with name of package to which the module belongs - * @param typedef - * type definition which is converted to the TO - * @param javaType - * JAVA Type to which is typedef mapped + * @param basePackageName string with name of package to which the module belongs + * @param typedef type definition which is converted to the TO + * @param javaType JAVA Type to which is typedef mapped * @return generated transfer object which representjavaType */ private GeneratedTransferObject wrapJavaTypeIntoTO(final String basePackageName, final TypeDefinition typedef, final Type javaType, final String moduleName) { - Preconditions.checkNotNull(javaType, "javaType cannot be null"); - final String propertyName = "value"; + requireNonNull(javaType, "javaType cannot be null"); final GeneratedTOBuilder genTOBuilder = typedefToTransferObject(basePackageName, typedef, moduleName); genTOBuilder.setRestrictions(BindingGeneratorUtil.getRestrictions(typedef)); - final GeneratedPropertyBuilder genPropBuilder = genTOBuilder.addProperty(propertyName); + final GeneratedPropertyBuilder genPropBuilder = genTOBuilder.addProperty(TypeConstants.VALUE_PROP); genPropBuilder.setReturnType(javaType); + genTOBuilder.addEqualsIdentity(genPropBuilder); genTOBuilder.addHashIdentity(genPropBuilder); genTOBuilder.addToStringProperty(genPropBuilder); + genTOBuilder.addImplementsType(BindingTypes.scalarTypeObject(javaType)); if (typedef.getStatus() == Status.DEPRECATED) { - genTOBuilder.addAnnotation("java.lang", "Deprecated"); + genTOBuilder.addAnnotation(DEPRECATED_ANNOTATION); } if (javaType instanceof ConcreteType && "String".equals(javaType.getName()) && typedef.getBaseType() != null) { addStringRegExAsConstant(genTOBuilder, resolveRegExpressionsFromTypedef(typedef)); @@ -935,20 +911,15 @@ public abstract class AbstractTypeProvider implements TypeProvider { final GeneratedTOBuilder resultTOBuilder = builders.remove(0); builders.forEach(resultTOBuilder::addEnclosingTransferObject); - - resultTOBuilder.addProperty("value").setReturnType(Types.CHAR_ARRAY); return resultTOBuilder; } /** - * Converts typedef to generated TO with - * typeDefName. Every union type from typedef is - * added to generated TO builder as property. + * Converts typedef to generated TO with typeDefName. Every union type from + * typedef is added to generated TO builder as property. * * @param typeName new type identifier - * @param typedef - * type definition which should be of type - * UnionTypeDefinition + * @param typedef type definition which should be of type UnionTypeDefinition * @return generated TO builder which represents typedef * @throws NullPointerException *

              @@ -959,20 +930,20 @@ public abstract class AbstractTypeProvider implements TypeProvider { */ public List provideGeneratedTOBuildersForUnionTypeDef(final JavaTypeName typeName, final UnionTypeDefinition typedef, final SchemaNode parentNode) { - Preconditions.checkNotNull(typedef, "Type Definition cannot be NULL!"); - Preconditions.checkNotNull(typedef.getQName(), "Type definition QName cannot be NULL!"); + requireNonNull(typedef, "Type Definition cannot be NULL!"); + requireNonNull(typedef.getQName(), "Type definition QName cannot be NULL!"); final List generatedTOBuilders = new ArrayList<>(); final List> unionTypes = typedef.getTypes(); final Module module = findParentModule(schemaContext, parentNode); final GeneratedTOBuilder unionGenTOBuilder = newGeneratedTOBuilder(typeName); + unionGenTOBuilder.setIsUnion(true); unionGenTOBuilder.setSchemaPath(typedef.getPath()); unionGenTOBuilder.setModuleName(module.getName()); + unionGenTOBuilder.addImplementsType(TYPE_OBJECT); addCodegenInformation(unionGenTOBuilder, typedef); - generatedTOBuilders.add(unionGenTOBuilder); - unionGenTOBuilder.setIsUnion(true); // Pattern string is the key, XSD regex is the value. The reason for this choice is that the pattern carries // also negation information and hence guarantees uniqueness. @@ -1004,26 +975,18 @@ public abstract class AbstractTypeProvider implements TypeProvider { } /** - * Wraps code which handle case when union subtype is also of the type - * UnionType. + * Wraps code which handles the case when union subtype is also of the type UnionType. * - * In this case the new generated TO is created for union subtype (recursive - * call of method - * {@link #provideGeneratedTOBuildersForUnionTypeDef(String, UnionTypeDefinition, - * String, SchemaNode)} - * provideGeneratedTOBuilderForUnionTypeDef} and in parent TO builder - * parentUnionGenTOBuilder is created property which type is - * equal to new generated TO. + *

              + * In this case the new generated TO is created for union subtype (recursive call of method + * {@link #provideGeneratedTOBuildersForUnionTypeDef(String, UnionTypeDefinition, String, SchemaNode)} + * provideGeneratedTOBuilderForUnionTypeDef} and in parent TO builder parentUnionGenTOBuilder is + * created property which type is equal to new generated TO. * - * @param parentUnionGenTOBuilder - * generated TO builder to which is the property with the child - * union subtype added - * @param basePackageName - * string with the name of the module package - * @param unionSubtype - * type definition which represents union subtype - * @return list of generated TO builders. The number of the builders can be - * bigger one due to recursive call of + * @param parentUnionGenTOBuilder generated TO builder to which is the property with the child union subtype added + * @param basePackageName string with the name of the module package + * @param unionSubtype type definition which represents union subtype + * @return list of generated TO builders. The number of the builders can be bigger one due to recursive call of * provideGeneratedTOBuildersForUnionTypeDef method. */ private List resolveUnionSubtypeAsUnion(final GeneratedTOBuilder parentUnionGenTOBuilder, @@ -1036,7 +999,7 @@ public abstract class AbstractTypeProvider implements TypeProvider { final GeneratedPropertyBuilder propertyBuilder; propertyBuilder = parentUnionGenTOBuilder.addProperty(BindingMapping.getPropertyName( newTOBuilderName.simpleName())); - propertyBuilder.setReturnType(subUnionGenTOBUilders.get(0)); + propertyBuilder.setReturnType(subUnionGenTOBUilders.get(0).build()); parentUnionGenTOBuilder.addEqualsIdentity(propertyBuilder); parentUnionGenTOBuilder.addToStringProperty(propertyBuilder); @@ -1044,23 +1007,14 @@ public abstract class AbstractTypeProvider implements TypeProvider { } /** - * Wraps code which handle case when union subtype is of the type - * ExtendedType. - * - * If TO for this type already exists it is used for the creation of the - * property in parentUnionGenTOBuilder. In other case the base - * type is used for the property creation. - * - * @param parentUnionGenTOBuilder - * generated TO builder in which new property is created - * @param unionSubtype - * type definition of the ExtendedType type which - * represents union subtype - * @param expressions - * list of strings with the regular expressions - * @param parentNode - * parent Schema Node for Extended Subtype + * Wraps code which handle case when union subtype is of the type ExtendedType. If TO for this type + * already exists it is used for the creation of the property in parentUnionGenTOBuilder. Otherwise + * the base type is used for the property creation. * + * @param parentUnionGenTOBuilder generated TO builder in which new property is created + * @param unionSubtype type definition of the ExtendedType type which represents union subtype + * @param expressions list of strings with the regular expressions + * @param parentNode parent Schema Node for Extended Subtype */ private void resolveExtendedSubtypeAsUnion(final GeneratedTOBuilder parentUnionGenTOBuilder, final TypeDefinition unionSubtype, final Map expressions, final SchemaNode parentNode) { @@ -1073,8 +1027,8 @@ public abstract class AbstractTypeProvider implements TypeProvider { final TypeDefinition baseType = baseTypeDefForExtendedType(unionSubtype); if (unionTypeName.equals(baseType.getQName().getLocalName())) { - final Type javaType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(baseType, - parentNode); + final Type javaType = BaseYangTypesProvider.INSTANCE.javaTypeForSchemaDefinitionType(baseType, parentNode, + BindingGeneratorUtil.getRestrictions(unionSubtype)); if (javaType != null) { updateUnionTypeAsProperty(parentUnionGenTOBuilder, javaType, unionTypeName); } @@ -1099,18 +1053,17 @@ public abstract class AbstractTypeProvider implements TypeProvider { } /** - * Searches for generated TO for searchedTypeDef type - * definition in {@link #genTypeDefsContextMap genTypeDefsContextMap} + * Searches for generated TO for searchedTypeDef type definition + * in {@link #genTypeDefsContextMap genTypeDefsContextMap}. * - * @param searchedTypeName - * string with name of searchedTypeDef - * @return generated TO for searchedTypeDef or - * null it it doesn't exist + * @param searchedTypeName string with name of searchedTypeDef + * @return generated TO for searchedTypeDef or null it it doesn't exist */ private Type findGenTO(final String searchedTypeName, final SchemaNode parentNode) { final Module typeModule = findParentModule(schemaContext, parentNode); if (typeModule != null && typeModule.getName() != null) { - final Map, Map> modulesByDate = genTypeDefsContextMap.get(typeModule.getName()); + final Map, Map> modulesByDate = genTypeDefsContextMap.get( + typeModule.getName()); final Map genTOs = modulesByDate.get(typeModule.getRevision()); if (genTOs != null) { return genTOs.get(searchedTypeName); @@ -1120,21 +1073,19 @@ public abstract class AbstractTypeProvider implements TypeProvider { } /** - * Stores generated TO created from genTOBuilder for - * newTypeDef to {@link #genTypeDefsContextMap - * genTypeDefsContextMap} if the module for newTypeDef exists + * Stores generated TO created from genTOBuilder for newTypeDef + * to {@link #genTypeDefsContextMap genTypeDefsContextMap} if the module for newTypeDef exists. * - * @param newTypeDef - * type definition for which is genTOBuilder created - * @param genTOBuilder - * generated TO builder which is converted to generated TO and - * stored + * @param newTypeDef type definition for which is genTOBuilder created + * @param genTOBuilder generated TO builder which is converted to generated TO and stored */ - private void storeGenTO(final TypeDefinition newTypeDef, final GeneratedTOBuilder genTOBuilder, final SchemaNode parentNode) { + private void storeGenTO(final TypeDefinition newTypeDef, final GeneratedTOBuilder genTOBuilder, + final SchemaNode parentNode) { if (!(newTypeDef instanceof UnionTypeDefinition)) { final Module parentModule = findParentModule(schemaContext, parentNode); if (parentModule != null && parentModule.getName() != null) { - final Map, Map> modulesByDate = genTypeDefsContextMap.get(parentModule.getName()); + final Map, Map> modulesByDate = genTypeDefsContextMap.get( + parentModule.getName()); final Map genTOsMap = modulesByDate.get(parentModule.getRevision()); genTOsMap.put(newTypeDef.getQName().getLocalName(), genTOBuilder.build()); } @@ -1142,19 +1093,15 @@ public abstract class AbstractTypeProvider implements TypeProvider { } /** - * Adds a new property with the name propertyName and with type - * type to unonGenTransObject. + * Adds a new property with the name propertyName and with type type + * to unonGenTransObject. * - * @param unionGenTransObject - * generated TO to which should be property added - * @param type - * JAVA type of the property which should be added - * to unionGentransObject - * @param propertyName - * string with name of property which should be added to - * unionGentransObject + * @param unionGenTransObject generated TO to which should be property added + * @param type JAVA type of the property which should be added to unionGentransObject + * @param propertyName string with name of property which should be added to unionGentransObject */ - private static void updateUnionTypeAsProperty(final GeneratedTOBuilder unionGenTransObject, final Type type, final String propertyName) { + private static void updateUnionTypeAsProperty(final GeneratedTOBuilder unionGenTransObject, final Type type, + final String propertyName) { if (unionGenTransObject != null && type != null && !unionGenTransObject.containsProperty(propertyName)) { final GeneratedPropertyBuilder propBuilder = unionGenTransObject .addProperty(BindingMapping.getPropertyName(propertyName)); @@ -1169,18 +1116,20 @@ public abstract class AbstractTypeProvider implements TypeProvider { /** * Converts typedef to the generated TO builder. * - * @param basePackageName - * string with name of package to which the module belongs - * @param typedef - * type definition from which is the generated TO builder created - * @return generated TO builder which contains data from - * typedef and basePackageName + * @param basePackageName string with name of package to which the module belongs + * @param typedef type definition from which is the generated TO builder created + * @return generated TO builder which contains data from typedef and basePackageName */ private GeneratedTOBuilder typedefToTransferObject(final String basePackageName, final TypeDefinition typedef, final String moduleName) { - final GeneratedTOBuilder newType = newGeneratedTOBuilder(JavaTypeName.create( - BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, typedef.getPath()), - BindingMapping.getClassName(typedef.getQName().getLocalName()))); + JavaTypeName name = renames.get(typedef); + if (name == null) { + name = JavaTypeName.create( + BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, typedef.getPath()), + BindingMapping.getClassName(typedef.getQName().getLocalName())); + } + + final GeneratedTOBuilder newType = newGeneratedTOBuilder(name); newType.setSchemaPath(typedef.getPath()); newType.setModuleName(moduleName); addCodegenInformation(newType, typedef); @@ -1188,15 +1137,12 @@ public abstract class AbstractTypeProvider implements TypeProvider { } /** - * Converts typeDef which should be of the type - * BitsTypeDefinition to GeneratedTOBuilder. - * - * All the bits of the typeDef are added to returning generated TO as + * Converts typeDef which should be of the type BitsTypeDefinition + * to GeneratedTOBuilder. All the bits of the typeDef are added to returning generated TO as * properties. * * @param typeName new type identifier - * @param typeDef - * type definition from which is the generated TO builder created + * @param typeDef type definition from which is the generated TO builder created * @return generated TO builder which represents typeDef * @throws IllegalArgumentException *

                @@ -1210,13 +1156,13 @@ public abstract class AbstractTypeProvider implements TypeProvider { genTOBuilder.setSchemaPath(typeDef.getPath()); genTOBuilder.setModuleName(moduleName); genTOBuilder.setBaseType(typeDef); + genTOBuilder.addImplementsType(TYPE_OBJECT); addCodegenInformation(genTOBuilder, typeDef); - final List bitList = typeDef.getBits(); - GeneratedPropertyBuilder genPropertyBuilder; - for (Bit bit : bitList) { + for (Bit bit : typeDef.getBits()) { final String name = bit.getName(); - genPropertyBuilder = genTOBuilder.addProperty(BindingMapping.getPropertyName(name)); + GeneratedPropertyBuilder genPropertyBuilder = genTOBuilder.addProperty( + BindingMapping.getPropertyName(name)); genPropertyBuilder.setReadOnly(true); genPropertyBuilder.setReturnType(BaseYangTypes.BOOLEAN_TYPE); @@ -1229,15 +1175,11 @@ public abstract class AbstractTypeProvider implements TypeProvider { } /** + * Adds to the genTOBuilder the constant which contains regular expressions from + * the regularExpressions. * - * Adds to the genTOBuilder the constant which contains regular - * expressions from the regularExpressions - * - * @param genTOBuilder - * generated TO builder to which are - * regular expressions added - * @param expressions - * list of string which represent regular expressions + * @param genTOBuilder generated TO builder to which are regular expressions added + * @param expressions list of string which represent regular expressions */ private static void addStringRegExAsConstant(final GeneratedTOBuilder genTOBuilder, final Map expressions) { @@ -1248,25 +1190,19 @@ public abstract class AbstractTypeProvider implements TypeProvider { } /** - * Creates generated TO with data about inner extended type - * innerExtendedType, about the package name - * typedefName and about the generated TO name - * typedefName. + * Creates generated TO with data about inner extended type innerExtendedType, about the package name + * typedefName and about the generated TO name typedefName. * - * It is supposed that innerExtendedType is already present in - * {@link AbstractTypeProvider#genTypeDefsContextMap genTypeDefsContextMap} to - * be possible set it as extended type for the returning generated TO. + *

                + * It is assumed that innerExtendedType is already present in + * {@link AbstractTypeProvider#genTypeDefsContextMap genTypeDefsContextMap} to be possible set it as extended type + * for the returning generated TO. * - * @param typedef - * Type Definition - * @param innerExtendedType - * extended type which is part of some other extended type - * @param basePackageName - * string with the package name of the module - * @param moduleName - * Module Name - * @return generated TO which extends generated TO for - * innerExtendedType + * @param typedef Type Definition + * @param innerExtendedType extended type which is part of some other extended type + * @param basePackageName string with the package name of the module + * @param moduleName Module Name + * @return generated TO which extends generated TO for innerExtendedType * @throws IllegalArgumentException *

                  *
                • if extendedType equals null
                • @@ -1288,8 +1224,10 @@ public abstract class AbstractTypeProvider implements TypeProvider { final Restrictions r = BindingGeneratorUtil.getRestrictions(typedef); genTOBuilder.setRestrictions(r); + addStringRegExAsConstant(genTOBuilder, resolveRegExpressionsFromTypedef(typedef)); + if (typedef.getStatus() == Status.DEPRECATED) { - genTOBuilder.addAnnotation("java.lang", "Deprecated"); + genTOBuilder.addAnnotation(DEPRECATED_ANNOTATION); } if (baseTypeDefForExtendedType(innerExtendedType) instanceof UnionTypeDefinition) { @@ -1318,32 +1256,27 @@ public abstract class AbstractTypeProvider implements TypeProvider { } /** - * Add {@link Serializable} to implemented interfaces of this TO. Also - * compute and add serialVersionUID property. + * Add {@link java.io.Serializable} to implemented interfaces of this TO. Also compute and add serialVersionUID + * property. * - * @param gto - * transfer object which needs to be serializable + * @param gto transfer object which needs to be made serializable */ private static void makeSerializable(final GeneratedTOBuilder gto) { - gto.addImplementsType(Types.typeForClass(Serializable.class)); + gto.addImplementsType(Types.serializableType()); final GeneratedPropertyBuilder prop = new GeneratedPropertyBuilderImpl("serialVersionUID"); prop.setValue(Long.toString(BindingGeneratorUtil.computeDefaultSUID(gto))); gto.setSUID(prop); } /** - * Finds out for each type definition how many immersion (depth) is - * necessary to get to the base type. Every type definition is inserted to - * the map which key is depth and value is list of type definitions with - * equal depth. In next step are lists from this map concatenated to one - * list in ascending order according to their depth. All type definitions - * are in the list behind all type definitions on which depends. + * Finds out for each type definition how many immersion (depth) is necessary to get to the base type. Every type + * definition is inserted to the map which key is depth and value is list of type definitions with equal depth. + * In next step are lists from this map concatenated to one list in ascending order according to their depth. All + * type definitions are in the list behind all type definitions on which depends. * - * @param unsortedTypeDefinitions - * list of type definitions which should be sorted by depth - * @return list of type definitions sorted according their each other - * dependencies (type definitions which are depend on other type - * definitions are in list behind them). + * @param unsortedTypeDefinitions list of type definitions which should be sorted by depth + * @return list of type definitions sorted according their each other dependencies (type definitions which are + * dependent on other type definitions are in list behind them). */ private static List> sortTypeDefinitionAccordingDepth( final Collection> unsortedTypeDefinitions) { @@ -1352,11 +1285,8 @@ public abstract class AbstractTypeProvider implements TypeProvider { final Map>> typeDefinitionsDepths = new TreeMap<>(); for (TypeDefinition unsortedTypeDefinition : unsortedTypeDefinitions) { final Integer depth = getTypeDefinitionDepth(unsortedTypeDefinition); - List> typeDefinitionsConcreteDepth = typeDefinitionsDepths.get(depth); - if (typeDefinitionsConcreteDepth == null) { - typeDefinitionsConcreteDepth = new ArrayList<>(); - typeDefinitionsDepths.put(depth, typeDefinitionsConcreteDepth); - } + List> typeDefinitionsConcreteDepth = + typeDefinitionsDepths.computeIfAbsent(depth, k -> new ArrayList<>()); typeDefinitionsConcreteDepth.add(unsortedTypeDefinition); } @@ -1369,13 +1299,10 @@ public abstract class AbstractTypeProvider implements TypeProvider { } /** - * Returns how many immersion is necessary to get from the type definition - * to the base type. + * Returns how many immersion is necessary to get from the type definition to the base type. * - * @param typeDefinition - * type definition for which is depth sought. - * @return number of immersions which are necessary to get from the type - * definition to the base type + * @param typeDefinition type definition for which is depth sought. + * @return number of immersions which are necessary to get from the type definition to the base type */ private static int getTypeDefinitionDepth(final TypeDefinition typeDefinition) { // FIXME: rewrite this in a non-recursive manner @@ -1406,21 +1333,22 @@ public abstract class AbstractTypeProvider implements TypeProvider { } /** - * Returns string which contains the same value as name but - * integer suffix is incremented by one. If name contains no - * number suffix then number 1 is added. + * Returns string which contains the same value as name but integer suffix is incremented by one. If + * name contains no number suffix, a new suffix initialized at 1 is added. A suffix is actually + * composed of a '$' marker, which is safe, as no YANG identifier can contain '$', and a unsigned decimal integer. * * @param name string with name of augmented node * @return string with the number suffix incremented by one (or 1 is added) */ private static String provideAvailableNameForGenTOBuilder(final String name) { - final Matcher mtch = NUMBERS_PATTERN.matcher(name); - if (mtch.find()) { - final int newSuffix = Integer.parseInt(name.substring(mtch.start())) + 1; - return name.substring(0, mtch.start()) + newSuffix; + final int dollar = name.indexOf('$'); + if (dollar == -1) { + return name + "$1"; } - return name + 1; + final int newSuffix = Integer.parseUnsignedInt(name.substring(dollar + 1)) + 1; + Preconditions.checkState(newSuffix > 0, "Suffix counter overflow"); + return name.substring(0, dollar + 1) + newSuffix; } public static void addUnitsToGenTO(final GeneratedTOBuilder to, final String units) { @@ -1438,12 +1366,12 @@ public abstract class AbstractTypeProvider implements TypeProvider { } public String getTypeDefaultConstruction(final LeafSchemaNode node, final String defaultValue) { - final TypeDefinition type = CompatUtils.compatLeafType(node); + final TypeDefinition type = CompatUtils.compatType(node); final QName typeQName = type.getQName(); final TypeDefinition base = baseTypeDefForExtendedType(type); - Preconditions.checkNotNull(type, "Cannot provide default construction for null type of %s", node); - Preconditions.checkNotNull(defaultValue, "Cannot provide default construction for null default statement of %s", - node); + requireNonNull(type, () -> "Cannot provide default construction for null type of " + node); + requireNonNull(defaultValue, () -> "Cannot provide default construction for null default statement of " + + node); final StringBuilder sb = new StringBuilder(); String result = null; @@ -1461,7 +1389,8 @@ public abstract class AbstractTypeProvider implements TypeProvider { className = basePackageName + "." + parentName + "." + BindingMapping.getClassName(node.getQName()); } else { final String basePackageName = BindingMapping.getRootPackageName(parent.getQNameModule()); - final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, type.getPath()); + final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, + type.getPath()); parentName = BindingMapping.getClassName(parent.getName()); className = packageName + "." + parentName + "." + BindingMapping.getClassName(node.getQName()); } @@ -1481,12 +1410,14 @@ public abstract class AbstractTypeProvider implements TypeProvider { if (type.getBaseType() != null) { final Module m = getParentModule(type); final String basePackageName = BindingMapping.getRootPackageName(m.getQNameModule()); - final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, type.getPath()); + final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, + type.getPath()); className = packageName + "." + BindingMapping.getClassName(typeQName); } else { final Module parentModule = getParentModule(node); final String basePackageName = BindingMapping.getRootPackageName(parentModule.getQNameModule()); - final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, node.getPath()); + final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, + node.getPath()); className = packageName + "." + BindingMapping.getClassName(node.getQName()); } result = className + "." + newDefVal; @@ -1494,38 +1425,26 @@ public abstract class AbstractTypeProvider implements TypeProvider { throw new UnsupportedOperationException("Cannot get default construction for identityref type"); } else if (base instanceof InstanceIdentifierTypeDefinition) { throw new UnsupportedOperationException("Cannot get default construction for instance-identifier type"); - } else if (BaseTypes.isInt8(base)) { + } else if (isInt8(base)) { result = typeToValueOfDef(Byte.class, defaultValue); - } else if (BaseTypes.isInt16(base)) { + } else if (isInt16(base)) { result = typeToValueOfDef(Short.class, defaultValue); - } else if (BaseTypes.isInt32(base)) { + } else if (isInt32(base)) { result = typeToValueOfDef(Integer.class, defaultValue); - } else if (BaseTypes.isInt64(base)) { + } else if (isInt64(base)) { result = typeToValueOfDef(Long.class, defaultValue); } else if (base instanceof LeafrefTypeDefinition) { result = leafrefToDef(node, (LeafrefTypeDefinition) base, defaultValue); } else if (base instanceof StringTypeDefinition) { result = "\"" + defaultValue + "\""; - } else if (BaseTypes.isUint8(base)) { - result = typeToValueOfDef(Short.class, defaultValue); - } else if (BaseTypes.isUint16(base)) { - result = typeToValueOfDef(Integer.class, defaultValue); - } else if (BaseTypes.isUint32(base)) { - result = typeToValueOfDef(Long.class, defaultValue); - } else if (BaseTypes.isUint64(base)) { - switch (defaultValue) { - case "0": - result = "java.math.BigInteger.ZERO"; - break; - case "1": - result = "java.math.BigInteger.ONE"; - break; - case "10": - result = "java.math.BigInteger.TEN"; - break; - default: - result = typeToDef(BigInteger.class, defaultValue); - } + } else if (isUint8(base)) { + result = typeToValueOfDef(Uint8.class, defaultValue); + } else if (isUint16(base)) { + result = typeToValueOfDef(Uint16.class, defaultValue); + } else if (isUint32(base)) { + result = typeToValueOfDef(Uint32.class, defaultValue); + } else if (isUint64(base)) { + result = typeToValueOfDef(Uint64.class, defaultValue); } else if (base instanceof UnionTypeDefinition) { result = unionToDef(node); } else { @@ -1537,7 +1456,8 @@ public abstract class AbstractTypeProvider implements TypeProvider { && !(base instanceof EnumTypeDefinition) && !(base instanceof UnionTypeDefinition)) { final Module m = getParentModule(type); final String basePackageName = BindingMapping.getRootPackageName(m.getQNameModule()); - final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, type.getPath()); + final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, + type.getPath()); final String className = packageName + "." + BindingMapping.getClassName(typeQName); sb.insert(0, "new " + className + "("); sb.insert(sb.length(), ')'); @@ -1546,6 +1466,91 @@ public abstract class AbstractTypeProvider implements TypeProvider { return sb.toString(); } + + /** + * Check if a particular type definition represents the built-in int8 type. + * + * @param type Type definition + * @return True if the definition is the built-in int8 type. + */ + private static boolean isInt8(final TypeDefinition type) { + return BaseTypes.int8Type().getPath().equals(type.getPath()); + } + + /** + * Check if a particular type definition represents the built-in int16 type. + * + * @param type Type definition + * @return True if the definition is the built-in int16 type. + */ + private static boolean isInt16(final TypeDefinition type) { + return BaseTypes.int16Type().getPath().equals(type.getPath()); + } + + /** + * Check if a particular type definition represents the built-in int32 type. + * + * @param type Type definition + * @return True if the definition is the built-in int32 type. + */ + private static boolean isInt32(final TypeDefinition type) { + return BaseTypes.int32Type().getPath().equals(type.getPath()); + } + + /** + * Check if a particular type definition represents the built-in int64 type. + * + * @param type Type definition + * @return True if the definition is the built-in int64 type. + */ + private static boolean isInt64(final TypeDefinition type) { + return BaseTypes.int64Type().getPath().equals(type.getPath()); + } + + /** + * Check if a particular type is the base type for uint8. + * + * @param type The type to check + * @return If the type corresponds to the base uint8 type. + * @throws NullPointerException if type is null + */ + private static boolean isUint8(final TypeDefinition type) { + return BaseTypes.uint8Type().getPath().equals(type.getPath()); + } + + /** + * Check if a particular type is the base type for uint16. + * + * @param type The type to check + * @return If the type corresponds to the base uint16 type. + * @throws NullPointerException if type is null + */ + private static boolean isUint16(final TypeDefinition type) { + return BaseTypes.uint16Type().getPath().equals(type.getPath()); + } + + /** + * Check if a particular type is the base type for uint32. + * + * @param type The type to check + * @return If the type corresponds to the base uint32 type. + * @throws NullPointerException if type is null + */ + private static boolean isUint32(final TypeDefinition type) { + return BaseTypes.uint32Type().getPath().equals(type.getPath()); + } + + /** + * Check if a particular type is the base type for uint64. + * + * @param type The type to check + * @return If the type corresponds to the base uint64 type. + * @throws NullPointerException if type is null + */ + private static boolean isUint64(final TypeDefinition type) { + return BaseTypes.uint64Type().getPath().equals(type.getPath()); + } + private static String typeToDef(final Class clazz, final String defaultValue) { return "new " + clazz.getName() + "(\"" + defaultValue + "\")"; } @@ -1567,8 +1572,7 @@ public abstract class AbstractTypeProvider implements TypeProvider { private static String binaryToDef(final String defaultValue) { final StringBuilder sb = new StringBuilder(); - final BaseEncoding en = BaseEncoding.base64(); - final byte[] encoded = en.decode(defaultValue); + final byte[] encoded = Base64.getDecoder().decode(defaultValue); sb.append("new byte[] {"); for (int i = 0; i < encoded.length; i++) { sb.append(encoded[i]); @@ -1580,23 +1584,18 @@ public abstract class AbstractTypeProvider implements TypeProvider { return sb.toString(); } - private static final Comparator BIT_NAME_COMPARATOR = (o1, o2) -> o1.getName().compareTo(o2.getName()); + private static final Comparator BIT_NAME_COMPARATOR = Comparator.comparing(Bit::getName); - private static String bitsToDef(final BitsTypeDefinition type, final String className, final String defaultValue, final boolean isExt) { + private static String bitsToDef(final BitsTypeDefinition type, final String className, final String defaultValue, + final boolean isExt) { final List bits = new ArrayList<>(type.getBits()); - Collections.sort(bits, BIT_NAME_COMPARATOR); + bits.sort(BIT_NAME_COMPARATOR); final StringBuilder sb = new StringBuilder(); if (!isExt) { - sb.append("new "); - sb.append(className); - sb.append('('); + sb.append("new ").append(className).append('('); } for (int i = 0; i < bits.size(); i++) { - if (bits.get(i).getName().equals(defaultValue)) { - sb.append(true); - } else { - sb.append(false); - } + sb.append(bits.get(i).getName().equals(defaultValue)); if (i != bits.size() - 1) { sb.append(", "); } @@ -1612,13 +1611,14 @@ public abstract class AbstractTypeProvider implements TypeProvider { return schemaContext.findModule(qname.getModule()).orElse(null); } - private String leafrefToDef(final LeafSchemaNode parentNode, final LeafrefTypeDefinition leafrefType, final String defaultValue) { + private String leafrefToDef(final LeafSchemaNode parentNode, final LeafrefTypeDefinition leafrefType, + final String defaultValue) { Preconditions.checkArgument(leafrefType != null, "Leafref Type Definition reference cannot be NULL!"); Preconditions.checkArgument(leafrefType.getPathStatement() != null, "The Path Statement for Leafref Type Definition cannot be NULL!"); - final RevisionAwareXPath xpath = leafrefType.getPathStatement(); - final String strXPath = xpath.toString(); + final PathExpression xpath = leafrefType.getPathStatement(); + final String strXPath = xpath.getOriginalString(); if (strXPath != null) { if (strXPath.indexOf('[') == -1) { @@ -1626,7 +1626,7 @@ public abstract class AbstractTypeProvider implements TypeProvider { if (module != null) { final SchemaNode dataNode; if (xpath.isAbsolute()) { - dataNode = findDataSchemaNode(schemaContext, module, xpath); + dataNode = findDataTreeSchemaNode(schemaContext, module.getQNameModule(), xpath); } else { dataNode = findDataSchemaNodeForRelativeXPath(schemaContext, module, parentNode, xpath); } @@ -1642,14 +1642,14 @@ public abstract class AbstractTypeProvider implements TypeProvider { } private String unionToDef(final LeafSchemaNode node) { - final TypeDefinition type = CompatUtils.compatLeafType(node); + final TypeDefinition type = CompatUtils.compatType(node); String parentName; String className; if (type.getBaseType() != null) { final QName typeQName = type.getQName(); Module module = null; - final Set modules = schemaContext.findModules(typeQName.getNamespace()); + final Collection modules = schemaContext.findModules(typeQName.getNamespace()); if (modules.size() > 1) { for (Module m : modules) { if (m.getRevision().equals(typeQName.getRevision())) { @@ -1659,7 +1659,7 @@ public abstract class AbstractTypeProvider implements TypeProvider { } if (module == null) { final List modulesList = new ArrayList<>(modules); - Collections.sort(modulesList, (o1, o2) -> Revision.compare(o1.getRevision(), o2.getRevision())); + modulesList.sort((o1, o2) -> Revision.compare(o1.getRevision(), o2.getRevision())); module = modulesList.get(0); } } else { @@ -1677,7 +1677,8 @@ public abstract class AbstractTypeProvider implements TypeProvider { parentName = BindingMapping.getClassName(parent.getName()) + "Data"; className = basePackageName + "." + parentName + "." + BindingMapping.getClassName(node.getQName()); } else { - final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, UNION_PATH); + final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, + UNION_PATH); className = packageName + "." + BindingMapping.getClassName(node.getQName()); } } @@ -1685,18 +1686,14 @@ public abstract class AbstractTypeProvider implements TypeProvider { } private static String union(final String className, final String defaultValue, final LeafSchemaNode node) { - final StringBuilder sb = new StringBuilder(); - sb.append("new "); - sb.append(className); - sb.append("(\""); - sb.append(defaultValue); - sb.append("\".toCharArray())"); - return sb.toString(); + return new StringBuilder() + .append("new ").append(className).append("(\"").append(defaultValue).append("\".toCharArray())") + .toString(); } @Override public String getConstructorPropertyName(final SchemaNode node) { - return node instanceof TypeDefinition ? "value" : ""; + return node instanceof TypeDefinition ? TypeConstants.VALUE_PROP : ""; } @Override