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=88af37f1e5d3ca53bd792f196d39dac0eba99a59;hb=8c4ab985c1723336640324789c65489e71deb4e0;hp=39f5931d9ae8876a19bcb579157bc7231759cebb;hpb=69edd49f361f97da4a99378830ca9aa2f34b97ae;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 39f5931d9a..88af37f1e5 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 @@ -9,8 +9,8 @@ package org.opendaylight.mdsal.binding.yang.types; 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.findDataSchemaNode; 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; @@ -18,7 +18,6 @@ import com.google.common.base.Preconditions; import com.google.common.base.Strings; import com.google.common.collect.ImmutableMap; import java.math.BigDecimal; -import java.math.BigInteger; import java.util.ArrayList; import java.util.Base64; import java.util.Collection; @@ -56,13 +55,17 @@ import org.opendaylight.mdsal.binding.model.util.generated.type.builder.Generate 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 +85,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; @@ -151,8 +154,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); } /** @@ -168,7 +172,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!)"); @@ -182,14 +186,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; } @@ -203,7 +207,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); @@ -219,6 +223,17 @@ public abstract class AbstractTypeProvider implements TypeProvider { return returnType; } + 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()); @@ -240,45 +255,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); } @@ -289,12 +301,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); } @@ -308,10 +321,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; @@ -328,7 +341,7 @@ public abstract class AbstractTypeProvider implements TypeProvider { } if (returnType == null) { returnType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType( - baseTypeDef, typeDefinition, r); + baseTypeDef, typeDefinition, r, lenient); } } } @@ -485,50 +498,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, 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; @@ -548,7 +590,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; } @@ -683,16 +725,16 @@ public abstract class AbstractTypeProvider implements TypeProvider { * @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; @@ -1320,7 +1362,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); @@ -1392,25 +1434,13 @@ public abstract class AbstractTypeProvider implements TypeProvider { } else if (base instanceof StringTypeDefinition) { result = "\"" + defaultValue + "\""; } else if (BaseTypes.isUint8(base)) { - result = typeToValueOfDef(Short.class, defaultValue); + result = typeToValueOfDef(Uint8.class, defaultValue); } else if (BaseTypes.isUint16(base)) { - result = typeToValueOfDef(Integer.class, defaultValue); + result = typeToValueOfDef(Uint16.class, defaultValue); } else if (BaseTypes.isUint32(base)) { - result = typeToValueOfDef(Long.class, defaultValue); + result = typeToValueOfDef(Uint32.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); - } + result = typeToValueOfDef(Uint64.class, defaultValue); } else if (base instanceof UnionTypeDefinition) { result = unionToDef(node); } else { @@ -1504,8 +1534,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) { @@ -1513,7 +1543,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); } @@ -1529,7 +1559,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;