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%2Fgenerator%2Fimpl%2FAbstractTypeGenerator.java;h=53d214f4140078ddf2342b3040d2fe2c474260d2;hb=aaf3b063417074cc92900629e917d6d0c5092dcd;hp=a066e120279575c0fb4f553bc647353fd2c311a8;hpb=c77348ddc6ccebb90ef32b5e55f38e0997047f36;p=mdsal.git diff --git a/binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/generator/impl/AbstractTypeGenerator.java b/binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/generator/impl/AbstractTypeGenerator.java index a066e12027..53d214f414 100644 --- a/binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/generator/impl/AbstractTypeGenerator.java +++ b/binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/generator/impl/AbstractTypeGenerator.java @@ -30,6 +30,7 @@ import static org.opendaylight.mdsal.binding.model.util.BindingTypes.choiceIn; import static org.opendaylight.mdsal.binding.model.util.BindingTypes.identifiable; import static org.opendaylight.mdsal.binding.model.util.BindingTypes.identifier; import static org.opendaylight.mdsal.binding.model.util.BindingTypes.keyedListAction; +import static org.opendaylight.mdsal.binding.model.util.BindingTypes.opaqueObject; import static org.opendaylight.mdsal.binding.model.util.BindingTypes.rpcResult; import static org.opendaylight.mdsal.binding.model.util.Types.BOOLEAN; import static org.opendaylight.mdsal.binding.model.util.Types.STRING; @@ -50,6 +51,7 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.util.AbstractMap.SimpleImmutableEntry; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; @@ -88,6 +90,8 @@ import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.QNameModule; import org.opendaylight.yangtools.yang.model.api.ActionDefinition; import org.opendaylight.yangtools.yang.model.api.ActionNodeContainer; +import org.opendaylight.yangtools.yang.model.api.AnyDataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode; import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode; import org.opendaylight.yangtools.yang.model.api.CaseSchemaNode; import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode; @@ -96,6 +100,7 @@ import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; import org.opendaylight.yangtools.yang.model.api.DerivableSchemaNode; import org.opendaylight.yangtools.yang.model.api.DocumentedNode; +import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus; import org.opendaylight.yangtools.yang.model.api.GroupingDefinition; import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode; import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode; @@ -108,7 +113,6 @@ import org.opendaylight.yangtools.yang.model.api.RpcDefinition; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.model.api.SchemaNode; import org.opendaylight.yangtools.yang.model.api.SchemaPath; -import org.opendaylight.yangtools.yang.model.api.Status; import org.opendaylight.yangtools.yang.model.api.TypeDefinition; import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode; import org.opendaylight.yangtools.yang.model.api.UsesNode; @@ -277,7 +281,7 @@ abstract class AbstractTypeGenerator { } final GeneratedTypeBuilder genType = addDefaultInterfaceDefinition(context, node, baseInterface); defaultImplementedInterace(genType); - annotateDeprecatedIfNecessary(node.getStatus(), genType); + annotateDeprecatedIfNecessary(node, genType); final Module module = context.module(); genType.setModuleName(module.getName()); @@ -421,6 +425,10 @@ abstract class AbstractTypeGenerator { private void actionsToGenType(final ModuleContext context, final Type parent, final T parentSchema, final Type keyType, final boolean inGrouping) { for (final ActionDefinition action : parentSchema.getActions()) { + if (action.isAugmenting()) { + continue; + } + final GeneratedType input; final GeneratedType output; if (action.isAddedByUses()) { @@ -443,7 +451,7 @@ abstract class AbstractTypeGenerator { qnameConstant(builder, JavaTypeName.create(context.modulePackageName(), BindingMapping.MODULE_INFO_CLASS_NAME), qname.getLocalName()); - annotateDeprecatedIfNecessary(action.getStatus(), builder); + annotateDeprecatedIfNecessary(action, builder); builder.addImplementsType(keyType != null ? keyedListAction(parent, keyType, input, output) : action(parent, input, output)); @@ -456,8 +464,7 @@ abstract class AbstractTypeGenerator { private Optional findOrigAction(final DataNodeContainer parent, final ActionDefinition action) { for (UsesNode uses : parent.getUses()) { final GroupingDefinition grp = findUsedGrouping(uses); - final Optional found = grp.getActions().stream() - .filter(act -> action.getQName().equals(act.getQName())).findFirst(); + final Optional found = grp.findAction(action.getQName()); if (found.isPresent()) { final ActionDefinition result = found.get(); return result.isAddedByUses() ? findOrigAction(grp, result) : found; @@ -511,9 +518,7 @@ abstract class AbstractTypeGenerator { final MethodSignatureBuilder method = interfaceBuilder.addMethod(rpcMethodName); // Do not refer to annotation class, as it may not be available at runtime - // FIXME: migrate this to some other annotation type and re-enable - // - // method.addAnnotation("javax.annotation", "CheckReturnValue"); + method.addAnnotation("edu.umd.cs.findbugs.annotations", "CheckReturnValue"); addComment(method, rpc); method.addParameter( createRpcContainer(context, rpcName, rpc, verifyNotNull(rpc.getInput()), RPC_INPUT), "input"); @@ -535,7 +540,7 @@ abstract class AbstractTypeGenerator { outType.addImplementsType(type); outType.addImplementsType(augmentable(outType)); defaultImplementedInterace(outType); - annotateDeprecatedIfNecessary(rpc.getStatus(), outType); + annotateDeprecatedIfNecessary(rpc, outType); resolveDataSchemaNodes(context, outType, outType, schema.getChildNodes(), false); context.addChildNodeType(schema, outType); return outType.build(); @@ -575,7 +580,7 @@ abstract class AbstractTypeGenerator { final GeneratedTypeBuilder notificationInterface = addDefaultInterfaceDefinition( context.modulePackageName(), notification, DATA_OBJECT, context); defaultImplementedInterace(notificationInterface); - annotateDeprecatedIfNecessary(notification.getStatus(), notificationInterface); + annotateDeprecatedIfNecessary(notification, notificationInterface); notificationInterface.addImplementsType(NOTIFICATION); context.addChildNodeType(notification, notificationInterface); @@ -695,7 +700,7 @@ abstract class AbstractTypeGenerator { // node of grouping is resolved to the method. final GeneratedTypeBuilder genType = addDefaultInterfaceDefinition(context, grouping); narrowImplementedInterface(genType); - annotateDeprecatedIfNecessary(grouping.getStatus(), genType); + annotateDeprecatedIfNecessary(grouping, genType); context.addGroupingType(grouping, genType); resolveDataSchemaNodes(context, genType, genType, grouping.getChildNodes(), true); groupingsToGenTypes(context, grouping.getGroupings()); @@ -926,16 +931,17 @@ abstract class AbstractTypeGenerator { defaultImplementedInterace(augTypeBuilder); augTypeBuilder.addImplementsType(augmentationTypeFor(targetTypeRef)); - annotateDeprecatedIfNecessary(augSchema.getStatus(), augTypeBuilder); + annotateDeprecatedIfNecessary(augSchema, augTypeBuilder); addImplementedInterfaceFromUses(augSchema, augTypeBuilder); augSchemaNodeToMethods(context, augTypeBuilder, augSchema.getChildNodes(), inGrouping); + actionsToGenType(context, augTypeBuilder, augSchema, null, inGrouping); augmentBuilders.put(augTypeName, augTypeBuilder); if (!augSchema.getChildNodes().isEmpty()) { context.addTypeToAugmentation(augTypeBuilder, augSchema); - } + context.addAugmentType(augTypeBuilder); return augTypeBuilder; } @@ -1052,8 +1058,9 @@ abstract class AbstractTypeGenerator { listToGenType(context, typeBuilder, baseInterface, (ListSchemaNode) node, inGrouping); } else if (node instanceof ChoiceSchemaNode) { choiceToGeneratedType(context, typeBuilder, (ChoiceSchemaNode) node, inGrouping); + } else if (node instanceof AnyXmlSchemaNode || node instanceof AnyDataSchemaNode) { + opaqueToGeneratedType(context, typeBuilder, node); } else { - // TODO: anyxml not yet supported LOG.debug("Unable to add schema node {} as method in {}: unsupported type of node.", node.getClass(), typeBuilder.getFullyQualifiedName()); } @@ -1078,14 +1085,12 @@ abstract class AbstractTypeGenerator { */ private void choiceToGeneratedType(final ModuleContext context, final GeneratedTypeBuilder parent, final ChoiceSchemaNode choiceNode, final boolean inGrouping) { - checkArgument(choiceNode != null, "Choice Schema Node cannot be NULL."); - if (!choiceNode.isAddedByUses()) { final GeneratedTypeBuilder choiceTypeBuilder = addRawInterfaceDefinition( JavaTypeName.create(packageNameForGeneratedType(context.modulePackageName(), choiceNode.getPath()), BindingMapping.getClassName(choiceNode.getQName())), choiceNode); choiceTypeBuilder.addImplementsType(choiceIn(parent)); - annotateDeprecatedIfNecessary(choiceNode.getStatus(), choiceTypeBuilder); + annotateDeprecatedIfNecessary(choiceNode, choiceTypeBuilder); context.addChildNodeType(choiceNode, choiceTypeBuilder); final GeneratedType choiceType = choiceTypeBuilder.build(); @@ -1095,6 +1100,21 @@ abstract class AbstractTypeGenerator { } } + private void opaqueToGeneratedType(final ModuleContext context, final GeneratedTypeBuilder parent, + final DataSchemaNode anyNode) { + if (!anyNode.isAddedByUses()) { + final GeneratedTypeBuilder anyxmlTypeBuilder = addRawInterfaceDefinition( + JavaTypeName.create(packageNameForGeneratedType(context.modulePackageName(), anyNode.getPath()), + BindingMapping.getClassName(anyNode.getQName())), anyNode); + anyxmlTypeBuilder.addImplementsType(opaqueObject(anyxmlTypeBuilder)).addImplementsType(childOf(parent)); + defaultImplementedInterace(anyxmlTypeBuilder); + annotateDeprecatedIfNecessary(anyNode, anyxmlTypeBuilder); + context.addChildNodeType(anyNode, anyxmlTypeBuilder); + + constructGetter(parent, anyxmlTypeBuilder.build(), anyNode); + } + } + /** * Converts caseNodes set to list of corresponding generated types. For every case which is not * added through augment or uses is created generated type builder. The package names for the builder is @@ -1120,7 +1140,7 @@ abstract class AbstractTypeGenerator { final GeneratedTypeBuilder caseTypeBuilder = addDefaultInterfaceDefinition(context, caseNode); caseTypeBuilder.addImplementsType(refChoiceType); defaultImplementedInterace(caseTypeBuilder); - annotateDeprecatedIfNecessary(caseNode.getStatus(), caseTypeBuilder); + annotateDeprecatedIfNecessary(caseNode, caseTypeBuilder); context.addCaseType(caseNode.getPath(), caseTypeBuilder); context.addChoiceToCaseMapping(refChoiceType, caseTypeBuilder, caseNode); final Iterable caseChildNodes = caseNode.getChildNodes(); @@ -1686,7 +1706,7 @@ abstract class AbstractTypeGenerator { getterMethodName(node.getQName().getLocalName(), returnType)); getMethod.setReturnType(returnType); - annotateDeprecatedIfNecessary(node.getStatus(), getMethod); + annotateDeprecatedIfNecessary(node, getMethod); addComment(getMethod, node); return getMethod; @@ -1697,7 +1717,7 @@ abstract class AbstractTypeGenerator { final MethodSignatureBuilder getMethod = interfaceBuilder.addMethod( BindingMapping.getNonnullMethodName(node.getQName().getLocalName())); getMethod.setReturnType(returnType).setDefault(true); - annotateDeprecatedIfNecessary(node.getStatus(), getMethod); + annotateDeprecatedIfNecessary(node, getMethod); } /** @@ -1769,15 +1789,19 @@ abstract class AbstractTypeGenerator { * an empty list is returned. */ private static List listKeys(final ListSchemaNode list) { - final List listKeys = new ArrayList<>(); - final List keyDefinition = list.getKeyDefinition(); - if (keyDefinition != null) { - for (final QName keyDef : keyDefinition) { - listKeys.add(keyDef.getLocalName()); - } + switch (keyDefinition.size()) { + case 0: + return Collections.emptyList(); + case 1: + return Collections.singletonList(keyDefinition.get(0).getLocalName()); + default: + final List listKeys = new ArrayList<>(keyDefinition.size()); + for (final QName keyDef : keyDefinition) { + listKeys.add(keyDef.getLocalName()); + } + return listKeys; } - return listKeys; } /** @@ -1811,8 +1835,7 @@ abstract class AbstractTypeGenerator { private Type addTOToTypeBuilder(final UnionTypeDefinition typeDef, final GeneratedTypeBuilder typeBuilder, final DataSchemaNode leaf, final Module parentModule) { final List types = typeProvider.provideGeneratedTOBuildersForUnionTypeDef( - typeBuilder.getIdentifier().createEnclosed(BindingMapping.getClassName(leaf.getQName())), - typeDef, leaf); + allocateNestedType(typeBuilder.getIdentifier(), leaf.getQName()), typeDef, leaf); checkState(!types.isEmpty(), "No GeneratedTOBuilder objects generated from union %s", typeDef); final List genTOBuilders = new ArrayList<>(types); @@ -1845,11 +1868,9 @@ abstract class AbstractTypeGenerator { private GeneratedTOBuilder addTOToTypeBuilder(final BitsTypeDefinition typeDef, final GeneratedTypeBuilder typeBuilder, final DataSchemaNode leaf, final Module parentModule) { final GeneratedTOBuilder genTOBuilder = typeProvider.provideGeneratedTOBuilderForBitsTypeDefinition( - typeBuilder.getIdentifier().createEnclosed(BindingMapping.getClassName(leaf.getQName())), - typeDef, parentModule.getName()); + allocateNestedType(typeBuilder.getIdentifier(), leaf.getQName()), typeDef, parentModule.getName()); typeBuilder.addEnclosingTransferObject(genTOBuilder); return genTOBuilder; - } /** @@ -1865,13 +1886,13 @@ abstract class AbstractTypeGenerator { private GeneratedTypeBuilder addImplementedInterfaceFromUses(final DataNodeContainer dataNodeContainer, final GeneratedTypeBuilder builder) { for (final UsesNode usesNode : dataNodeContainer.getUses()) { - final GeneratedType genType = findGroupingByPath(usesNode.getGroupingPath()).build(); + final GeneratedTypeBuilder genType = findGroupingByPath(usesNode.getGroupingPath()); if (genType == null) { throw new IllegalStateException("Grouping " + usesNode.getGroupingPath() + "is not resolved for " + builder.getName()); } - builder.addImplementsType(genType); + builder.addImplementsType(genType.build()); } return builder; } @@ -1906,9 +1927,23 @@ abstract class AbstractTypeGenerator { return null; } - private static void annotateDeprecatedIfNecessary(final Status status, final AnnotableTypeBuilder builder) { - if (status == Status.DEPRECATED) { - builder.addAnnotation(DEPRECATED_ANNOTATION); + private static JavaTypeName allocateNestedType(final JavaTypeName parent, final QName child) { + // Single '$' suffix cannot come from user, this mirrors AbstractGeneratedTypeBuilder.addEnumeration() + return parent.createEnclosed(BindingMapping.getClassName(child), "$"); + } + + private static void annotateDeprecatedIfNecessary(final WithStatus node, final AnnotableTypeBuilder builder) { + switch (node.getStatus()) { + case DEPRECATED: + case OBSOLETE: + // FIXME: we really want to use a pre-made annotation + builder.addAnnotation(DEPRECATED_ANNOTATION); + break; + case CURRENT: + // No-op + break; + default: + throw new IllegalStateException("Unhandled status in " + node); } }