/* * Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.mdsal.binding.javav2.generator.impl; import static com.google.common.base.Preconditions.checkArgument; import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.addTOToTypeBuilder; import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.annotateDeprecatedIfNecessary; import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.augGenTypeName; import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.constructGetter; import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.createDescription; import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.createReturnTypeForUnion; import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.getAugmentIdentifier; import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.isInnerType; import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.qNameConstant; import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.resolveInnerEnumFromTypeDefinition; import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.resolveListKeyTOBuilder; import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingGeneratorUtil.computeDefaultSUID; import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingGeneratorUtil.encodeAngleBrackets; import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingGeneratorUtil.packageNameForGeneratedType; import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingTypes.INSTANTIABLE; import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingTypes.NOTIFICATION; import static org.opendaylight.mdsal.binding.javav2.generator.util.Types.parameterizedTypeFor; import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataSchemaNode; import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findParentModule; import com.google.common.annotations.Beta; import com.google.common.base.Preconditions; import com.google.common.collect.Iterables; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import org.opendaylight.mdsal.binding.javav2.generator.spi.TypeProvider; import org.opendaylight.mdsal.binding.javav2.generator.util.BindingGeneratorUtil; import org.opendaylight.mdsal.binding.javav2.generator.util.BindingTypes; import org.opendaylight.mdsal.binding.javav2.generator.util.JavaIdentifier; import org.opendaylight.mdsal.binding.javav2.generator.util.JavaIdentifierNormalizer; import org.opendaylight.mdsal.binding.javav2.generator.util.ReferencedTypeImpl; import org.opendaylight.mdsal.binding.javav2.generator.util.Types; import org.opendaylight.mdsal.binding.javav2.generator.util.generated.type.builder.GeneratedPropertyBuilderImpl; import org.opendaylight.mdsal.binding.javav2.generator.util.generated.type.builder.GeneratedTOBuilderImpl; import org.opendaylight.mdsal.binding.javav2.generator.util.generated.type.builder.GeneratedTypeBuilderImpl; import org.opendaylight.mdsal.binding.javav2.generator.yang.types.GroupingDefinitionDependencySort; import org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeProviderImpl; import org.opendaylight.mdsal.binding.javav2.model.api.AccessModifier; import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedTransferObject; import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedType; import org.opendaylight.mdsal.binding.javav2.model.api.ParameterizedType; import org.opendaylight.mdsal.binding.javav2.model.api.Restrictions; import org.opendaylight.mdsal.binding.javav2.model.api.Type; import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.EnumBuilder; import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.GeneratedPropertyBuilder; import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.GeneratedTOBuilder; import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.GeneratedTypeBuilder; import org.opendaylight.mdsal.binding.javav2.spec.base.BaseIdentity; import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode; import org.opendaylight.mdsal.binding.javav2.spec.runtime.BindingNamespaceType; import org.opendaylight.mdsal.binding.javav2.spec.structural.Augmentable; import org.opendaylight.mdsal.binding.javav2.util.BindingMapping; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.model.api.AnyDataSchemaNode; import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode; import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode; import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode; 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.NotificationDefinition; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.model.api.SchemaNode; import org.opendaylight.yangtools.yang.model.api.SchemaPath; import org.opendaylight.yangtools.yang.model.api.Status; import org.opendaylight.yangtools.yang.model.api.TypeDefinition; import org.opendaylight.yangtools.yang.model.api.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.UnionTypeDefinition; import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil; import org.opendaylight.yangtools.yang.model.util.SchemaNodeUtils; /** * Helper util class used for generation of types in Binding spec v2. */ @Beta final class GenHelperUtil { private GenHelperUtil() { throw new UnsupportedOperationException("Util class"); } /** * Create GeneratedTypeBuilder object from module argument. * * @param module * Module object from which builder will be created * @param genCtx * @param verboseClassComments * * @return GeneratedTypeBuilder which is internal * representation of the module * @throws IllegalArgumentException * if module is null */ static GeneratedTypeBuilder moduleToDataType(final Module module, final Map genCtx, final boolean verboseClassComments) { Preconditions.checkArgument(module != null, "Module reference cannot be NULL."); final GeneratedTypeBuilder moduleDataTypeBuilder = moduleTypeBuilder(module, "Data", verboseClassComments); addImplementedInterfaceFromUses(module, moduleDataTypeBuilder, genCtx); moduleDataTypeBuilder.addImplementsType(BindingTypes.TREE_ROOT); moduleDataTypeBuilder.addComment(module.getDescription()); moduleDataTypeBuilder.setDescription(createDescription(module, verboseClassComments)); moduleDataTypeBuilder.setReference(module.getReference()); return moduleDataTypeBuilder; } /** * Generates type builder for module. * * @param module * Module which is source of package name for generated type * builder * @param postfix * string which is added to the module class name representation * as suffix * @param verboseClassComments * @return instance of GeneratedTypeBuilder which represents * module. * @throws IllegalArgumentException * if module is null */ static GeneratedTypeBuilder moduleTypeBuilder(final Module module, final String postfix, final boolean verboseClassComments) { Preconditions.checkArgument(module != null, "Module reference cannot be NULL."); final String packageName = BindingMapping.getRootPackageName(module); // underscore used as separator for distinction of module name parts final String moduleName = new StringBuilder(module.getName()).append('_').append(postfix).toString(); final GeneratedTypeBuilderImpl moduleBuilder = new GeneratedTypeBuilderImpl(packageName, moduleName); moduleBuilder.setDescription(createDescription(module, verboseClassComments)); moduleBuilder.setReference(module.getReference()); moduleBuilder.setModuleName(moduleName); return moduleBuilder; } /** * 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 all groupings * 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 * @param genCtx generated context * @return generated type builder with all implemented types */ static GeneratedTypeBuilder addImplementedInterfaceFromUses(final DataNodeContainer dataNodeContainer, final GeneratedTypeBuilder builder, final Map genCtx) { for (final UsesNode usesNode : dataNodeContainer.getUses()) { final GeneratedType genType = findGroupingByPath(usesNode.getGroupingPath(), genCtx).toInstance(); if (genType == null) { throw new IllegalStateException("Grouping " + usesNode.getGroupingPath() + "is not resolved for " + builder.getName()); } builder.addImplementsType(genType); } return builder; } static GeneratedTypeBuilder findGroupingByPath(final SchemaPath path, final Map genCtx) { for (final ModuleContext ctx : genCtx.values()) { final GeneratedTypeBuilder result = ctx.getGrouping(path); if (result != null) { return result; } } return null; } /** * 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 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. */ static GeneratedTypeBuilder resolveDataSchemaNodes(final Module module, final String basePackageName, final GeneratedTypeBuilder parent, final GeneratedTypeBuilder childOf, final Iterable schemaNodes, final Map genCtx, final SchemaContext schemaContext, final boolean verboseClassComments, final Map> genTypeBuilders, final TypeProvider typeProvider) { if (schemaNodes != null && parent != null) { for (final DataSchemaNode schemaNode : schemaNodes) { if (!schemaNode.isAugmenting() && !schemaNode.isAddedByUses()) { addSchemaNodeToBuilderAsMethod(basePackageName, schemaNode, parent, childOf, module, genCtx, schemaContext, verboseClassComments, genTypeBuilders, typeProvider); } } } return parent; } static GeneratedTypeBuilder addDefaultInterfaceDefinition(final String packageName, final SchemaNode schemaNode, final Module module, final Map genCtx, final SchemaContext schemaContext, final boolean verboseClassComments, final Map> genTypeBuilders, final TypeProvider typeProvider) { return addDefaultInterfaceDefinition(packageName, schemaNode, null, module, genCtx, schemaContext, verboseClassComments, genTypeBuilders, typeProvider); } static Map processUsesAugments(final SchemaContext schemaContext, final DataNodeContainer node, final Module module, Map genCtx, final Map> genTypeBuilders, final boolean verboseClassComments, final TypeProvider typeProvider) { final String basePackageName = BindingMapping.getRootPackageName(module); for (final UsesNode usesNode : node.getUses()) { Map> augmentationsGrouped = usesNode.getAugmentations().stream().collect(Collectors.groupingBy(AugmentationSchema::getTargetPath)); for (Map.Entry> schemaPathAugmentListEntry : augmentationsGrouped.entrySet()) { genCtx = AugmentToGenType.usesAugmentationToGenTypes(schemaContext, basePackageName, schemaPathAugmentListEntry.getValue(), module, usesNode, node, genCtx, genTypeBuilders, verboseClassComments, typeProvider); for (AugmentationSchema augSchema : schemaPathAugmentListEntry.getValue()) { genCtx = processUsesAugments(schemaContext, augSchema, module, genCtx, genTypeBuilders, verboseClassComments, typeProvider); } } } return genCtx; } static GeneratedTypeBuilder findChildNodeByPath(final SchemaPath path, final Map genCtx) { for (final ModuleContext ctx : genCtx.values()) { final GeneratedTypeBuilder result = ctx.getChildNode(path); if (result != null) { return result; } } return null; } static GeneratedTypeBuilder findCaseByPath(final SchemaPath path, final Map genCtx) { for (final ModuleContext ctx : genCtx.values()) { final GeneratedTypeBuilder result = ctx.getCase(path); if (result != null) { return result; } } return null; } static Map addRawAugmentGenTypeDefinition(final Module module, final String augmentPackageName, final Type targetTypeRef, final List schemaPathAugmentListEntry, final Map> genTypeBuilders, final Map genCtx, final SchemaContext schemaContext, final boolean verboseClassComments, final TypeProvider typeProvider) { //pick augmentation grouped by augmentation target, there is always at least one final AugmentationSchema augSchema = schemaPathAugmentListEntry.get(0); Map augmentBuilders = genTypeBuilders.computeIfAbsent( augmentPackageName, k -> new HashMap<>()); //this requires valid semantics in YANG model String augIdentifier = null; for (AugmentationSchema aug : schemaPathAugmentListEntry) { augIdentifier = getAugmentIdentifier(aug.getUnknownSchemaNodes()); break; } if (augIdentifier == null) { augIdentifier = augGenTypeName(augmentBuilders, targetTypeRef.getName()); } GeneratedTypeBuilder augTypeBuilder = new GeneratedTypeBuilderImpl(augmentPackageName, augIdentifier, false, true); augTypeBuilder.addImplementsType(BindingTypes.TREE_NODE); augTypeBuilder.addImplementsType(parameterizedTypeFor(BindingTypes.INSTANTIABLE, augTypeBuilder)); augTypeBuilder.addImplementsType(Types.augmentationTypeFor(targetTypeRef)); annotateDeprecatedIfNecessary(augSchema.getStatus(), augTypeBuilder); //produces getters for augTypeBuilder eventually for (AugmentationSchema aug : schemaPathAugmentListEntry) { //apply all uses addImplementedInterfaceFromUses(aug, augTypeBuilder, genCtx); augSchemaNodeToMethods(module, BindingMapping.getRootPackageName(module), augTypeBuilder, augTypeBuilder, aug.getChildNodes(), genCtx, schemaContext, verboseClassComments, typeProvider, genTypeBuilders); } augmentBuilders.put(augTypeBuilder.getName(), augTypeBuilder); if(!augSchema.getChildNodes().isEmpty()) { genCtx.get(module).addTypeToAugmentation(augTypeBuilder, augSchema); genCtx.get(module).addTargetToAugmentation(augTypeBuilder, augSchema.getTargetPath()); } genCtx.get(module).addAugmentType(augTypeBuilder); return genCtx; } //TODO: delete this method eventually when uses-augments & augmented choice cases are implemented /** * 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 basePackageName * string with the package name to which the augmented node * belongs * @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 in genCtx */ @Deprecated static Map addRawAugmentGenTypeDefinition(final Module module, final String augmentPackageName, final String basePackageName, final Type targetTypeRef, final AugmentationSchema augSchema, final Map> genTypeBuilders, final Map genCtx, final SchemaContext schemaContext, final boolean verboseClassComments, final TypeProvider typeProvider) { Map augmentBuilders = genTypeBuilders.computeIfAbsent(augmentPackageName, k -> new HashMap<>()); String augIdentifier = getAugmentIdentifier(augSchema.getUnknownSchemaNodes()); if (augIdentifier == null) { augIdentifier = augGenTypeName(augmentBuilders, targetTypeRef.getName()); } GeneratedTypeBuilder augTypeBuilder = new GeneratedTypeBuilderImpl(augmentPackageName, augIdentifier); augTypeBuilder.addImplementsType(BindingTypes.TREE_NODE); augTypeBuilder.addImplementsType(parameterizedTypeFor(BindingTypes.INSTANTIABLE, augTypeBuilder)); augTypeBuilder.addImplementsType(Types.augmentationTypeFor(targetTypeRef)); annotateDeprecatedIfNecessary(augSchema.getStatus(), augTypeBuilder); augTypeBuilder = addImplementedInterfaceFromUses(augSchema, augTypeBuilder, genCtx); augTypeBuilder = augSchemaNodeToMethods(module, basePackageName, augTypeBuilder, augTypeBuilder, augSchema .getChildNodes(), genCtx, schemaContext, verboseClassComments, typeProvider, genTypeBuilders); augmentBuilders.put(augTypeBuilder.getName(), augTypeBuilder); if(!augSchema.getChildNodes().isEmpty()) { genCtx.get(module).addTypeToAugmentation(augTypeBuilder, augSchema); } genCtx.get(module).addAugmentType(augTypeBuilder); return genCtx; } /** * 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 * 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 static GeneratedTypeBuilder augSchemaNodeToMethods(final Module module, final String basePackageName, final GeneratedTypeBuilder typeBuilder, final GeneratedTypeBuilder childOf, final Iterable schemaNodes, final Map genCtx, final SchemaContext schemaContext, final boolean verboseClassComments, final TypeProvider typeProvider, final Map> genTypeBuilders) { if (schemaNodes != null && typeBuilder != null) { for (final DataSchemaNode schemaNode : schemaNodes) { if (!schemaNode.isAugmenting()) { addSchemaNodeToBuilderAsMethod(basePackageName, schemaNode, typeBuilder, childOf, module, genCtx, schemaContext, verboseClassComments, genTypeBuilders, typeProvider); } } } return typeBuilder; } /** * Instantiates generated type builder with packageName and * schemaNode. * * The new builder always implements * {@link TreeNode TreeNode}.
* If schemaNode is instance of GroupingDefinition it also * implements {@link 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 * string with the name of the package to which * schemaNode belongs. * @param schemaNode * schema node for which is created generated type builder * @param parent * parent type (can be null) * @param schemaContext schema context * @return generated type builder schemaNode */ private static GeneratedTypeBuilder addDefaultInterfaceDefinition(final String packageName, final SchemaNode schemaNode, final Type parent, final Module module, final Map genCtx, final SchemaContext schemaContext, final boolean verboseClassComments, final Map> genTypeBuilders, final TypeProvider typeProvider) { GeneratedTypeBuilder it = addRawInterfaceDefinition(packageName, schemaNode, schemaContext, "", verboseClassComments, genTypeBuilders); if (parent == null) { it.addImplementsType(BindingTypes.TREE_NODE); } else { if (parent instanceof ListSchemaNode) { it.addImplementsType(parameterizedTypeFor(BindingTypes.TREE_CHILD_NODE, parent, parameterizedTypeFor (BindingTypes.IDENTIFIABLE_ITEM, parent))); } else { it.addImplementsType(parameterizedTypeFor(BindingTypes.TREE_CHILD_NODE, parent, parameterizedTypeFor (BindingTypes.ITEM, parent))); it.addImplementsType(parameterizedTypeFor(BindingTypes.INSTANTIABLE, it)); } } if (!(schemaNode instanceof GroupingDefinition)) { it.addImplementsType(BindingTypes.augmentable(it)); } if (schemaNode instanceof DataNodeContainer) { groupingsToGenTypes(module, ((DataNodeContainer) schemaNode).getGroupings(), genCtx, schemaContext, verboseClassComments, genTypeBuilders, typeProvider); it = addImplementedInterfaceFromUses((DataNodeContainer) schemaNode, it, genCtx); } return it; } static GeneratedTypeBuilder resolveNotification(final GeneratedTypeBuilder listenerInterface, String parentName, final String basePackageName, final NotificationDefinition notification, final Module module, final SchemaContext schemaContext, final boolean verboseClassComments, Map> genTypeBuilders, TypeProvider typeProvider, Map genCtx) { processUsesAugments(schemaContext, notification, module, genCtx, genTypeBuilders, verboseClassComments, typeProvider); final GeneratedTypeBuilder notificationInterface = addDefaultInterfaceDefinition (basePackageName, notification, null, module, genCtx, schemaContext, verboseClassComments, genTypeBuilders, typeProvider); annotateDeprecatedIfNecessary(notification.getStatus(), notificationInterface); notificationInterface.addImplementsType(NOTIFICATION); genCtx.get(module).addChildNodeType(notification, notificationInterface); // Notification object resolveDataSchemaNodes(module, basePackageName, notificationInterface, notificationInterface, notification.getChildNodes(), genCtx, schemaContext, verboseClassComments, genTypeBuilders, typeProvider); //in case of tied notification, incorporate parent's localName final StringBuilder sb = new StringBuilder("on_"); if (parentName != null) { sb.append(parentName).append('_'); } sb.append(notificationInterface.getName()); listenerInterface.addMethod(JavaIdentifierNormalizer.normalizeSpecificIdentifier(sb.toString(), JavaIdentifier.METHOD)) .setAccessModifier(AccessModifier.PUBLIC).addParameter(notificationInterface, "notification") .setComment(encodeAngleBrackets(notification.getDescription())).setReturnType(Types.VOID); return listenerInterface; } /** * 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 schemaContext schema context * @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
  • *
* */ static GeneratedTypeBuilder addRawInterfaceDefinition(final String packageName, final SchemaNode schemaNode, final SchemaContext schemaContext, final String prefix, final boolean verboseClassComments, final Map> genTypeBuilders) { Preconditions.checkArgument(schemaNode != null, "Data Schema Node cannot be NULL."); Preconditions.checkArgument(packageName != null, "Package Name for Generated Type cannot be NULL."); String schemaNodeName = schemaNode.getQName().getLocalName(); Preconditions.checkArgument(schemaNodeName != null, "Local Name of QName for Data Schema Node cannot be NULL."); if (prefix != null && !prefix.isEmpty()) { // underscore used as separator for distinction of class name parts schemaNodeName = new StringBuilder(prefix).append('_').append(schemaNodeName).toString(); } final GeneratedTypeBuilderImpl newType = new GeneratedTypeBuilderImpl(packageName, schemaNodeName); final Module module = SchemaContextUtil.findParentModule(schemaContext, schemaNode); qNameConstant(newType, BindingMapping.QNAME_STATIC_FIELD_NAME, schemaNode.getQName()); newType.addComment(schemaNode.getDescription()); newType.setDescription(createDescription(schemaNode, newType.getFullyQualifiedName(), schemaContext, verboseClassComments)); newType.setReference(schemaNode.getReference()); newType.setSchemaPath((List) schemaNode.getPath().getPathFromRoot()); newType.setModuleName(module.getName()); if (!genTypeBuilders.containsKey(packageName)) { final Map builders = new HashMap<>(); builders.put(newType.getName(), newType); genTypeBuilders.put(packageName, builders); } else { final Map builders = genTypeBuilders.get(packageName); if (!builders.containsKey(newType.getName())) { builders.put(newType.getName(), newType); } } return newType; } private static void addSchemaNodeToBuilderAsMethod(final String basePackageName, final DataSchemaNode node, final GeneratedTypeBuilder typeBuilder, final GeneratedTypeBuilder childOf, final Module module, final Map genCtx, final SchemaContext schemaContext, final boolean verboseClassComments, final Map> genTypeBuilders, final TypeProvider typeProvider) { if (node != null && typeBuilder != null) { if (node instanceof ContainerSchemaNode) { containerToGenType(module, basePackageName, typeBuilder, childOf, (ContainerSchemaNode) node, schemaContext, verboseClassComments, genCtx, genTypeBuilders, typeProvider); } else if (node instanceof LeafListSchemaNode) { resolveLeafListSchemaNode(schemaContext, typeBuilder, (LeafListSchemaNode) node, module, typeProvider, genCtx); } else if (node instanceof LeafSchemaNode) { resolveLeafSchemaNodeAsMethod("", schemaContext, typeBuilder, genCtx, (LeafSchemaNode) node, module, typeProvider); } else if (node instanceof ListSchemaNode) { listToGenType(module, basePackageName, typeBuilder, childOf, (ListSchemaNode) node, schemaContext, verboseClassComments, genCtx, genTypeBuilders, typeProvider); } else if (node instanceof ChoiceSchemaNode) { choiceToGenType(module, schemaContext, verboseClassComments, basePackageName, childOf, (ChoiceSchemaNode) node, genTypeBuilders, genCtx, typeProvider); } else if (node instanceof AnyXmlSchemaNode || node instanceof AnyDataSchemaNode) { resolveAnyNodeAsMethod(schemaContext, typeBuilder, genCtx, node, module, typeProvider); } } } /** * 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 static void choiceToGenType(final Module module, final SchemaContext schemaContext, final boolean verboseClasssComments, final String basePackageName, final GeneratedTypeBuilder parent, final ChoiceSchemaNode choiceNode, final Map> genTypeBuilders, final Map genCtx, final TypeProvider typeProvider) { checkArgument(basePackageName != null, "Base Package Name cannot be NULL."); checkArgument(choiceNode != null, "Choice Schema Node cannot be NULL."); if (!choiceNode.isAddedByUses()) { final String packageName = packageNameForGeneratedType(basePackageName, choiceNode.getPath(), BindingNamespaceType.Data); final GeneratedTypeBuilder choiceTypeBuilder = addRawInterfaceDefinition(packageName, choiceNode, schemaContext, "", verboseClasssComments, genTypeBuilders); constructGetter(parent, choiceNode.getQName().getLocalName(), choiceNode.getDescription(), choiceTypeBuilder, choiceNode.getStatus()); choiceTypeBuilder.addImplementsType(parameterizedTypeFor(BindingTypes.INSTANTIABLE, choiceTypeBuilder)); annotateDeprecatedIfNecessary(choiceNode.getStatus(), choiceTypeBuilder); genCtx.get(module).addChildNodeType(choiceNode, choiceTypeBuilder); generateTypesFromChoiceCases(module, schemaContext, genCtx, basePackageName, choiceTypeBuilder.toInstance(), choiceNode, verboseClasssComments, typeProvider, genTypeBuilders); } } private static void containerToGenType(final Module module, final String basePackageName, final GeneratedTypeBuilder parent, final GeneratedTypeBuilder childOf, final ContainerSchemaNode node, final SchemaContext schemaContext, final boolean verboseClassComments, final Map genCtx, final Map> genTypeBuilders, final TypeProvider typeProvider) { final GeneratedTypeBuilder genType = processDataSchemaNode(module, basePackageName, childOf, node, schemaContext, verboseClassComments, genCtx, genTypeBuilders, typeProvider); if (genType != null) { constructGetter(parent, node.getQName().getLocalName(), node.getDescription(), genType, node.getStatus()); resolveDataSchemaNodes(module, basePackageName, genType, genType, node.getChildNodes(), genCtx, schemaContext, verboseClassComments, genTypeBuilders, typeProvider); } } private static void listToGenType(final Module module, final String basePackageName, final GeneratedTypeBuilder parent, final GeneratedTypeBuilder childOf, final ListSchemaNode node, final SchemaContext schemaContext, final boolean verboseClassComments, final Map genCtx, final Map> genTypeBuilders, final TypeProvider typeProvider) { final GeneratedTypeBuilder genType = processDataSchemaNode(module, basePackageName, childOf, node, schemaContext, verboseClassComments, genCtx, genTypeBuilders, typeProvider); if (genType != null) { final String nodeName = node.getQName().getLocalName(); constructGetter(parent, nodeName, node.getDescription(), Types.listTypeFor(genType), node.getStatus()); final List listKeys = node.getKeyDefinition(); final String packageName = new StringBuilder(packageNameForGeneratedType(basePackageName, node.getPath(), BindingNamespaceType.Key)).append('.').append(nodeName).toString(); final GeneratedTOBuilder genTOBuilder = resolveListKeyTOBuilder(packageName, node); for (final DataSchemaNode schemaNode : node.getChildNodes()) { if (!schemaNode.isAugmenting()) { addSchemaNodeToListBuilders(nodeName, basePackageName, schemaNode, genType, genTOBuilder, listKeys, module, typeProvider, schemaContext, genCtx, genTypeBuilders, verboseClassComments); } } // serialVersionUID if (genTOBuilder != null) { final GeneratedPropertyBuilder prop = new GeneratedPropertyBuilderImpl("serialVersionUID"); prop.setValue(Long.toString(computeDefaultSUID(genTOBuilder))); genTOBuilder.setSUID(prop); } typeBuildersToGenTypes(module, genType, genTOBuilder, genCtx); } } private static void typeBuildersToGenTypes(final Module module, final GeneratedTypeBuilder typeBuilder, final GeneratedTOBuilder genTOBuilder, final Map genCtx) { checkArgument(typeBuilder != null, "Generated Type Builder cannot be NULL."); if (genTOBuilder != null) { final GeneratedTransferObject genTO = genTOBuilder.toInstance(); constructGetter(typeBuilder, "key", "Returns Primary Key of Yang List Type", genTO, Status.CURRENT); genCtx.get(module).addGeneratedTOBuilder(genTOBuilder); } } /** * 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 * @param module * Module in which type was defined * @return boolean value *
    *
  • false - if leaf or typeBuilder are * null
  • *
  • true - in other cases
  • *
*/ private static Type resolveLeafSchemaNodeAsMethod(final String nodeName, final SchemaContext schemaContext, final GeneratedTypeBuilder typeBuilder, final Map genCtx, final LeafSchemaNode leaf, final Module module, final TypeProvider typeProvider) { if (leaf == null || typeBuilder == null || leaf.isAddedByUses()) { return null; } final String leafName = leaf.getQName().getLocalName(); if (leafName == null) { return null; } final Module parentModule = findParentModule(schemaContext, leaf); Type returnType = null; final TypeDefinition typeDef = leaf.getType(); if (isInnerType(leaf, typeDef)) { if (typeDef instanceof EnumTypeDefinition) { returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf); final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) typeDef; final EnumBuilder enumBuilder = resolveInnerEnumFromTypeDefinition(enumTypeDef, leaf.getQName(), genCtx, typeBuilder, module); if (enumBuilder != null) { returnType = enumBuilder.toInstance(typeBuilder); } ((TypeProviderImpl) typeProvider).putReferencedType(leaf.getPath(), returnType); } else if (typeDef instanceof UnionTypeDefinition) { final GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, leaf, parentModule, typeProvider, schemaContext); if (genTOBuilder != null) { //TODO: https://bugs.opendaylight.org/show_bug.cgi?id=2289 returnType = createReturnTypeForUnion(genTOBuilder, typeDef, typeBuilder, parentModule, typeProvider); } } else if (typeDef instanceof BitsTypeDefinition) { final GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, leaf, parentModule, typeProvider, schemaContext); if (genTOBuilder != null) { returnType = genTOBuilder.toInstance(); } } else { // It is constrained version of already declared type (inner declared type exists, // onlyfor special cases (Enum, Union, Bits), which were already checked. // In order to get proper class we need to look up closest derived type // and apply restrictions from leaf type final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef); returnType = typeProvider.javaTypeForSchemaDefinitionType(getBaseOrDeclaredType(typeDef), leaf, restrictions); } } else { final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef); returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf, restrictions); } if (returnType == null) { return null; } if (typeDef instanceof EnumTypeDefinition) { ((TypeProviderImpl) typeProvider).putReferencedType(leaf.getPath(), returnType); } String leafDesc = leaf.getDescription(); if (leafDesc == null) { leafDesc = ""; } final String leafGetterName; if (!"".equals(nodeName)) { StringBuilder sb = new StringBuilder(nodeName) .append('_') .append(leafName); leafGetterName = sb.toString(); } else { leafGetterName = leafName; } constructGetter(typeBuilder, leafGetterName, leafDesc, returnType, leaf.getStatus()); return returnType; } /** * 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 * @param module module * @param typeProvider type provider instance * @param genCtx actual generated context * @param genCtx actual generated context * @return boolean value *
    *
  • true - if node, typeBuilder, * nodeName equal null or node is added by uses
  • *
  • false - other cases
  • *
*/ private static boolean resolveLeafListSchemaNode(final SchemaContext schemaContext, final GeneratedTypeBuilder typeBuilder, final LeafListSchemaNode node, final Module module, final TypeProvider typeProvider, final Map genCtx) { if (node == null || typeBuilder == null || node.isAddedByUses()) { return false; } final QName nodeName = node.getQName(); final TypeDefinition typeDef = node.getType(); final Module parentModule = findParentModule(schemaContext, node); Type returnType = null; if (typeDef.getBaseType() == null) { if (typeDef instanceof EnumTypeDefinition) { returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, node); final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) typeDef; final EnumBuilder enumBuilder = resolveInnerEnumFromTypeDefinition(enumTypeDef, nodeName, genCtx, typeBuilder, module); returnType = new ReferencedTypeImpl(enumBuilder.getPackageName(), enumBuilder.getName()); ((TypeProviderImpl) typeProvider).putReferencedType(node.getPath(), returnType); } else if (typeDef instanceof UnionTypeDefinition) { final GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, node, parentModule, typeProvider, schemaContext); if (genTOBuilder != null) { returnType = createReturnTypeForUnion(genTOBuilder, typeDef, typeBuilder, parentModule, typeProvider); } } else if (typeDef instanceof BitsTypeDefinition) { final GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, node, parentModule, typeProvider, schemaContext); returnType = genTOBuilder.toInstance(); } else { final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef); returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, node, restrictions); } } else { final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef); returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, node, restrictions); } final ParameterizedType listType = Types.listTypeFor(returnType); constructGetter(typeBuilder, nodeName.getLocalName(), node.getDescription(), listType, node.getStatus()); return true; } /** * 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 schemaContext * current schema context * @param genCtx * actual generated context * @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 * @param verboseClassComments * Javadoc verbosity switch * @throws IllegalArgumentException *
    *
  • if basePackageName equals null
  • *
  • if refChoiceType equals null
  • *
  • if caseNodes equals null
  • *
*/ private static void generateTypesFromChoiceCases(final Module module, final SchemaContext schemaContext, final Map genCtx, final String basePackageName, final Type refChoiceType, final ChoiceSchemaNode choiceNode, final boolean verboseClassComments, final TypeProvider typeProvider, final Map> genTypeBuilders) { 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."); final Set caseNodes = choiceNode.getCases(); if (caseNodes == null) { return; } for (final ChoiceCaseNode caseNode : caseNodes) { if (caseNode != null && !caseNode.isAddedByUses() && !caseNode.isAugmenting()) { final String packageName = packageNameForGeneratedType(basePackageName, caseNode.getPath(), BindingNamespaceType.Data); final GeneratedTypeBuilder caseTypeBuilder = addDefaultInterfaceDefinition(packageName, caseNode, module, genCtx, schemaContext, verboseClassComments, genTypeBuilders, typeProvider); caseTypeBuilder.addImplementsType(refChoiceType); caseTypeBuilder.setParentTypeForBuilder(refChoiceType); annotateDeprecatedIfNecessary(caseNode.getStatus(), caseTypeBuilder); genCtx.get(module).addCaseType(caseNode.getPath(), caseTypeBuilder); genCtx.get(module).addChoiceToCaseMapping(refChoiceType, caseTypeBuilder, caseNode); final Iterable caseChildNodes = caseNode.getChildNodes(); if (caseChildNodes != null) { final SchemaPath choiceNodeParentPath = choiceNode.getPath().getParent(); if (!Iterables.isEmpty(choiceNodeParentPath.getPathFromRoot())) { SchemaNode parent = findDataSchemaNode(schemaContext, choiceNodeParentPath); if (parent instanceof AugmentationSchema) { final AugmentationSchema augSchema = (AugmentationSchema) parent; 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; } Preconditions.checkState(parent != null, "Could not find Choice node parent %s", choiceNodeParentPath); GeneratedTypeBuilder childOfType = findChildNodeByPath(parent.getPath(), genCtx); if (childOfType == null) { childOfType = findGroupingByPath(parent.getPath(), genCtx); } resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, childOfType, caseChildNodes, genCtx, schemaContext, verboseClassComments, genTypeBuilders, typeProvider); } else { resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, moduleToDataType(module, genCtx, verboseClassComments), caseChildNodes, genCtx, schemaContext, verboseClassComments, genTypeBuilders, typeProvider); } } } processUsesAugments(schemaContext, caseNode, module, genCtx, genTypeBuilders, verboseClassComments, typeProvider); } } private static Type resolveAnyNodeAsMethod(final SchemaContext schemaContext, final GeneratedTypeBuilder typeBuilder, final Map genCtx, final DataSchemaNode node, final Module module, final TypeProvider typeProvider) { final String anyName = node.getQName().getLocalName(); if (anyName == null) { return null; } String anyDesc = node.getDescription(); if (anyDesc == null) { anyDesc = ""; } Type returnType = Types.DOCUMENT; constructGetter(typeBuilder, anyName, anyDesc, returnType, node.getStatus()); return returnType; } /** * Adds schemaNode to typeBuilder as getter method * or to genTOBuilder as property. * * @param nodeName * string contains the name of list * @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 QNames of the list keys * @param module * current module * @param typeProvider * provider that defines contract for generated types * @param schemaContext * schema context * @param genCtx * map of generated entities in context of YANG modules * @param genTypeBuilders * map of generated type builders * @param verboseClassComments * generate verbose comments * @throws IllegalArgumentException *
    *
  • if schemaNode equals null
  • *
  • if typeBuilder equals null
  • *
*/ private static void addSchemaNodeToListBuilders(final String nodeName, final String basePackageName, final DataSchemaNode schemaNode, final GeneratedTypeBuilder typeBuilder, final GeneratedTOBuilder genTOBuilder, final List listKeys, final Module module, final TypeProvider typeProvider, final SchemaContext schemaContext, final Map genCtx, final Map> genTypeBuilders, final boolean verboseClassComments) { checkArgument(schemaNode != null, "Data Schema Node cannot be NULL."); checkArgument(typeBuilder != null, "Generated Type Builder cannot be NULL."); if (schemaNode instanceof LeafSchemaNode) { final LeafSchemaNode leaf = (LeafSchemaNode) schemaNode; final QName leafQName = leaf.getQName(); final Type type = resolveLeafSchemaNodeAsMethod(nodeName, schemaContext, typeBuilder, genCtx, leaf, module, typeProvider); if (listKeys.contains(leafQName)) { if (type == null) { resolveLeafSchemaNodeAsProperty(schemaContext, typeProvider, genCtx, genTOBuilder, leaf, true, module); } else { AuxiliaryGenUtils.resolveLeafSchemaNodeAsProperty(genTOBuilder, leaf, type, true); } } } else if (!schemaNode.isAddedByUses()) { if (schemaNode instanceof LeafListSchemaNode) { resolveLeafListSchemaNode(schemaContext, typeBuilder, (LeafListSchemaNode) schemaNode, module, typeProvider, genCtx); } else if (schemaNode instanceof ContainerSchemaNode) { containerToGenType(module, basePackageName, typeBuilder, typeBuilder, (ContainerSchemaNode) schemaNode, schemaContext, verboseClassComments, genCtx, genTypeBuilders, typeProvider); } else if (schemaNode instanceof ListSchemaNode) { listToGenType(module, basePackageName, typeBuilder, typeBuilder, (ListSchemaNode) schemaNode, schemaContext, verboseClassComments, genCtx, genTypeBuilders, typeProvider); } else if (schemaNode instanceof ChoiceSchemaNode) { choiceToGenType(module, schemaContext, verboseClassComments, basePackageName, typeBuilder, (ChoiceSchemaNode) schemaNode, genTypeBuilders, genCtx, typeProvider); } } } private static boolean resolveLeafSchemaNodeAsProperty(final SchemaContext schemaContext, final TypeProvider typeProvider, final Map genCtx, final GeneratedTOBuilder toBuilder, final LeafSchemaNode leaf, final boolean isReadOnly, final Module module) { if (leaf != null && toBuilder != null) { Type returnType; final TypeDefinition typeDef = leaf.getType(); if (typeDef instanceof UnionTypeDefinition) { // GeneratedType for this type definition should be already // created final QName qname = typeDef.getQName(); final Module unionModule = schemaContext.findModuleByNamespaceAndRevision(qname.getNamespace(), qname.getRevision()); final ModuleContext mc = genCtx.get(unionModule); returnType = mc.getTypedefs().get(typeDef.getPath()); } else if (typeDef instanceof EnumTypeDefinition && typeDef.getBaseType() == null) { // Annonymous enumeration (already generated, since it is inherited via uses). LeafSchemaNode originalLeaf = (LeafSchemaNode) SchemaNodeUtils.getRootOriginalIfPossible(leaf); QName qname = originalLeaf.getQName(); final Module enumModule = schemaContext.findModuleByNamespaceAndRevision(qname.getNamespace(), qname.getRevision()); returnType = genCtx.get(enumModule).getInnerType(originalLeaf.getType().getPath()); } else { returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf); } return AuxiliaryGenUtils.resolveLeafSchemaNodeAsProperty(toBuilder, leaf, returnType, isReadOnly); } return false; } private static TypeDefinition getBaseOrDeclaredType(final TypeDefinition typeDef) { final TypeDefinition baseType = typeDef.getBaseType(); return (baseType != null && baseType.getBaseType() != null) ? baseType : typeDef; } @SuppressWarnings({ "rawtypes", "unchecked" }) private static GeneratedTypeBuilder processDataSchemaNode(final Module module, final String basePackageName, final GeneratedTypeBuilder childOf, final DataSchemaNode node, final SchemaContext schemaContext, final boolean verboseClassComments, Map genCtx, final Map> genTypeBuilders, final TypeProvider typeProvider) { if (node.isAugmenting() || node.isAddedByUses()) { return null; } final String packageName = packageNameForGeneratedType(basePackageName, node.getPath(), BindingNamespaceType.Data); final GeneratedTypeBuilder genType = addDefaultInterfaceDefinition(packageName, node, childOf, module, genCtx, schemaContext, verboseClassComments, genTypeBuilders, typeProvider); genType.addComment(node.getDescription()); annotateDeprecatedIfNecessary(node.getStatus(), genType); genType.setDescription(createDescription(node, genType.getFullyQualifiedName(), schemaContext, verboseClassComments)); genType.setModuleName(module.getName()); genType.setReference(node.getReference()); genType.setSchemaPath((List) node.getPath().getPathFromRoot()); genType.setParentTypeForBuilder(childOf); if (node instanceof DataNodeContainer) { genCtx.get(module).addChildNodeType(node, genType); genCtx = groupingsToGenTypes(module, ((DataNodeContainer) node).getGroupings(), genCtx, schemaContext, verboseClassComments, genTypeBuilders, typeProvider); processUsesAugments(schemaContext, (DataNodeContainer) node, module, genCtx, genTypeBuilders, verboseClassComments, typeProvider); } return genType; } /** * Converts all groupings of the module to the list of * Type objects. Firstly are groupings sorted according mutual * dependencies. At least dependent (independent) groupings are in the list * saved at first positions. For every grouping the record is added to map * {@link ModuleContext#groupings allGroupings} * * @param module * current module * @param groupings * collection of groupings from which types will be generated * @param typeProvider * provider that defines contract for generated types * @param schemaContext * schema context * @param genCtx * map of generated entities in context of YANG modules * @param genTypeBuilders * map of generated type builders * @param verboseClassComments * generate verbose comments * */ static Map groupingsToGenTypes(final Module module, final Collection groupings, Map genCtx, final SchemaContext schemaContext, final boolean verboseClassComments, Map> genTypeBuilders, final TypeProvider typeProvider) { final String basePackageName = BindingMapping.getRootPackageName(module); final List groupingsSortedByDependencies = new GroupingDefinitionDependencySort() .sort(groupings); for (final GroupingDefinition grouping : groupingsSortedByDependencies) { genCtx = groupingToGenType(basePackageName, grouping, module, genCtx, schemaContext, verboseClassComments, genTypeBuilders, typeProvider); } return genCtx; } /** * Converts individual grouping to GeneratedType. Firstly generated type * builder is created and every child node of grouping is resolved to the * method. * * @param basePackageName * string contains the module package name * @param grouping * GroupingDefinition which contains data about grouping * @param module * current module * @param typeProvider * provider that defines contract for generated types * @param schemaContext * schema context * @param genCtx * map of generated entities in context of YANG modules * @param genTypeBuilders * map of generated type builders * @param verboseClassComments * generate verbose comments * * @return GeneratedType which is generated from grouping (object of type * GroupingDefinition) */ private static Map groupingToGenType(final String basePackageName, final GroupingDefinition grouping, final Module module, Map genCtx, final SchemaContext schemaContext, final boolean verboseClassComments, Map> genTypeBuilders, final TypeProvider typeProvider) { final String packageName = packageNameForGeneratedType(basePackageName, grouping.getPath(), BindingNamespaceType.Grouping); final GeneratedTypeBuilder genType = addDefaultInterfaceDefinition(packageName, grouping, module, genCtx, schemaContext, verboseClassComments, genTypeBuilders, typeProvider); annotateDeprecatedIfNecessary(grouping.getStatus(), genType); genCtx.get(module).addGroupingType(grouping.getPath(), genType); resolveDataSchemaNodes(module, basePackageName, genType, genType, grouping.getChildNodes(), genCtx, schemaContext, verboseClassComments, genTypeBuilders, typeProvider); genCtx = groupingsToGenTypes(module, grouping.getGroupings(), genCtx, schemaContext, verboseClassComments, genTypeBuilders, typeProvider); genCtx = processUsesAugments(schemaContext, grouping, module, genCtx, genTypeBuilders, verboseClassComments, typeProvider); return genCtx; } /** * //TODO: add information about multiple base identities in YANG 1.1 * Converts the identity object to GeneratedType. Firstly it is * created transport object builder. If identity contains base identity then * reference to base identity is added to superior identity as its extend. * If identity doesn't contain base identity then only reference to abstract * class {@link org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode * BaseIdentity} is added * * @param module * current module * @param basePackageName * string contains the module package name * @param identity * IdentitySchemaNode which contains data about identity * @param schemaContext * SchemaContext which is used to get package and name * information about base of identity * @param genCtx generated context * @return returns generated context */ static Map identityToGenType(final Module module, final String basePackageName, final IdentitySchemaNode identity, final SchemaContext schemaContext, Map genCtx, boolean verboseClassComments, final Map> genTypeBuilders, final TypeProvider typeProvider, Map generatedIdentities) { final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, identity.getPath(), BindingNamespaceType.Identity); final GeneratedTOBuilderImpl newType = new GeneratedTOBuilderImpl(packageName, identity.getQName().getLocalName()); final Set baseIdentities = identity.getBaseIdentities(); if (baseIdentities.size() == 0) { //no base - abstract final GeneratedTOBuilderImpl gto = new GeneratedTOBuilderImpl(BaseIdentity.class.getPackage().getName(), BaseIdentity.class.getSimpleName()); newType.setExtendsType(gto.toInstance()); generatedIdentities.put(identity.getQName(), newType); } else { //one base - inheritance final IdentitySchemaNode baseIdentity = baseIdentities.iterator().next(); final Module baseIdentityParentModule = SchemaContextUtil.findParentModule(schemaContext, baseIdentity); final String returnTypePkgName = new StringBuilder(BindingMapping.getRootPackageName (baseIdentityParentModule)) .append('.') .append(BindingNamespaceType.Identity.getPackagePrefix()) .toString(); final GeneratedTOBuilderImpl existingIdentityGto = generatedIdentities.get(baseIdentity.getQName()); if (existingIdentityGto != null) { newType.setExtendsType(existingIdentityGto.toInstance()); } else { final GeneratedTOBuilderImpl gto = new GeneratedTOBuilderImpl(returnTypePkgName, baseIdentity.getQName().getLocalName()); newType.setExtendsType(gto.toInstance()); generatedIdentities.put(baseIdentity.getQName(), gto); } //FIXME: more bases - possible composition, multiple inheritance not possible } generatedIdentities.put(identity.getQName(), newType); newType.setAbstract(true); newType.addComment(identity.getDescription()); newType.setDescription(createDescription(identity, newType.getFullyQualifiedName(), schemaContext, verboseClassComments)); newType.setReference(identity.getReference()); newType.setModuleName(module.getName()); newType.setSchemaPath((List) identity.getPath().getPathFromRoot()); qNameConstant(newType, BindingMapping.QNAME_STATIC_FIELD_NAME, identity.getQName()); genCtx.get(module).addIdentityType(identity.getQName(), newType); return genCtx; } }