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=691e541597c3bed516598a1ca948e573e65d18c1;hb=7d208ad0139c820dd6c11329f73d6d11b1055bda;hp=307fb5fd27eb1c246648af6e7dcaad23de7b6ab4;hpb=5ab5d6335f237c2ddb8a09c4d56bfda1dfbaa5ad;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 307fb5fd27..691e541597 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 @@ -9,19 +9,26 @@ package org.opendaylight.mdsal.binding.generator.impl; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkState; +import static com.google.common.base.Verify.verifyNotNull; import static java.util.Objects.requireNonNull; import static org.opendaylight.mdsal.binding.model.util.BindingGeneratorUtil.computeDefaultSUID; import static org.opendaylight.mdsal.binding.model.util.BindingGeneratorUtil.packageNameForAugmentedGeneratedType; import static org.opendaylight.mdsal.binding.model.util.BindingGeneratorUtil.packageNameForGeneratedType; +import static org.opendaylight.mdsal.binding.model.util.BindingTypes.BASE_IDENTITY; import static org.opendaylight.mdsal.binding.model.util.BindingTypes.DATA_OBJECT; import static org.opendaylight.mdsal.binding.model.util.BindingTypes.DATA_ROOT; -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.NOTIFICATION; +import static org.opendaylight.mdsal.binding.model.util.BindingTypes.NOTIFICATION_LISTENER; +import static org.opendaylight.mdsal.binding.model.util.BindingTypes.ROUTING_CONTEXT; +import static org.opendaylight.mdsal.binding.model.util.BindingTypes.RPC_SERVICE; import static org.opendaylight.mdsal.binding.model.util.BindingTypes.augmentable; +import static org.opendaylight.mdsal.binding.model.util.BindingTypes.childOf; +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.rpcResult; import static org.opendaylight.mdsal.binding.model.util.Types.BOOLEAN; import static org.opendaylight.mdsal.binding.model.util.Types.FUTURE; -import static org.opendaylight.mdsal.binding.model.util.Types.VOID; import static org.opendaylight.mdsal.binding.model.util.Types.typeForClass; import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataSchemaNode; import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findNodeInSchemaContext; @@ -30,11 +37,10 @@ import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findP import com.google.common.base.Splitter; import com.google.common.collect.Iterables; import com.google.common.collect.Sets; -import java.util.ArrayDeque; +import java.util.AbstractMap.SimpleImmutableEntry; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; -import java.util.Deque; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -49,6 +55,7 @@ import org.opendaylight.mdsal.binding.model.api.JavaTypeName; import org.opendaylight.mdsal.binding.model.api.ParameterizedType; import org.opendaylight.mdsal.binding.model.api.Restrictions; import org.opendaylight.mdsal.binding.model.api.Type; +import org.opendaylight.mdsal.binding.model.api.type.builder.AnnotableTypeBuilder; import org.opendaylight.mdsal.binding.model.api.type.builder.AnnotationTypeBuilder; import org.opendaylight.mdsal.binding.model.api.type.builder.EnumBuilder; import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedPropertyBuilder; @@ -58,7 +65,6 @@ import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilde import org.opendaylight.mdsal.binding.model.api.type.builder.MethodSignatureBuilder; import org.opendaylight.mdsal.binding.model.api.type.builder.TypeMemberBuilder; import org.opendaylight.mdsal.binding.model.util.BindingGeneratorUtil; -import org.opendaylight.mdsal.binding.model.util.BindingTypes; import org.opendaylight.mdsal.binding.model.util.ReferencedTypeImpl; import org.opendaylight.mdsal.binding.model.util.TypeConstants; import org.opendaylight.mdsal.binding.model.util.Types; @@ -66,14 +72,9 @@ import org.opendaylight.mdsal.binding.model.util.generated.type.builder.Generate import org.opendaylight.mdsal.binding.yang.types.AbstractTypeProvider; import org.opendaylight.mdsal.binding.yang.types.BaseYangTypes; import org.opendaylight.mdsal.binding.yang.types.GroupingDefinitionDependencySort; -import org.opendaylight.yangtools.yang.binding.BaseIdentity; import org.opendaylight.yangtools.yang.binding.BindingMapping; -import org.opendaylight.yangtools.yang.binding.DataContainer; -import org.opendaylight.yangtools.yang.binding.RpcService; -import org.opendaylight.yangtools.yang.binding.annotations.RoutingContext; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.QNameModule; -import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode; import org.opendaylight.yangtools.yang.model.api.CaseSchemaNode; import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode; @@ -98,8 +99,6 @@ 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; -import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement; -import org.opendaylight.yangtools.yang.model.api.meta.StatementSource; import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint; @@ -114,6 +113,8 @@ import org.slf4j.LoggerFactory; abstract class AbstractTypeGenerator { private static final Logger LOG = LoggerFactory.getLogger(BindingGeneratorImpl.class); private static final Splitter COLON_SPLITTER = Splitter.on(':'); + private static final JavaTypeName DEPRECATED_ANNOTATION = JavaTypeName.create(Deprecated.class); + private static final JavaTypeName OVERRIDE_ANNOTATION = JavaTypeName.create(Override.class); /** * Comparator based on augment target path. @@ -288,8 +289,8 @@ abstract class AbstractTypeGenerator { final List listKeys = listKeys(node); final GeneratedTOBuilder genTOBuilder = resolveListKeyTOBuilder(context, node); if (genTOBuilder != null) { - final Type identifierMarker = Types.parameterizedTypeFor(IDENTIFIER, genType); - final Type identifiableMarker = Types.parameterizedTypeFor(IDENTIFIABLE, genTOBuilder); + final Type identifierMarker = identifier(genType); + final Type identifiableMarker = identifiable(genTOBuilder); genTOBuilder.addImplementsType(identifierMarker); genType.addImplementsType(identifiableMarker); } @@ -417,7 +418,7 @@ abstract class AbstractTypeGenerator { } final GeneratedTypeBuilder interfaceBuilder = moduleTypeBuilder(context, "Service"); - interfaceBuilder.addImplementsType(Types.typeForClass(RpcService.class)); + interfaceBuilder.addImplementsType(RPC_SERVICE); addCodegenInformation(interfaceBuilder, module, "RPCs", rpcDefinitions); @@ -426,42 +427,20 @@ abstract class AbstractTypeGenerator { final String rpcName = BindingMapping.getClassName(rpc.getQName()); final String rpcMethodName = BindingMapping.getPropertyName(rpcName); final MethodSignatureBuilder method = interfaceBuilder.addMethod(rpcMethodName); - final ContainerSchemaNode input = rpc.getInput(); - final ContainerSchemaNode output = rpc.getOutput(); // Do not refer to annotation class, as it may not be available at runtime method.addAnnotation("javax.annotation", "CheckReturnValue"); - - //in case of implicit RPC input (StatementSource.CONTEXT), - // stay compatible (no input argument generated) - if (input != null && isExplicitStatement(input)) { - final Type inTypeInstance = createRpcContainer(context, rpcName, rpc, input); - method.addParameter(inTypeInstance, "input"); - } - - final Type outTypeInstance; - //in case of implicit RPC output (StatementSource.CONTEXT), - //stay compatible (Future> return type generated) - if (output != null && isExplicitStatement(output)) { - outTypeInstance = createRpcContainer(context, rpcName, rpc, output); - } else { - outTypeInstance = VOID; - } - - final Type rpcRes = Types.parameterizedTypeFor(Types.typeForClass(RpcResult.class), outTypeInstance); addComment(method, rpc); - method.setReturnType(Types.parameterizedTypeFor(FUTURE, rpcRes)); + method.addParameter( + createRpcContainer(context, rpcName, rpc, verifyNotNull(rpc.getInput())), "input"); + method.setReturnType(Types.parameterizedTypeFor(FUTURE, + rpcResult(createRpcContainer(context, rpcName, rpc, verifyNotNull(rpc.getOutput()))))); } } context.addTopLevelNodeType(interfaceBuilder); } - private static boolean isExplicitStatement(final ContainerSchemaNode node) { - return node instanceof EffectiveStatement - && ((EffectiveStatement) node).getDeclared().getStatementSource() == StatementSource.DECLARATION; - } - private Type createRpcContainer(final ModuleContext context, final String rpcName, final RpcDefinition rpc, final ContainerSchemaNode schema) { processUsesAugments(schema, context); @@ -502,7 +481,7 @@ abstract class AbstractTypeGenerator { } final GeneratedTypeBuilder listenerInterface = moduleTypeBuilder(context, "Listener"); - listenerInterface.addImplementsType(BindingTypes.NOTIFICATION_LISTENER); + listenerInterface.addImplementsType(NOTIFICATION_LISTENER); for (final NotificationDefinition notification : notifications) { if (notification != null) { @@ -573,16 +552,15 @@ abstract class AbstractTypeGenerator { packageNameForGeneratedType(context.modulePackageName(), identity.getPath()), BindingMapping.getClassName(identity.getQName()))); final Set baseIdentities = identity.getBaseIdentities(); - if (baseIdentities.isEmpty()) { - final GeneratedTOBuilder gto = typeProvider.newGeneratedTOBuilder(JavaTypeName.create(BaseIdentity.class)); - newType.addImplementsType(gto.build()); - } else { + if (!baseIdentities.isEmpty()) { for (IdentitySchemaNode baseIdentity : baseIdentities) { final QName qname = baseIdentity.getQName(); final GeneratedTransferObject gto = typeProvider.newGeneratedTOBuilder(JavaTypeName.create( BindingMapping.getRootPackageName(qname.getModule()), BindingMapping.getClassName(qname))).build(); newType.addImplementsType(gto); } + } else { + newType.addImplementsType(BASE_IDENTITY); } final Module module = context.module(); @@ -590,15 +568,16 @@ abstract class AbstractTypeGenerator { newType.setModuleName(module.getName()); newType.setSchemaPath(identity.getPath()); - qnameConstant(newType, BindingMapping.QNAME_STATIC_FIELD_NAME, identity.getQName()); + qnameConstant(newType, JavaTypeName.create(context.modulePackageName(), BindingMapping.MODULE_INFO_CLASS_NAME), + identity.getQName().getLocalName()); context.addIdentityType(identity.getQName(), newType); } - - private static Constant qnameConstant(final GeneratedTypeBuilderBase toBuilder, final String constantName, - final QName name) { - return toBuilder.addConstant(typeForClass(QName.class), constantName, name); + private static Constant qnameConstant(final GeneratedTypeBuilderBase toBuilder, + final JavaTypeName yangModuleInfo, final String localName) { + return toBuilder.addConstant(typeForClass(QName.class), BindingMapping.QNAME_STATIC_FIELD_NAME, + new SimpleImmutableEntry<>(yangModuleInfo, localName)); } /** @@ -802,7 +781,7 @@ abstract class AbstractTypeGenerator { SchemaNode result = targetGrouping; for (final QName node : targetPath.getPathFromRoot()) { if (result instanceof DataNodeContainer) { - final QName resultNode = QName.create(result.getQName().getModule(), node.getLocalName()); + final QName resultNode = node.withModule(result.getQName().getModule()); result = ((DataNodeContainer) result).getDataChildByName(resultNode); } else if (result instanceof ChoiceSchemaNode) { result = findNamedCase((ChoiceSchemaNode) result, node.getLocalName()); @@ -1072,11 +1051,14 @@ abstract class AbstractTypeGenerator { final GeneratedTypeBuilder choiceTypeBuilder = addRawInterfaceDefinition( JavaTypeName.create(packageNameForGeneratedType(context.modulePackageName(), choiceNode.getPath()), BindingMapping.getClassName(choiceNode.getQName())), choiceNode); - constructGetter(parent, choiceTypeBuilder, choiceNode); - choiceTypeBuilder.addImplementsType(typeForClass(DataContainer.class)); + choiceTypeBuilder.addImplementsType(choiceIn(parent)); annotateDeprecatedIfNecessary(choiceNode.getStatus(), choiceTypeBuilder); context.addChildNodeType(choiceNode, choiceTypeBuilder); - generateTypesFromChoiceCases(context, choiceTypeBuilder.build(), choiceNode); + + final GeneratedType choiceType = choiceTypeBuilder.build(); + generateTypesFromChoiceCases(context, choiceType, choiceNode); + + constructGetter(parent, choiceType, choiceNode); } } @@ -1189,25 +1171,7 @@ abstract class AbstractTypeGenerator { final GeneratedTypeBuilder caseTypeBuilder = addDefaultInterfaceDefinition(context, caseNode); caseTypeBuilder.addImplementsType(targetType); - SchemaNode parent; - final SchemaPath nodeSp = targetNode.getPath(); - parent = findDataSchemaNode(schemaContext, nodeSp.getParent()); - - GeneratedTypeBuilder childOfType = null; - if (parent instanceof Module) { - childOfType = moduleContext(((Module) parent).getQNameModule()).getModuleNode(); - } else if (parent instanceof CaseSchemaNode) { - childOfType = findCaseByPath(parent.getPath()); - } else if (parent instanceof DataSchemaNode || parent instanceof NotificationDefinition) { - childOfType = findChildNodeByPath(parent.getPath()); - } else if (parent instanceof GroupingDefinition) { - childOfType = findGroupingByPath(parent.getPath()); - } - - if (childOfType == null) { - throw new IllegalArgumentException("Failed to find parent type of choice " + targetNode); - } - + GeneratedTypeBuilder childOfType = findChildOfType(targetNode); CaseSchemaNode node = null; final String caseLocalName = caseNode.getQName().getLocalName(); if (caseNode instanceof CaseSchemaNode) { @@ -1234,6 +1198,30 @@ abstract class AbstractTypeGenerator { } } + private GeneratedTypeBuilder findChildOfType(final ChoiceSchemaNode targetNode) { + final SchemaPath nodePath = targetNode.getPath(); + final SchemaPath parentSp = nodePath.getParent(); + if (parentSp.getParent() == null) { + return moduleContext(nodePath.getLastComponent().getModule()).getModuleNode(); + } + + final SchemaNode parent = findDataSchemaNode(schemaContext, parentSp); + GeneratedTypeBuilder childOfType = null; + if (parent instanceof CaseSchemaNode) { + childOfType = findCaseByPath(parent.getPath()); + } else if (parent instanceof DataSchemaNode || parent instanceof NotificationDefinition) { + childOfType = findChildNodeByPath(parent.getPath()); + } else if (parent instanceof GroupingDefinition) { + childOfType = findGroupingByPath(parent.getPath()); + } + + if (childOfType == null) { + throw new IllegalArgumentException("Failed to find parent type of choice " + targetNode); + } + + return childOfType; + } + private static CaseSchemaNode findNamedCase(final ChoiceSchemaNode choice, final String caseName) { final List cases = choice.findCaseNodes(caseName); return cases.isEmpty() ? null : cases.get(0); @@ -1383,7 +1371,7 @@ abstract class AbstractTypeGenerator { + nodeParam); } - final AnnotationTypeBuilder rc = getter.addAnnotation(JavaTypeName.create(RoutingContext.class)); + final AnnotationTypeBuilder rc = getter.addAnnotation(ROUTING_CONTEXT); final String packageName = packageNameForGeneratedType(basePackageName, identity.getPath()); final String genTypeName = BindingMapping.getClassName(identity.getQName().getLocalName()); rc.addParameter("value", packageName + "." + genTypeName + ".class"); @@ -1572,28 +1560,11 @@ abstract class AbstractTypeGenerator { private GeneratedTOBuilder createUnionBuilder(final GeneratedTOBuilder genTOBuilder, final GeneratedTypeBuilder typeBuilder) { - final StringBuilder sb = new StringBuilder(); - // Append enclosing path hierarchy without dots - // TODO: JavaTypeName could be giving us a Stream or similar, but there is no sense in generalizing - // unless there is another caller. - Optional outerClass = genTOBuilder.getIdentifier().immediatelyEnclosingClass(); - if (outerClass.isPresent()) { - final Deque enclosingPath = new ArrayDeque<>(); - do { - final JavaTypeName outerName = outerClass.get(); - enclosingPath.push(outerName.simpleName()); - outerClass = outerName.immediatelyEnclosingClass(); - } while (outerClass.isPresent()); - - while (!enclosingPath.isEmpty()) { - sb.append(enclosingPath.pop()); - } - } - - sb.append(genTOBuilder.getName()).append("Builder"); + final StringBuilder sb = new StringBuilder(); + genTOBuilder.getIdentifier().localNameComponents().forEach(sb::append); final GeneratedTOBuilder unionBuilder = typeProvider.newGeneratedTOBuilder( - JavaTypeName.create(typeBuilder.getPackageName(), sb.toString())); + JavaTypeName.create(typeBuilder.getPackageName(), sb.append("Builder").toString())); unionBuilder.setIsUnionBuilder(true); return unionBuilder; } @@ -1637,18 +1608,15 @@ abstract class AbstractTypeGenerator { final Type parent, final ModuleContext context) { final GeneratedTypeBuilder it = addRawInterfaceDefinition( JavaTypeName.create(packageName, BindingMapping.getClassName(schemaNode.getQName())), schemaNode); - if (parent == null) { - it.addImplementsType(DATA_OBJECT); - } else { - it.addImplementsType(BindingTypes.childOf(parent)); - } + + it.addImplementsType(parent == null ? DATA_OBJECT : childOf(parent)); if (!(schemaNode instanceof GroupingDefinition)) { it.addImplementsType(augmentable(it)); } - if (schemaNode instanceof DataNodeContainer) { - groupingsToGenTypes(context, ((DataNodeContainer) schemaNode).getGroupings()); - addImplementedInterfaceFromUses((DataNodeContainer) schemaNode, it); + final DataNodeContainer containerSchema = (DataNodeContainer) schemaNode; + groupingsToGenTypes(context, containerSchema.getGroupings()); + addImplementedInterfaceFromUses(containerSchema, it); } return it; @@ -1705,7 +1673,8 @@ abstract class AbstractTypeGenerator { // FIXME: Validation of name conflict final GeneratedTypeBuilder newType = typeProvider.newGeneratedTypeBuilder(identifier); final Module module = findParentModule(schemaContext, schemaNode); - qnameConstant(newType, BindingMapping.QNAME_STATIC_FIELD_NAME, schemaNode.getQName()); + qnameConstant(newType, JavaTypeName.create(BindingMapping.getRootPackageName(module.getQNameModule()), + BindingMapping.MODULE_INFO_CLASS_NAME), schemaNode.getQName().getLocalName()); addCodegenInformation(newType, module, schemaNode); newType.setSchemaPath(schemaNode.getPath()); @@ -1767,8 +1736,10 @@ abstract class AbstractTypeGenerator { getterMethodName(node.getQName().getLocalName(), returnType)); getMethod.setReturnType(returnType); - if (node.getStatus() == Status.DEPRECATED) { - getMethod.addAnnotation("java.lang", "Deprecated"); + annotateDeprecatedIfNecessary(node.getStatus(), getMethod); + if (!returnType.getPackageName().isEmpty()) { + // The return type has a package, so it's not a primitive type + getMethod.addAnnotation("javax.annotation", "Nullable"); } addComment(getMethod, node); @@ -1835,11 +1806,9 @@ abstract class AbstractTypeGenerator { if (genTOBuilder != null) { final GeneratedTransferObject genTO = genTOBuilder.build(); - - // Fake the 'getKey()' for items, this is equivalent to constructGetter() - final MethodSignatureBuilder getMethod = typeBuilder.addMethod(getterMethodName("key", genTO)); - getMethod.setReturnType(genTO); - getMethod.setComment("Returns Primary Key of Yang List Type"); + // Add Identifiable.getKey() for items + typeBuilder.addMethod(BindingMapping.IDENTIFIABLE_KEY_NAME).setReturnType(genTO) + .addAnnotation(OVERRIDE_ANNOTATION); context.addGeneratedTOBuilder(genTOBuilder); } } @@ -2026,9 +1995,9 @@ abstract class AbstractTypeGenerator { return null; } - private static void annotateDeprecatedIfNecessary(final Status status, final GeneratedTypeBuilder builder) { + private static void annotateDeprecatedIfNecessary(final Status status, final AnnotableTypeBuilder builder) { if (status == Status.DEPRECATED) { - builder.addAnnotation("java.lang", "Deprecated"); + builder.addAnnotation(DEPRECATED_ANNOTATION); } } }