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=306726b674f6751f58ad51b25efcfb1105fdd46d;hb=9134ff50aac46ce533308d3e44cbdc3db00d0865;hp=538dd07cf497bc4cd12d495fef26115cdf236fb9;hpb=f06d62ff5e85ce7c953ca606da08248138415873;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 538dd07cf4..306726b674 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 @@ -8,21 +8,32 @@ package org.opendaylight.mdsal.binding.generator.impl; import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; 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_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.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.keyedListAction; +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.listTypeFor; +import static org.opendaylight.mdsal.binding.model.util.Types.listenableFutureTypeFor; 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; @@ -31,6 +42,7 @@ 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.AbstractMap.SimpleImmutableEntry; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; @@ -40,13 +52,16 @@ import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; +import org.eclipse.jdt.annotation.Nullable; import org.opendaylight.mdsal.binding.model.api.AccessModifier; import org.opendaylight.mdsal.binding.model.api.Constant; import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject; import org.opendaylight.mdsal.binding.model.api.GeneratedType; +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; @@ -56,20 +71,18 @@ 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; -import org.opendaylight.mdsal.binding.model.util.generated.type.builder.CodegenGeneratedTOBuilder; import org.opendaylight.mdsal.binding.model.util.generated.type.builder.GeneratedPropertyBuilderImpl; +import org.opendaylight.mdsal.binding.spec.naming.BindingMapping; 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.RpcResult; +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.AugmentationSchemaNode; import org.opendaylight.yangtools.yang.model.api.CaseSchemaNode; import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode; @@ -94,14 +107,12 @@ 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; import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition; import org.opendaylight.yangtools.yang.model.util.DataNodeIterator; import org.opendaylight.yangtools.yang.model.util.ModuleDependencySort; -import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil; import org.opendaylight.yangtools.yang.model.util.SchemaNodeUtils; import org.opendaylight.yangtools.yang.model.util.type.CompatUtils; import org.slf4j.Logger; @@ -110,6 +121,9 @@ 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); + private static final Type LIST_STRING_TYPE = listTypeFor(BaseYangTypes.STRING_TYPE); /** * Comparator based on augment target path. @@ -142,7 +156,7 @@ abstract class AbstractTypeGenerator { */ private static final String YANG_EXT_NAMESPACE = "urn:opendaylight:yang:extension:yang-ext"; - private final Map genCtx = new HashMap<>(); + private final Map genCtx = new HashMap<>(); /** * Outer key represents the package name. Outer value represents map of all @@ -163,25 +177,32 @@ abstract class AbstractTypeGenerator { */ private final SchemaContext schemaContext; - AbstractTypeGenerator(final SchemaContext context, final AbstractTypeProvider typeProvider) { + /** + * Holds renamed elements. + */ + private final Map renames; + + AbstractTypeGenerator(final SchemaContext context, final AbstractTypeProvider typeProvider, + final Map renames) { this.schemaContext = requireNonNull(context); this.typeProvider = requireNonNull(typeProvider); + this.renames = requireNonNull(renames); final List contextModules = ModuleDependencySort.sort(schemaContext.getModules()); + final List contexts = new ArrayList<>(contextModules.size()); for (final Module contextModule : contextModules) { - moduleToGenTypes(contextModule, schemaContext); - } - for (final Module contextModule : contextModules) { - allAugmentsToGenTypes(contextModule); + contexts.add(moduleToGenTypes(contextModule)); } + + contexts.forEach(this::allAugmentsToGenTypes); } final Collection moduleContexts() { return genCtx.values(); } - final ModuleContext moduleContext(final Module module) { - return checkNotNull(genCtx.get(module), "Module context not found for module %s", module); + final ModuleContext moduleContext(final QNameModule module) { + return requireNonNull(genCtx.get(module), () -> "Module context not found for module " + module); } final AbstractTypeProvider typeProvider() { @@ -197,20 +218,21 @@ abstract class AbstractTypeGenerator { abstract void addComment(TypeMemberBuilder genType, DocumentedNode node); - private void moduleToGenTypes(final Module m, final SchemaContext context) { - genCtx.put(m, new ModuleContext()); - allTypeDefinitionsToGenTypes(m); - groupingsToGenTypes(m, m.getGroupings()); - rpcMethodsToGenType(m); - allIdentitiesToGenTypes(m, context); - notificationsToGenType(m); - - if (!m.getChildNodes().isEmpty()) { - final GeneratedTypeBuilder moduleType = moduleToDataType(m); - genCtx.get(m).addModuleNode(moduleType); - final String basePackageName = BindingMapping.getRootPackageName(m.getQNameModule()); - resolveDataSchemaNodes(m, basePackageName, moduleType, moduleType, m.getChildNodes()); - } + private ModuleContext moduleToGenTypes(final Module module) { + final ModuleContext context = new ModuleContext(module); + genCtx.put(module.getQNameModule(), context); + allTypeDefinitionsToGenTypes(context); + groupingsToGenTypes(context, module.getGroupings()); + rpcMethodsToGenType(context); + allIdentitiesToGenTypes(context); + notificationsToGenType(context); + + if (!module.getChildNodes().isEmpty()) { + final GeneratedTypeBuilder moduleType = moduleToDataType(context); + context.addModuleNode(moduleType); + resolveDataSchemaNodes(context, moduleType, moduleType, module.getChildNodes()); + } + return context; } /** @@ -227,8 +249,8 @@ abstract class AbstractTypeGenerator { * @throws IllegalStateException * if set of type definitions from module is null */ - private void allTypeDefinitionsToGenTypes(final Module module) { - checkArgument(module != null, "Module reference cannot be NULL."); + private void allTypeDefinitionsToGenTypes(final ModuleContext context) { + final Module module = context.module(); checkArgument(module.getName() != null, "Module name cannot be NULL."); final DataNodeIterator it = new DataNodeIterator(module); final List> typeDefinitions = it.allTypedefs(); @@ -236,65 +258,65 @@ abstract class AbstractTypeGenerator { for (final TypeDefinition typedef : typeDefinitions) { if (typedef != null) { - final Type type = typeProvider.generatedTypeForExtendedDefinitionType(typedef, - typedef); + final Type type = typeProvider.generatedTypeForExtendedDefinitionType(typedef, typedef); if (type != null) { - final ModuleContext ctx = genCtx.get(module); - ctx.addTypedefType(typedef.getPath(), type); - ctx.addTypeToSchema(type,typedef); + context.addTypedefType(typedef, type); + context.addTypeToSchema(type,typedef); } } } } - private GeneratedTypeBuilder processDataSchemaNode(final Module module, final String basePackageName, - final GeneratedTypeBuilder childOf, final DataSchemaNode node) { + private GeneratedTypeBuilder processDataSchemaNode(final ModuleContext context, final Type baseInterface, + final DataSchemaNode node) { if (node.isAugmenting() || node.isAddedByUses()) { return null; } - final String packageName = packageNameForGeneratedType(basePackageName, node.getPath()); - final GeneratedTypeBuilder genType = addDefaultInterfaceDefinition(packageName, node, childOf, module); + final GeneratedTypeBuilder genType = addDefaultInterfaceDefinition(context, node, baseInterface); annotateDeprecatedIfNecessary(node.getStatus(), genType); + final Module module = context.module(); genType.setModuleName(module.getName()); addCodegenInformation(genType, module, node); - genType.setSchemaPath(node.getPath().getPathFromRoot()); + genType.setSchemaPath(node.getPath()); if (node instanceof DataNodeContainer) { - genCtx.get(module).addChildNodeType(node, genType); - groupingsToGenTypes(module, ((DataNodeContainer) node).getGroupings()); - processUsesAugments((DataNodeContainer) node, module); + context.addChildNodeType(node, genType); + groupingsToGenTypes(context, ((DataNodeContainer) node).getGroupings()); + processUsesAugments((DataNodeContainer) node, context); } return genType; } - private void containerToGenType(final Module module, final String basePackageName, - final GeneratedTypeBuilder parent, final GeneratedTypeBuilder childOf, final ContainerSchemaNode node) { - final GeneratedTypeBuilder genType = processDataSchemaNode(module, basePackageName, childOf, node); + private void containerToGenType(final ModuleContext context, final GeneratedTypeBuilder parent, + final Type baseInterface, final ContainerSchemaNode node) { + final GeneratedTypeBuilder genType = processDataSchemaNode(context, baseInterface, node); if (genType != null) { constructGetter(parent, genType, node); - resolveDataSchemaNodes(module, basePackageName, genType, genType, node.getChildNodes()); + resolveDataSchemaNodes(context, genType, genType, node.getChildNodes()); + actionsToGenType(context, genType, node, null); } } - private void listToGenType(final Module module, final String basePackageName, final GeneratedTypeBuilder parent, - final GeneratedTypeBuilder childOf, final ListSchemaNode node) { - final GeneratedTypeBuilder genType = processDataSchemaNode(module, basePackageName, childOf, node); + private void listToGenType(final ModuleContext context, final GeneratedTypeBuilder parent, + final Type baseInterface, final ListSchemaNode node) { + final GeneratedTypeBuilder genType = processDataSchemaNode(context, baseInterface, node); if (genType != null) { - constructGetter(parent, Types.listTypeFor(genType), node); + constructGetter(parent, listTypeFor(genType), node); final List listKeys = listKeys(node); - final String packageName = packageNameForGeneratedType(basePackageName, node.getPath()); - final GeneratedTOBuilder genTOBuilder = resolveListKeyTOBuilder(packageName, 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); + } + actionsToGenType(context, genType, node, genTOBuilder); for (final DataSchemaNode schemaNode : node.getChildNodes()) { if (!schemaNode.isAugmenting()) { - addSchemaNodeToListBuilders(basePackageName, schemaNode, genType, genTOBuilder, listKeys, module); + addSchemaNodeToListBuilders(context, schemaNode, genType, genTOBuilder, listKeys); } } @@ -305,16 +327,15 @@ abstract class AbstractTypeGenerator { genTOBuilder.setSUID(prop); } - typeBuildersToGenTypes(module, genType, genTOBuilder); + typeBuildersToGenTypes(context, genType, genTOBuilder); } } - private void processUsesAugments(final DataNodeContainer node, final Module module) { - final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule()); + private void processUsesAugments(final DataNodeContainer node, final ModuleContext context) { for (final UsesNode usesNode : node.getUses()) { for (final AugmentationSchemaNode augment : usesNode.getAugmentations()) { - usesAugmentationToGenTypes(basePackageName, augment, module, usesNode, node); - processUsesAugments(augment, module); + usesAugmentationToGenTypes(context, augment, usesNode, node); + processUsesAugments(augment, context); } } } @@ -334,14 +355,14 @@ abstract class AbstractTypeGenerator { * @throws IllegalStateException * if set of augmentations from module is null */ - private void allAugmentsToGenTypes(final Module module) { + private void allAugmentsToGenTypes(final ModuleContext context) { + final Module module = context.module(); checkArgument(module != null, "Module reference cannot be NULL."); checkArgument(module.getName() != null, "Module name cannot be NULL."); checkState(module.getAugmentations() != null, "Augmentations Set cannot be NULL."); - final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule()); for (final AugmentationSchemaNode augment : resolveAugmentations(module)) { - augmentationToGenTypes(basePackageName, augment, module); + augmentationToGenTypes(context, augment); } } @@ -380,10 +401,9 @@ abstract class AbstractTypeGenerator { * @throws IllegalArgumentException * if module is null */ - private GeneratedTypeBuilder moduleToDataType(final Module module) { - checkArgument(module != null, "Module reference cannot be NULL."); - - final GeneratedTypeBuilder moduleDataTypeBuilder = moduleTypeBuilder(module, "Data"); + private GeneratedTypeBuilder moduleToDataType(final ModuleContext context) { + final GeneratedTypeBuilder moduleDataTypeBuilder = moduleTypeBuilder(context, "Data"); + final Module module = context.module(); addImplementedInterfaceFromUses(module, moduleDataTypeBuilder); moduleDataTypeBuilder.addImplementsType(DATA_ROOT); @@ -391,6 +411,62 @@ abstract class AbstractTypeGenerator { return moduleDataTypeBuilder; } + private void actionsToGenType(final ModuleContext context, + final Type parent, final T parentSchema, final Type keyType) { + for (final ActionDefinition action : parentSchema.getActions()) { + final GeneratedType input; + final GeneratedType output; + if (action.isAddedByUses()) { + final ActionDefinition orig = findOrigAction(parentSchema, action).get(); + input = context.getChildNode(orig.getInput().getPath()).build(); + output = context.getChildNode(orig.getOutput().getPath()).build(); + } else { + input = actionContainer(context, RPC_INPUT, action.getInput()); + output = actionContainer(context, RPC_OUTPUT, action.getOutput()); + } + + if (!(parentSchema instanceof GroupingDefinition)) { + // Parent is a non-grouping, hence we need to establish an Action instance, which can be completely + // identified by an InstanceIdentifier. We do not generate Actions for groupings as they are inexact, + // and do not capture an actual instantiation. + final QName qname = action.getQName(); + final GeneratedTypeBuilder builder = typeProvider.newGeneratedTypeBuilder(JavaTypeName.create( + packageNameForGeneratedType(context.modulePackageName(), action.getPath()), + BindingMapping.getClassName(qname))); + qnameConstant(builder, JavaTypeName.create(context.modulePackageName(), + BindingMapping.MODULE_INFO_CLASS_NAME), qname.getLocalName()); + + annotateDeprecatedIfNecessary(action.getStatus(), builder); + builder.addImplementsType(keyType != null ? keyedListAction(parent, keyType, input, output) + : action(parent, input, output)); + + addCodegenInformation(builder, context.module(), action); + context.addChildNodeType(action, builder); + } + } + } + + 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(); + if (found.isPresent()) { + final ActionDefinition result = found.get(); + return result.isAddedByUses() ? findOrigAction(grp, result) : found; + } + } + + return Optional.empty(); + } + + private GeneratedType actionContainer(final ModuleContext context, final Type baseInterface, + final ContainerSchemaNode schema) { + final GeneratedTypeBuilder genType = processDataSchemaNode(context, baseInterface, schema); + resolveDataSchemaNodes(context, genType, genType, schema.getChildNodes()); + return genType.build(); + } + /** * Converts all RPCs input and output substatements of the module * to the list of Type objects. In addition are to containers @@ -407,8 +483,8 @@ abstract class AbstractTypeGenerator { * @throws IllegalStateException * if set of rpcs from module is null */ - private void rpcMethodsToGenType(final Module module) { - checkArgument(module != null, "Module reference cannot be NULL."); + private void rpcMethodsToGenType(final ModuleContext context) { + final Module module = context.module(); checkArgument(module.getName() != null, "Module name cannot be NULL."); final Set rpcDefinitions = module.getRpcs(); checkState(rpcDefinitions != null, "Set of rpcs from module " + module.getName() + " cannot be NULL."); @@ -416,9 +492,8 @@ abstract class AbstractTypeGenerator { return; } - final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule()); - final GeneratedTypeBuilder interfaceBuilder = moduleTypeBuilder(module, "Service"); - interfaceBuilder.addImplementsType(Types.typeForClass(RpcService.class)); + final GeneratedTypeBuilder interfaceBuilder = moduleTypeBuilder(context, "Service"); + interfaceBuilder.addImplementsType(RPC_SERVICE); addCodegenInformation(interfaceBuilder, module, "RPCs", rpcDefinitions); @@ -427,54 +502,33 @@ 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)) { - processUsesAugments(input, module); - final GeneratedTypeBuilder inType = addRawInterfaceDefinition(basePackageName, input, rpcName); - addImplementedInterfaceFromUses(input, inType); - inType.addImplementsType(DATA_OBJECT); - inType.addImplementsType(augmentable(inType)); - annotateDeprecatedIfNecessary(rpc.getStatus(), inType); - resolveDataSchemaNodes(module, basePackageName, inType, inType, input.getChildNodes()); - genCtx.get(module).addChildNodeType(input, inType); - final GeneratedType inTypeInstance = inType.toInstance(); - method.addParameter(inTypeInstance, "input"); - } - - Type outTypeInstance = VOID; - //in case of implicit RPC output (StatementSource.CONTEXT), - //stay compatible (Future> return type generated) - if (output != null && isExplicitStatement(output)) { - processUsesAugments(output, module); - final GeneratedTypeBuilder outType = addRawInterfaceDefinition(basePackageName, output, rpcName); - addImplementedInterfaceFromUses(output, outType); - outType.addImplementsType(DATA_OBJECT); - outType.addImplementsType(augmentable(outType)); - annotateDeprecatedIfNecessary(rpc.getStatus(), outType); - resolveDataSchemaNodes(module, basePackageName, outType, outType, output.getChildNodes()); - genCtx.get(module).addChildNodeType(output, outType); - outTypeInstance = outType.toInstance(); - } - - 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()), RPC_INPUT), "input"); + method.setReturnType(listenableFutureTypeFor( + rpcResult(createRpcContainer(context, rpcName, rpc, verifyNotNull(rpc.getOutput()), RPC_OUTPUT)))); } } - genCtx.get(module).addTopLevelNodeType(interfaceBuilder); + 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, final Type type) { + processUsesAugments(schema, context); + final GeneratedTypeBuilder outType = addRawInterfaceDefinition( + JavaTypeName.create(context.modulePackageName(), rpcName + BindingMapping.getClassName(schema.getQName())), + schema); + addImplementedInterfaceFromUses(schema, outType); + outType.addImplementsType(type); + outType.addImplementsType(augmentable(outType)); + annotateDeprecatedIfNecessary(rpc.getStatus(), outType); + resolveDataSchemaNodes(context, outType, outType, schema.getChildNodes()); + context.addChildNodeType(schema, outType); + return outType.build(); } /** @@ -493,40 +547,39 @@ abstract class AbstractTypeGenerator { * @throws IllegalStateException * if set of notifications from module is null */ - private void notificationsToGenType(final Module module) { - checkArgument(module != null, "Module reference cannot be NULL."); + private void notificationsToGenType(final ModuleContext context) { + final Module module = context.module(); checkArgument(module.getName() != null, "Module name cannot be NULL."); final Set notifications = module.getNotifications(); if (notifications.isEmpty()) { return; } - final GeneratedTypeBuilder listenerInterface = moduleTypeBuilder(module, "Listener"); - listenerInterface.addImplementsType(BindingTypes.NOTIFICATION_LISTENER); - final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule()); + final GeneratedTypeBuilder listenerInterface = moduleTypeBuilder(context, "Listener"); + listenerInterface.addImplementsType(NOTIFICATION_LISTENER); for (final NotificationDefinition notification : notifications) { if (notification != null) { - processUsesAugments(notification, module); + processUsesAugments(notification, context); - final GeneratedTypeBuilder notificationInterface = addDefaultInterfaceDefinition(basePackageName, - notification, null, module); + final GeneratedTypeBuilder notificationInterface = addDefaultInterfaceDefinition( + context.modulePackageName(), notification, DATA_OBJECT, context); annotateDeprecatedIfNecessary(notification.getStatus(), notificationInterface); notificationInterface.addImplementsType(NOTIFICATION); - genCtx.get(module).addChildNodeType(notification, notificationInterface); + context.addChildNodeType(notification, notificationInterface); // Notification object - resolveDataSchemaNodes(module, basePackageName, notificationInterface, notificationInterface, - notification.getChildNodes()); + resolveDataSchemaNodes(context, notificationInterface, notificationInterface, + notification.getChildNodes()); addComment(listenerInterface.addMethod("on" + notificationInterface.getName()) .setAccessModifier(AccessModifier.PUBLIC).addParameter(notificationInterface, "notification") - .setReturnType(Types.VOID), notification); + .setReturnType(Types.primitiveVoidType()), notification); } } addCodegenInformation(listenerInterface, module, "notifications", notifications); - genCtx.get(module).addTopLevelNodeType(listenerInterface); + context.addTopLevelNodeType(listenerInterface); } /** @@ -536,18 +589,17 @@ abstract class AbstractTypeGenerator { * @param module * module from which is obtained set of all identity objects to * iterate over them - * @param context + * @param schemaContext * schema context only used as input parameter for method * {@link BindingGeneratorImpl#identityToGenType} * */ - private void allIdentitiesToGenTypes(final Module module, final SchemaContext context) { - final Set schemaIdentities = module.getIdentities(); - final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule()); + private void allIdentitiesToGenTypes(final ModuleContext context) { + final Set schemaIdentities = context.module().getIdentities(); if (schemaIdentities != null && !schemaIdentities.isEmpty()) { for (final IdentitySchemaNode identity : schemaIdentities) { - identityToGenType(module, basePackageName, identity, context); + identityToGenType(context, identity); } } } @@ -566,50 +618,51 @@ abstract class AbstractTypeGenerator { * string contains the module package name * @param identity * IdentitySchemaNode which contains data about identity - * @param context - * SchemaContext which is used to get package and name - * information about base of identity - * */ - private void identityToGenType(final Module module, final String basePackageName, - final IdentitySchemaNode identity, final SchemaContext context) { + private void identityToGenType(final ModuleContext context,final IdentitySchemaNode identity) { if (identity == null) { return; } - final String packageName = packageNameForGeneratedType(basePackageName, identity.getPath()); - final String genTypeName = BindingMapping.getClassName(identity.getQName()); - final GeneratedTOBuilder newType = typeProvider.newGeneratedTOBuilder(packageName, genTypeName); + + JavaTypeName name = renames.get(identity); + if (name == null) { + name = JavaTypeName.create(packageNameForGeneratedType(context.modulePackageName(), identity.getPath()), + BindingMapping.getClassName(identity.getQName())); + } + + final GeneratedTypeBuilder newType = typeProvider.newGeneratedTypeBuilder(name); final Set baseIdentities = identity.getBaseIdentities(); - if (baseIdentities.isEmpty()) { - final GeneratedTOBuilder gto = typeProvider.newGeneratedTOBuilder( - BaseIdentity.class.getPackage().getName(), BaseIdentity.class.getSimpleName()); - newType.setExtendsType(gto.toInstance()); + if (!baseIdentities.isEmpty()) { + for (IdentitySchemaNode baseIdentity : baseIdentities) { + JavaTypeName base = renames.get(baseIdentity); + if (base == null) { + final QName qname = baseIdentity.getQName(); + base = JavaTypeName.create(BindingMapping.getRootPackageName(qname.getModule()), + BindingMapping.getClassName(qname)); + } + + final GeneratedTransferObject gto = typeProvider.newGeneratedTOBuilder(base).build(); + newType.addImplementsType(gto); + } } else { - final IdentitySchemaNode baseIdentity = baseIdentities.iterator().next(); - final Module baseIdentityParentModule = SchemaContextUtil.findParentModule(context, baseIdentity); - final String returnTypePkgName = BindingMapping.getRootPackageName(baseIdentityParentModule - .getQNameModule()); - final String returnTypeName = BindingMapping.getClassName(baseIdentity.getQName()); - final GeneratedTransferObject gto = new CodegenGeneratedTOBuilder(returnTypePkgName, returnTypeName) - .toInstance(); - newType.setExtendsType(gto); + newType.addImplementsType(BASE_IDENTITY); } - newType.setAbstract(true); + final Module module = context.module(); addCodegenInformation(newType, module, identity); newType.setModuleName(module.getName()); - newType.setSchemaPath(identity.getPath().getPathFromRoot()); + newType.setSchemaPath(identity.getPath()); - final QName qname = identity.getQName(); - qnameConstant(newType, BindingMapping.QNAME_STATIC_FIELD_NAME, qname); + qnameConstant(newType, JavaTypeName.create(context.modulePackageName(), BindingMapping.MODULE_INFO_CLASS_NAME), + identity.getQName().getLocalName()); - genCtx.get(module).addIdentityType(identity.getQName(), newType); + context.addIdentityType(identity, 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)); } /** @@ -625,38 +678,20 @@ abstract class AbstractTypeGenerator { * collection of groupings from which types will be generated * */ - private void groupingsToGenTypes(final Module module, final Collection groupings) { - final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule()); - final List groupingsSortedByDependencies = new GroupingDefinitionDependencySort() - .sort(groupings); - for (final GroupingDefinition grouping : groupingsSortedByDependencies) { - groupingToGenType(basePackageName, grouping, module); + private void groupingsToGenTypes(final ModuleContext context, final Collection groupings) { + for (final GroupingDefinition grouping : new GroupingDefinitionDependencySort().sort(groupings)) { + // Converts individual grouping to GeneratedType. Firstly generated type builder is created and every child + // node of grouping is resolved to the method. + final GeneratedTypeBuilder genType = addDefaultInterfaceDefinition(context, grouping); + annotateDeprecatedIfNecessary(grouping.getStatus(), genType); + context.addGroupingType(grouping, genType); + resolveDataSchemaNodes(context, genType, genType, grouping.getChildNodes()); + groupingsToGenTypes(context, grouping.getGroupings()); + processUsesAugments(grouping, context); + actionsToGenType(context, genType, grouping, null); } } - /** - * Converts individual grouping to GeneratedType. Firstly generated type - * builder is created and every child node of grouping is resolved to the - * method. - * - * @param basePackageName - * string contains the module package name - * @param grouping - * GroupingDefinition which contains data about grouping - * @param module - * current module - */ - private void groupingToGenType(final String basePackageName, final GroupingDefinition grouping, - final Module module) { - final String packageName = packageNameForGeneratedType(basePackageName, grouping.getPath()); - final GeneratedTypeBuilder genType = addDefaultInterfaceDefinition(packageName, grouping, module); - annotateDeprecatedIfNecessary(grouping.getStatus(), genType); - genCtx.get(module).addGroupingType(grouping.getPath(), genType); - resolveDataSchemaNodes(module, basePackageName, genType, genType, grouping.getChildNodes()); - groupingsToGenTypes(module, grouping.getGroupings()); - processUsesAugments(grouping, module); - } - /** * Adds enumeration builder created from enumTypeDef to * typeBuilder. @@ -677,14 +712,12 @@ abstract class AbstractTypeGenerator { * enumTypeDef */ private EnumBuilder resolveInnerEnumFromTypeDefinition(final EnumTypeDefinition enumTypeDef, final QName enumName, - final GeneratedTypeBuilder typeBuilder, final Module module) { + final GeneratedTypeBuilder typeBuilder, final ModuleContext context) { if (enumTypeDef != null && typeBuilder != null && enumTypeDef.getQName().getLocalName() != null) { - final String enumerationName = BindingMapping.getClassName(enumName); - final EnumBuilder enumBuilder = typeBuilder.addEnumeration(enumerationName); + final EnumBuilder enumBuilder = typeBuilder.addEnumeration(BindingMapping.getClassName(enumName)); typeProvider.addEnumDescription(enumBuilder, enumTypeDef); enumBuilder.updateEnumPairsFromEnumTypeDef(enumTypeDef); - ModuleContext ctx = genCtx.get(module); - ctx.addInnerTypedefType(enumTypeDef.getPath(), enumBuilder); + context.addInnerTypedefType(enumTypeDef.getPath(), enumBuilder); return enumBuilder; } return null; @@ -704,12 +737,11 @@ abstract class AbstractTypeGenerator { * @throws IllegalArgumentException * if module is null */ - private GeneratedTypeBuilder moduleTypeBuilder(final Module module, final String postfix) { - checkArgument(module != null, "Module reference cannot be NULL."); - final String packageName = BindingMapping.getRootPackageName(module.getQNameModule()); + private GeneratedTypeBuilder moduleTypeBuilder(final ModuleContext context, final String postfix) { + final Module module = context.module(); final String moduleName = BindingMapping.getClassName(module.getName()) + postfix; - - final GeneratedTypeBuilder moduleBuilder = typeProvider.newGeneratedTypeBuilder(packageName, moduleName); + final GeneratedTypeBuilder moduleBuilder = typeProvider.newGeneratedTypeBuilder( + JavaTypeName.create(context.modulePackageName(), moduleName)); moduleBuilder.setModuleName(moduleName); addCodegenInformation(moduleBuilder, module); @@ -739,14 +771,12 @@ abstract class AbstractTypeGenerator { * @throws IllegalStateException * if augment target path is null */ - private void augmentationToGenTypes(final String augmentPackageName, final AugmentationSchemaNode augSchema, - final Module module) { - checkArgument(augmentPackageName != null, "Package Name cannot be NULL."); + private void augmentationToGenTypes(final ModuleContext context, final AugmentationSchemaNode augSchema) { checkArgument(augSchema != null, "Augmentation Schema cannot be NULL."); checkState(augSchema.getTargetPath() != null, "Augmentation Schema does not contain Target Path (Target Path is NULL)."); - processUsesAugments(augSchema, module); + processUsesAugments(augSchema, context); final SchemaPath targetPath = augSchema.getTargetPath(); SchemaNode targetSchemaNode = null; @@ -757,7 +787,7 @@ abstract class AbstractTypeGenerator { } if (targetSchemaNode == null) { throw new IllegalStateException("Failed to find target node from grouping in augmentation " + augSchema - + " in module " + module.getName()); + + " in module " + context.module().getName()); } } if (targetSchemaNode == null) { @@ -773,24 +803,22 @@ abstract class AbstractTypeGenerator { } if (!(targetSchemaNode instanceof ChoiceSchemaNode)) { - final Type targetType = new ReferencedTypeImpl(targetTypeBuilder.getPackageName(), - targetTypeBuilder.getName()); - addRawAugmentGenTypeDefinition(module, augmentPackageName, augmentPackageName, targetType, augSchema); + final Type targetType = new ReferencedTypeImpl(targetTypeBuilder.getIdentifier()); + addRawAugmentGenTypeDefinition(context, targetType, augSchema); } else { - generateTypesFromAugmentedChoiceCases(module, augmentPackageName, targetTypeBuilder.toInstance(), + generateTypesFromAugmentedChoiceCases(context, targetTypeBuilder.build(), (ChoiceSchemaNode) targetSchemaNode, augSchema.getChildNodes(), null); } } - private void usesAugmentationToGenTypes(final String augmentPackageName, final AugmentationSchemaNode augSchema, - final Module module, final UsesNode usesNode, final DataNodeContainer usesNodeParent) { - checkArgument(augmentPackageName != null, "Package Name cannot be NULL."); + private void usesAugmentationToGenTypes(final ModuleContext context, final AugmentationSchemaNode augSchema, + final UsesNode usesNode, final DataNodeContainer usesNodeParent) { checkArgument(augSchema != null, "Augmentation Schema cannot be NULL."); checkState(augSchema.getTargetPath() != null, "Augmentation Schema does not contain Target Path (Target Path is NULL)."); - processUsesAugments(augSchema, module); + processUsesAugments(augSchema, context); final SchemaPath targetPath = augSchema.getTargetPath(); final SchemaNode targetSchemaNode = findOriginalTargetFromGrouping(targetPath, usesNode); if (targetSchemaNode == null) { @@ -806,19 +834,30 @@ abstract class AbstractTypeGenerator { } if (!(targetSchemaNode instanceof ChoiceSchemaNode)) { - String packageName = augmentPackageName; if (usesNodeParent instanceof SchemaNode) { - packageName = packageNameForAugmentedGeneratedType(augmentPackageName, - ((SchemaNode) usesNodeParent).getPath()); + addRawAugmentGenTypeDefinition(context, + packageNameForAugmentedGeneratedType(context.modulePackageName(), + ((SchemaNode) usesNodeParent).getPath()), + targetTypeBuilder.build(), augSchema); + } else { + addRawAugmentGenTypeDefinition(context, targetTypeBuilder.build(), augSchema); } - addRawAugmentGenTypeDefinition(module, packageName, augmentPackageName, targetTypeBuilder.toInstance(), - augSchema); } else { - generateTypesFromAugmentedChoiceCases(module, augmentPackageName, targetTypeBuilder.toInstance(), - (ChoiceSchemaNode) targetSchemaNode, augSchema.getChildNodes(), usesNodeParent); + generateTypesFromAugmentedChoiceCases(context, targetTypeBuilder.build(), + (ChoiceSchemaNode) targetSchemaNode, augSchema.getChildNodes(), usesNodeParent); } } + private GroupingDefinition findUsedGrouping(final UsesNode uses) { + final SchemaNode targetGrouping = findNodeInSchemaContext(schemaContext, uses.getGroupingPath() + .getPathFromRoot()); + if (targetGrouping instanceof GroupingDefinition) { + return (GroupingDefinition) targetGrouping; + } + + throw new IllegalArgumentException("Failed to resolve used grouping for " + uses); + } + /** * Convenient method to find node added by uses statement. * @@ -829,16 +868,10 @@ abstract class AbstractTypeGenerator { * @return node from its original location in grouping */ private DataSchemaNode findOriginalTargetFromGrouping(final SchemaPath targetPath, final UsesNode parentUsesNode) { - final SchemaNode targetGrouping = findNodeInSchemaContext(schemaContext, parentUsesNode.getGroupingPath() - .getPathFromRoot()); - if (!(targetGrouping instanceof GroupingDefinition)) { - throw new IllegalArgumentException("Failed to generate code for augment in " + parentUsesNode); - } - - SchemaNode result = targetGrouping; + SchemaNode result = findUsedGrouping(parentUsesNode); 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()); @@ -879,7 +912,7 @@ abstract class AbstractTypeGenerator { * The name of the type builder is equal to the name of augmented node with * serial number as suffix. * - * @param module + * @param context * current module * @param augmentPackageName * string with contains the package name to which the augment @@ -894,8 +927,9 @@ abstract class AbstractTypeGenerator { * and uses of augment * @return generated type builder for augment */ - private GeneratedTypeBuilder addRawAugmentGenTypeDefinition(final Module module, final String augmentPackageName, - final String basePackageName, final Type targetTypeRef, final AugmentationSchemaNode augSchema) { + private GeneratedTypeBuilder addRawAugmentGenTypeDefinition(final ModuleContext context, + final String augmentPackageName, final Type targetTypeRef, + final AugmentationSchemaNode augSchema) { Map augmentBuilders = genTypeBuilders.get(augmentPackageName); if (augmentBuilders == null) { augmentBuilders = new HashMap<>(); @@ -910,25 +944,30 @@ abstract class AbstractTypeGenerator { augTypeName = augGenTypeName(augmentBuilders, targetTypeRef.getName()); } - final GeneratedTypeBuilder augTypeBuilder = typeProvider.newGeneratedTypeBuilder(augmentPackageName, - augTypeName); + final GeneratedTypeBuilder augTypeBuilder = typeProvider.newGeneratedTypeBuilder( + JavaTypeName.create(augmentPackageName, augTypeName)); augTypeBuilder.addImplementsType(DATA_OBJECT); augTypeBuilder.addImplementsType(Types.augmentationTypeFor(targetTypeRef)); annotateDeprecatedIfNecessary(augSchema.getStatus(), augTypeBuilder); addImplementedInterfaceFromUses(augSchema, augTypeBuilder); - augSchemaNodeToMethods(module, basePackageName, augTypeBuilder, augTypeBuilder, augSchema.getChildNodes()); + augSchemaNodeToMethods(context, augTypeBuilder, augSchema.getChildNodes()); augmentBuilders.put(augTypeName, augTypeBuilder); if (!augSchema.getChildNodes().isEmpty()) { - genCtx.get(module).addTypeToAugmentation(augTypeBuilder, augSchema); + context.addTypeToAugmentation(augTypeBuilder, augSchema); } - genCtx.get(module).addAugmentType(augTypeBuilder); + context.addAugmentType(augTypeBuilder); return augTypeBuilder; } + private GeneratedTypeBuilder addRawAugmentGenTypeDefinition(final ModuleContext context, final Type targetTypeRef, + final AugmentationSchemaNode augSchema) { + return addRawAugmentGenTypeDefinition(context, context.modulePackageName(), targetTypeRef, augSchema); + } + /** * * @param unknownSchemaNodes @@ -976,8 +1015,6 @@ abstract class AbstractTypeGenerator { * * @param module * current module - * @param basePackageName - * string contains the module package name * @param parent * generated type builder which represents any node. The subnodes * of this node are added to the typeBuilder as @@ -992,12 +1029,13 @@ abstract class AbstractTypeGenerator { * parameter. The getter methods (representing child nodes) could be * added to it. */ - private GeneratedTypeBuilder resolveDataSchemaNodes(final Module module, final String basePackageName, - final GeneratedTypeBuilder parent, final GeneratedTypeBuilder childOf, final Iterable schemaNodes) { + private GeneratedTypeBuilder resolveDataSchemaNodes(final ModuleContext context, final GeneratedTypeBuilder parent, + final @Nullable Type childOf, final Iterable schemaNodes) { if (schemaNodes != null && parent != null) { + final Type baseInterface = childOf == null ? DATA_OBJECT : childOf(childOf); for (final DataSchemaNode schemaNode : schemaNodes) { if (!schemaNode.isAugmenting() && !schemaNode.isAddedByUses()) { - addSchemaNodeToBuilderAsMethod(basePackageName, schemaNode, parent, childOf, module); + addSchemaNodeToBuilderAsMethod(context, schemaNode, parent, baseInterface); } } } @@ -1010,8 +1048,6 @@ abstract class AbstractTypeGenerator { * * @param module * current module - * @param basePackageName - * string contains the module package name * @param typeBuilder * generated type builder which represents any node. The subnodes * of this node are added to the typeBuilder as @@ -1026,13 +1062,13 @@ abstract class AbstractTypeGenerator { * parameter typeBuilder. The getter method could be * added to it. */ - private GeneratedTypeBuilder augSchemaNodeToMethods(final Module module, final String basePackageName, - final GeneratedTypeBuilder typeBuilder, final GeneratedTypeBuilder childOf, - final Iterable schemaNodes) { + private GeneratedTypeBuilder augSchemaNodeToMethods(final ModuleContext context, + final GeneratedTypeBuilder typeBuilder, final Iterable schemaNodes) { if (schemaNodes != null && typeBuilder != null) { + final Type baseInterface = childOf(typeBuilder); for (final DataSchemaNode schemaNode : schemaNodes) { if (!schemaNode.isAugmenting()) { - addSchemaNodeToBuilderAsMethod(basePackageName, schemaNode, typeBuilder, childOf, module); + addSchemaNodeToBuilderAsMethod(context, schemaNode, typeBuilder, baseInterface); } } } @@ -1043,8 +1079,6 @@ abstract class AbstractTypeGenerator { * Adds to typeBuilder a method which is derived from * schemaNode. * - * @param basePackageName - * string with the module package name * @param node * data schema node which is added to typeBuilder as * a method @@ -1056,19 +1090,19 @@ abstract class AbstractTypeGenerator { * @param module * current module */ - private void addSchemaNodeToBuilderAsMethod(final String basePackageName, final DataSchemaNode node, - final GeneratedTypeBuilder typeBuilder, final GeneratedTypeBuilder childOf, final Module module) { + private void addSchemaNodeToBuilderAsMethod(final ModuleContext context, final DataSchemaNode node, + final GeneratedTypeBuilder typeBuilder, final Type baseInterface) { if (node != null && typeBuilder != null) { if (node instanceof LeafSchemaNode) { - resolveLeafSchemaNodeAsMethod(typeBuilder, (LeafSchemaNode) node, module); + resolveLeafSchemaNodeAsMethod(typeBuilder, (LeafSchemaNode) node, context); } else if (node instanceof LeafListSchemaNode) { - resolveLeafListSchemaNode(typeBuilder, (LeafListSchemaNode) node,module); + resolveLeafListSchemaNode(typeBuilder, (LeafListSchemaNode) node, context); } else if (node instanceof ContainerSchemaNode) { - containerToGenType(module, basePackageName, typeBuilder, childOf, (ContainerSchemaNode) node); + containerToGenType(context, typeBuilder, baseInterface, (ContainerSchemaNode) node); } else if (node instanceof ListSchemaNode) { - listToGenType(module, basePackageName, typeBuilder, childOf, (ListSchemaNode) node); + listToGenType(context, typeBuilder, baseInterface, (ListSchemaNode) node); } else if (node instanceof ChoiceSchemaNode) { - choiceToGeneratedType(module, basePackageName, typeBuilder, (ChoiceSchemaNode) node); + choiceToGeneratedType(context, typeBuilder, (ChoiceSchemaNode) node); } else { // TODO: anyxml not yet supported LOG.debug("Unable to add schema node {} as method in {}: unsupported type of node.", node.getClass(), @@ -1085,7 +1119,7 @@ abstract class AbstractTypeGenerator { * concatenation of the module package (basePackageName) and * names of all parents node. * - * @param module + * @param context * current module * @param basePackageName * string with the module package name @@ -1100,63 +1134,57 @@ abstract class AbstractTypeGenerator { *
  • if choiceNode is null
  • * */ - private void choiceToGeneratedType(final Module module, final String basePackageName, - final GeneratedTypeBuilder parent, final ChoiceSchemaNode choiceNode) { - checkArgument(basePackageName != null, "Base Package Name cannot be NULL."); + private void choiceToGeneratedType(final ModuleContext context, final GeneratedTypeBuilder parent, + final ChoiceSchemaNode choiceNode) { checkArgument(choiceNode != null, "Choice Schema Node cannot be NULL."); if (!choiceNode.isAddedByUses()) { - final String packageName = packageNameForGeneratedType(basePackageName, choiceNode.getPath()); - final GeneratedTypeBuilder choiceTypeBuilder = addRawInterfaceDefinition(packageName, choiceNode); - constructGetter(parent, choiceTypeBuilder, choiceNode); - choiceTypeBuilder.addImplementsType(typeForClass(DataContainer.class)); + final GeneratedTypeBuilder choiceTypeBuilder = addRawInterfaceDefinition( + JavaTypeName.create(packageNameForGeneratedType(context.modulePackageName(), choiceNode.getPath()), + BindingMapping.getClassName(choiceNode.getQName())), choiceNode); + choiceTypeBuilder.addImplementsType(choiceIn(parent)); annotateDeprecatedIfNecessary(choiceNode.getStatus(), choiceTypeBuilder); - genCtx.get(module).addChildNodeType(choiceNode, choiceTypeBuilder); - generateTypesFromChoiceCases(module, basePackageName, choiceTypeBuilder.toInstance(), choiceNode); + context.addChildNodeType(choiceNode, choiceTypeBuilder); + + final GeneratedType choiceType = choiceTypeBuilder.build(); + generateTypesFromChoiceCases(context, choiceType, choiceNode); + + constructGetter(parent, choiceType, choiceNode); } } /** - * Converts caseNodes set to list of corresponding generated - * types. + * Converts caseNodes set to list of corresponding generated types. * - * For every case which isn't added through augment or uses is - * created generated type builder. The package names for the builder is - * created as concatenation of the module package ( - * basePackageName) and names of all parents nodes of the - * concrete case. There is also relation "implements type" - * between every case builder and choice type + * For every case which isn't added through augment or uses is created generated type builder. + * The package names for the builder is created as concatenation of the module package and names of all parents + * nodes of the concrete case. There is also relation "implements type" between every case builder + * and choice type * - * @param module - * current module - * @param basePackageName - * string with the module package name + * @param context + * current module context * @param refChoiceType * type which represents superior case * @param choiceNode * choice case node which is mapped to generated type * @throws IllegalArgumentException *
      - *
    • if basePackageName equals null
    • *
    • if refChoiceType equals null
    • *
    • if caseNodes equals null
    • *
    */ - private void generateTypesFromChoiceCases(final Module module, final String basePackageName, - final Type refChoiceType, final ChoiceSchemaNode choiceNode) { - checkArgument(basePackageName != null, "Base Package Name cannot be NULL."); + private void generateTypesFromChoiceCases(final ModuleContext context, final Type refChoiceType, + final ChoiceSchemaNode choiceNode) { checkArgument(refChoiceType != null, "Referenced Choice Type cannot be NULL."); checkArgument(choiceNode != null, "ChoiceNode cannot be NULL."); for (final CaseSchemaNode caseNode : choiceNode.getCases().values()) { if (caseNode != null && !caseNode.isAddedByUses() && !caseNode.isAugmenting()) { - final String packageName = packageNameForGeneratedType(basePackageName, caseNode.getPath()); - final GeneratedTypeBuilder caseTypeBuilder = addDefaultInterfaceDefinition(packageName, caseNode, - module); + final GeneratedTypeBuilder caseTypeBuilder = addDefaultInterfaceDefinition(context, caseNode); caseTypeBuilder.addImplementsType(refChoiceType); annotateDeprecatedIfNecessary(caseNode.getStatus(), caseTypeBuilder); - genCtx.get(module).addCaseType(caseNode.getPath(), caseTypeBuilder); - genCtx.get(module).addChoiceToCaseMapping(refChoiceType, caseTypeBuilder, caseNode); + context.addCaseType(caseNode.getPath(), caseTypeBuilder); + context.addChoiceToCaseMapping(refChoiceType, caseTypeBuilder, caseNode); final Iterable caseChildNodes = caseNode.getChildNodes(); if (caseChildNodes != null) { final SchemaPath choiceNodeParentPath = choiceNode.getPath().getParent(); @@ -1177,25 +1205,24 @@ abstract class AbstractTypeGenerator { if (targetSchemaNode == null) { throw new IllegalStateException( "Failed to find target node from grouping for augmentation " + augSchema - + " in module " + module.getName()); + + " in module " + context.module().getName()); } } parent = targetSchemaNode; } checkState(parent != null, "Could not find Choice node parent %s", choiceNodeParentPath); - GeneratedTypeBuilder childOfType = findChildNodeByPath(parent.getPath()); + Type childOfType = findChildNodeByPath(parent.getPath()); if (childOfType == null) { childOfType = findGroupingByPath(parent.getPath()); } - resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, childOfType, caseChildNodes); + resolveDataSchemaNodes(context, caseTypeBuilder, childOfType, caseChildNodes); } else { - resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, moduleToDataType(module), - caseChildNodes); + resolveDataSchemaNodes(context, caseTypeBuilder, moduleToDataType(context), caseChildNodes); } } } - processUsesAugments(caseNode, module); + processUsesAugments(caseNode, context); } } @@ -1224,38 +1251,17 @@ abstract class AbstractTypeGenerator { *
  • if augmentedNodes is null
  • * */ - private void generateTypesFromAugmentedChoiceCases(final Module module, final String basePackageName, + private void generateTypesFromAugmentedChoiceCases(final ModuleContext context, final Type targetType, final ChoiceSchemaNode targetNode, final Iterable augmentedNodes, final DataNodeContainer usesNodeParent) { - checkArgument(basePackageName != null, "Base Package Name cannot be NULL."); checkArgument(targetType != null, "Referenced Choice Type cannot be NULL."); checkArgument(augmentedNodes != null, "Set of Choice Case Nodes cannot be NULL."); for (final DataSchemaNode caseNode : augmentedNodes) { if (caseNode != null) { - final String packageName = packageNameForGeneratedType(basePackageName, caseNode.getPath()); - final GeneratedTypeBuilder caseTypeBuilder = addDefaultInterfaceDefinition(packageName, caseNode, module); + 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 = genCtx.get(parent).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); - } - CaseSchemaNode node = null; final String caseLocalName = caseNode.getQName().getLocalName(); if (caseNode instanceof CaseSchemaNode) { @@ -1263,8 +1269,8 @@ abstract class AbstractTypeGenerator { } else if (findNamedCase(targetNode, caseLocalName) == null) { final String targetNodeLocalName = targetNode.getQName().getLocalName(); for (DataSchemaNode dataSchemaNode : usesNodeParent.getChildNodes()) { - if (dataSchemaNode instanceof ChoiceSchemaNode && targetNodeLocalName.equals(dataSchemaNode.getQName - ().getLocalName())) { + if (dataSchemaNode instanceof ChoiceSchemaNode + && targetNodeLocalName.equals(dataSchemaNode.getQName().getLocalName())) { node = findNamedCase((ChoiceSchemaNode) dataSchemaNode, caseLocalName); break; } @@ -1274,14 +1280,38 @@ abstract class AbstractTypeGenerator { } final Iterable childNodes = node.getChildNodes(); if (childNodes != null) { - resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, childOfType, childNodes); + resolveDataSchemaNodes(context, caseTypeBuilder, findChildOfType(targetNode), childNodes); } - genCtx.get(module).addCaseType(caseNode.getPath(), caseTypeBuilder); - genCtx.get(module).addChoiceToCaseMapping(targetType, caseTypeBuilder, node); + context.addCaseType(caseNode.getPath(), caseTypeBuilder); + context.addChoiceToCaseMapping(targetType, caseTypeBuilder, node); } } } + 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); @@ -1301,6 +1331,16 @@ abstract class AbstractTypeGenerator { return false; } + private void addPatternConstant(final GeneratedTypeBuilder typeBuilder, final String leafName, + final List patternConstraints) { + if (!patternConstraints.isEmpty()) { + final StringBuilder field = new StringBuilder().append(TypeConstants.PATTERN_CONSTANT_NAME).append("_") + .append(BindingMapping.getPropertyName(leafName)); + typeBuilder.addConstant(LIST_STRING_TYPE, field.toString(), + typeProvider.resolveRegExpressions(patternConstraints)); + } + } + /** * Converts leaf to the getter method which is added to * typeBuilder. @@ -1320,7 +1360,8 @@ abstract class AbstractTypeGenerator { *
  • true - in other cases
  • * */ - private Type resolveLeafSchemaNodeAsMethod(final GeneratedTypeBuilder typeBuilder, final LeafSchemaNode leaf, final Module module) { + private Type resolveLeafSchemaNodeAsMethod(final GeneratedTypeBuilder typeBuilder, final LeafSchemaNode leaf, + final ModuleContext context) { if (leaf == null || typeBuilder == null || leaf.isAddedByUses()) { return null; } @@ -1334,22 +1375,24 @@ abstract class AbstractTypeGenerator { returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf); final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) typeDef; final EnumBuilder enumBuilder = resolveInnerEnumFromTypeDefinition(enumTypeDef, leaf.getQName(), - typeBuilder, module); + typeBuilder, context); if (enumBuilder != null) { returnType = enumBuilder.toInstance(typeBuilder); } typeProvider.putReferencedType(leaf.getPath(), returnType); } else if (typeDef instanceof UnionTypeDefinition) { - GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, leaf, parentModule); + GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder((UnionTypeDefinition) typeDef, typeBuilder, leaf, + parentModule); if (genTOBuilder != null) { returnType = createReturnTypeForUnion(genTOBuilder, typeDef, typeBuilder, parentModule); // Store the inner type within the union so that we can find the reference for it - genCtx.get(module).addInnerTypedefType(typeDef.getPath(), returnType); + context.addInnerTypedefType(typeDef.getPath(), returnType); } } else if (typeDef instanceof BitsTypeDefinition) { - GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, leaf, parentModule); + GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder((BitsTypeDefinition) typeDef, typeBuilder, leaf, + parentModule); if (genTOBuilder != null) { - returnType = genTOBuilder.toInstance(); + returnType = genTOBuilder.build(); } } else { // It is constrained version of already declared type (inner declared type exists, @@ -1359,10 +1402,12 @@ abstract class AbstractTypeGenerator { final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef); returnType = typeProvider.javaTypeForSchemaDefinitionType(getBaseOrDeclaredType(typeDef), leaf, restrictions); + addPatternConstant(typeBuilder, leaf.getQName().getLocalName(), restrictions.getPatternConstraints()); } } else { final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef); returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf, restrictions); + addPatternConstant(typeBuilder, leaf.getQName().getLocalName(), restrictions.getPatternConstraints()); } if (returnType == null) { @@ -1416,9 +1461,7 @@ abstract class AbstractTypeGenerator { + nodeParam); } - final Class clazz = RoutingContext.class; - final AnnotationTypeBuilder rc = getter.addAnnotation(clazz.getPackage().getName(), - clazz.getSimpleName()); + 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"); @@ -1445,15 +1488,13 @@ abstract class AbstractTypeGenerator { } private boolean resolveLeafSchemaNodeAsProperty(final GeneratedTOBuilder toBuilder, final LeafSchemaNode leaf, - final boolean isReadOnly, final Module module) { + final boolean isReadOnly) { if (leaf != null && toBuilder != null) { Type returnType; final TypeDefinition typeDef = CompatUtils.compatLeafType(leaf); if (typeDef instanceof UnionTypeDefinition) { // GeneratedType for this type definition should have be already created - final QName qname = typeDef.getQName(); - final Module unionModule = schemaContext.findModule(qname.getModule()).orElse(null); - final ModuleContext mc = genCtx.get(unionModule); + final ModuleContext mc = moduleContext(typeDef.getQName().getModule()); returnType = mc.getTypedefs().get(typeDef.getPath()); if (returnType == null) { // This may still be an inner type, try to find it @@ -1463,8 +1504,7 @@ abstract class AbstractTypeGenerator { // Annonymous enumeration (already generated, since it is inherited via uses). LeafSchemaNode originalLeaf = (LeafSchemaNode) SchemaNodeUtils.getRootOriginalIfPossible(leaf); QName qname = originalLeaf.getQName(); - final Module enumModule = schemaContext.findModule(qname.getModule()).orElse(null); - returnType = genCtx.get(enumModule).getInnerType(originalLeaf.getType().getPath()); + returnType = moduleContext(qname.getModule()).getInnerType(originalLeaf.getType().getPath()); } else { returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf); } @@ -1530,7 +1570,7 @@ abstract class AbstractTypeGenerator { * */ private boolean resolveLeafListSchemaNode(final GeneratedTypeBuilder typeBuilder, final LeafListSchemaNode node, - final Module module) { + final ModuleContext context) { if (node == null || typeBuilder == null || node.isAddedByUses()) { return false; } @@ -1546,38 +1586,41 @@ abstract class AbstractTypeGenerator { returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, node); final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) typeDef; final EnumBuilder enumBuilder = resolveInnerEnumFromTypeDefinition(enumTypeDef, nodeName, - typeBuilder, module); - returnType = new ReferencedTypeImpl(enumBuilder.getPackageName(), enumBuilder.getName()); + typeBuilder, context); + returnType = new ReferencedTypeImpl(enumBuilder.getIdentifier()); typeProvider.putReferencedType(node.getPath(), returnType); } else if (typeDef instanceof UnionTypeDefinition) { - final GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, node, parentModule); + final GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder((UnionTypeDefinition)typeDef, typeBuilder, + node, parentModule); if (genTOBuilder != null) { returnType = createReturnTypeForUnion(genTOBuilder, typeDef, typeBuilder, parentModule); } } else if (typeDef instanceof BitsTypeDefinition) { - final GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, node, parentModule); - returnType = genTOBuilder.toInstance(); + final GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder((BitsTypeDefinition)typeDef, typeBuilder, + node, parentModule); + returnType = genTOBuilder.build(); } else { final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef); returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, node, restrictions); + addPatternConstant(typeBuilder, node.getQName().getLocalName(), restrictions.getPatternConstraints()); } } else { final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef); returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, node, restrictions); + addPatternConstant(typeBuilder, node.getQName().getLocalName(), restrictions.getPatternConstraints()); } - final ParameterizedType listType = Types.listTypeFor(returnType); + final ParameterizedType listType = listTypeFor(returnType); constructGetter(typeBuilder, listType, node); return true; } private Type createReturnTypeForUnion(final GeneratedTOBuilder genTOBuilder, final TypeDefinition typeDef, final GeneratedTypeBuilder typeBuilder, final Module parentModule) { - final GeneratedTOBuilder returnType = typeProvider.newGeneratedTOBuilder(genTOBuilder.getPackageName(), - genTOBuilder.getName()); + final GeneratedTOBuilder returnType = typeProvider.newGeneratedTOBuilder(genTOBuilder.getIdentifier()); addCodegenInformation(returnType, parentModule, typeDef); - returnType.setSchemaPath(typeDef.getPath().getPathFromRoot()); + returnType.setSchemaPath(typeDef.getPath()); returnType.setModuleName(parentModule.getName()); genTOBuilder.setTypedef(true); @@ -1586,7 +1629,7 @@ abstract class AbstractTypeGenerator { - final GeneratedTOBuilder unionBuilder = createUnionBuilder(genTOBuilder,typeBuilder); + final GeneratedTOBuilder unionBuilder = createUnionBuilder(genTOBuilder, typeBuilder); final MethodSignatureBuilder method = unionBuilder.addMethod("getDefaultInstance"); @@ -1598,35 +1641,36 @@ abstract class AbstractTypeGenerator { final Set types = typeProvider.getAdditionalTypes().get(parentModule); if (types == null) { typeProvider.getAdditionalTypes().put(parentModule, - Sets.newHashSet(unionBuilder.toInstance())); + Sets.newHashSet(unionBuilder.build())); } else { - types.add(unionBuilder.toInstance()); + types.add(unionBuilder.build()); } - return returnType.toInstance(); + return returnType.build(); } private GeneratedTOBuilder createUnionBuilder(final GeneratedTOBuilder genTOBuilder, final GeneratedTypeBuilder typeBuilder) { - final String outerCls = Types.getOuterClassName(genTOBuilder); - final StringBuilder name; - if (outerCls != null) { - name = new StringBuilder(outerCls); - } else { - name = new StringBuilder(); - } - name.append(genTOBuilder.getName()); - name.append("Builder"); - final GeneratedTOBuilder unionBuilder = typeProvider.newGeneratedTOBuilder(typeBuilder.getPackageName(), - name.toString()); + // Append enclosing path hierarchy without dots + final StringBuilder sb = new StringBuilder(); + genTOBuilder.getIdentifier().localNameComponents().forEach(sb::append); + final GeneratedTOBuilder unionBuilder = typeProvider.newGeneratedTOBuilder( + JavaTypeName.create(typeBuilder.getPackageName(), sb.append("Builder").toString())); unionBuilder.setIsUnionBuilder(true); return unionBuilder; } - private GeneratedTypeBuilder addDefaultInterfaceDefinition(final String packageName, final SchemaNode schemaNode, - final Module module) { - return addDefaultInterfaceDefinition(packageName, schemaNode, null, module); + private GeneratedTypeBuilder addDefaultInterfaceDefinition(final ModuleContext context, + final SchemaNode schemaNode) { + return addDefaultInterfaceDefinition(context, schemaNode, DATA_OBJECT); + } + + private GeneratedTypeBuilder addDefaultInterfaceDefinition(final ModuleContext context, + final SchemaNode schemaNode, final Type baseInterface) { + final String packageName = packageNameForGeneratedType(context.modulePackageName(), schemaNode.getPath()); + return addDefaultInterfaceDefinition(packageName, schemaNode, baseInterface, context); } + /** * Instantiates generated type builder with packageName and * schemaNode. @@ -1651,20 +1695,22 @@ abstract class AbstractTypeGenerator { * @return generated type builder schemaNode */ private GeneratedTypeBuilder addDefaultInterfaceDefinition(final String packageName, final SchemaNode schemaNode, - final Type parent, final Module module) { - final GeneratedTypeBuilder it = addRawInterfaceDefinition(packageName, schemaNode, ""); - if (parent == null) { - it.addImplementsType(DATA_OBJECT); - } else { - it.addImplementsType(BindingTypes.childOf(parent)); + final Type baseInterface, final ModuleContext context) { + JavaTypeName name = renames.get(schemaNode); + if (name == null) { + name = JavaTypeName.create(packageName, BindingMapping.getClassName(schemaNode.getQName())); } + + final GeneratedTypeBuilder it = addRawInterfaceDefinition(name, schemaNode); + + it.addImplementsType(baseInterface); if (!(schemaNode instanceof GroupingDefinition)) { it.addImplementsType(augmentable(it)); } - if (schemaNode instanceof DataNodeContainer) { - groupingsToGenTypes(module, ((DataNodeContainer) schemaNode).getGroupings()); - addImplementedInterfaceFromUses((DataNodeContainer) schemaNode, it); + final DataNodeContainer containerSchema = (DataNodeContainer) schemaNode; + groupingsToGenTypes(context, containerSchema.getGroupings()); + addImplementedInterfaceFromUses(containerSchema, it); } return it; @@ -1680,8 +1726,11 @@ abstract class AbstractTypeGenerator { * schema node which provide data about the schema node name * @return generated type builder for schemaNode */ - private GeneratedTypeBuilder addRawInterfaceDefinition(final String packageName, final SchemaNode schemaNode) { - return addRawInterfaceDefinition(packageName, schemaNode, ""); + private GeneratedTypeBuilder addRawInterfaceDefinition(final ModuleContext context, final SchemaNode schemaNode, + final String prefix) { + return addRawInterfaceDefinition( + JavaTypeName.create(packageNameForGeneratedType(context.modulePackageName(), schemaNode.getPath()), + prefix + BindingMapping.getClassName(schemaNode.getQName())), schemaNode); } /** @@ -1709,38 +1758,32 @@ abstract class AbstractTypeGenerator { * * */ - private GeneratedTypeBuilder addRawInterfaceDefinition(final String packageName, final SchemaNode schemaNode, - final String prefix) { + private GeneratedTypeBuilder addRawInterfaceDefinition(final JavaTypeName identifier, final SchemaNode schemaNode) { checkArgument(schemaNode != null, "Data Schema Node cannot be NULL."); - checkArgument(packageName != null, "Package Name for Generated Type cannot be NULL."); checkArgument(schemaNode.getQName() != null, "QName for Data Schema Node cannot be NULL."); final String schemaNodeName = schemaNode.getQName().getLocalName(); checkArgument(schemaNodeName != null, "Local Name of QName for Data Schema Node cannot be NULL."); - String genTypeName; - if (prefix == null) { - genTypeName = BindingMapping.getClassName(schemaNodeName); - } else { - genTypeName = prefix + BindingMapping.getClassName(schemaNodeName); - } - // FIXME: Validation of name conflict - final GeneratedTypeBuilder newType = typeProvider.newGeneratedTypeBuilder(packageName, genTypeName); + 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().getPathFromRoot()); + newType.setSchemaPath(schemaNode.getPath()); newType.setModuleName(module.getName()); + final String packageName = identifier.packageName(); + final String simpleName = identifier.simpleName(); if (!genTypeBuilders.containsKey(packageName)) { final Map builders = new HashMap<>(); - builders.put(genTypeName, newType); + builders.put(simpleName, newType); genTypeBuilders.put(packageName, builders); } else { final Map builders = genTypeBuilders.get(packageName); - if (!builders.containsKey(genTypeName)) { - builders.put(genTypeName, newType); + if (!builders.containsKey(simpleName)) { + builders.put(simpleName, newType); } } return newType; @@ -1787,8 +1830,10 @@ abstract class AbstractTypeGenerator { getterMethodName(node.getQName().getLocalName(), returnType)); getMethod.setReturnType(returnType); - if (node.getStatus() == Status.DEPRECATED) { - getMethod.addAnnotation("", "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); @@ -1819,48 +1864,47 @@ abstract class AbstractTypeGenerator { *
  • if typeBuilder equals null
  • * */ - private void addSchemaNodeToListBuilders(final String basePackageName, final DataSchemaNode schemaNode, - final GeneratedTypeBuilder typeBuilder, final GeneratedTOBuilder genTOBuilder, final List listKeys, - final Module module) { + private void addSchemaNodeToListBuilders(final ModuleContext context, final DataSchemaNode schemaNode, + final GeneratedTypeBuilder typeBuilder, final GeneratedTOBuilder genTOBuilder, + final List listKeys) { checkArgument(schemaNode != null, "Data Schema Node cannot be NULL."); checkArgument(typeBuilder != null, "Generated Type Builder cannot be NULL."); if (schemaNode instanceof LeafSchemaNode) { final LeafSchemaNode leaf = (LeafSchemaNode) schemaNode; final String leafName = leaf.getQName().getLocalName(); - Type type = resolveLeafSchemaNodeAsMethod(typeBuilder, leaf, module); + Type type = resolveLeafSchemaNodeAsMethod(typeBuilder, leaf, context); if (listKeys.contains(leafName)) { if (type == null) { - resolveLeafSchemaNodeAsProperty(genTOBuilder, leaf, true, module); + resolveLeafSchemaNodeAsProperty(genTOBuilder, leaf, true); } else { resolveLeafSchemaNodeAsProperty(genTOBuilder, leaf, type, true); } } } else if (!schemaNode.isAddedByUses()) { if (schemaNode instanceof LeafListSchemaNode) { - resolveLeafListSchemaNode(typeBuilder, (LeafListSchemaNode) schemaNode, module); + resolveLeafListSchemaNode(typeBuilder, (LeafListSchemaNode) schemaNode, context); } else if (schemaNode instanceof ContainerSchemaNode) { - containerToGenType(module, basePackageName, typeBuilder, typeBuilder, (ContainerSchemaNode) schemaNode); + containerToGenType(context, typeBuilder, childOf(typeBuilder), + (ContainerSchemaNode) schemaNode); } else if (schemaNode instanceof ChoiceSchemaNode) { - choiceToGeneratedType(module, basePackageName, typeBuilder, (ChoiceSchemaNode) schemaNode); + choiceToGeneratedType(context, typeBuilder, (ChoiceSchemaNode) schemaNode); } else if (schemaNode instanceof ListSchemaNode) { - listToGenType(module, basePackageName, typeBuilder, typeBuilder, (ListSchemaNode) schemaNode); + listToGenType(context, typeBuilder, childOf(typeBuilder), (ListSchemaNode) schemaNode); } } } - private void typeBuildersToGenTypes(final Module module, final GeneratedTypeBuilder typeBuilder, + private static void typeBuildersToGenTypes(final ModuleContext context, final GeneratedTypeBuilder typeBuilder, final GeneratedTOBuilder genTOBuilder) { checkArgument(typeBuilder != null, "Generated Type Builder cannot be NULL."); if (genTOBuilder != null) { - final GeneratedTransferObject genTO = genTOBuilder.toInstance(); - - // 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"); - genCtx.get(module).addGeneratedTOBuilder(genTOBuilder); + final GeneratedTransferObject genTO = genTOBuilder.build(); + // Add Identifiable.getKey() for items + typeBuilder.addMethod(BindingMapping.IDENTIFIABLE_KEY_NAME).setReturnType(genTO) + .addAnnotation(OVERRIDE_ANNOTATION); + context.addGeneratedTOBuilder(genTOBuilder); } } @@ -1898,19 +1942,53 @@ abstract class AbstractTypeGenerator { * list or null if list is null or list of * key definitions is null or empty. */ - private GeneratedTOBuilder resolveListKeyTOBuilder(final String packageName, final ListSchemaNode list) { - GeneratedTOBuilder genTOBuilder = null; + private GeneratedTOBuilder resolveListKeyTOBuilder(final ModuleContext context, final ListSchemaNode list) { if (list.getKeyDefinition() != null && !list.getKeyDefinition().isEmpty()) { - final String listName = list.getQName().getLocalName() + "Key"; - final String genTOName = BindingMapping.getClassName(listName); - genTOBuilder = typeProvider.newGeneratedTOBuilder(packageName, genTOName); + return typeProvider.newGeneratedTOBuilder(JavaTypeName.create( + packageNameForGeneratedType(context.modulePackageName(), list.getPath()), + BindingMapping.getClassName(list.getQName().getLocalName() + "Key"))); } - return genTOBuilder; + return null; } /** - * Builds generated TO builders for typeDef of type - * {@link UnionTypeDefinition} or {@link BitsTypeDefinition} which are + * Builds a GeneratedTOBuilder for a UnionType {@link UnionTypeDefinition}. + * + * If more then one generated TO builder is created for enclosing then all + * of the generated TO builders are added to typeBuilder as + * enclosing transfer objects. + * + * @param typeDef + * type definition which can be of type UnionType or + * BitsTypeDefinition + * @param typeBuilder + * generated type builder to which is added generated TO created + * from typeDef + * @param leaf + * string with name for generated TO builder + * @param parentModule + * parent module + * @return generated TO builder for typeDef + */ + private GeneratedTOBuilder 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); + + checkState(!types.isEmpty(), "No GeneratedTOBuilder objects generated from union %s", typeDef); + final List genTOBuilders = new ArrayList<>(types); + final GeneratedTOBuilder resultTOBuilder = types.remove(0); + for (final GeneratedTOBuilder genTOBuilder : types) { + resultTOBuilder.addEnclosingTransferObject(genTOBuilder); + } + + processEnclosedTOBuilderes(typeBuilder, genTOBuilders); + return resultTOBuilder; + } + + /** + * Builds generated TO builders for typeDef of type {@link BitsTypeDefinition} which are * also added to typeBuilder as enclosing transfer object. * * If more then one generated TO builder is created for enclosing then all @@ -1929,44 +2007,22 @@ abstract class AbstractTypeGenerator { * parent module * @return generated TO builder for typeDef */ - private GeneratedTOBuilder addTOToTypeBuilder(final TypeDefinition typeDef, + private GeneratedTOBuilder addTOToTypeBuilder(final BitsTypeDefinition typeDef, final GeneratedTypeBuilder typeBuilder, final DataSchemaNode leaf, final Module parentModule) { - final String classNameFromLeaf = BindingMapping.getClassName(leaf.getQName()); - final List genTOBuilders = new ArrayList<>(); - final String packageName = typeBuilder.getFullyQualifiedName(); - if (typeDef instanceof UnionTypeDefinition) { - final List types = typeProvider - .provideGeneratedTOBuildersForUnionTypeDef(packageName, (UnionTypeDefinition) typeDef, - classNameFromLeaf, leaf); - genTOBuilders.addAll(types); - - GeneratedTOBuilder resultTOBuilder; - if (types.isEmpty()) { - throw new IllegalStateException("No GeneratedTOBuilder objects generated from union " + typeDef); - } - resultTOBuilder = types.remove(0); - for (final GeneratedTOBuilder genTOBuilder : types) { - resultTOBuilder.addEnclosingTransferObject(genTOBuilder); - } + final GeneratedTOBuilder genTOBuilder = typeProvider.provideGeneratedTOBuilderForBitsTypeDefinition( + typeBuilder.getIdentifier().createEnclosed(BindingMapping.getClassName(leaf.getQName())), + typeDef, parentModule.getName()); + typeBuilder.addEnclosingTransferObject(genTOBuilder); + return genTOBuilder; - final GeneratedPropertyBuilder genPropBuilder = resultTOBuilder.addProperty("value"); - genPropBuilder.setReturnType(Types.CHAR_ARRAY); - resultTOBuilder.addEqualsIdentity(genPropBuilder); - resultTOBuilder.addHashIdentity(genPropBuilder); - resultTOBuilder.addToStringProperty(genPropBuilder); + } - } else if (typeDef instanceof BitsTypeDefinition) { - genTOBuilders.add(typeProvider.provideGeneratedTOBuilderForBitsTypeDefinition( - packageName, typeDef, classNameFromLeaf, parentModule.getName())); + private static GeneratedTOBuilder processEnclosedTOBuilderes(final GeneratedTypeBuilder typeBuilder, + final List genTOBuilders) { + for (final GeneratedTOBuilder genTOBuilder : genTOBuilders) { + typeBuilder.addEnclosingTransferObject(genTOBuilder); } - if (!genTOBuilders.isEmpty()) { - for (final GeneratedTOBuilder genTOBuilder : genTOBuilders) { - typeBuilder.addEnclosingTransferObject(genTOBuilder); - } - return genTOBuilders.get(0); - } - return null; - + return genTOBuilders.get(0); } /** @@ -1988,7 +2044,7 @@ abstract class AbstractTypeGenerator { private GeneratedTypeBuilder addImplementedInterfaceFromUses(final DataNodeContainer dataNodeContainer, final GeneratedTypeBuilder builder) { for (final UsesNode usesNode : dataNodeContainer.getUses()) { - final GeneratedType genType = findGroupingByPath(usesNode.getGroupingPath()).toInstance(); + final GeneratedType genType = findGroupingByPath(usesNode.getGroupingPath()).build(); if (genType == null) { throw new IllegalStateException("Grouping " + usesNode.getGroupingPath() + "is not resolved for " + builder.getName()); @@ -2029,9 +2085,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("", "Deprecated"); + builder.addAnnotation(DEPRECATED_ANNOTATION); } } }