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=4f422cb04e817e90be95aef9fed4b0461eec98b8;hb=c8c1ed80b2949b5eda8bdb57bc9a25ef0db1aef0;hp=f9e1abb9fb961daa2b59eaa3e13cd0389b67ac08;hpb=d478b9053c77f561f401844de685b5d0334c0809;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 f9e1abb9fb..4f422cb04e 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,6 +8,7 @@ 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.findParentModule; @@ -16,15 +17,14 @@ 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 com.google.common.io.BaseEncoding; 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; @@ -55,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; @@ -81,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; @@ -150,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); } /** @@ -167,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!)"); @@ -181,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; } @@ -202,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); @@ -239,39 +244,35 @@ 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 PathExpression leafRefStrippedXPath = new PathExpressionImpl( + GROUPS_PATTERN.matcher(leafRefXPath.getOriginalString()).replaceAll(""), leafRefXPath.isAbsolute()); final Module parentModule = getParentModule(parentNode); + final SchemaNode leafRefValueNode; if (!leafRefStrippedXPath.isAbsolute()) { leafRefValueNode = SchemaContextUtil.findDataSchemaNodeForRelativeXPath(schemaContext, parentModule, parentNode, leafRefStrippedXPath); @@ -288,12 +289,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 +309,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 +329,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 +486,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 = findDataSchemaNode(schemaContext, module, 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 +578,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 +718,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 +811,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; @@ -831,7 +856,7 @@ public abstract class AbstractTypeProvider implements TypeProvider { */ private GeneratedTransferObject wrapJavaTypeIntoTO(final String basePackageName, final TypeDefinition typedef, final Type javaType, final String moduleName) { - Preconditions.checkNotNull(javaType, "javaType cannot be null"); + requireNonNull(javaType, "javaType cannot be null"); final GeneratedTOBuilder genTOBuilder = typedefToTransferObject(basePackageName, typedef, moduleName); genTOBuilder.setRestrictions(BindingGeneratorUtil.getRestrictions(typedef)); @@ -840,6 +865,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"); } @@ -887,8 +913,8 @@ 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(); @@ -898,6 +924,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 +1139,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,12 +1350,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; @@ -1394,25 +1422,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 { @@ -1455,8 +1471,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]); @@ -1507,8 +1522,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) { @@ -1532,7 +1547,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;