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=2efc0f64c3fe6dc619dd89d1a4966b021fda9ba4;hb=5257d1f5ee59ade8f1b56078eda5e0b78e6d9183;hp=bf18b8ceb9e91a869fe753090d215d851fe3f4c0;hpb=bfb3b357df148461df21408e856334c8983ecb6d;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 bf18b8ceb9..2efc0f64c3 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 @@ -8,15 +8,15 @@ package org.opendaylight.mdsal.binding.yang.types; import static java.util.Objects.requireNonNull; -import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataSchemaNode; +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.base.Preconditions; import com.google.common.base.Strings; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Sets; import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; @@ -25,6 +25,7 @@ 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; @@ -61,7 +62,7 @@ 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; @@ -81,7 +82,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; @@ -150,8 +151,9 @@ public abstract class AbstractTypeProvider implements TypeProvider { } @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); } /** @@ -167,7 +169,7 @@ public abstract class AbstractTypeProvider implements TypeProvider { */ @Override public Type javaTypeForSchemaDefinitionType(final TypeDefinition typeDefinition, final SchemaNode parentNode, - final Restrictions restrictions) { + 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!)"); @@ -181,14 +183,14 @@ public abstract class AbstractTypeProvider implements TypeProvider { // a base type which holds these constraints. if (typeDefinition instanceof DecimalTypeDefinition) { final Type ret = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(typeDefinition, - parentNode, restrictions); + 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; } @@ -202,7 +204,7 @@ public abstract class AbstractTypeProvider implements TypeProvider { return ret; } - Type returnType = javaTypeForExtendedType(typeDefinition); + Type returnType = javaTypeForExtendedType(typeDefinition, lenientRelativeLeafrefs); if (restrictions != null && returnType instanceof GeneratedTransferObject) { final GeneratedTransferObject gto = (GeneratedTransferObject) returnType; final Module module = findParentModule(schemaContext, parentNode); @@ -239,45 +241,42 @@ 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); } @@ -288,12 +287,13 @@ public abstract class AbstractTypeProvider implements TypeProvider { * @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); } @@ -307,10 +307,10 @@ public abstract class AbstractTypeProvider implements TypeProvider { * @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; @@ -327,7 +327,7 @@ public abstract class AbstractTypeProvider implements TypeProvider { } if (returnType == null) { returnType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType( - baseTypeDef, typeDefinition, r); + baseTypeDef, typeDefinition, r, lenient); } } } @@ -484,50 +484,79 @@ public abstract class AbstractTypeProvider implements TypeProvider { * to find referenced node and its Type is returned. * * @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 * - * */ - public Type provideTypeForLeafref(final LeafrefTypeDefinition leafrefType, final SchemaNode parentNode) { + public 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 RevisionAwareXPath xpath = leafrefType.getPathStatement(); - final String strXPath = xpath.toString(); - Type returnType = null; + final PathExpression xpath = leafrefType.getPathStatement(); + Preconditions.checkArgument(xpath != null, "The Path Statement for Leafref Type Definition cannot be NULL!"); - 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 String strXPath = xpath.getOriginalString(); + if (strXPath.indexOf('[') != -1) { + // XXX: why are we special-casing this? + return Types.objectType(); + } - 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()); - - // FIXME: this block seems to be some weird magic hack. Analyze and refactor it. - 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); - } - } else { - returnType = Types.objectType(); + 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 = 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); + } 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; @@ -547,7 +576,7 @@ public abstract class AbstractTypeProvider implements TypeProvider { private static boolean leafContainsEnumDefinition(final SchemaNode dataNode) { if (dataNode instanceof LeafSchemaNode) { final LeafSchemaNode leaf = (LeafSchemaNode) dataNode; - return CompatUtils.compatLeafType(leaf) instanceof EnumTypeDefinition; + return CompatUtils.compatType(leaf) instanceof EnumTypeDefinition; } return false; } @@ -687,7 +716,7 @@ public abstract class AbstractTypeProvider implements TypeProvider { if (dataNode != null) { if (dataNode instanceof LeafSchemaNode) { final LeafSchemaNode leaf = (LeafSchemaNode) dataNode; - final TypeDefinition type = CompatUtils.compatLeafType(leaf); + final TypeDefinition type = CompatUtils.compatType(leaf); returnType = javaTypeForSchemaDefinitionType(type, leaf); } else if (dataNode instanceof LeafListSchemaNode) { final LeafListSchemaNode leafList = (LeafListSchemaNode) dataNode; @@ -780,13 +809,7 @@ 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()); - } + additionalTypes.computeIfAbsent(module, key -> new HashSet<>()).add(unionBuilder.build()); } else if (baseTypedef instanceof EnumTypeDefinition) { // enums are automatically Serializable final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) baseTypedef; @@ -840,6 +863,7 @@ public abstract class AbstractTypeProvider implements TypeProvider { genTOBuilder.addEqualsIdentity(genPropBuilder); genTOBuilder.addHashIdentity(genPropBuilder); genTOBuilder.addToStringProperty(genPropBuilder); + genTOBuilder.addImplementsType(TYPE_OBJECT); if (typedef.getStatus() == Status.DEPRECATED) { genTOBuilder.addAnnotation("java.lang", "Deprecated"); } @@ -898,6 +922,7 @@ public abstract class AbstractTypeProvider implements TypeProvider { unionGenTOBuilder.setIsUnion(true); unionGenTOBuilder.setSchemaPath(typedef.getPath()); unionGenTOBuilder.setModuleName(module.getName()); + unionGenTOBuilder.addImplementsType(TYPE_OBJECT); addCodegenInformation(unionGenTOBuilder, typedef); generatedTOBuilders.add(unionGenTOBuilder); @@ -1112,6 +1137,7 @@ 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(); @@ -1322,7 +1348,7 @@ 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); requireNonNull(type, () -> "Cannot provide default construction for null type of " + node); @@ -1506,8 +1532,8 @@ public abstract class AbstractTypeProvider implements TypeProvider { 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) { @@ -1515,7 +1541,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); } @@ -1531,7 +1557,7 @@ 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;