X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=code-generator%2Fbinding-generator-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fyangtools%2Fsal%2Fbinding%2Fgenerator%2Fimpl%2FBindingGeneratorImpl.java;h=befe3e88e02c494e48b287d8089cf2f05eb8fd08;hb=6787dc344194eae8521de885433605f3052b9b8a;hp=48df06b1374a66614eab7fe0392dc32a3490639c;hpb=6ccf0164de8374d2d74625fe53c3841d6456c4b3;p=yangtools.git diff --git a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/BindingGeneratorImpl.java b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/BindingGeneratorImpl.java index 48df06b137..befe3e88e0 100644 --- a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/BindingGeneratorImpl.java +++ b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/BindingGeneratorImpl.java @@ -7,41 +7,69 @@ */ package org.opendaylight.yangtools.sal.binding.generator.impl; -import static org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil.moduleNamespaceToPackageName; +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 org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil.computeDefaultSUID; import static org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil.packageNameForGeneratedType; -import static org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil.parseToClassName; import static org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil.parseToValidParamName; -import static org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil.schemaNodeToTransferObjectBuilder; +import static org.opendaylight.yangtools.binding.generator.util.BindingTypes.DATA_OBJECT; +import static org.opendaylight.yangtools.binding.generator.util.BindingTypes.DATA_ROOT; +import static org.opendaylight.yangtools.binding.generator.util.BindingTypes.IDENTIFIABLE; +import static org.opendaylight.yangtools.binding.generator.util.BindingTypes.IDENTIFIER; +import static org.opendaylight.yangtools.binding.generator.util.BindingTypes.NOTIFICATION; +import static org.opendaylight.yangtools.binding.generator.util.BindingTypes.augmentable; +import static org.opendaylight.yangtools.binding.generator.util.Types.BOOLEAN; +import static org.opendaylight.yangtools.binding.generator.util.Types.FUTURE; +import static org.opendaylight.yangtools.binding.generator.util.Types.VOID; +import static org.opendaylight.yangtools.binding.generator.util.Types.typeForClass; import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataSchemaNode; +import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findNodeInSchemaContext; import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findParentModule; +import com.google.common.base.Splitter; +import com.google.common.collect.Iterables; +import com.google.common.collect.Sets; + import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; -import java.util.Comparator; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.concurrent.Future; +import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil; +import org.opendaylight.yangtools.binding.generator.util.BindingTypes; import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl; import org.opendaylight.yangtools.binding.generator.util.Types; +import org.opendaylight.yangtools.binding.generator.util.generated.type.builder.GeneratedPropertyBuilderImpl; import org.opendaylight.yangtools.binding.generator.util.generated.type.builder.GeneratedTOBuilderImpl; import org.opendaylight.yangtools.binding.generator.util.generated.type.builder.GeneratedTypeBuilderImpl; import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator; import org.opendaylight.yangtools.sal.binding.generator.spi.TypeProvider; +import org.opendaylight.yangtools.sal.binding.model.api.AccessModifier; +import org.opendaylight.yangtools.sal.binding.model.api.Constant; import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject; import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType; +import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType; +import org.opendaylight.yangtools.sal.binding.model.api.Restrictions; import org.opendaylight.yangtools.sal.binding.model.api.Type; +import org.opendaylight.yangtools.sal.binding.model.api.type.builder.AnnotationTypeBuilder; import org.opendaylight.yangtools.sal.binding.model.api.type.builder.EnumBuilder; import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedPropertyBuilder; import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTOBuilder; import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder; +import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilderBase; import org.opendaylight.yangtools.sal.binding.model.api.type.builder.MethodSignatureBuilder; import org.opendaylight.yangtools.sal.binding.yang.types.GroupingDefinitionDependencySort; import org.opendaylight.yangtools.sal.binding.yang.types.TypeProviderImpl; -import org.opendaylight.yangtools.yang.binding.DataRoot; +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.model.api.AugmentationSchema; @@ -50,34 +78,62 @@ import org.opendaylight.yangtools.yang.model.api.ChoiceNode; import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; 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.GroupingDefinition; import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode; import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode; import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode; import org.opendaylight.yangtools.yang.model.api.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.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.TypeDefinition; +import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode; import org.opendaylight.yangtools.yang.model.api.UsesNode; 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.EnumTypeDefinition.EnumPair; +import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition; import org.opendaylight.yangtools.yang.model.util.DataNodeIterator; -import org.opendaylight.yangtools.yang.model.util.ExtendedType; import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil; import org.opendaylight.yangtools.yang.model.util.UnionType; +import org.opendaylight.yangtools.yang.parser.builder.util.Comparators; +import org.opendaylight.yangtools.yang.parser.util.ModuleDependencySort; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class BindingGeneratorImpl implements BindingGenerator { + private static final Logger LOG = LoggerFactory.getLogger(BindingGeneratorImpl.class); + private static final Splitter COLON_SPLITTER = Splitter.on(':'); + private static final Splitter BSDOT_SPLITTER = Splitter.on("\\."); + private static final char NEW_LINE = '\n'; + + /** + * Constant with the concrete name of identifier. + */ + private static final String AUGMENT_IDENTIFIER_NAME = "augment-identifier"; + + /** + * Constant with the concrete name of namespace. + */ + private static final String YANG_EXT_NAMESPACE = "urn:opendaylight:yang:extension:yang-ext"; -public final class BindingGeneratorImpl implements BindingGenerator { + private final Map genCtx = new HashMap<>(); /** - * Outter key represents the package name. Outter value represents map of - * all builders in the same package. Inner key represents the schema node - * name (in JAVA class/interface name format). Inner value represents - * instance of builder for schema node specified in key part. + * When set to true, generated classes will include javadoc comments which + * are useful for users. + */ + private final boolean verboseClassComments; + + /** + * Outer key represents the package name. Outer value represents map of all + * builders in the same package. Inner key represents the schema node name + * (in JAVA class/interface name format). Inner value represents instance of + * builder for schema node specified in key part. */ private Map> genTypeBuilders; @@ -87,35 +143,37 @@ public final class BindingGeneratorImpl implements BindingGenerator { private TypeProvider typeProvider; /** - * Holds reference to schema context to resolve data of augmented elemnt + * Holds reference to schema context to resolve data of augmented element * when creating augmentation builder */ private SchemaContext schemaContext; /** - * Each grouping which is converted from schema node to generated type is - * added to this map with its Schema path as key to make it easier to get - * reference to it. In schema nodes in uses attribute there is - * only Schema Path but when building list of implemented interfaces for - * Schema node the object of type Type is required. So in this - * case is used this map. + * Create a new binding generator with verboe comments. + * + * @deprecated Use {@link #BindingGeneratorImpl(boolean)} instead. */ - private final Map allGroupings = new HashMap(); + @Deprecated + public BindingGeneratorImpl() { + this(true); + } /** - * Only parent constructor is invoked. + * Create a new binding generator. + * + * @param verboseClassComments generate verbose comments */ - public BindingGeneratorImpl() { - super(); + public BindingGeneratorImpl(final boolean verboseClassComments) { + this.verboseClassComments = verboseClassComments; } /** * Resolves generated types from context schema nodes of all * modules. - * + * * Generated types are created for modules, groupings, types, containers, * lists, choices, augments, rpcs, notification, identities. - * + * * @param context * schema context which contains data about all schema nodes * saved in modules @@ -123,51 +181,27 @@ public final class BindingGeneratorImpl implements BindingGenerator { * GeneratedTransferObjectwhich are generated from * context data. * @throws IllegalArgumentException - * if param context is null + * if arg context is null * @throws IllegalStateException * if context contain no modules */ @Override public List generateTypes(final SchemaContext context) { - if (context == null) { - throw new IllegalArgumentException("Schema Context reference cannot be NULL!"); - } - if (context.getModules() == null) { - throw new IllegalStateException("Schema Context does not contain defined modules!"); - } - - final List generatedTypes = new ArrayList<>(); + checkArgument(context != null, "Schema Context reference cannot be NULL."); + checkState(context.getModules() != null, "Schema Context does not contain defined modules."); schemaContext = context; typeProvider = new TypeProviderImpl(context); final Set modules = context.getModules(); - genTypeBuilders = new HashMap<>(); - for (final Module module : modules) { - - generatedTypes.addAll(allGroupingsToGenTypes(module)); - - if (false == module.getChildNodes().isEmpty()) { - generatedTypes.add(moduleToDataType(module)); - } - generatedTypes.addAll(allTypeDefinitionsToGenTypes(module)); - generatedTypes.addAll(allContainersToGenTypes(module)); - generatedTypes.addAll(allListsToGenTypes(module)); - generatedTypes.addAll(allChoicesToGenTypes(module)); - generatedTypes.addAll(allAugmentsToGenTypes(module)); - generatedTypes.addAll(allRPCMethodsToGenType(module)); - generatedTypes.addAll(allNotificationsToGenType(module)); - generatedTypes.addAll(allIdentitiesToGenTypes(module, context)); - - } - return generatedTypes; + return generateTypes(context, modules); } /** * Resolves generated types from context schema nodes only for * modules specified in modules - * + * * Generated types are created for modules, groupings, types, containers, * lists, choices, augments, rpcs, notification, identities. - * + * * @param context * schema context which contains data about all schema nodes * saved in modules @@ -183,525 +217,384 @@ public final class BindingGeneratorImpl implements BindingGenerator { * * @throws IllegalArgumentException *
    - *
  • if param context is null or
  • - *
  • if param modules is null
  • + *
  • if arg context is null or
  • + *
  • if arg modules is null
  • *
* @throws IllegalStateException * if context contain no modules */ @Override public List generateTypes(final SchemaContext context, final Set modules) { - if (context == null) { - throw new IllegalArgumentException("Schema Context reference cannot be NULL!"); - } - if (context.getModules() == null) { - throw new IllegalStateException("Schema Context does not contain defined modules!"); - } - if (modules == null) { - throw new IllegalArgumentException("Sef of Modules cannot be NULL!"); - } + checkArgument(context != null, "Schema Context reference cannot be NULL."); + checkState(context.getModules() != null, "Schema Context does not contain defined modules."); + checkArgument(modules != null, "Set of Modules cannot be NULL."); - final List filteredGenTypes = new ArrayList<>(); schemaContext = context; typeProvider = new TypeProviderImpl(context); - final Set contextModules = context.getModules(); + Module[] modulesArray = new Module[context.getModules().size()]; + context.getModules().toArray(modulesArray); + final List contextModules = ModuleDependencySort.sort(modulesArray); genTypeBuilders = new HashMap<>(); - for (final Module contextModule : contextModules) { - final List generatedTypes = new ArrayList<>(); - generatedTypes.addAll(allGroupingsToGenTypes(contextModule)); - if (false == contextModule.getChildNodes().isEmpty()) { - generatedTypes.add(moduleToDataType(contextModule)); - } - generatedTypes.addAll(allTypeDefinitionsToGenTypes(contextModule)); - generatedTypes.addAll(allContainersToGenTypes(contextModule)); - generatedTypes.addAll(allListsToGenTypes(contextModule)); - generatedTypes.addAll(allChoicesToGenTypes(contextModule)); - generatedTypes.addAll(allAugmentsToGenTypes(contextModule)); - generatedTypes.addAll(allRPCMethodsToGenType(contextModule)); - generatedTypes.addAll(allNotificationsToGenType(contextModule)); - generatedTypes.addAll(allIdentitiesToGenTypes(contextModule, context)); - - if (modules.contains(contextModule)) { - filteredGenTypes.addAll(generatedTypes); + for (Module contextModule : contextModules) { + moduleToGenTypes(contextModule, context); + } + for (Module contextModule : contextModules) { + allAugmentsToGenTypes(contextModule); + } + + final List filteredGenTypes = new ArrayList<>(); + for (Module m : modules) { + final ModuleContext ctx = checkNotNull(genCtx.get(m), "Module context not found for module %s", m); + filteredGenTypes.addAll(ctx.getGeneratedTypes()); + final Set additionalTypes = ((TypeProviderImpl) typeProvider).getAdditionalTypes().get(m); + if (additionalTypes != null) { + filteredGenTypes.addAll(additionalTypes); } } + return filteredGenTypes; } + 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()); + } + } + /** * Converts all extended type definitions of module to the list of * Type objects. - * + * * @param module * module from which is obtained set of type definitions - * @return list of Type which are generated from extended - * definition types (object of type ExtendedType) * @throws IllegalArgumentException *
    - *
  • if module equals null
  • - *
  • if name of module equals null
  • - *
  • if type definitions of module equal null
  • + *
  • if module is null
  • + *
  • if name of module is null
  • *
- * + * @throws IllegalStateException + * if set of type definitions from module is null */ - private List allTypeDefinitionsToGenTypes(final Module module) { - if (module == null) { - throw new IllegalArgumentException("Module reference cannot be NULL!"); - } - if (module.getName() == null) { - throw new IllegalArgumentException("Module name cannot be NULL!"); - } - if (module.getTypeDefinitions() == null) { - throw new IllegalArgumentException("Type Definitions for module " + module.getName() + " cannot be NULL!"); - } + private void allTypeDefinitionsToGenTypes(final Module module) { + checkArgument(module != null, "Module reference cannot be NULL."); + checkArgument(module.getName() != null, "Module name cannot be NULL."); + final DataNodeIterator it = new DataNodeIterator(module); + final List> typeDefinitions = it.allTypedefs(); + checkState(typeDefinitions != null, "Type Definitions for module «module.name» cannot be NULL."); - final Set> typeDefinitions = module.getTypeDefinitions(); - final List generatedTypes = new ArrayList<>(); - for (final TypeDefinition typedef : typeDefinitions) { + for (TypeDefinition typedef : typeDefinitions) { if (typedef != null) { - final Type type = ((TypeProviderImpl) typeProvider).generatedTypeForExtendedDefinitionType(typedef); - if ((type != null) && !generatedTypes.contains(type)) { - generatedTypes.add(type); + final Type type = ((TypeProviderImpl) typeProvider).generatedTypeForExtendedDefinitionType(typedef, + typedef); + if (type != null) { + genCtx.get(module).addTypedefType(typedef.getPath(), type); } } } - return generatedTypes; } - /** - * Converts all containers of the module to the list of - * Type objects. - * - * @param module - * module from which is obtained DataNodeIterator to iterate over - * all containers - * @return list of Type which are generated from containers - * (objects of type ContainerSchemaNode) - * @throws IllegalArgumentException - *
    - *
  • if the module equals null
  • - *
  • if the name of module equals null
  • - *
  • if the set of child nodes equals null
  • - *
- * - */ - private List allContainersToGenTypes(final Module module) { - if (module == null) { - throw new IllegalArgumentException("Module reference cannot be NULL!"); - } - - if (module.getName() == null) { - throw new IllegalArgumentException("Module name cannot be NULL!"); - } - - if (module.getChildNodes() == null) { - throw new IllegalArgumentException("Reference to Set of Child Nodes in module " + module.getName() - + " cannot be NULL!"); - } - - final List generatedTypes = new ArrayList<>(); - final DataNodeIterator it = new DataNodeIterator(module); - final List schemaContainers = it.allContainers(); - final String basePackageName = moduleNamespaceToPackageName(module); - for (final ContainerSchemaNode container : schemaContainers) { - if (!container.isAddedByUses()) { - generatedTypes.add(containerToGenType(basePackageName, container)); - } + private GeneratedTypeBuilder processDataSchemaNode(final Module module, final String basePackageName, + final GeneratedTypeBuilder childOf, final DataSchemaNode node) { + if (node.isAugmenting() || node.isAddedByUses()) { + return null; } - return generatedTypes; + final String packageName = packageNameForGeneratedType(basePackageName, node.getPath()); + final GeneratedTypeBuilder genType = addDefaultInterfaceDefinition(packageName, node, childOf); + genType.addComment(node.getDescription()); + genType.setDescription(createDescription(node, genType.getFullyQualifiedName())); + genType.setModuleName(module.getName()); + genType.setReference(node.getReference()); + genType.setSchemaPath(node.getPath().getPathFromRoot()); + if (node instanceof DataNodeContainer) { + genCtx.get(module).addChildNodeType(node, genType); + groupingsToGenTypes(module, ((DataNodeContainer) node).getGroupings()); + processUsesAugments((DataNodeContainer) node, module); + } + return genType; } - /** - * Converts all lists of the module to the list of Type - * objects. - * - * @param module - * module from which is obtained DataNodeIterator to iterate over - * all lists - * @return list of Type which are generated from lists (objects - * of type ListSchemaNode) - * @throws IllegalArgumentException - *
    - *
  • if the module equals null
  • - *
  • if the name of module equals null
  • - *
  • if the set of child nodes equals null
  • - *
- * - */ - private List allListsToGenTypes(final Module module) { - if (module == null) { - throw new IllegalArgumentException("Module reference cannot be NULL!"); - } - - if (module.getName() == null) { - throw new IllegalArgumentException("Module name cannot be NULL!"); + 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); + if (genType != null) { + constructGetter(parent, node.getQName().getLocalName(), node.getDescription(), genType); + resolveDataSchemaNodes(module, basePackageName, genType, genType, node.getChildNodes()); } + } - if (module.getChildNodes() == null) { - throw new IllegalArgumentException("Reference to Set of Child Nodes in module " + module.getName() - + " cannot be 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); + if (genType != null) { + constructGetter(parent, node.getQName().getLocalName(), node.getDescription(), Types.listTypeFor(genType)); + + final List listKeys = listKeys(node); + final String packageName = packageNameForGeneratedType(basePackageName, node.getPath()); + final GeneratedTOBuilder genTOBuilder = resolveListKeyTOBuilder(packageName, node); + if (genTOBuilder != null) { + final Type identifierMarker = Types.parameterizedTypeFor(IDENTIFIER, genType); + final Type identifiableMarker = Types.parameterizedTypeFor(IDENTIFIABLE, genTOBuilder); + genTOBuilder.addImplementsType(identifierMarker); + genType.addImplementsType(identifiableMarker); + } - final List generatedTypes = new ArrayList<>(); - final DataNodeIterator it = new DataNodeIterator(module); - final List schemaLists = it.allLists(); - final String basePackageName = moduleNamespaceToPackageName(module); - if (schemaLists != null) { - for (final ListSchemaNode list : schemaLists) { - if (!list.isAddedByUses()) { - generatedTypes.addAll(listToGenType(basePackageName, list)); + for (DataSchemaNode schemaNode : node.getChildNodes()) { + if (!schemaNode.isAugmenting()) { + addSchemaNodeToListBuilders(basePackageName, schemaNode, genType, genTOBuilder, listKeys, module); } } - } - return generatedTypes; - } - /** - * Converts all choices of the module to the list of - * Type objects. - * - * @param module - * module from which is obtained DataNodeIterator to iterate over - * all choices - * @return list of Type which are generated from choices - * (objects of type ChoiceNode) - * @throws IllegalArgumentException - *
    - *
  • if the module equals null
  • - *
  • if the name of module equals null
  • * - *
- * - */ - private List allChoicesToGenTypes(final Module module) { - if (module == null) { - throw new IllegalArgumentException("Module reference cannot be NULL!"); - } - if (module.getName() == null) { - throw new IllegalArgumentException("Module name cannot be NULL!"); - } + // serialVersionUID + if (genTOBuilder != null) { + final GeneratedPropertyBuilder prop = new GeneratedPropertyBuilderImpl("serialVersionUID"); + prop.setValue(Long.toString(computeDefaultSUID(genTOBuilder))); + genTOBuilder.setSUID(prop); + } - final DataNodeIterator it = new DataNodeIterator(module); - final List choiceNodes = it.allChoices(); - final String basePackageName = moduleNamespaceToPackageName(module); + typeBuildersToGenTypes(module, genType, genTOBuilder); + } + } - final List generatedTypes = new ArrayList<>(); - for (final ChoiceNode choice : choiceNodes) { - if ((choice != null) && !choice.isAddedByUses()) { - generatedTypes.addAll(choiceToGeneratedType(basePackageName, choice)); + private void processUsesAugments(final DataNodeContainer node, final Module module) { + final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule()); + for (UsesNode usesNode : node.getUses()) { + for (AugmentationSchema augment : usesNode.getAugmentations()) { + usesAugmentationToGenTypes(basePackageName, augment, module, usesNode, node); + processUsesAugments(augment, module); } } - return generatedTypes; } /** * Converts all augmentation of the module to the list * Type objects. - * + * * @param module * module from which is obtained list of all augmentation objects * to iterate over them - * @return list of Type which are generated from augments - * (objects of type AugmentationSchema) * @throws IllegalArgumentException *
    - *
  • if the module equals null
  • - *
  • if the name of module equals null
  • - *
  • if the set of child nodes equals null
  • + *
  • if the module is null
  • + *
  • if the name of module is null
  • *
- * + * @throws IllegalStateException + * if set of augmentations from module is null */ - private List allAugmentsToGenTypes(final Module module) { - if (module == null) { - throw new IllegalArgumentException("Module reference cannot be NULL!"); - } - if (module.getName() == null) { - throw new IllegalArgumentException("Module name cannot be NULL!"); - } - if (module.getChildNodes() == null) { - throw new IllegalArgumentException("Reference to Set of Augmentation Definitions in module " - + module.getName() + " cannot be NULL!"); - } + private void allAugmentsToGenTypes(final Module 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 List generatedTypes = new ArrayList<>(); - final String basePackageName = moduleNamespaceToPackageName(module); + final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule()); final List augmentations = resolveAugmentations(module); - for (final AugmentationSchema augment : augmentations) { - generatedTypes.addAll(augmentationToGenTypes(basePackageName, augment)); + for (AugmentationSchema augment : augmentations) { + augmentationToGenTypes(basePackageName, augment, module); } - return generatedTypes; } /** * Returns list of AugmentationSchema objects. The objects are * sorted according to the length of their target path from the shortest to * the longest. - * + * * @param module * module from which is obtained list of all augmentation objects * @return list of sorted AugmentationSchema objects obtained * from module * @throws IllegalArgumentException - *
    - *
  • if the module equals null
  • - *
  • if the set of augmentation equals null
  • - *
- * + * if module is null + * @throws IllegalStateException + * if set of module augmentations is null */ private List resolveAugmentations(final Module module) { - if (module == null) { - throw new IllegalArgumentException("Module reference cannot be NULL!"); - } - if (module.getAugmentations() == null) { - throw new IllegalStateException("Augmentations Set cannot be NULL!"); - } + checkArgument(module != null, "Module reference cannot be NULL."); + checkState(module.getAugmentations() != null, "Augmentations Set cannot be NULL."); final Set augmentations = module.getAugmentations(); - final List sortedAugmentations = new ArrayList<>(augmentations); - Collections.sort(sortedAugmentations, new Comparator() { - - @Override - public int compare(AugmentationSchema augSchema1, AugmentationSchema augSchema2) { - - if (augSchema1.getTargetPath().getPath().size() > augSchema2.getTargetPath().getPath().size()) { - return 1; - } else if (augSchema1.getTargetPath().getPath().size() < augSchema2.getTargetPath().getPath().size()) { - return -1; - } - return 0; - - } - }); + List sortedAugmentations = new ArrayList<>(augmentations); + Collections.sort(sortedAugmentations, Comparators.AUGMENT_COMP); return sortedAugmentations; } /** - * Converts whole module to GeneratedType object. - * Firstly is created the module builder object from which is finally - * obtained reference to GeneratedType object. - * + * Create GeneratedTypeBuilder object from module argument. + * * @param module - * module from which are obtained the module name, child nodes, - * uses and is derived package name - * @return GeneratedType which is internal representation of - * the module + * Module object from which builder will be created + * @return GeneratedTypeBuilder which is internal + * representation of the module * @throws IllegalArgumentException - * if the module equals null - * + * if module is null */ - private GeneratedType moduleToDataType(final Module module) { - if (module == null) { - throw new IllegalArgumentException("Module reference cannot be NULL!"); - } + private GeneratedTypeBuilder moduleToDataType(final Module module) { + checkArgument(module != null, "Module reference cannot be NULL."); final GeneratedTypeBuilder moduleDataTypeBuilder = moduleTypeBuilder(module, "Data"); addImplementedInterfaceFromUses(module, moduleDataTypeBuilder); - moduleDataTypeBuilder.addImplementsType(Types.typeForClass(DataRoot.class)); - - final String basePackageName = moduleNamespaceToPackageName(module); - if (moduleDataTypeBuilder != null) { - final Set dataNodes = module.getChildNodes(); - resolveDataSchemaNodes(basePackageName, moduleDataTypeBuilder, dataNodes); - } - return moduleDataTypeBuilder.toInstance(); + moduleDataTypeBuilder.addImplementsType(DATA_ROOT); + moduleDataTypeBuilder.addComment(module.getDescription()); + moduleDataTypeBuilder.setDescription(createDescription(module)); + moduleDataTypeBuilder.setReference(module.getReference()); + return moduleDataTypeBuilder; } /** * Converts all rpcs inputs and outputs substatements of the module * to the list of Type objects. In addition are to containers * and lists which belong to input or output also part of returning list. - * + * * @param module * module from which is obtained set of all rpc objects to * iterate over them - * @return list of Type which are generated from rpcs inputs, - * outputs + container and lists which are part of inputs or outputs * @throws IllegalArgumentException *
    - *
  • if the module equals null
  • - *
  • if the name of module equals null
  • - *
  • if the set of child nodes equals null
  • + *
  • if the module is null
  • + *
  • if the name of module is null
  • *
- * + * @throws IllegalStateException + * if set of rpcs from module is null */ - private List allRPCMethodsToGenType(final Module module) { - if (module == null) { - throw new IllegalArgumentException("Module reference cannot be NULL!"); - } - - if (module.getName() == null) { - throw new IllegalArgumentException("Module name cannot be NULL!"); - } - - if (module.getChildNodes() == null) { - throw new IllegalArgumentException("Reference to Set of RPC Method Definitions in module " - + module.getName() + " cannot be NULL!"); - } - - final String basePackageName = moduleNamespaceToPackageName(module); + private void rpcMethodsToGenType(final Module module) { + checkArgument(module != null, "Module reference cannot be NULL."); + 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."); if (rpcDefinitions.isEmpty()) { - return Collections.emptyList(); + return; } - final List genRPCTypes = new ArrayList<>(); + final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule()); final GeneratedTypeBuilder interfaceBuilder = moduleTypeBuilder(module, "Service"); interfaceBuilder.addImplementsType(Types.typeForClass(RpcService.class)); - final Type future = Types.typeForClass(Future.class); - for (final RpcDefinition rpc : rpcDefinitions) { - if (rpc != null) { - - String rpcName = parseToClassName(rpc.getQName().getLocalName()); - String rpcMethodName = parseToValidParamName(rpcName); - MethodSignatureBuilder method = interfaceBuilder.addMethod(rpcMethodName); + interfaceBuilder.setDescription(createDescription(rpcDefinitions, module.getName(), module.getModuleSourcePath())); - final List rpcInOut = new ArrayList<>(); - - ContainerSchemaNode input = rpc.getInput(); - ContainerSchemaNode output = rpc.getOutput(); + for (RpcDefinition rpc : rpcDefinitions) { + if (rpc != null) { + final String rpcName = BindingMapping.getClassName(rpc.getQName()); + final String rpcMethodName = parseToValidParamName(rpcName); + final String rpcComment = rpc.getDescription(); + final MethodSignatureBuilder method = interfaceBuilder.addMethod(rpcMethodName); + final ContainerSchemaNode input = rpc.getInput(); + final ContainerSchemaNode output = rpc.getOutput(); if (input != null) { - rpcInOut.add(new DataNodeIterator(input)); - GeneratedTypeBuilder inType = addRawInterfaceDefinition(basePackageName, input, rpcName); + final GeneratedTypeBuilder inType = addRawInterfaceDefinition(basePackageName, input, rpcName); addImplementedInterfaceFromUses(input, inType); - inType.addImplementsType(Types.DATA_OBJECT); - resolveDataSchemaNodes(basePackageName, inType, input.getChildNodes()); - Type inTypeInstance = inType.toInstance(); - genRPCTypes.add(inTypeInstance); + inType.addImplementsType(DATA_OBJECT); + inType.addImplementsType(augmentable(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 = Types.typeForClass(Void.class); + Type outTypeInstance = VOID; if (output != null) { - rpcInOut.add(new DataNodeIterator(output)); - GeneratedTypeBuilder outType = addRawInterfaceDefinition(basePackageName, output, rpcName); + final GeneratedTypeBuilder outType = addRawInterfaceDefinition(basePackageName, output, rpcName); addImplementedInterfaceFromUses(output, outType); - outType.addImplementsType(Types.DATA_OBJECT); - resolveDataSchemaNodes(basePackageName, outType, output.getChildNodes()); + outType.addImplementsType(DATA_OBJECT); + outType.addImplementsType(augmentable(outType)); + resolveDataSchemaNodes(module, basePackageName, outType, outType, output.getChildNodes()); + genCtx.get(module).addChildNodeType(output, outType); outTypeInstance = outType.toInstance(); - genRPCTypes.add(outTypeInstance); - } final Type rpcRes = Types.parameterizedTypeFor(Types.typeForClass(RpcResult.class), outTypeInstance); - method.setReturnType(Types.parameterizedTypeFor(future, rpcRes)); - for (DataNodeIterator it : rpcInOut) { - List nContainers = it.allContainers(); - if ((nContainers != null) && !nContainers.isEmpty()) { - for (final ContainerSchemaNode container : nContainers) { - if (!container.isAddedByUses()) { - genRPCTypes.add(containerToGenType(basePackageName, container)); - } - } - } - List nLists = it.allLists(); - if ((nLists != null) && !nLists.isEmpty()) { - for (final ListSchemaNode list : nLists) { - if (!list.isAddedByUses()) { - genRPCTypes.addAll(listToGenType(basePackageName, list)); - } - } - } - } + method.setComment(rpcComment); + method.setReturnType(Types.parameterizedTypeFor(FUTURE, rpcRes)); } } - genRPCTypes.add(interfaceBuilder.toInstance()); - return genRPCTypes; + + genCtx.get(module).addTopLevelNodeType(interfaceBuilder); } /** * Converts all notifications of the module to the list of * Type objects. In addition are to this list added containers * and lists which are part of this notification. - * + * * @param module * module from which is obtained set of all notification objects * to iterate over them - * @return list of Type which are generated from notification - * (object of type NotificationDefinition * @throws IllegalArgumentException *
    *
  • if the module equals null
  • *
  • if the name of module equals null
  • - *
  • if the set of child nodes equals null
  • *
- * + * @throws IllegalStateException + * if set of notifications from module is null */ - private List allNotificationsToGenType(final Module module) { - if (module == null) { - throw new IllegalArgumentException("Module reference cannot be NULL!"); + private void notificationsToGenType(final Module module) { + checkArgument(module != null, "Module reference cannot be NULL."); + checkArgument(module.getName() != null, "Module name cannot be NULL."); + final Set notifications = module.getNotifications(); + checkState(notifications != null, "Set of notification from module " + module.getName() + " cannot be NULL."); + if (notifications.isEmpty()) { + return; } - if (module.getName() == null) { - throw new IllegalArgumentException("Module name cannot be NULL!"); - } + final GeneratedTypeBuilder listenerInterface = moduleTypeBuilder(module, "Listener"); + listenerInterface.addImplementsType(BindingTypes.NOTIFICATION_LISTENER); + final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule()); - if (module.getChildNodes() == null) { - throw new IllegalArgumentException("Reference to Set of Notification Definitions in module " - + module.getName() + " cannot be NULL!"); - } - final String basePackageName = moduleNamespaceToPackageName(module); - final List genNotifyTypes = new ArrayList<>(); - final Set notifications = module.getNotifications(); - for (final NotificationDefinition notification : notifications) { + for (NotificationDefinition notification : notifications) { if (notification != null) { - DataNodeIterator it = new DataNodeIterator(notification); + processUsesAugments(notification, module); + + final GeneratedTypeBuilder notificationInterface = addDefaultInterfaceDefinition(basePackageName, + notification, BindingTypes.DATA_OBJECT); + notificationInterface.addImplementsType(NOTIFICATION); + genCtx.get(module).addChildNodeType(notification, notificationInterface); - // Containers - for (ContainerSchemaNode node : it.allContainers()) { - if (!node.isAddedByUses()) { - genNotifyTypes.add(containerToGenType(basePackageName, node)); - } - } - // Lists - for (ListSchemaNode node : it.allLists()) { - if (!node.isAddedByUses()) { - genNotifyTypes.addAll(listToGenType(basePackageName, node)); - } - } - final GeneratedTypeBuilder notificationTypeBuilder = addDefaultInterfaceDefinition(basePackageName, - notification); - notificationTypeBuilder.addImplementsType(Types - .typeForClass(org.opendaylight.yangtools.yang.binding.Notification.class)); // Notification object - resolveDataSchemaNodes(basePackageName, notificationTypeBuilder, notification.getChildNodes()); - genNotifyTypes.add(notificationTypeBuilder.toInstance()); + resolveDataSchemaNodes(module, basePackageName, notificationInterface, notificationInterface, + notification.getChildNodes()); + + listenerInterface.addMethod("on" + notificationInterface.getName()) + .setAccessModifier(AccessModifier.PUBLIC).addParameter(notificationInterface, "notification") + .setComment(notification.getDescription()).setReturnType(Types.VOID); } } - return genNotifyTypes; + listenerInterface.setDescription(createDescription(notifications, module.getName(), module.getModuleSourcePath())); + + genCtx.get(module).addTopLevelNodeType(listenerInterface); } /** * Converts all identities of the module to the list of * Type objects. - * + * * @param module * module from which is obtained set of all identity objects to * iterate over them * @param context * schema context only used as input parameter for method * {@link identityToGenType} - * @return list of Type which are generated from identities - * (object of type IdentitySchemaNode - * + * */ - private List allIdentitiesToGenTypes(final Module module, final SchemaContext context) { - List genTypes = new ArrayList<>(); - + private void allIdentitiesToGenTypes(final Module module, final SchemaContext context) { final Set schemaIdentities = module.getIdentities(); - - final String basePackageName = moduleNamespaceToPackageName(module); + final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule()); if (schemaIdentities != null && !schemaIdentities.isEmpty()) { - for (final IdentitySchemaNode identity : schemaIdentities) { - genTypes.add(identityToGenType(basePackageName, identity, context)); + for (IdentitySchemaNode identity : schemaIdentities) { + identityToGenType(module, basePackageName, identity, context); } } - return genTypes; } /** @@ -711,133 +604,120 @@ public final class BindingGeneratorImpl implements BindingGenerator { * If identity doesn't contain base identity then only reference to abstract * class {@link org.opendaylight.yangtools.yang.model.api.BaseIdentity * BaseIdentity} is added - * + * + * @param module + * current module * @param basePackageName - * string containing package name to which identity belongs + * 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 - * - * @return GeneratedType which is generated from identity (object of type - * IdentitySchemaNode - * + * */ - private GeneratedType identityToGenType(final String basePackageName, final IdentitySchemaNode identity, - final SchemaContext context) { + private void identityToGenType(final Module module, final String basePackageName, + final IdentitySchemaNode identity, final SchemaContext context) { if (identity == null) { - return null; + return; } - final String packageName = packageNameForGeneratedType(basePackageName, identity.getPath()); - final String genTypeName = parseToClassName(identity.getQName().getLocalName()); + final String genTypeName = BindingMapping.getClassName(identity.getQName()); final GeneratedTOBuilderImpl newType = new GeneratedTOBuilderImpl(packageName, genTypeName); - - IdentitySchemaNode baseIdentity = identity.getBaseIdentity(); - if (baseIdentity != null) { - Module baseIdentityParentModule = SchemaContextUtil.findParentModule(context, baseIdentity); - - final String returnTypePkgName = moduleNamespaceToPackageName(baseIdentityParentModule); - final String returnTypeName = parseToClassName(baseIdentity.getQName().getLocalName()); - - GeneratedTransferObject gto = new GeneratedTOBuilderImpl(returnTypePkgName, returnTypeName).toInstance(); - newType.setExtendsType(gto); + final IdentitySchemaNode baseIdentity = identity.getBaseIdentity(); + if (baseIdentity == null) { + final GeneratedTOBuilderImpl gto = new GeneratedTOBuilderImpl(BaseIdentity.class.getPackage().getName(), + BaseIdentity.class.getSimpleName()); + newType.setExtendsType(gto.toInstance()); } else { - newType.setExtendsType(Types.getBaseIdentityTO()); + 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 GeneratedTOBuilderImpl(returnTypePkgName, returnTypeName) + .toInstance(); + newType.setExtendsType(gto); } newType.setAbstract(true); - return newType.toInstance(); + newType.addComment(identity.getDescription()); + newType.setDescription(createDescription(identity, newType.getFullyQualifiedName())); + newType.setReference(identity.getReference()); + newType.setModuleName(module.getName()); + newType.setSchemaPath(identity.getPath().getPathFromRoot()); + + final QName qname = identity.getQName(); + qnameConstant(newType, BindingMapping.QNAME_STATIC_FIELD_NAME, qname); + + genCtx.get(module).addIdentityType(identity.getQName(), newType); + } + + private static Constant qnameConstant(final GeneratedTypeBuilderBase toBuilder, final String constantName, + final QName name) { + StringBuilder sb = new StringBuilder("org.opendaylight.yangtools.yang.common.QName"); + sb.append(".create("); + sb.append('"'); + sb.append(name.getNamespace()); + sb.append("\",\""); + sb.append(name.getFormattedRevision()); + sb.append("\",\""); + sb.append(name.getLocalName()); + sb.append("\");"); + + return toBuilder.addConstant(typeForClass(QName.class), constantName, sb.toString()); } /** * Converts all groupings of the module to the list of * Type objects. Firstly are groupings sorted according mutual - * dependencies. At least dependend (indepedent) groupings are in the list + * dependencies. At least dependent (independent) groupings are in the list * saved at first positions. For every grouping the record is added to map * {@link BindingGeneratorImpl#allGroupings allGroupings} - * + * * @param module - * module from which is obtained set of all grouping objects to - * iterate over them - * @return list of Type which are generated from groupings - * (object of type GroupingDefinition) - * + * current module + * @param collection + * of groupings from which types will be generated + * */ - private List allGroupingsToGenTypes(final Module module) { - if (module == null) { - throw new IllegalArgumentException("Module parameter can not be null"); + private void groupingsToGenTypes(final Module module, final Collection groupings) { + final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule()); + final List groupingsSortedByDependencies = new GroupingDefinitionDependencySort() + .sort(groupings); + for (GroupingDefinition grouping : groupingsSortedByDependencies) { + groupingToGenType(basePackageName, grouping, module); } - final List genTypes = new ArrayList<>(); - final String basePackageName = moduleNamespaceToPackageName(module); - final Set groupings = module.getGroupings(); - List groupingsSortedByDependencies; - - groupingsSortedByDependencies = GroupingDefinitionDependencySort.sort(groupings); - - for (final GroupingDefinition grouping : groupingsSortedByDependencies) { - GeneratedType genType = groupingToGenType(basePackageName, grouping); - genTypes.add(genType); - SchemaPath schemaPath = grouping.getPath(); - allGroupings.put(schemaPath, genType); - } - return genTypes; } /** * 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 containing name of package to which grouping belongs. + * string contains the module package name * @param grouping * GroupingDefinition which contains data about grouping + * @param module + * current module * @return GeneratedType which is generated from grouping (object of type * GroupingDefinition) */ - private GeneratedType groupingToGenType(final String basePackageName, GroupingDefinition grouping) { - if (grouping == null) { - return null; - } - + private void groupingToGenType(final String basePackageName, final GroupingDefinition grouping, final Module module) { final String packageName = packageNameForGeneratedType(basePackageName, grouping.getPath()); - final Set schemaNodes = grouping.getChildNodes(); - final GeneratedTypeBuilder typeBuilder = addDefaultInterfaceDefinition(packageName, grouping); - - resolveDataSchemaNodes(basePackageName, typeBuilder, schemaNodes); - return typeBuilder.toInstance(); - } - - /** - * Tries to find EnumTypeDefinition in typeDefinition. If base - * type of typeDefinition is of the type ExtendedType then this - * method is recursivelly called with this base type. - * - * @param typeDefinition - * TypeDefinition in which should be EnumTypeDefinition found as - * base type - * @return EnumTypeDefinition if it is found inside - * typeDefinition or null in other case - */ - private EnumTypeDefinition enumTypeDefFromExtendedType(final TypeDefinition typeDefinition) { - if (typeDefinition != null) { - if (typeDefinition.getBaseType() instanceof EnumTypeDefinition) { - return (EnumTypeDefinition) typeDefinition.getBaseType(); - } else if (typeDefinition.getBaseType() instanceof ExtendedType) { - return enumTypeDefFromExtendedType(typeDefinition.getBaseType()); - } - } - return null; + final GeneratedTypeBuilder genType = addDefaultInterfaceDefinition(packageName, grouping); + 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. - * + * * Each enumTypeDef item is added to builder with its name and * value. - * + * * @param enumTypeDef * EnumTypeDefinition contains enum data * @param enumName @@ -845,43 +725,25 @@ public final class BindingGeneratorImpl implements BindingGenerator { * builder * @param typeBuilder * GeneratedTypeBuilder to which will be enum builder assigned - * @return enumeration builder which contais data from + * @return enumeration builder which contains data from * enumTypeDef */ - private EnumBuilder resolveInnerEnumFromTypeDefinition(final EnumTypeDefinition enumTypeDef, final String enumName, + private EnumBuilder resolveInnerEnumFromTypeDefinition(final EnumTypeDefinition enumTypeDef, final QName enumName, final GeneratedTypeBuilder typeBuilder) { if ((enumTypeDef != null) && (typeBuilder != null) && (enumTypeDef.getQName() != null) && (enumTypeDef.getQName().getLocalName() != null)) { - - final String enumerationName = parseToClassName(enumName); + final String enumerationName = BindingMapping.getClassName(enumName); final EnumBuilder enumBuilder = typeBuilder.addEnumeration(enumerationName); - - if (enumBuilder != null) { - final List enums = enumTypeDef.getValues(); - if (enums != null) { - int listIndex = 0; - for (final EnumPair enumPair : enums) { - if (enumPair != null) { - final String enumPairName = parseToClassName(enumPair.getName()); - Integer enumPairValue = enumPair.getValue(); - - if (enumPairValue == null) { - enumPairValue = listIndex; - } - enumBuilder.addValue(enumPairName, enumPairValue); - listIndex++; - } - } - } - return enumBuilder; - } + enumBuilder.setDescription(enumTypeDef.getDescription()); + enumBuilder.updateEnumPairsFromEnumTypeDef(enumTypeDef); + return enumBuilder; } return null; } /** * Generates type builder for module. - * + * * @param module * Module which is source of package name for generated type * builder @@ -891,17 +753,19 @@ public final class BindingGeneratorImpl implements BindingGenerator { * @return instance of GeneratedTypeBuilder which represents * module. * @throws IllegalArgumentException - * if module equals null + * if module is null */ private GeneratedTypeBuilder moduleTypeBuilder(final Module module, final String postfix) { - if (module == null) { - throw new IllegalArgumentException("Module reference cannot be NULL!"); - } - String packageName = moduleNamespaceToPackageName(module); - final String moduleName = parseToClassName(module.getName()) + postfix; + checkArgument(module != null, "Module reference cannot be NULL."); + final String packageName = BindingMapping.getRootPackageName(module.getQNameModule()); + final String moduleName = BindingMapping.getClassName(module.getName()) + postfix; - return new GeneratedTypeBuilderImpl(packageName, moduleName); + final GeneratedTypeBuilderImpl moduleBuilder = new GeneratedTypeBuilderImpl(packageName, moduleName); + moduleBuilder.setDescription(createDescription(module)); + moduleBuilder.setReference(module.getReference()); + moduleBuilder.setModuleName(moduleName); + return moduleBuilder; } /** @@ -910,172 +774,229 @@ public final class BindingGeneratorImpl implements BindingGenerator { * generated types for all containers, list and choices which are child of * augSchema node or a generated types for cases are added if * augmented node is choice. - * + * * @param augmentPackageName * string with the name of the package to which the augmentation * belongs * @param augSchema - * AugmentationSchema which is contains data about agumentation + * AugmentationSchema which is contains data about augmentation * (target path, childs...) - * @return list of Type objects which contains generated type - * for augmentation and for container, list and choice child nodes + * @param module + * current module + * @param parentUsesNode * @throws IllegalArgumentException *
    *
  • if augmentPackageName equals null
  • *
  • if augSchema equals null
  • - *
  • if target path of augSchema equals null
  • *
+ * @throws IllegalStateException + * if augment target path is null */ - private List augmentationToGenTypes(final String augmentPackageName, final AugmentationSchema augSchema) { - if (augmentPackageName == null) { - throw new IllegalArgumentException("Package Name cannot be NULL!"); + private void augmentationToGenTypes(final String augmentPackageName, final AugmentationSchema augSchema, + final Module module) { + checkArgument(augmentPackageName != null, "Package Name cannot be NULL."); + 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); + final SchemaPath targetPath = augSchema.getTargetPath(); + SchemaNode targetSchemaNode = null; + + targetSchemaNode = findDataSchemaNode(schemaContext, targetPath); + if (targetSchemaNode instanceof DataSchemaNode && ((DataSchemaNode) targetSchemaNode).isAddedByUses()) { + if (targetSchemaNode instanceof DerivableSchemaNode) { + targetSchemaNode = ((DerivableSchemaNode) targetSchemaNode).getOriginal().orNull(); + } + if (targetSchemaNode == null) { + throw new IllegalStateException("Failed to find target node from grouping in augmentation " + augSchema + + " in module " + module.getName()); + } + } + if (targetSchemaNode == null) { + throw new IllegalArgumentException("augment target not found: " + targetPath); + } + + GeneratedTypeBuilder targetTypeBuilder = findChildNodeByPath(targetSchemaNode.getPath()); + if (targetTypeBuilder == null) { + targetTypeBuilder = findCaseByPath(targetSchemaNode.getPath()); } - if (augSchema == null) { - throw new IllegalArgumentException("Augmentation Schema cannot be NULL!"); + if (targetTypeBuilder == null) { + throw new NullPointerException("Target type not yet generated: " + targetSchemaNode); } - if (augSchema.getTargetPath() == null) { - throw new IllegalStateException("Augmentation Schema does not contain Target Path (Target Path is NULL)."); + + if (!(targetSchemaNode instanceof ChoiceNode)) { + String packageName = augmentPackageName; + final Type targetType = new ReferencedTypeImpl(targetTypeBuilder.getPackageName(), + targetTypeBuilder.getName()); + addRawAugmentGenTypeDefinition(module, packageName, augmentPackageName, targetType, augSchema); + + } else { + generateTypesFromAugmentedChoiceCases(module, augmentPackageName, targetTypeBuilder.toInstance(), + (ChoiceNode) targetSchemaNode, augSchema.getChildNodes()); } + } - final List genTypes = new ArrayList<>(); + private void usesAugmentationToGenTypes(final String augmentPackageName, final AugmentationSchema augSchema, + final Module module, final UsesNode usesNode, final DataNodeContainer usesNodeParent) { + checkArgument(augmentPackageName != null, "Package Name cannot be NULL."); + checkArgument(augSchema != null, "Augmentation Schema cannot be NULL."); + checkState(augSchema.getTargetPath() != null, + "Augmentation Schema does not contain Target Path (Target Path is NULL)."); - // EVERY augmented interface will extends Augmentation interface - // and DataObject interface!!! + processUsesAugments(augSchema, module); final SchemaPath targetPath = augSchema.getTargetPath(); - final DataSchemaNode targetSchemaNode = findDataSchemaNode(schemaContext, targetPath); - if ((targetSchemaNode != null) && (targetSchemaNode.getQName() != null) - && (targetSchemaNode.getQName().getLocalName() != null)) { - final Module targetModule = findParentModule(schemaContext, targetSchemaNode); - final String targetBasePackage = moduleNamespaceToPackageName(targetModule); - final String targetPackageName = packageNameForGeneratedType(targetBasePackage, targetSchemaNode.getPath()); - final String targetSchemaNodeName = targetSchemaNode.getQName().getLocalName(); - final Set augChildNodes = augSchema.getChildNodes(); - - if (!(targetSchemaNode instanceof ChoiceNode)) { - final GeneratedTypeBuilder augTypeBuilder = addRawAugmentGenTypeDefinition(augmentPackageName, - targetPackageName, targetSchemaNodeName, augSchema); - final GeneratedType augType = augTypeBuilder.toInstance(); - genTypes.add(augType); - } else { - final Type refChoiceType = new ReferencedTypeImpl(targetPackageName, - parseToClassName(targetSchemaNodeName)); - final ChoiceNode choiceTarget = (ChoiceNode) targetSchemaNode; - final Set choiceCaseNodes = choiceTarget.getCases(); - genTypes.addAll(generateTypesFromAugmentedChoiceCases(augmentPackageName, refChoiceType, - choiceCaseNodes)); + SchemaNode targetSchemaNode = findOriginalTargetFromGrouping(targetPath, usesNode); + if (targetSchemaNode == null) { + throw new IllegalArgumentException("augment target not found: " + targetPath); + } + + GeneratedTypeBuilder targetTypeBuilder = findChildNodeByPath(targetSchemaNode.getPath()); + if (targetTypeBuilder == null) { + targetTypeBuilder = findCaseByPath(targetSchemaNode.getPath()); + } + if (targetTypeBuilder == null) { + throw new NullPointerException("Target type not yet generated: " + targetSchemaNode); + } + + if (!(targetSchemaNode instanceof ChoiceNode)) { + String packageName = augmentPackageName; + if (usesNodeParent instanceof SchemaNode) { + packageName = packageNameForGeneratedType(augmentPackageName, ((SchemaNode) usesNodeParent).getPath(), + true); + } + addRawAugmentGenTypeDefinition(module, packageName, augmentPackageName, targetTypeBuilder.toInstance(), + augSchema); + } else { + generateTypesFromAugmentedChoiceCases(module, augmentPackageName, targetTypeBuilder.toInstance(), + (ChoiceNode) targetSchemaNode, augSchema.getChildNodes()); + } + } + + /** + * Convenient method to find node added by uses statement. + * + * @param targetPath + * node path + * @param parentUsesNode + * parent of uses node + * @return node from its original location in grouping + */ + private DataSchemaNode findOriginalTargetFromGrouping(final SchemaPath targetPath, final UsesNode parentUsesNode) { + SchemaNode targetGrouping = findNodeInSchemaContext(schemaContext, parentUsesNode.getGroupingPath() + .getPathFromRoot()); + if (!(targetGrouping instanceof GroupingDefinition)) { + throw new IllegalArgumentException("Failed to generate code for augment in " + parentUsesNode); + } + + GroupingDefinition grouping = (GroupingDefinition) targetGrouping; + SchemaNode result = grouping; + for (QName node : targetPath.getPathFromRoot()) { + // finding by local name is valid, grouping cannot contain nodes + // with same name and different namespace + if (result instanceof DataNodeContainer) { + result = ((DataNodeContainer) result).getDataChildByName(node.getLocalName()); + } else if (result instanceof ChoiceNode) { + result = ((ChoiceNode) result).getCaseNodeByName(node.getLocalName()); + } + } + if (result == null) { + return null; + } + + boolean fromUses = ((DataSchemaNode) result).isAddedByUses(); + Iterator groupingUses = grouping.getUses().iterator(); + while (groupingUses.hasNext() && fromUses) { + result = findOriginalTargetFromGrouping(targetPath, groupingUses.next()); + if (result != null) { + fromUses = ((DataSchemaNode) result).isAddedByUses(); } - genTypes.addAll(augmentationBodyToGenTypes(augmentPackageName, augChildNodes)); } - return genTypes; + if (fromUses) { + // this indicates invalid yang and thus possible bug in code because + // invalid yang should be already spotted by parser + throw new IllegalStateException("Failed to generate code for augment in " + parentUsesNode); + } + + return (DataSchemaNode) result; } /** * Returns a generated type builder for an augmentation. - * + * * The name of the type builder is equal to the name of augmented node with * serial number as suffix. - * + * + * @param module + * current module * @param augmentPackageName * string with contains the package name to which the augment * belongs - * @param targetPackageName + * @param basePackageName * string with the package name to which the augmented node * belongs - * @param targetSchemaNodeName - * string with the name of the augmented node + * @param targetTypeRef + * target type * @param augSchema * augmentation schema which contains data about the child nodes * and uses of augment * @return generated type builder for augment */ - private GeneratedTypeBuilder addRawAugmentGenTypeDefinition(final String augmentPackageName, - final String targetPackageName, final String targetSchemaNodeName, final AugmentationSchema augSchema) { - final String targetTypeName = parseToClassName(targetSchemaNodeName); + private GeneratedTypeBuilder addRawAugmentGenTypeDefinition(final Module module, final String augmentPackageName, + final String basePackageName, final Type targetTypeRef, final AugmentationSchema augSchema) { Map augmentBuilders = genTypeBuilders.get(augmentPackageName); if (augmentBuilders == null) { augmentBuilders = new HashMap<>(); genTypeBuilders.put(augmentPackageName, augmentBuilders); } + final String augIdentifier = getAugmentIdentifier(augSchema.getUnknownSchemaNodes()); - final String augTypeName = augGenTypeName(augmentBuilders, targetTypeName); - final Type targetTypeRef = new ReferencedTypeImpl(targetPackageName, targetTypeName); - final Set augChildNodes = augSchema.getChildNodes(); + String augTypeName; + if (augIdentifier != null) { + augTypeName = BindingMapping.getClassName(augIdentifier); + } else { + augTypeName = augGenTypeName(augmentBuilders, targetTypeRef.getName()); + } final GeneratedTypeBuilder augTypeBuilder = new GeneratedTypeBuilderImpl(augmentPackageName, augTypeName); - augTypeBuilder.addImplementsType(Types.DATA_OBJECT); + augTypeBuilder.addImplementsType(DATA_OBJECT); augTypeBuilder.addImplementsType(Types.augmentationTypeFor(targetTypeRef)); addImplementedInterfaceFromUses(augSchema, augTypeBuilder); - augSchemaNodeToMethods(augmentPackageName, augTypeBuilder, augChildNodes); + augSchemaNodeToMethods(module, basePackageName, augTypeBuilder, augTypeBuilder, augSchema.getChildNodes()); augmentBuilders.put(augTypeName, augTypeBuilder); + + if(!augSchema.getChildNodes().isEmpty()) { + genCtx.get(module).addTargetToAugmentation(targetTypeRef, augTypeBuilder); + genCtx.get(module).addTypeToAugmentation(augTypeBuilder, augSchema); + + } + genCtx.get(module).addAugmentType(augTypeBuilder); return augTypeBuilder; } /** - * Convert a container, list and choice subnodes (and recursivelly their - * subnodes) of augment to generated types - * - * @param augBasePackageName - * string with the augment package name - * @param augChildNodes - * set of data schema nodes which represents child nodes of the - * augment - * - * @return list of Type which represents container, list and - * choice subnodes of augment + * + * @param unknownSchemaNodes + * @return nodeParameter of UnknownSchemaNode */ - private List augmentationBodyToGenTypes(final String augBasePackageName, - final Set augChildNodes) { - final List genTypes = new ArrayList<>(); - final List augSchemaIts = new ArrayList<>(); - for (final DataSchemaNode childNode : augChildNodes) { - if (childNode instanceof DataNodeContainer) { - augSchemaIts.add(new DataNodeIterator((DataNodeContainer) childNode)); - - if (childNode instanceof ContainerSchemaNode) { - genTypes.add(containerToGenType(augBasePackageName, (ContainerSchemaNode) childNode)); - } else if (childNode instanceof ListSchemaNode) { - genTypes.addAll(listToGenType(augBasePackageName, (ListSchemaNode) childNode)); - } - } else if (childNode instanceof ChoiceNode) { - final ChoiceNode choice = (ChoiceNode) childNode; - for (final ChoiceCaseNode caseNode : choice.getCases()) { - augSchemaIts.add(new DataNodeIterator(caseNode)); - } - genTypes.addAll(choiceToGeneratedType(augBasePackageName, (ChoiceNode) childNode)); - } - } - - for (final DataNodeIterator it : augSchemaIts) { - final List augContainers = it.allContainers(); - final List augLists = it.allLists(); - final List augChoices = it.allChoices(); - - if (augContainers != null) { - for (final ContainerSchemaNode container : augContainers) { - genTypes.add(containerToGenType(augBasePackageName, container)); - } - } - if (augLists != null) { - for (final ListSchemaNode list : augLists) { - genTypes.addAll(listToGenType(augBasePackageName, list)); - } - } - if (augChoices != null) { - for (final ChoiceNode choice : augChoices) { - genTypes.addAll(choiceToGeneratedType(augBasePackageName, choice)); - } + private String getAugmentIdentifier(final List unknownSchemaNodes) { + for (UnknownSchemaNode unknownSchemaNode : unknownSchemaNodes) { + final QName nodeType = unknownSchemaNode.getNodeType(); + if (AUGMENT_IDENTIFIER_NAME.equals(nodeType.getLocalName()) + && YANG_EXT_NAMESPACE.equals(nodeType.getNamespace().toString())) { + return unknownSchemaNode.getNodeParameter(); } } - return genTypes; + return null; } /** * Returns first unique name for the augment generated type builder. The * generated type builder name for augment consists from name of augmented * node and serial number of its augmentation. - * + * * @param builders * map of builders which were created in the package to which the * augmentation belongs @@ -1084,220 +1005,341 @@ public final class BindingGeneratorImpl implements BindingGenerator { * @return string with unique name for augmentation builder */ private String augGenTypeName(final Map builders, final String genTypeName) { - String augTypeName = genTypeName; - int index = 1; - while ((builders != null) && builders.containsKey(genTypeName + index)) { - index++; + if (builders != null) { + while (builders.containsKey(genTypeName + index)) { + index = index + 1; + } } - augTypeName += index; - return augTypeName; + return genTypeName + index; } /** - * Converts containerNode to generated type. Firstly the - * generated type builder is created. The subnodes of - * containerNode are added as methods and the instance of - * GeneratedType is returned. - * + * Adds the methods to typeBuilder which represent subnodes of + * node for which typeBuilder was created. + * + * The subnodes aren't mapped to the methods if they are part of grouping or + * augment (in this case are already part of them). + * + * @param module + * current module * @param basePackageName - * string with name of the package to which the superior node - * belongs - * @param containerNode - * container schema node with the data about childs nodes and - * schema paths - * @return generated type for containerNode + * 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 + * methods. The subnode can be of type leaf, leaf-list, list, + * container, choice. + * @param childOf + * parent type + * @param schemaNodes + * set of data schema nodes which are the children of the node + * for which typeBuilder was created + * @return generated type builder which is the same builder as input + * parameter. The getter methods (representing child nodes) could be + * added to it. */ - private GeneratedType containerToGenType(final String basePackageName, ContainerSchemaNode containerNode) { - if (containerNode == null) { - return null; + private GeneratedTypeBuilder resolveDataSchemaNodes(final Module module, final String basePackageName, + final GeneratedTypeBuilder parent, final GeneratedTypeBuilder childOf, final Iterable schemaNodes) { + if (schemaNodes != null && parent != null) { + for (DataSchemaNode schemaNode : schemaNodes) { + if (!schemaNode.isAugmenting() && !schemaNode.isAddedByUses()) { + addSchemaNodeToBuilderAsMethod(basePackageName, schemaNode, parent, childOf, module); + } + } } - - final String packageName = packageNameForGeneratedType(basePackageName, containerNode.getPath()); - final Set schemaNodes = containerNode.getChildNodes(); - final GeneratedTypeBuilder typeBuilder = addDefaultInterfaceDefinition(packageName, containerNode); - - resolveDataSchemaNodes(basePackageName, typeBuilder, schemaNodes); - return typeBuilder.toInstance(); + return parent; } /** - * + * Adds the methods to typeBuilder what represents subnodes of + * node for which typeBuilder was created. + * + * @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 + * methods. The subnode can be of type leaf, leaf-list, list, + * container, choice. + * @param childOf + * parent type * @param schemaNodes - * @return + * set of data schema nodes which are the children of the node + * for which typeBuilder was created + * @return generated type builder which is the same object as the input + * parameter typeBuilder. The getter method could be + * added to it. */ - private GeneratedTypeBuilder resolveDataSchemaNodes(final String basePackageName, - final GeneratedTypeBuilder typeBuilder, final Set schemaNodes) { + private GeneratedTypeBuilder augSchemaNodeToMethods(final Module module, final String basePackageName, + final GeneratedTypeBuilder typeBuilder, final GeneratedTypeBuilder childOf, + final Iterable schemaNodes) { if ((schemaNodes != null) && (typeBuilder != null)) { - for (final DataSchemaNode schemaNode : schemaNodes) { - if (schemaNode.isAugmenting() || schemaNode.isAddedByUses()) { - continue; + for (DataSchemaNode schemaNode : schemaNodes) { + if (!schemaNode.isAugmenting()) { + addSchemaNodeToBuilderAsMethod(basePackageName, schemaNode, typeBuilder, childOf, module); } - addSchemaNodeToBuilderAsMethod(basePackageName, schemaNode, typeBuilder); } } return typeBuilder; } - private GeneratedTypeBuilder augSchemaNodeToMethods(final String basePackageName, - final GeneratedTypeBuilder typeBuilder, final Set schemaNodes) { - if ((schemaNodes != null) && (typeBuilder != null)) { - for (final DataSchemaNode schemaNode : schemaNodes) { - if (schemaNode.isAugmenting()) { - addSchemaNodeToBuilderAsMethod(basePackageName, schemaNode, typeBuilder); - } + /** + * 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 + * @param typeBuilder + * generated type builder to which is schemaNode + * added as a method. + * @param childOf + * parent type + * @param module + * current module + */ + private void addSchemaNodeToBuilderAsMethod(final String basePackageName, final DataSchemaNode node, + final GeneratedTypeBuilder typeBuilder, final GeneratedTypeBuilder childOf, final Module module) { + if (node != null && typeBuilder != null) { + if (node instanceof LeafSchemaNode) { + resolveLeafSchemaNodeAsMethod(typeBuilder, (LeafSchemaNode) node); + } else if (node instanceof LeafListSchemaNode) { + resolveLeafListSchemaNode(typeBuilder, (LeafListSchemaNode) node); + } else if (node instanceof ContainerSchemaNode) { + containerToGenType(module, basePackageName, typeBuilder, childOf, (ContainerSchemaNode) node); + } else if (node instanceof ListSchemaNode) { + listToGenType(module, basePackageName, typeBuilder, childOf, (ListSchemaNode) node); + } else if (node instanceof ChoiceNode) { + choiceToGeneratedType(module, basePackageName, typeBuilder, (ChoiceNode) 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()); } } - return typeBuilder; } - private void addSchemaNodeToBuilderAsMethod(final String basePackageName, final DataSchemaNode schemaNode, - final GeneratedTypeBuilder typeBuilder) { - if (schemaNode != null && typeBuilder != null) { - if (schemaNode instanceof LeafSchemaNode) { - resolveLeafSchemaNodeAsMethod(typeBuilder, (LeafSchemaNode) schemaNode); - } else if (schemaNode instanceof LeafListSchemaNode) { - resolveLeafListSchemaNode(typeBuilder, (LeafListSchemaNode) schemaNode); - } else if (schemaNode instanceof ContainerSchemaNode) { - resolveContainerSchemaNode(basePackageName, typeBuilder, (ContainerSchemaNode) schemaNode); - } else if (schemaNode instanceof ListSchemaNode) { - resolveListSchemaNode(basePackageName, typeBuilder, (ListSchemaNode) schemaNode); - } else if (schemaNode instanceof ChoiceNode) { - resolveChoiceSchemaNode(basePackageName, typeBuilder, (ChoiceNode) schemaNode); - } - } - } - - private void resolveChoiceSchemaNode(final String basePackageName, final GeneratedTypeBuilder typeBuilder, - final ChoiceNode choiceNode) { - if (basePackageName == null) { - throw new IllegalArgumentException("Base Package Name cannot be NULL!"); - } - if (typeBuilder == null) { - throw new IllegalArgumentException("Generated Type Builder cannot be NULL!"); - } - if (choiceNode == null) { - throw new IllegalArgumentException("Choice Schema Node cannot be NULL!"); - } + /** + * Converts choiceNode to the list of generated types for + * choice and its cases. + * + * The package names for choice and for its cases are created as + * concatenation of the module package (basePackageName) and + * names of all parents node. + * + * @param module + * current module + * @param basePackageName + * string with the module package name + * @param parent + * parent type + * @param choiceNode + * choice node which is mapped to generated type. Also child + * nodes - cases are mapped to generated types. + * @throws IllegalArgumentException + *
    + *
  • if basePackageName is null
  • + *
  • if choiceNode is null
  • + *
+ */ + private void choiceToGeneratedType(final Module module, final String basePackageName, + final GeneratedTypeBuilder parent, final ChoiceNode choiceNode) { + checkArgument(basePackageName != null, "Base Package Name cannot be NULL."); + checkArgument(choiceNode != null, "Choice Schema Node cannot be NULL."); - final String choiceName = choiceNode.getQName().getLocalName(); - if (choiceName != null && !choiceNode.isAddedByUses()) { + if (!choiceNode.isAddedByUses()) { final String packageName = packageNameForGeneratedType(basePackageName, choiceNode.getPath()); - final GeneratedTypeBuilder choiceType = addDefaultInterfaceDefinition(packageName, choiceNode); - constructGetter(typeBuilder, choiceName, choiceNode.getDescription(), choiceType); + final GeneratedTypeBuilder choiceTypeBuilder = addRawInterfaceDefinition(packageName, choiceNode); + constructGetter(parent, choiceNode.getQName().getLocalName(), choiceNode.getDescription(), + choiceTypeBuilder); + choiceTypeBuilder.addImplementsType(typeForClass(DataContainer.class)); + genCtx.get(module).addChildNodeType(choiceNode, choiceTypeBuilder); + generateTypesFromChoiceCases(module, basePackageName, choiceTypeBuilder.toInstance(), choiceNode); } } - private List choiceToGeneratedType(final String basePackageName, final ChoiceNode choiceNode) { - if (basePackageName == null) { - throw new IllegalArgumentException("Base Package Name cannot be NULL!"); - } - if (choiceNode == null) { - throw new IllegalArgumentException("Choice Schema Node cannot be NULL!"); - } - - final List generatedTypes = new ArrayList<>(); - final String packageName = packageNameForGeneratedType(basePackageName, choiceNode.getPath()); - final GeneratedTypeBuilder choiceTypeBuilder = addRawInterfaceDefinition(packageName, choiceNode); - choiceTypeBuilder.addImplementsType(Types.DATA_OBJECT); - final GeneratedType choiceType = choiceTypeBuilder.toInstance(); + /** + * 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 + * + * @param module + * current module + * @param basePackageName + * string with the module package name + * @param refChoiceType + * type which represents superior case + * @param choiceNode + * choice case node which is mapped to generated type + * @return list of generated types for caseNodes. + * @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 ChoiceNode choiceNode) { + checkArgument(basePackageName != null, "Base Package Name cannot be NULL."); + checkArgument(refChoiceType != null, "Referenced Choice Type cannot be NULL."); + checkArgument(choiceNode != null, "ChoiceNode cannot be NULL."); - generatedTypes.add(choiceType); final Set caseNodes = choiceNode.getCases(); - if ((caseNodes != null) && !caseNodes.isEmpty()) { - generatedTypes.addAll(generateTypesFromChoiceCases(basePackageName, choiceType, caseNodes)); - } - return generatedTypes; - } - - private List generateTypesFromChoiceCases(final String basePackageName, final Type refChoiceType, - final Set caseNodes) { - if (basePackageName == null) { - throw new IllegalArgumentException("Base Package Name cannot be NULL!"); - } - if (refChoiceType == null) { - throw new IllegalArgumentException("Referenced Choice Type cannot be NULL!"); - } if (caseNodes == null) { - throw new IllegalArgumentException("Set of Choice Case Nodes cannot be NULL!"); + return; } - final List generatedTypes = new ArrayList<>(); - for (final ChoiceCaseNode caseNode : caseNodes) { + for (ChoiceCaseNode caseNode : caseNodes) { if (caseNode != null && !caseNode.isAddedByUses() && !caseNode.isAugmenting()) { final String packageName = packageNameForGeneratedType(basePackageName, caseNode.getPath()); final GeneratedTypeBuilder caseTypeBuilder = addDefaultInterfaceDefinition(packageName, caseNode); caseTypeBuilder.addImplementsType(refChoiceType); - - final Set childNodes = caseNode.getChildNodes(); - if (childNodes != null) { - resolveDataSchemaNodes(basePackageName, caseTypeBuilder, childNodes); + genCtx.get(module).addCaseType(caseNode.getPath(), caseTypeBuilder); + genCtx.get(module).addChoiceToCaseMapping(refChoiceType, caseTypeBuilder, caseNode); + final Iterable caseChildNodes = caseNode.getChildNodes(); + if (caseChildNodes != null) { + Object parentNode = null; + final SchemaPath nodeSp = choiceNode.getPath(); + parentNode = findDataSchemaNode(schemaContext, nodeSp.getParent()); + + SchemaNode parent; + if (parentNode instanceof AugmentationSchema) { + final AugmentationSchema augSchema = (AugmentationSchema) parentNode; + final SchemaPath targetPath = augSchema.getTargetPath(); + SchemaNode targetSchemaNode = findDataSchemaNode(schemaContext, targetPath); + if (targetSchemaNode instanceof DataSchemaNode + && ((DataSchemaNode) targetSchemaNode).isAddedByUses()) { + if (targetSchemaNode instanceof DerivableSchemaNode) { + targetSchemaNode = ((DerivableSchemaNode) targetSchemaNode).getOriginal().orNull(); + } + if (targetSchemaNode == null) { + throw new IllegalStateException( + "Failed to find target node from grouping for augmentation " + augSchema + + " in module " + module.getName()); + } + } + parent = targetSchemaNode; + } else { + final SchemaPath sp = choiceNode.getPath(); + parent = findDataSchemaNode(schemaContext, sp.getParent()); + } + GeneratedTypeBuilder childOfType = findChildNodeByPath(parent.getPath()); + if (childOfType == null) { + childOfType = findGroupingByPath(parent.getPath()); + } + resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, childOfType, caseChildNodes); } - generatedTypes.add(caseTypeBuilder.toInstance()); } - } - return generatedTypes; + processUsesAugments(caseNode, module); + } } /** * Generates list of generated types for all the cases of a choice which are * added to the choice through the augment. - * - * + * + * @param module + * current module * @param basePackageName * string contains name of package to which augment belongs. If * an augmented choice is from an other package (pcg1) than an * augmenting choice (pcg2) then case's of the augmenting choice * will belong to pcg2. - * @param refChoiceType - * Type which represents the choice to which case belongs. Every - * case has to contain its choice in extend part. - * @param caseNodes + * @param targetType + * Type which represents target choice + * @param targetNode + * node which represents target choice + * @param augmentedNodes * set of choice case nodes for which is checked if are/aren't * added to choice through augmentation * @return list of generated types which represents augmented cases of * choice refChoiceType * @throws IllegalArgumentException *
    - *
  • if basePackageName equals null
  • - *
  • if refChoiceType equals null
  • - *
  • if caseNodes equals null
  • + *
  • if basePackageName is null
  • + *
  • if targetType is null
  • + *
  • if augmentedNodes is null
  • *
*/ - private List generateTypesFromAugmentedChoiceCases(final String basePackageName, - final Type refChoiceType, final Set caseNodes) { - if (basePackageName == null) { - throw new IllegalArgumentException("Base Package Name cannot be NULL!"); - } - if (refChoiceType == null) { - throw new IllegalArgumentException("Referenced Choice Type cannot be NULL!"); - } - if (caseNodes == null) { - throw new IllegalArgumentException("Set of Choice Case Nodes cannot be NULL!"); - } - - final List generatedTypes = new ArrayList<>(); - for (final ChoiceCaseNode caseNode : caseNodes) { - if (caseNode != null && caseNode.isAugmenting()) { + private void generateTypesFromAugmentedChoiceCases(final Module module, final String basePackageName, + final Type targetType, final ChoiceNode targetNode, final Iterable augmentedNodes) { + 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 (DataSchemaNode caseNode : augmentedNodes) { + if (caseNode != null) { final String packageName = packageNameForGeneratedType(basePackageName, caseNode.getPath()); final GeneratedTypeBuilder caseTypeBuilder = addDefaultInterfaceDefinition(packageName, caseNode); - caseTypeBuilder.addImplementsType(refChoiceType); + caseTypeBuilder.addImplementsType(targetType); + + SchemaNode parent = null; + 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 ChoiceCaseNode) { + 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()); + } - final Set childNodes = caseNode.getChildNodes(); + if (childOfType == null) { + throw new IllegalArgumentException("Failed to find parent type of choice " + targetNode); + } + + ChoiceCaseNode node = null; + if (caseNode instanceof ChoiceCaseNode) { + node = (ChoiceCaseNode) caseNode; + } else { + node = targetNode.getCaseNodeByName(caseNode.getQName().getLocalName()); + } + final Iterable childNodes = node.getChildNodes(); if (childNodes != null) { - resolveDataSchemaNodes(basePackageName, caseTypeBuilder, childNodes); + resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, childOfType, childNodes); } - generatedTypes.add(caseTypeBuilder.toInstance()); + genCtx.get(module).addCaseType(caseNode.getPath(), caseTypeBuilder); + genCtx.get(module).addChoiceToCaseMapping(targetType, caseTypeBuilder, node); } } - - return generatedTypes; } - private boolean resolveLeafSchemaNodeAsMethod(final GeneratedTypeBuilder typeBuilder, final LeafSchemaNode leaf) { + /** + * Converts leaf to the getter method which is added to + * typeBuilder. + * + * @param typeBuilder + * generated type builder to which is added getter method as + * leaf mapping + * @param leaf + * leaf schema node which is mapped as getter method which is + * added to typeBuilder + * @return boolean value + *
    + *
  • false - if leaf or typeBuilder are + * null
  • + *
  • true - in other cases
  • + *
+ */ + private Type resolveLeafSchemaNodeAsMethod(final GeneratedTypeBuilder typeBuilder, final LeafSchemaNode leaf) { + Type returnType = null; if ((leaf != null) && (typeBuilder != null)) { final String leafName = leaf.getQName().getLocalName(); String leafDesc = leaf.getDescription(); @@ -1305,44 +1347,106 @@ public final class BindingGeneratorImpl implements BindingGenerator { leafDesc = ""; } + final Module parentModule = findParentModule(schemaContext, leaf); if (leafName != null && !leaf.isAddedByUses()) { final TypeDefinition typeDef = leaf.getType(); - Type returnType = null; + GeneratedTOBuilder genTOBuilder; if (typeDef instanceof EnumTypeDefinition) { - returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef); - final EnumTypeDefinition enumTypeDef = enumTypeDefFromExtendedType(typeDef); - final EnumBuilder enumBuilder = resolveInnerEnumFromTypeDefinition(enumTypeDef, leafName, + returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf); + final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) typeDef; + final EnumBuilder enumBuilder = resolveInnerEnumFromTypeDefinition(enumTypeDef, leaf.getQName(), typeBuilder); if (enumBuilder != null) { - returnType = new ReferencedTypeImpl(enumBuilder.getPackageName(), enumBuilder.getName()); + returnType = enumBuilder.toInstance(typeBuilder); } ((TypeProviderImpl) typeProvider).putReferencedType(leaf.getPath(), returnType); } else if (typeDef instanceof UnionType) { - GeneratedTOBuilder genTOBuilder = addEnclosedTOToTypeBuilder(typeDef, typeBuilder, leafName); + genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, leaf, parentModule); if (genTOBuilder != null) { - returnType = new ReferencedTypeImpl(genTOBuilder.getPackageName(), genTOBuilder.getName()); + returnType = createReturnTypeForUnion(genTOBuilder, typeDef, typeBuilder, parentModule); } } else if (typeDef instanceof BitsTypeDefinition) { - GeneratedTOBuilder genTOBuilder = addEnclosedTOToTypeBuilder(typeDef, typeBuilder, leafName); + genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, leaf, parentModule); if (genTOBuilder != null) { - returnType = new ReferencedTypeImpl(genTOBuilder.getPackageName(), genTOBuilder.getName()); + returnType = genTOBuilder.toInstance(); } } else { - returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef); + final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef); + returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf, restrictions); } if (returnType != null) { - constructGetter(typeBuilder, leafName, leafDesc, returnType); - return true; + final MethodSignatureBuilder getter = constructGetter(typeBuilder, leafName, leafDesc, returnType); + processContextRefExtension(leaf, getter, parentModule); } } } - return false; + return returnType; + } + + private void processContextRefExtension(final LeafSchemaNode leaf, final MethodSignatureBuilder getter, + final Module module) { + for (UnknownSchemaNode node : leaf.getUnknownSchemaNodes()) { + final QName nodeType = node.getNodeType(); + if ("context-reference".equals(nodeType.getLocalName())) { + final String nodeParam = node.getNodeParameter(); + IdentitySchemaNode identity = null; + String basePackageName = null; + final Iterable splittedElement = COLON_SPLITTER.split(nodeParam); + final Iterator iterator = splittedElement.iterator(); + final int length = Iterables.size(splittedElement); + if (length == 1) { + identity = findIdentityByName(module.getIdentities(), iterator.next()); + basePackageName = BindingMapping.getRootPackageName(module.getQNameModule()); + } else if (length == 2) { + String prefix = iterator.next(); + final Module dependentModule = findModuleFromImports(module.getImports(), prefix); + if (dependentModule == null) { + throw new IllegalArgumentException("Failed to process context-reference: unknown prefix " + + prefix); + } + identity = findIdentityByName(dependentModule.getIdentities(), iterator.next()); + basePackageName = BindingMapping.getRootPackageName(dependentModule.getQNameModule()); + } else { + throw new IllegalArgumentException("Failed to process context-reference: unknown identity " + + nodeParam); + } + if (identity == null) { + throw new IllegalArgumentException("Failed to process context-reference: unknown identity " + + nodeParam); + } + + final Class clazz = RoutingContext.class; + final AnnotationTypeBuilder rc = getter.addAnnotation(clazz.getPackage().getName(), + clazz.getSimpleName()); + final String packageName = packageNameForGeneratedType(basePackageName, identity.getPath()); + final String genTypeName = BindingMapping.getClassName(identity.getQName().getLocalName()); + rc.addParameter("value", packageName + "." + genTypeName + ".class"); + } + } + } + + private IdentitySchemaNode findIdentityByName(final Set identities, final String name) { + for (IdentitySchemaNode id : identities) { + if (id.getQName().getLocalName().equals(name)) { + return id; + } + } + return null; + } + + private Module findModuleFromImports(final Set imports, final String prefix) { + for (ModuleImport imp : imports) { + if (imp.getPrefix().equals(prefix)) { + return schemaContext.findModuleByName(imp.getModuleName(), imp.getRevision()); + } + } + return null; } private boolean resolveLeafSchemaNodeAsProperty(final GeneratedTOBuilder toBuilder, final LeafSchemaNode leaf, - boolean isReadOnly) { + final boolean isReadOnly, final Module module) { if ((leaf != null) && (toBuilder != null)) { final String leafName = leaf.getQName().getLocalName(); String leafDesc = leaf.getDescription(); @@ -1350,139 +1454,262 @@ public final class BindingGeneratorImpl implements BindingGenerator { leafDesc = ""; } - if (leafName != null && !leaf.isAddedByUses()) { + if (leafName != null) { + Type returnType = null; final TypeDefinition typeDef = leaf.getType(); - - // TODO: properly resolve enum types - final Type returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef); - - if (returnType != null) { - final GeneratedPropertyBuilder propBuilder = toBuilder.addProperty(parseToClassName(leafName)); - - propBuilder.setReadOnly(isReadOnly); - propBuilder.setReturnType(returnType); - propBuilder.setComment(leafDesc); - - toBuilder.addEqualsIdentity(propBuilder); - toBuilder.addHashIdentity(propBuilder); - toBuilder.addToStringProperty(propBuilder); - - return true; + if (typeDef instanceof UnionTypeDefinition) { + // GeneratedType for this type definition should be already + // created + QName qname = typeDef.getQName(); + Module unionModule = schemaContext.findModuleByNamespaceAndRevision(qname.getNamespace(), + qname.getRevision()); + final ModuleContext mc = genCtx.get(unionModule); + returnType = mc.getTypedefs().get(typeDef.getPath()); + } else { + returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf); } + return resolveLeafSchemaNodeAsProperty(toBuilder, leaf, returnType, isReadOnly); } } return false; } + /** + * Converts leaf schema node to property of generated TO + * builder. + * + * @param toBuilder + * generated TO builder to which is leaf added as + * property + * @param leaf + * leaf schema node which is added to toBuilder as + * property + * @param returnType + * property type + * @param isReadOnly + * boolean value which says if leaf property is|isn't read only + * @return boolean value + *
    + *
  • false - if leaf, toBuilder or leaf + * name equals null or if leaf is added by uses.
  • + *
  • true - other cases
  • + *
+ */ + private boolean resolveLeafSchemaNodeAsProperty(final GeneratedTOBuilder toBuilder, final LeafSchemaNode leaf, + final Type returnType, final boolean isReadOnly) { + if (returnType == null) { + return false; + } + final String leafName = leaf.getQName().getLocalName(); + final String leafDesc = leaf.getDescription(); + final GeneratedPropertyBuilder propBuilder = toBuilder.addProperty(parseToValidParamName(leafName)); + propBuilder.setReadOnly(isReadOnly); + propBuilder.setReturnType(returnType); + propBuilder.setComment(leafDesc); + toBuilder.addEqualsIdentity(propBuilder); + toBuilder.addHashIdentity(propBuilder); + toBuilder.addToStringProperty(propBuilder); + return true; + } + + /** + * Converts node leaf list schema node to getter method of + * typeBuilder. + * + * @param typeBuilder + * generated type builder to which is node added as + * getter method + * @param node + * leaf list schema node which is added to + * typeBuilder as getter method + * @return boolean value + *
    + *
  • true - if node, typeBuilder, + * nodeName equal null or node is added by uses
  • + *
  • false - other cases
  • + *
+ */ private boolean resolveLeafListSchemaNode(final GeneratedTypeBuilder typeBuilder, final LeafListSchemaNode node) { if ((node != null) && (typeBuilder != null)) { - final String nodeName = node.getQName().getLocalName(); - String nodeDesc = node.getDescription(); - if (nodeDesc == null) { - nodeDesc = ""; - } + final QName nodeName = node.getQName(); if (nodeName != null && !node.isAddedByUses()) { - final TypeDefinition type = node.getType(); - final Type listType = Types.listTypeFor(typeProvider.javaTypeForSchemaDefinitionType(type)); + final TypeDefinition typeDef = node.getType(); + final Module parentModule = findParentModule(schemaContext, node); + + Type returnType = null; + if (typeDef instanceof EnumTypeDefinition) { + returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, node); + final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) typeDef; + final EnumBuilder enumBuilder = resolveInnerEnumFromTypeDefinition(enumTypeDef, nodeName, + typeBuilder); + returnType = new ReferencedTypeImpl(enumBuilder.getPackageName(), enumBuilder.getName()); + ((TypeProviderImpl) typeProvider).putReferencedType(node.getPath(), returnType); + } else if (typeDef instanceof UnionType) { + final GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(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(); + } else { + final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef); + returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, node, restrictions); + } - constructGetter(typeBuilder, nodeName, nodeDesc, listType); + final ParameterizedType listType = Types.listTypeFor(returnType); + constructGetter(typeBuilder, nodeName.getLocalName(), node.getDescription(), listType); return true; } } return false; } - private boolean resolveContainerSchemaNode(final String basePackageName, final GeneratedTypeBuilder typeBuilder, - final ContainerSchemaNode containerNode) { - if ((containerNode != null) && (typeBuilder != null)) { - final String nodeName = containerNode.getQName().getLocalName(); - - if (nodeName != null && !containerNode.isAddedByUses()) { - final String packageName = packageNameForGeneratedType(basePackageName, containerNode.getPath()); - - final GeneratedTypeBuilder rawGenType = addDefaultInterfaceDefinition(packageName, containerNode); - constructGetter(typeBuilder, nodeName, containerNode.getDescription(), rawGenType); - - return true; - } + private Type createReturnTypeForUnion(final GeneratedTOBuilder genTOBuilder, final TypeDefinition typeDef, + final GeneratedTypeBuilder typeBuilder, final Module parentModule) { + final GeneratedTOBuilderImpl returnType = new GeneratedTOBuilderImpl(genTOBuilder.getPackageName(), + genTOBuilder.getName()); + + returnType.setDescription(typeDef.getDescription()); + returnType.setReference(typeDef.getReference()); + returnType.setSchemaPath(typeDef.getPath().getPathFromRoot()); + returnType.setModuleName(parentModule.getName()); + + genTOBuilder.setTypedef(true); + genTOBuilder.setIsUnion(true); + ((TypeProviderImpl) typeProvider).addUnitsToGenTO(genTOBuilder, typeDef.getUnits()); + + // union builder + final GeneratedTOBuilder unionBuilder = new GeneratedTOBuilderImpl(typeBuilder.getPackageName(), + genTOBuilder.getName() + "Builder"); + unionBuilder.setIsUnionBuilder(true); + final MethodSignatureBuilder method = unionBuilder.addMethod("getDefaultInstance"); + method.setReturnType(returnType); + method.addParameter(Types.STRING, "defaultValue"); + method.setAccessModifier(AccessModifier.PUBLIC); + method.setStatic(true); + + final Set types = ((TypeProviderImpl) typeProvider).getAdditionalTypes().get(parentModule); + if (types == null) { + ((TypeProviderImpl) typeProvider).getAdditionalTypes().put(parentModule, + Sets. newHashSet(unionBuilder.toInstance())); + } else { + types.add(unionBuilder.toInstance()); } - return false; + return returnType.toInstance(); } - private boolean resolveListSchemaNode(final String basePackageName, final GeneratedTypeBuilder typeBuilder, - final ListSchemaNode schemaNode) { - if ((schemaNode != null) && (typeBuilder != null)) { - final String listName = schemaNode.getQName().getLocalName(); - - if (listName != null && !schemaNode.isAddedByUses()) { - final String packageName = packageNameForGeneratedType(basePackageName, schemaNode.getPath()); - final GeneratedTypeBuilder rawGenType = addDefaultInterfaceDefinition(packageName, schemaNode); - constructGetter(typeBuilder, listName, schemaNode.getDescription(), Types.listTypeFor(rawGenType)); - return true; - } - } - return false; + private GeneratedTypeBuilder addDefaultInterfaceDefinition(final String packageName, final SchemaNode schemaNode) { + return addDefaultInterfaceDefinition(packageName, schemaNode, null); } /** - * Method instantiates new Generated Type Builder and sets the implements - * definitions of Data Object and Augmentable. - * + * Instantiates generated type builder with packageName and + * schemaNode. + * + * The new builder always implements + * {@link org.opendaylight.yangtools.yang.binding.DataObject DataObject}.
+ * If schemaNode is instance of GroupingDefinition it also + * implements {@link org.opendaylight.yangtools.yang.binding.Augmentable + * Augmentable}.
+ * If schemaNode is instance of + * {@link org.opendaylight.yangtools.yang.model.api.DataNodeContainer + * DataNodeContainer} it can also implement nodes which are specified in + * uses. + * * @param packageName - * Generated Type Package Name + * string with the name of the package to which + * schemaNode belongs. * @param schemaNode - * Schema Node definition - * @return Generated Type Builder instance for Schema Node definition + * schema node for which is created generated type builder + * @param parent + * parent type (can be null) + * @return generated type builder schemaNode */ - private GeneratedTypeBuilder addDefaultInterfaceDefinition(final String packageName, final SchemaNode schemaNode) { - final GeneratedTypeBuilder builder = addRawInterfaceDefinition(packageName, schemaNode, ""); - builder.addImplementsType(Types.DATA_OBJECT); + private GeneratedTypeBuilder addDefaultInterfaceDefinition(final String packageName, final SchemaNode schemaNode, + final Type parent) { + final GeneratedTypeBuilder it = addRawInterfaceDefinition(packageName, schemaNode, ""); + if (parent == null) { + it.addImplementsType(DATA_OBJECT); + } else { + it.addImplementsType(BindingTypes.childOf(parent)); + } if (!(schemaNode instanceof GroupingDefinition)) { - builder.addImplementsType(Types.augmentableTypeFor(builder)); + it.addImplementsType(augmentable(it)); } if (schemaNode instanceof DataNodeContainer) { - addImplementedInterfaceFromUses((DataNodeContainer) schemaNode, builder); + addImplementedInterfaceFromUses((DataNodeContainer) schemaNode, it); } - return builder; + return it; } /** - * + * Wraps the calling of the same overloaded method. + * * @param packageName + * string with the package name to which returning generated type + * builder belongs * @param schemaNode - * @return + * 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, ""); } + /** + * Returns reference to generated type builder for specified + * schemaNode with packageName. + * + * Firstly the generated type builder is searched in + * {@link BindingGeneratorImpl#genTypeBuilders genTypeBuilders}. If it isn't + * found it is created and added to genTypeBuilders. + * + * @param packageName + * string with the package name to which returning generated type + * builder belongs + * @param schemaNode + * schema node which provide data about the schema node name + * @param prefix + * return type name prefix + * @return generated type builder for schemaNode + * @throws IllegalArgumentException + *
    + *
  • if schemaNode is null
  • + *
  • if packageName is null
  • + *
  • if QName of schema node is null
  • + *
  • if schemaNode name is null
  • + *
+ * + */ private GeneratedTypeBuilder addRawInterfaceDefinition(final String packageName, final SchemaNode schemaNode, final String prefix) { - if (schemaNode == null) { - throw new IllegalArgumentException("Data Schema Node cannot be NULL!"); - } - if (packageName == null) { - throw new IllegalArgumentException("Package Name for Generated Type cannot be NULL!"); - } - if (schemaNode.getQName() == null) { - throw new IllegalArgumentException("QName for Data Schema Node cannot be NULL!"); - } + 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(); - if (schemaNodeName == null) { - throw new IllegalArgumentException("Local Name of QName for Data Schema Node cannot be NULL!"); - } + checkArgument(schemaNodeName != null, "Local Name of QName for Data Schema Node cannot be NULL."); - final String genTypeName; + String genTypeName; if (prefix == null) { - genTypeName = parseToClassName(schemaNodeName); + genTypeName = BindingMapping.getClassName(schemaNodeName); } else { - genTypeName = prefix + parseToClassName(schemaNodeName); + genTypeName = prefix + BindingMapping.getClassName(schemaNodeName); } - final GeneratedTypeBuilder newType = new GeneratedTypeBuilderImpl(packageName, genTypeName); + // FIXME: Validation of name conflict + final GeneratedTypeBuilderImpl newType = new GeneratedTypeBuilderImpl(packageName, genTypeName); + final Module module = findParentModule(schemaContext, schemaNode); + qnameConstant(newType, BindingMapping.QNAME_STATIC_FIELD_NAME, schemaNode.getQName()); + newType.addComment(schemaNode.getDescription()); + newType.setDescription(createDescription(schemaNode, newType.getFullyQualifiedName())); + newType.setReference(schemaNode.getReference()); + newType.setSchemaPath(schemaNode.getPath().getPathFromRoot()); + newType.setModuleName(module.getName()); + if (!genTypeBuilders.containsKey(packageName)) { final Map builders = new HashMap<>(); builders.put(genTypeName, newType); @@ -1496,213 +1723,436 @@ public final class BindingGeneratorImpl implements BindingGenerator { return newType; } - private String getterMethodName(final String methodName) { - final StringBuilder method = new StringBuilder(); - method.append("get"); - method.append(parseToClassName(methodName)); - return method.toString(); - } - - private String setterMethodName(final String methodName) { + /** + * Creates the name of the getter method name from localName. + * + * @param localName + * string with the name of the getter method + * @param returnType + * return type + * @return string with the name of the getter method for + * methodName in JAVA method format + */ + public static String getterMethodName(final String localName, final Type returnType) { final StringBuilder method = new StringBuilder(); - method.append("set"); - method.append(parseToClassName(methodName)); + if (BOOLEAN.equals(returnType)) { + method.append("is"); + } else { + method.append("get"); + } + String name = BindingMapping.toFirstUpper(BindingMapping.getPropertyName(localName)); + method.append(name); return method.toString(); } + /** + * Created a method signature builder as part of + * interfaceBuilder. + * + * The method signature builder is created for the getter method of + * schemaNodeName. Also comment and + * returnType information are added to the builder. + * + * @param interfaceBuilder + * generated type builder for which the getter method should be + * created + * @param schemaNodeName + * string with schema node name. The name will be the part of the + * getter method name. + * @param comment + * string with comment for the getter method + * @param returnType + * type which represents the return type of the getter method + * @return method signature builder which represents the getter method of + * interfaceBuilder + */ private MethodSignatureBuilder constructGetter(final GeneratedTypeBuilder interfaceBuilder, final String schemaNodeName, final String comment, final Type returnType) { - final MethodSignatureBuilder getMethod = interfaceBuilder.addMethod(getterMethodName(schemaNodeName)); - + final MethodSignatureBuilder getMethod = interfaceBuilder + .addMethod(getterMethodName(schemaNodeName, returnType)); getMethod.setComment(comment); getMethod.setReturnType(returnType); - return getMethod; } - private MethodSignatureBuilder constructSetter(final GeneratedTypeBuilder interfaceBuilder, - final String schemaNodeName, final String comment, final Type parameterType) { - final MethodSignatureBuilder setMethod = interfaceBuilder.addMethod(setterMethodName(schemaNodeName)); - - setMethod.setComment(comment); - setMethod.addParameter(parameterType, parseToValidParamName(schemaNodeName)); - setMethod.setReturnType(Types.voidType()); - - return setMethod; - } - - private List listToGenType(final String basePackageName, final ListSchemaNode list) { - if (basePackageName == null) { - throw new IllegalArgumentException("Package Name for Generated Type cannot be NULL!"); - } - if (list == null) { - throw new IllegalArgumentException("List Schema Node cannot be NULL!"); - } - - final String packageName = packageNameForGeneratedType(basePackageName, list.getPath()); - final GeneratedTypeBuilder typeBuilder = resolveListTypeBuilder(packageName, list); - final List listKeys = listKeys(list); - GeneratedTOBuilder genTOBuilder = resolveListKeyTOBuilder(packageName, list, listKeys); - - final Set schemaNodes = list.getChildNodes(); - - for (final DataSchemaNode schemaNode : schemaNodes) { - if (schemaNode.isAugmenting()) { - continue; - } - addSchemaNodeToListBuilders(basePackageName, schemaNode, typeBuilder, genTOBuilder, listKeys); - } - return typeBuildersToGenTypes(typeBuilder, genTOBuilder); - } - + /** + * Adds schemaNode to typeBuilder as getter method + * or to genTOBuilder as property. + * + * @param basePackageName + * string contains the module package name + * @param schemaNode + * data schema node which should be added as getter method to + * typeBuilder or as a property to + * genTOBuilder if is part of the list key + * @param typeBuilder + * generated type builder for the list schema node + * @param genTOBuilder + * generated TO builder for the list keys + * @param listKeys + * list of string which contains names of the list keys + * @param module + * current module + * @throws IllegalArgumentException + *
    + *
  • if schemaNode equals null
  • + *
  • if typeBuilder equals null
  • + *
+ */ private void addSchemaNodeToListBuilders(final String basePackageName, final DataSchemaNode schemaNode, - final GeneratedTypeBuilder typeBuilder, final GeneratedTOBuilder genTOBuilder, final List listKeys) { - if (schemaNode == null) { - throw new IllegalArgumentException("Data Schema Node cannot be NULL!"); - } - - if (typeBuilder == null) { - throw new IllegalArgumentException("Generated Type Builder cannot be NULL!"); - } + final GeneratedTypeBuilder typeBuilder, final GeneratedTOBuilder genTOBuilder, final List listKeys, + final Module module) { + 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; - if (!isPartOfListKey(leaf, listKeys)) { - resolveLeafSchemaNodeAsMethod(typeBuilder, leaf); - } else { - resolveLeafSchemaNodeAsProperty(genTOBuilder, leaf, true); + final String leafName = leaf.getQName().getLocalName(); + final Type type = resolveLeafSchemaNodeAsMethod(typeBuilder, leaf); + if (listKeys.contains(leafName)) { + if (type == null) { + resolveLeafSchemaNodeAsProperty(genTOBuilder, leaf, true, module); + } else { + resolveLeafSchemaNodeAsProperty(genTOBuilder, leaf, type, true); + } + } + } else if (!schemaNode.isAddedByUses()) { + if (schemaNode instanceof LeafListSchemaNode) { + resolveLeafListSchemaNode(typeBuilder, (LeafListSchemaNode) schemaNode); + } else if (schemaNode instanceof ContainerSchemaNode) { + containerToGenType(module, basePackageName, typeBuilder, typeBuilder, (ContainerSchemaNode) schemaNode); + } else if (schemaNode instanceof ChoiceNode) { + choiceToGeneratedType(module, basePackageName, typeBuilder, (ChoiceNode) schemaNode); + } else if (schemaNode instanceof ListSchemaNode) { + listToGenType(module, basePackageName, typeBuilder, typeBuilder, (ListSchemaNode) schemaNode); } - } else if (schemaNode instanceof LeafListSchemaNode) { - resolveLeafListSchemaNode(typeBuilder, (LeafListSchemaNode) schemaNode); - } else if (schemaNode instanceof ContainerSchemaNode) { - resolveContainerSchemaNode(basePackageName, typeBuilder, (ContainerSchemaNode) schemaNode); - } else if (schemaNode instanceof ListSchemaNode) { - resolveListSchemaNode(basePackageName, typeBuilder, (ListSchemaNode) schemaNode); } } - private List typeBuildersToGenTypes(final GeneratedTypeBuilder typeBuilder, GeneratedTOBuilder genTOBuilder) { - final List genTypes = new ArrayList<>(); - if (typeBuilder == null) { - throw new IllegalArgumentException("Generated Type Builder cannot be NULL!"); - } + private void typeBuildersToGenTypes(final Module module, final GeneratedTypeBuilder typeBuilder, + final GeneratedTOBuilder genTOBuilder) { + checkArgument(typeBuilder != null, "Generated Type Builder cannot be NULL."); if (genTOBuilder != null) { - final GeneratedTransferObject genTO = genTOBuilder.toInstance(); - constructGetter(typeBuilder, genTO.getName(), "Returns Primary Key of Yang List Type", genTO); - genTypes.add(genTO); + GeneratedTransferObject genTO = genTOBuilder.toInstance(); + constructGetter(typeBuilder, "key", "Returns Primary Key of Yang List Type", genTO); + genCtx.get(module).addGeneratedTOBuilder(genTOBuilder); } - genTypes.add(typeBuilder.toInstance()); - return genTypes; } /** + * Selects the names of the list keys from list and returns + * them as the list of the strings + * * @param list - * @return + * of string with names of the list keys + * @return list of string which represents names of the list keys. If the + * list contains no keys then the empty list is + * returned. */ - private GeneratedTOBuilder resolveListKey(final String packageName, final ListSchemaNode list) { - final String listName = list.getQName().getLocalName() + "Key"; - return schemaNodeToTransferObjectBuilder(packageName, list, listName); - } - - private boolean isPartOfListKey(final LeafSchemaNode leaf, final List keys) { - if ((leaf != null) && (keys != null) && (leaf.getQName() != null)) { - final String leafName = leaf.getQName().getLocalName(); - if (keys.contains(leafName)) { - return true; - } - } - return false; - } - private List listKeys(final ListSchemaNode list) { final List listKeys = new ArrayList<>(); - if (list.getKeyDefinition() != null) { - final List keyDefinitions = list.getKeyDefinition(); - - for (final QName keyDefinition : keyDefinitions) { - listKeys.add(keyDefinition.getLocalName()); + List keyDefinition = list.getKeyDefinition(); + if (keyDefinition != null) { + for (QName keyDef : keyDefinition) { + listKeys.add(keyDef.getLocalName()); } } return listKeys; } - private GeneratedTypeBuilder resolveListTypeBuilder(final String packageName, final ListSchemaNode list) { - if (packageName == null) { - throw new IllegalArgumentException("Package Name for Generated Type cannot be NULL!"); - } - if (list == null) { - throw new IllegalArgumentException("List Schema Node cannot be NULL!"); - } - - final String schemaNodeName = list.getQName().getLocalName(); - final String genTypeName = parseToClassName(schemaNodeName); - - GeneratedTypeBuilder typeBuilder = null; - final Map builders = genTypeBuilders.get(packageName); - if (builders != null) { - typeBuilder = builders.get(genTypeName); - } - if (typeBuilder == null) { - typeBuilder = addDefaultInterfaceDefinition(packageName, list); - } - return typeBuilder; - } - - private GeneratedTOBuilder resolveListKeyTOBuilder(final String packageName, final ListSchemaNode list, - final List 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 String packageName, final ListSchemaNode list) { GeneratedTOBuilder genTOBuilder = null; - if (listKeys.size() > 0) { - genTOBuilder = resolveListKey(packageName, list); + if ((list.getKeyDefinition() != null) && (!list.getKeyDefinition().isEmpty())) { + final String listName = list.getQName().getLocalName() + "Key"; + final String genTOName = BindingMapping.getClassName(listName); + genTOBuilder = new GeneratedTOBuilderImpl(packageName, genTOName); } return genTOBuilder; } - private GeneratedTOBuilder addEnclosedTOToTypeBuilder(TypeDefinition typeDef, GeneratedTypeBuilder typeBuilder, - String leafName) { - String className = parseToClassName(leafName); - GeneratedTOBuilder genTOBuilder = null; - if (typeDef instanceof UnionType) { - genTOBuilder = ((TypeProviderImpl) typeProvider).addUnionGeneratedTypeDefinition( - typeBuilder.getFullyQualifiedName(), typeDef, className); + /** + * Builds generated TO builders for typeDef of type + * {@link org.opendaylight.yangtools.yang.model.util.UnionType UnionType} or + * {@link org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition + * BitsTypeDefinition} which are also added to typeBuilder as + * enclosing transfer object. + * + * 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 leafName + * string with name for generated TO builder + * @param leaf + * @return generated TO builder for typeDef + */ + private GeneratedTOBuilder addTOToTypeBuilder(final TypeDefinition 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 = ((TypeProviderImpl) typeProvider) + .provideGeneratedTOBuildersForUnionTypeDef(packageName, ((UnionTypeDefinition) typeDef), + classNameFromLeaf, leaf); + genTOBuilders.addAll(types); + + GeneratedTOBuilder resultTOBuilder = null; + if (!types.isEmpty()) { + resultTOBuilder = types.remove(0); + for (GeneratedTOBuilder genTOBuilder : types) { + resultTOBuilder.addEnclosingTransferObject(genTOBuilder); + } + } + + final GeneratedPropertyBuilder genPropBuilder = resultTOBuilder.addProperty("value"); + genPropBuilder.setReturnType(Types.primitiveType("char[]", null)); + resultTOBuilder.addEqualsIdentity(genPropBuilder); + resultTOBuilder.addHashIdentity(genPropBuilder); + resultTOBuilder.addToStringProperty(genPropBuilder); + } else if (typeDef instanceof BitsTypeDefinition) { - genTOBuilder = ((TypeProviderImpl) typeProvider).bitsTypedefToTransferObject( - typeBuilder.getFullyQualifiedName(), typeDef, className); + genTOBuilders.add((((TypeProviderImpl) typeProvider)).provideGeneratedTOBuilderForBitsTypeDefinition( + packageName, typeDef, classNameFromLeaf, parentModule.getName())); } - if (genTOBuilder != null) { - typeBuilder.addEnclosingTransferObject(genTOBuilder); - return genTOBuilder; + if (genTOBuilders != null && !genTOBuilders.isEmpty()) { + for (GeneratedTOBuilder genTOBuilder : genTOBuilders) { + typeBuilder.addEnclosingTransferObject(genTOBuilder); + } + return genTOBuilders.get(0); } return null; } /** - * Adds the implemented types to type builder. The method passes through the - * list of elements which contains {@code dataNodeContainer} and adds them - * as implements type to builder - * + * Adds the implemented types to type builder. + * + * The method passes through the list of uses in + * {@code dataNodeContainer}. For every use is obtained corresponding + * generated type from {@link BindingGeneratorImpl#allGroupings + * allGroupings} which is added as implements type to + * builder + * * @param dataNodeContainer * element which contains the list of used YANG groupings * @param builder * builder to which are added implemented types according to * dataNodeContainer - * @return generated type builder which contains implemented types + * @return generated type builder with all implemented types */ private GeneratedTypeBuilder addImplementedInterfaceFromUses(final DataNodeContainer dataNodeContainer, final GeneratedTypeBuilder builder) { for (UsesNode usesNode : dataNodeContainer.getUses()) { if (usesNode.getGroupingPath() != null) { - GeneratedType genType = allGroupings.get(usesNode.getGroupingPath()); + final GeneratedType genType = findGroupingByPath(usesNode.getGroupingPath()).toInstance(); if (genType == null) { throw new IllegalStateException("Grouping " + usesNode.getGroupingPath() + "is not resolved for " + builder.getName()); } + builder.addImplementsType(genType); + /* + builder.addComment(genType.getDescription()); + builder.setDescription(genType.getDescription()); + builder.setModuleName(genType.getModuleName()); + builder.setReference(genType.getReference()); + builder.setSchemaPath(genType.getSchemaPath()); + */ } } return builder; } + private boolean isNullOrEmpty(final Collection list) { + return (list == null || list.isEmpty() ? true : false); + } + + private String createDescription(final Set schemaNodes, final String moduleName, final String moduleSourcePath) { + final StringBuilder sb = new StringBuilder(); + + if (!isNullOrEmpty(schemaNodes)) { + final SchemaNode node = schemaNodes.iterator().next(); + + if (node instanceof RpcDefinition) { + sb.append("Interface for implementing the following YANG RPCs defined in module " + moduleName + ""); + } else if (node instanceof NotificationDefinition) { + sb.append("Interface for receiving the following YANG notifications defined in module " + moduleName + ""); + } + } + sb.append(NEW_LINE); + sb.append("
(Source path: "); + sb.append(moduleSourcePath); + sb.append("):"); + sb.append(NEW_LINE); + + if (verboseClassComments) { + sb.append("
");
+            sb.append(NEW_LINE);
+            sb.append(YangTemplate.generateYangSnipet(schemaNodes));
+            sb.append("
"); + sb.append(NEW_LINE); + } + + return sb.toString(); + } + + private String createDescription(final SchemaNode schemaNode, final String fullyQualifiedName) { + final StringBuilder sb = new StringBuilder(); + final String formattedDescription = YangTemplate.formatToParagraph(schemaNode.getDescription(), 0); + + if (!isNullOrEmpty(formattedDescription)) { + sb.append(formattedDescription); + sb.append(NEW_LINE); + } + + if (verboseClassComments) { + final Module module = findParentModule(schemaContext, schemaNode); + final StringBuilder linkToBuilderClass = new StringBuilder(); + final StringBuilder linkToKeyClass = new StringBuilder(); + final String[] namespace = Iterables.toArray(BSDOT_SPLITTER.split(fullyQualifiedName), String.class); + String className = namespace[namespace.length - 1]; + + if (hasBuilderClass(schemaNode)) { + linkToBuilderClass.append(className); + linkToBuilderClass.append("Builder"); + + if (schemaNode instanceof ListSchemaNode) { + linkToKeyClass.append(className); + linkToKeyClass.append("Key"); + } + } + + sb.append("

"); + sb.append("This class represents the following YANG schema fragment defined in module "); + sb.append(module.getName()); + sb.append(""); + sb.append(NEW_LINE); + sb.append("
(Source path: "); + sb.append(module.getModuleSourcePath()); + sb.append("):"); + sb.append(NEW_LINE); + sb.append("

");
+            sb.append(NEW_LINE);
+            sb.append(YangTemplate.generateYangSnipet(schemaNode));
+            sb.append("
"); + sb.append(NEW_LINE); + sb.append("The schema path to identify an instance is"); + sb.append(NEW_LINE); + sb.append(""); + sb.append(YangTemplate.formatSchemaPath(module.getName(), schemaNode.getPath().getPathFromRoot())); + sb.append(""); + sb.append(NEW_LINE); + + if (hasBuilderClass(schemaNode)) { + sb.append(NEW_LINE); + sb.append("

To create instances of this class use " + "{@link " + linkToBuilderClass + "}."); + sb.append(NEW_LINE); + sb.append("@see "); + sb.append(linkToBuilderClass); + if (schemaNode instanceof ListSchemaNode) { + sb.append("@see "); + sb.append(linkToKeyClass); + } + sb.append(NEW_LINE); + } + } + + return sb.toString(); + } + + private boolean hasBuilderClass(final SchemaNode schemaNode) { + if (schemaNode instanceof ContainerSchemaNode || schemaNode instanceof ListSchemaNode || + schemaNode instanceof RpcDefinition || schemaNode instanceof NotificationDefinition) { + return true; + } + return false; + } + + private boolean isNullOrEmpty(final String string) { + return (string == null || string.isEmpty() ? true : false); + } + + private String createDescription(final Module module) { + final StringBuilder sb = new StringBuilder(); + final String formattedDescription = YangTemplate.formatToParagraph(module.getDescription(), 0); + + if (!isNullOrEmpty(formattedDescription)) { + sb.append(formattedDescription); + sb.append(NEW_LINE); + } + + if (verboseClassComments) { + sb.append("

"); + sb.append("This class represents the following YANG schema fragment defined in module "); + sb.append(module.getName()); + sb.append(""); + sb.append(NEW_LINE); + sb.append("
Source path: "); + sb.append(module.getModuleSourcePath()); + sb.append("):"); + sb.append(NEW_LINE); + sb.append("

");
+            sb.append(NEW_LINE);
+            sb.append(YangTemplate.generateYangSnipet(module));
+            sb.append("
"); + } + + return sb.toString(); + } + + private GeneratedTypeBuilder findChildNodeByPath(final SchemaPath path) { + for (ModuleContext ctx : genCtx.values()) { + GeneratedTypeBuilder result = ctx.getChildNode(path); + if (result != null) { + return result; + } + } + return null; + } + + private GeneratedTypeBuilder findGroupingByPath(final SchemaPath path) { + for (ModuleContext ctx : genCtx.values()) { + GeneratedTypeBuilder result = ctx.getGrouping(path); + if (result != null) { + return result; + } + } + return null; + } + + private GeneratedTypeBuilder findCaseByPath(final SchemaPath path) { + for (ModuleContext ctx : genCtx.values()) { + GeneratedTypeBuilder result = ctx.getCase(path); + if (result != null) { + return result; + } + } + return null; + } + + public Map getModuleContexts() { + return genCtx; + } + }