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=59ab7e26ff6841e768be623f67c6d56e565b7edd;hb=4df2f71dd1bfc29cd5773d1cd2609c91a002e2b1;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..59ab7e26ff 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 @@ -19,26 +19,29 @@ 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.NOTIFICATION; import static org.opendaylight.mdsal.binding.model.util.BindingTypes.NOTIFICATION_LISTENER; +import static org.opendaylight.mdsal.binding.model.util.BindingTypes.QNAME; import static org.opendaylight.mdsal.binding.model.util.BindingTypes.ROUTING_CONTEXT; import static org.opendaylight.mdsal.binding.model.util.BindingTypes.RPC_INPUT; import static org.opendaylight.mdsal.binding.model.util.BindingTypes.RPC_OUTPUT; import static org.opendaylight.mdsal.binding.model.util.BindingTypes.RPC_SERVICE; import static org.opendaylight.mdsal.binding.model.util.BindingTypes.action; import static org.opendaylight.mdsal.binding.model.util.BindingTypes.augmentable; +import static org.opendaylight.mdsal.binding.model.util.BindingTypes.augmentation; 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.instanceNotification; import static org.opendaylight.mdsal.binding.model.util.BindingTypes.keyedListAction; +import static org.opendaylight.mdsal.binding.model.util.BindingTypes.keyedListNotification; +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; -import static org.opendaylight.mdsal.binding.model.util.Types.augmentationTypeFor; import static org.opendaylight.mdsal.binding.model.util.Types.classType; import static org.opendaylight.mdsal.binding.model.util.Types.listTypeFor; import static org.opendaylight.mdsal.binding.model.util.Types.listenableFutureTypeFor; import static org.opendaylight.mdsal.binding.model.util.Types.primitiveVoidType; -import static org.opendaylight.mdsal.binding.model.util.Types.typeForClass; import static org.opendaylight.mdsal.binding.model.util.Types.wildcardTypeFor; import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataSchemaNode; import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findNodeInSchemaContext; @@ -50,6 +53,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 +92,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 +102,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; @@ -104,11 +111,11 @@ import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; import org.opendaylight.yangtools.yang.model.api.Module; import org.opendaylight.yangtools.yang.model.api.ModuleImport; import org.opendaylight.yangtools.yang.model.api.NotificationDefinition; +import org.opendaylight.yangtools.yang.model.api.NotificationNodeContainer; 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 +284,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()); @@ -298,6 +305,7 @@ abstract class AbstractTypeGenerator { constructGetter(parent, genType, node); resolveDataSchemaNodes(context, genType, genType, node.getChildNodes(), inGrouping); actionsToGenType(context, genType, node, null, inGrouping); + notificationsToGenType(context, genType, node, null, inGrouping); } } @@ -305,35 +313,39 @@ abstract class AbstractTypeGenerator { final Type baseInterface, final ListSchemaNode node, final boolean inGrouping) { final GeneratedTypeBuilder genType = processDataSchemaNode(context, baseInterface, node, inGrouping); if (genType != null) { + final List listKeys = listKeys(node); + final GeneratedTOBuilder keyTypeBuilder; + if (!listKeys.isEmpty()) { + keyTypeBuilder = typeProvider.newGeneratedTOBuilder(JavaTypeName.create( + packageNameForGeneratedType(context.modulePackageName(), node.getPath()), + BindingMapping.getClassName(node.getQName().getLocalName() + "Key"))) + .addImplementsType(identifier(genType)); + genType.addImplementsType(identifiable(keyTypeBuilder)); + } else { + keyTypeBuilder = null; + } + final ParameterizedType listType = listTypeFor(genType); constructGetter(parent, listType, node); constructNonnull(parent, listType, node); - final List listKeys = listKeys(node); - final GeneratedTOBuilder genTOBuilder = resolveListKeyTOBuilder(context, node); - if (genTOBuilder != null) { - final Type identifierMarker = identifier(genType); - final Type identifiableMarker = identifiable(genTOBuilder); - genTOBuilder.addImplementsType(identifierMarker); - genType.addImplementsType(identifiableMarker); - - } - actionsToGenType(context, genType, node, genTOBuilder, inGrouping); + actionsToGenType(context, genType, node, keyTypeBuilder, inGrouping); + notificationsToGenType(context, genType, node, keyTypeBuilder, inGrouping); for (final DataSchemaNode schemaNode : node.getChildNodes()) { if (!schemaNode.isAugmenting()) { - addSchemaNodeToListBuilders(context, schemaNode, genType, genTOBuilder, listKeys, inGrouping); + addSchemaNodeToListBuilders(context, schemaNode, genType, keyTypeBuilder, listKeys, inGrouping); } } // serialVersionUID - if (genTOBuilder != null) { + if (keyTypeBuilder != null) { final GeneratedPropertyBuilder prop = new GeneratedPropertyBuilderImpl("serialVersionUID"); - prop.setValue(Long.toString(computeDefaultSUID(genTOBuilder))); - genTOBuilder.setSUID(prop); + prop.setValue(Long.toString(computeDefaultSUID(keyTypeBuilder))); + keyTypeBuilder.setSUID(prop); } - typeBuildersToGenTypes(context, genType, genTOBuilder); + typeBuildersToGenTypes(context, genType, keyTypeBuilder); } } @@ -421,6 +433,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 +459,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 +472,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; @@ -507,13 +522,11 @@ abstract class AbstractTypeGenerator { for (final RpcDefinition rpc : rpcDefinitions) { if (rpc != null) { final String rpcName = BindingMapping.getClassName(rpc.getQName()); - final String rpcMethodName = BindingMapping.getPropertyName(rpcName); + final String rpcMethodName = BindingMapping.getRpcMethodName(rpc.getQName()); 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 +548,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 +588,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); @@ -593,6 +606,40 @@ abstract class AbstractTypeGenerator { context.addTopLevelNodeType(listenerInterface); } + private void notificationsToGenType( + final ModuleContext context, final Type parent, final T parentSchema, final Type keyType, + final boolean inGrouping) { + final Set notifications = parentSchema.getNotifications(); + if (notifications.isEmpty()) { + return; + } + + for (NotificationDefinition notif : notifications) { + if (notif.isAugmenting()) { + continue; + } + if (parentSchema instanceof GroupingDefinition) { + // Notifications cannot be really established, as they lack instantiation context, which would be + // completely described by an InstanceIdentifier -- hence we cannot create a binding class + continue; + } + + processUsesAugments(notif, context, false); + + final GeneratedTypeBuilder notifInterface = addDefaultInterfaceDefinition( + packageNameForGeneratedType(context.modulePackageName(), notif.getPath()), notif, DATA_OBJECT, context); + defaultImplementedInterace(notifInterface); + annotateDeprecatedIfNecessary(notif, notifInterface); + + notifInterface.addImplementsType(keyType != null ? keyedListNotification(notifInterface, parent, keyType) + : instanceNotification(notifInterface, parent)); + context.addChildNodeType(notif, notifInterface); + + // Notification object + resolveDataSchemaNodes(context, notifInterface, notifInterface, notif.getChildNodes(), false); + } + } + /** * Converts all identities of the module to the list of * Type objects. @@ -672,7 +719,7 @@ abstract class AbstractTypeGenerator { private static Constant qnameConstant(final GeneratedTypeBuilderBase toBuilder, final JavaTypeName yangModuleInfo, final String localName) { - return toBuilder.addConstant(typeForClass(QName.class), BindingMapping.QNAME_STATIC_FIELD_NAME, + return toBuilder.addConstant(QNAME, BindingMapping.QNAME_STATIC_FIELD_NAME, new SimpleImmutableEntry<>(yangModuleInfo, localName)); } @@ -695,12 +742,13 @@ 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()); processUsesAugments(grouping, context, true); actionsToGenType(context, genType, grouping, null, true); + notificationsToGenType(context, genType, grouping, null, true); } } @@ -925,17 +973,20 @@ abstract class AbstractTypeGenerator { augTypeBuilder.addImplementsType(DATA_OBJECT); defaultImplementedInterace(augTypeBuilder); - augTypeBuilder.addImplementsType(augmentationTypeFor(targetTypeRef)); - annotateDeprecatedIfNecessary(augSchema.getStatus(), augTypeBuilder); + augTypeBuilder.addImplementsType(augmentation(targetTypeRef)); + annotateDeprecatedIfNecessary(augSchema, augTypeBuilder); addImplementedInterfaceFromUses(augSchema, augTypeBuilder); augSchemaNodeToMethods(context, augTypeBuilder, augSchema.getChildNodes(), inGrouping); + actionsToGenType(context, augTypeBuilder, augSchema, null, inGrouping); + notificationsToGenType(context, augTypeBuilder, augSchema, null, inGrouping); + augmentBuilders.put(augTypeName, augTypeBuilder); if (!augSchema.getChildNodes().isEmpty()) { context.addTypeToAugmentation(augTypeBuilder, augSchema); - } + context.addAugmentType(augTypeBuilder); return augTypeBuilder; } @@ -1052,8 +1103,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 +1130,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 +1145,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 +1185,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 +1751,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 +1762,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); } /** @@ -1744,6 +1809,8 @@ abstract class AbstractTypeGenerator { choiceToGeneratedType(context, typeBuilder, (ChoiceSchemaNode) schemaNode, inGrouping); } else if (schemaNode instanceof ListSchemaNode) { listToGenType(context, typeBuilder, childOf(typeBuilder), (ListSchemaNode) schemaNode, inGrouping); + } else if (schemaNode instanceof AnyXmlSchemaNode || schemaNode instanceof AnyDataSchemaNode) { + opaqueToGeneratedType(context, typeBuilder, schemaNode); } } } @@ -1769,32 +1836,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()); - } - } - return listKeys; - } - - /** - * Generates for the list which contains any list keys special generated TO builder. - * - * @param packageName string with package name to which the list belongs - * @param list list schema node which is source of data about the list name - * @return generated TO builder which represents the keys of the list or null if list is - * null or list of key definitions is null or empty. - */ - private GeneratedTOBuilder resolveListKeyTOBuilder(final ModuleContext context, final ListSchemaNode list) { - if (list.getKeyDefinition() != null && !list.getKeyDefinition().isEmpty()) { - return typeProvider.newGeneratedTOBuilder(JavaTypeName.create( - packageNameForGeneratedType(context.modulePackageName(), list.getPath()), - BindingMapping.getClassName(list.getQName().getLocalName() + "Key"))); + 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 null; } /** @@ -1811,8 +1865,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 +1898,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 +1916,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 +1957,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); } }