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=c7e09e66456e11ea185d0460489329b1106562a1;hb=26dfd30eff2908d73404eb7624e913cc39023071;hp=ea3b472710fbeb84b4783396ee0e73809d274b56;hpb=df1236c753c1e917b587686efb9251f83e49cfb2;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 ea3b472710..c7e09e6645 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 @@ -1,1739 +1,2127 @@ -/* - * Copyright (c) 2013 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.yangtools.sal.binding.generator.impl; - -import static org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil.moduleNamespaceToPackageName; -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.yang.model.util.SchemaContextUtil.findDataSchemaNode; -import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findParentModule; - -import java.net.URI; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.Future; - -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.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.ConcreteType; -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.Type; -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.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.Identifiable; -import org.opendaylight.yangtools.yang.binding.Identifier; -import org.opendaylight.yangtools.yang.binding.RpcService; -import org.opendaylight.yangtools.yang.common.QName; -import org.opendaylight.yangtools.yang.common.RpcResult; -import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; -import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode; -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.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.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.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; - -public final class BindingGeneratorImpl implements BindingGenerator { - - /** - * 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. - */ - private Map> genTypeBuilders; - - /** - * Provide methods for converting YANG types to JAVA types. - */ - private TypeProvider typeProvider; - - /** - * Holds reference to schema context to resolve data of augmented elemnt - * 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. - */ - private final Map allGroupings = new HashMap(); - - /** - * Only parent constructor is invoked. - */ - - private final static String YANG_EXT_NAMESPACE = "urn:opendaylight:yang:extension:yang-ext"; - private final static String AUGMENT_IDENTIFIER_NAME = "augment-identifier"; - - public BindingGeneratorImpl() { - super(); - } - - /** - * 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 - * @return list of types (usually GeneratedType - * GeneratedTransferObjectwhich are generated from - * context data. - * @throws IllegalArgumentException - * if param 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<>(); - 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; - } - - /** - * 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 - * @param modules - * set of modules for which schema nodes should be generated - * types - * @return list of types (usually GeneratedType or - * GeneratedTransferObject) which: - *
    - *
  • are generated from context schema nodes and
  • - *
  • are also part of some of the module in modules - * set
  • . - *
- * @throws IllegalArgumentException - *
    - *
  • if param context is null or
  • - *
  • if param 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!"); - } - - final List filteredGenTypes = new ArrayList<>(); - schemaContext = context; - typeProvider = new TypeProviderImpl(context); - final Set contextModules = context.getModules(); - 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); - } - } - return filteredGenTypes; - } - - /** - * 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
  • - *
- * - */ - 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!"); - } - - final Set> typeDefinitions = module.getTypeDefinitions(); - final List generatedTypes = new ArrayList<>(); - for (final TypeDefinition typedef : typeDefinitions) { - if (typedef != null) { - final Type type = ((TypeProviderImpl) typeProvider).generatedTypeForExtendedDefinitionType(typedef); - if ((type != null) && !generatedTypes.contains(type)) { - generatedTypes.add(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)); - } - } - return generatedTypes; - } - - /** - * 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!"); - } - - 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 schemaLists = it.allLists(); - final String basePackageName = moduleNamespaceToPackageName(module); - if (schemaLists != null) { - for (final ListSchemaNode list : schemaLists) { - if (!list.isAddedByUses()) { - generatedTypes.addAll(listToGenType(basePackageName, list)); - } - } - } - 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!"); - } - - final DataNodeIterator it = new DataNodeIterator(module); - final List choiceNodes = it.allChoices(); - final String basePackageName = moduleNamespaceToPackageName(module); - - final List generatedTypes = new ArrayList<>(); - for (final ChoiceNode choice : choiceNodes) { - if ((choice != null) && !choice.isAddedByUses()) { - generatedTypes.addAll(choiceToGeneratedType(basePackageName, choice)); - } - } - 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
  • - *
- * - */ - 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!"); - } - - final List generatedTypes = new ArrayList<>(); - final String basePackageName = moduleNamespaceToPackageName(module); - final List augmentations = resolveAugmentations(module); - for (final AugmentationSchema augment : augmentations) { - generatedTypes.addAll(augmentationToGenTypes(basePackageName, augment)); - } - 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
  • - *
- * - */ - 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!"); - } - - 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; - - } - }); - - return sortedAugmentations; - } - - /** - * Converts whole module to GeneratedType object. - * Firstly is created the module builder object from which is finally - * obtained reference to GeneratedType object. - * - * @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 - * @throws IllegalArgumentException - * if the module equals null - * - */ - private GeneratedType moduleToDataType(final Module module) { - if (module == null) { - throw new IllegalArgumentException("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(); - } - - /** - * 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
  • - *
- * - */ - 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); - final Set rpcDefinitions = module.getRpcs(); - - if (rpcDefinitions.isEmpty()) { - return Collections.emptyList(); - } - - final List genRPCTypes = new ArrayList<>(); - 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); - - final List rpcInOut = new ArrayList<>(); - - ContainerSchemaNode input = rpc.getInput(); - ContainerSchemaNode output = rpc.getOutput(); - - if (input != null) { - rpcInOut.add(new DataNodeIterator(input)); - 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); - method.addParameter(inTypeInstance, "input"); - } - - Type outTypeInstance = Types.typeForClass(Void.class); - if (output != null) { - rpcInOut.add(new DataNodeIterator(output)); - GeneratedTypeBuilder outType = addRawInterfaceDefinition(basePackageName, output, rpcName); - addImplementedInterfaceFromUses(output, outType); - outType.addImplementsType(Types.DATA_OBJECT); - resolveDataSchemaNodes(basePackageName, outType, output.getChildNodes()); - 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)); - } - } - } - } - } - } - genRPCTypes.add(interfaceBuilder.toInstance()); - return genRPCTypes; - } - - /** - * 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
  • - *
- * - */ - private List allNotificationsToGenType(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 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) { - if (notification != null) { - DataNodeIterator it = new DataNodeIterator(notification); - - // 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()); - } - } - return genNotifyTypes; - } - - /** - * 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<>(); - - final Set schemaIdentities = module.getIdentities(); - - final String basePackageName = moduleNamespaceToPackageName(module); - - if (schemaIdentities != null && !schemaIdentities.isEmpty()) { - for (final IdentitySchemaNode identity : schemaIdentities) { - genTypes.add(identityToGenType(basePackageName, identity, context)); - } - } - return genTypes; - } - - /** - * 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.BaseIdentity - * BaseIdentity} is added - * - * @param basePackageName - * string containing package name to which identity belongs - * @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) { - if (identity == null) { - return null; - } - - final String packageName = packageNameForGeneratedType(basePackageName, identity.getPath()); - final String genTypeName = parseToClassName(identity.getQName().getLocalName()); - 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); - } else { - newType.setExtendsType(Types.getBaseIdentityTO()); - } - newType.setAbstract(true); - return newType.toInstance(); - } - - /** - * 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 - * 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) - * - */ - private List allGroupingsToGenTypes(final Module module) { - if (module == null) { - throw new IllegalArgumentException("Module parameter can not be null"); - } - 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. - * @param grouping - * GroupingDefinition which contains data about grouping - * @return GeneratedType which is generated from grouping (object of type - * GroupingDefinition) - */ - private GeneratedType groupingToGenType(final String basePackageName, GroupingDefinition grouping) { - if (grouping == null) { - return null; - } - - 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; - } - - /** - * 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 - * string contains name which will be assigned to enumeration - * builder - * @param typeBuilder - * GeneratedTypeBuilder to which will be enum builder assigned - * @return enumeration builder which contais data from - * enumTypeDef - */ - private EnumBuilder resolveInnerEnumFromTypeDefinition(final EnumTypeDefinition enumTypeDef, final String enumName, - final GeneratedTypeBuilder typeBuilder) { - if ((enumTypeDef != null) && (typeBuilder != null) && (enumTypeDef.getQName() != null) - && (enumTypeDef.getQName().getLocalName() != null)) { - - final String enumerationName = parseToClassName(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; - } - } - return null; - } - - /** - * 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 - * @return instance of GeneratedTypeBuilder which represents - * module. - * @throws IllegalArgumentException - * if module equals 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; - - return new GeneratedTypeBuilderImpl(packageName, moduleName); - - } - - /** - * Converts augSchema to list of Type which - * contains generated type for augmentation. In addition there are also - * 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 - * (target path, childs...) - * @return list of Type objects which contains generated type - * for augmentation and for container, list and choice child nodes - * @throws IllegalArgumentException - *
    - *
  • if augmentPackageName equals null
  • - *
  • if augSchema equals null
  • - *
  • if target path of augSchema equals null
  • - *
- */ - private List augmentationToGenTypes(final String augmentPackageName, final AugmentationSchema augSchema) { - if (augmentPackageName == null) { - throw new IllegalArgumentException("Package Name cannot be NULL!"); - } - if (augSchema == null) { - throw new IllegalArgumentException("Augmentation Schema cannot be NULL!"); - } - if (augSchema.getTargetPath() == null) { - throw new IllegalStateException("Augmentation Schema does not contain Target Path (Target Path is NULL)."); - } - - final List genTypes = new ArrayList<>(); - - // EVERY augmented interface will extends Augmentation interface - // and DataObject interface!!! - 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)); - } - genTypes.addAll(augmentationBodyToGenTypes(augmentPackageName, augChildNodes)); - } - return genTypes; - } - - /** - * 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 augmentPackageName - * string with contains the package name to which the augment - * belongs - * @param targetPackageName - * string with the package name to which the augmented node - * belongs - * @param targetSchemaNodeName - * string with the name of the augmented node - * @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); - Map augmentBuilders = genTypeBuilders.get(augmentPackageName); - if (augmentBuilders == null) { - augmentBuilders = new HashMap<>(); - genTypeBuilders.put(augmentPackageName, augmentBuilders); - } - final String augIdentifier = getAugmentIdentifier(augSchema.getUnknownSchemaNodes()); - - final String augTypeName = augIdentifier != null ? parseToClassName(augIdentifier): augGenTypeName(augmentBuilders, targetTypeName); - final Type targetTypeRef = new ReferencedTypeImpl(targetPackageName, targetTypeName); - final Set augChildNodes = augSchema.getChildNodes(); - - final GeneratedTypeBuilder augTypeBuilder = new GeneratedTypeBuilderImpl(augmentPackageName, augTypeName); - - augTypeBuilder.addImplementsType(Types.DATA_OBJECT); - augTypeBuilder.addImplementsType(Types.augmentationTypeFor(targetTypeRef)); - addImplementedInterfaceFromUses(augSchema, augTypeBuilder); - - augSchemaNodeToMethods(augmentPackageName, augTypeBuilder, augChildNodes); - augmentBuilders.put(augTypeName, augTypeBuilder); - return augTypeBuilder; - } - - private String getAugmentIdentifier(List unknownSchemaNodes) { - String ret = null; - for (UnknownSchemaNode unknownSchemaNode : unknownSchemaNodes) { - QName nodeType = unknownSchemaNode.getNodeType(); - if(AUGMENT_IDENTIFIER_NAME.equals(nodeType.getLocalName()) && - YANG_EXT_NAMESPACE.equals(nodeType.getNamespace().toString())) { - return unknownSchemaNode.getNodeParameter(); - } - } - return ret; - } - - /** - * 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 - */ - 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)); - } - } - } - return genTypes; - } - - /** - * 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 - * @param genTypeName - * string with name of augmented node - * @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++; - } - augTypeName += index; - return augTypeName; - } - - /** - * 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. - * - * @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 - */ - private GeneratedType containerToGenType(final String basePackageName, ContainerSchemaNode containerNode) { - if (containerNode == null) { - return null; - } - - 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(); - } - - /** - * - * @param basePackageName - * @param typeBuilder - * @param schemaNodes - * @return - */ - private GeneratedTypeBuilder resolveDataSchemaNodes(final String basePackageName, - final GeneratedTypeBuilder typeBuilder, final Set schemaNodes) { - if ((schemaNodes != null) && (typeBuilder != null)) { - for (final DataSchemaNode schemaNode : schemaNodes) { - if (schemaNode.isAugmenting() || schemaNode.isAddedByUses()) { - continue; - } - 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); - } - } - } - 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!"); - } - - final String choiceName = choiceNode.getQName().getLocalName(); - if (choiceName != null && !choiceNode.isAddedByUses()) { - final String packageName = packageNameForGeneratedType(basePackageName, choiceNode.getPath()); - final GeneratedTypeBuilder choiceType = addDefaultInterfaceDefinition(packageName, choiceNode); - constructGetter(typeBuilder, choiceName, choiceNode.getDescription(), choiceType); - } - } - - 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(); - - 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!"); - } - - final List generatedTypes = new ArrayList<>(); - for (final 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); - } - generatedTypes.add(caseTypeBuilder.toInstance()); - } - } - - return generatedTypes; - } - - /** - * Generates list of generated types for all the cases of a choice which are - * added to the choice through the augment. - * - * - * @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 - * 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
  • - *
- */ - 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()) { - 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); - } - generatedTypes.add(caseTypeBuilder.toInstance()); - } - } - - return generatedTypes; - } - - private boolean resolveLeafSchemaNodeAsMethod(final GeneratedTypeBuilder typeBuilder, final LeafSchemaNode leaf) { - if ((leaf != null) && (typeBuilder != null)) { - final String leafName = leaf.getQName().getLocalName(); - String leafDesc = leaf.getDescription(); - if (leafDesc == null) { - leafDesc = ""; - } - - if (leafName != null && !leaf.isAddedByUses()) { - final TypeDefinition typeDef = leaf.getType(); - - Type returnType = null; - if (typeDef instanceof EnumTypeDefinition) { - returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef); - final EnumTypeDefinition enumTypeDef = enumTypeDefFromExtendedType(typeDef); - final EnumBuilder enumBuilder = resolveInnerEnumFromTypeDefinition(enumTypeDef, leafName, - typeBuilder); - - if (enumBuilder != null) { - returnType = new ReferencedTypeImpl(enumBuilder.getPackageName(), enumBuilder.getName()); - } - ((TypeProviderImpl) typeProvider).putReferencedType(leaf.getPath(), returnType); - } else if (typeDef instanceof UnionType) { - GeneratedTOBuilder genTOBuilder = addEnclosedTOToTypeBuilder(typeDef, typeBuilder, leafName); - if (genTOBuilder != null) { - returnType = new ReferencedTypeImpl(genTOBuilder.getPackageName(), genTOBuilder.getName()); - } - } else if (typeDef instanceof BitsTypeDefinition) { - GeneratedTOBuilder genTOBuilder = addEnclosedTOToTypeBuilder(typeDef, typeBuilder, leafName); - if (genTOBuilder != null) { - returnType = new ReferencedTypeImpl(genTOBuilder.getPackageName(), genTOBuilder.getName()); - } - } else { - returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef); - } - if (returnType != null) { - constructGetter(typeBuilder, leafName, leafDesc, returnType); - return true; - } - } - } - return false; - } - - private boolean resolveLeafSchemaNodeAsProperty(final GeneratedTOBuilder toBuilder, final LeafSchemaNode leaf, - boolean isReadOnly) { - if ((leaf != null) && (toBuilder != null)) { - final String leafName = leaf.getQName().getLocalName(); - String leafDesc = leaf.getDescription(); - if (leafDesc == null) { - leafDesc = ""; - } - - if (leafName != null && !leaf.isAddedByUses()) { - 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; - } - } - } - return false; - } - - 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 = ""; - } - - if (nodeName != null && !node.isAddedByUses()) { - final TypeDefinition type = node.getType(); - final Type listType = Types.listTypeFor(typeProvider.javaTypeForSchemaDefinitionType(type)); - - constructGetter(typeBuilder, nodeName, nodeDesc, 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; - } - } - return false; - } - - 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; - } - - /** - * Method instantiates new Generated Type Builder and sets the implements - * definitions of Data Object and Augmentable. - * - * @param packageName - * Generated Type Package Name - * @param schemaNode - * Schema Node definition - * @return Generated Type Builder instance for Schema Node definition - */ - private GeneratedTypeBuilder addDefaultInterfaceDefinition(final String packageName, final SchemaNode schemaNode) { - final GeneratedTypeBuilder builder = addRawInterfaceDefinition(packageName, schemaNode, ""); - builder.addImplementsType(Types.DATA_OBJECT); - if (!(schemaNode instanceof GroupingDefinition)) { - builder.addImplementsType(Types.augmentableTypeFor(builder)); - } - - if (schemaNode instanceof DataNodeContainer) { - addImplementedInterfaceFromUses((DataNodeContainer) schemaNode, builder); - } - - return builder; - } - - /** - * - * @param packageName - * @param schemaNode - * @return - */ - private GeneratedTypeBuilder addRawInterfaceDefinition(final String packageName, final SchemaNode schemaNode) { - return addRawInterfaceDefinition(packageName, schemaNode, ""); - } - - 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!"); - } - final String schemaNodeName = schemaNode.getQName().getLocalName(); - if (schemaNodeName == null) { - throw new IllegalArgumentException("Local Name of QName for Data Schema Node cannot be NULL!"); - } - - final String genTypeName; - if (prefix == null) { - genTypeName = parseToClassName(schemaNodeName); - } else { - genTypeName = prefix + parseToClassName(schemaNodeName); - } - - final GeneratedTypeBuilder newType = new GeneratedTypeBuilderImpl(packageName, genTypeName); - if (!genTypeBuilders.containsKey(packageName)) { - final Map builders = new HashMap<>(); - builders.put(genTypeName, newType); - genTypeBuilders.put(packageName, builders); - } else { - final Map builders = genTypeBuilders.get(packageName); - if (!builders.containsKey(genTypeName)) { - builders.put(genTypeName, newType); - } - } - 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) { - final StringBuilder method = new StringBuilder(); - method.append("set"); - method.append(parseToClassName(methodName)); - return method.toString(); - } - - private MethodSignatureBuilder constructGetter(final GeneratedTypeBuilder interfaceBuilder, - final String schemaNodeName, final String comment, final Type returnType) { - final MethodSignatureBuilder getMethod = interfaceBuilder.addMethod(getterMethodName(schemaNodeName)); - - 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); - - - if(genTOBuilder != null) { - ParameterizedType identifierMarker = Types.parameterizedTypeFor( Types.typeForClass(Identifier.class), typeBuilder); - ParameterizedType identifiableMarker = Types.parameterizedTypeFor(Types.typeForClass(Identifiable.class), genTOBuilder); - genTOBuilder.addImplementsType(identifierMarker); - typeBuilder.addImplementsType(identifiableMarker); - } - final Set schemaNodes = list.getChildNodes(); - - for (final DataSchemaNode schemaNode : schemaNodes) { - if (schemaNode.isAugmenting()) { - continue; - } - addSchemaNodeToListBuilders(basePackageName, schemaNode, typeBuilder, genTOBuilder, listKeys); - } - return typeBuildersToGenTypes(typeBuilder, genTOBuilder); - } - - 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!"); - } - - if (schemaNode instanceof LeafSchemaNode) { - final LeafSchemaNode leaf = (LeafSchemaNode) schemaNode; - if (!isPartOfListKey(leaf, listKeys)) { - resolveLeafSchemaNodeAsMethod(typeBuilder, leaf); - } else { - resolveLeafSchemaNodeAsProperty(genTOBuilder, leaf, true); - } - } 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!"); - } - - if (genTOBuilder != null) { - final GeneratedTransferObject genTO = genTOBuilder.toInstance(); - constructGetter(typeBuilder, "key", "Returns Primary Key of Yang List Type", genTO); - genTypes.add(genTO); - } - genTypes.add(typeBuilder.toInstance()); - return genTypes; - } - - /** - * @param list - * @return - */ - 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()); - } - } - 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) { - GeneratedTOBuilder genTOBuilder = null; - if (listKeys.size() > 0) { - genTOBuilder = resolveListKey(packageName, list); - } - 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); - } else if (typeDef instanceof BitsTypeDefinition) { - genTOBuilder = ((TypeProviderImpl) typeProvider).bitsTypedefToTransferObject( - typeBuilder.getFullyQualifiedName(), typeDef, className); - } - if (genTOBuilder != null) { - typeBuilder.addEnclosingTransferObject(genTOBuilder); - return genTOBuilder; - } - 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 - * - * @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 - */ - private GeneratedTypeBuilder addImplementedInterfaceFromUses(final DataNodeContainer dataNodeContainer, - final GeneratedTypeBuilder builder) { - for (UsesNode usesNode : dataNodeContainer.getUses()) { - if (usesNode.getGroupingPath() != null) { - GeneratedType genType = allGroupings.get(usesNode.getGroupingPath()); - if (genType == null) { - throw new IllegalStateException("Grouping " + usesNode.getGroupingPath() + "is not resolved for " - + builder.getName()); - } - builder.addImplementsType(genType); - } - } - return builder; - } - -} +/* + * Copyright (c) 2013 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.yangtools.sal.binding.generator.impl; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static 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.parseToValidParamName; +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.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +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.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; +import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode; +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.UnionTypeDefinition; +import org.opendaylight.yangtools.yang.model.util.DataNodeIterator; +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("\\."); + + /** + * Constant with the concrete name of identifier. + */ + private static final String AUGMENT_IDENTIFIER_NAME = "augment-identifier"; + private static final char NEW_LINE = '\n'; + + private final Map genCtx = new HashMap<>(); + + /** + * 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; + + /** + * Provide methods for converting YANG types to JAVA types. + */ + private TypeProvider typeProvider; + + /** + * Holds reference to schema context to resolve data of augmented element + * when creating augmentation builder + */ + private SchemaContext schemaContext; + + /** + * Constant with the concrete name of namespace. + */ + private static final String YANG_EXT_NAMESPACE = "urn:opendaylight:yang:extension:yang-ext"; + + /** + * 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 + * @return list of types (usually GeneratedType + * GeneratedTransferObjectwhich are generated from + * context data. + * @throws IllegalArgumentException + * if arg context is null + * @throws IllegalStateException + * if context contain no modules + */ + @Override + public List generateTypes(final SchemaContext context) { + 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(); + 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 + * @param modules + * set of modules for which schema nodes should be generated + * types + * @return list of types (usually GeneratedType or + * GeneratedTransferObject) which: + *
    + *
  • are generated from context schema nodes and
  • + *
  • are also part of some of the module in modules + * set
  • . + *
+ * @throws IllegalArgumentException + *
    + *
  • 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) { + 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."); + + schemaContext = context; + typeProvider = new TypeProviderImpl(context); + Module[] modulesArray = new Module[context.getModules().size()]; + context.getModules().toArray(modulesArray); + final List contextModules = ModuleDependencySort.sort(modulesArray); + genTypeBuilders = new HashMap<>(); + + 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 + * @throws IllegalArgumentException + *
    + *
  • if module is null
  • + *
  • if name of module is null
  • + *
+ * @throws IllegalStateException + * if set of type definitions from module is null + */ + private void allTypeDefinitionsToGenTypes(final Module module) { + checkArgument(module != null, "Module reference cannot be NULL."); + 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."); + + for (TypeDefinition typedef : typeDefinitions) { + if (typedef != null) { + final Type type = ((TypeProviderImpl) typeProvider).generatedTypeForExtendedDefinitionType(typedef, + typedef); + if (type != null) { + genCtx.get(module).addTypedefType(typedef.getPath(), type); + } + } + } + } + + private GeneratedTypeBuilder processDataSchemaNode(final Module module, final String basePackageName, + final GeneratedTypeBuilder childOf, final DataSchemaNode node) { + if (node.isAugmenting() || node.isAddedByUses()) { + return null; + } + 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; + } + + 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()); + } + } + + 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); + } + + for (DataSchemaNode schemaNode : node.getChildNodes()) { + if (!schemaNode.isAugmenting()) { + addSchemaNodeToListBuilders(basePackageName, schemaNode, genType, genTOBuilder, listKeys, module); + } + } + + // serialVersionUID + if (genTOBuilder != null) { + final GeneratedPropertyBuilder prop = new GeneratedPropertyBuilderImpl("serialVersionUID"); + prop.setValue(Long.toString(computeDefaultSUID(genTOBuilder))); + genTOBuilder.setSUID(prop); + } + + typeBuildersToGenTypes(module, genType, genTOBuilder); + } + } + + 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); + } + } + } + + /** + * 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 + * @throws IllegalArgumentException + *
    + *
  • if the module is null
  • + *
  • if the name of module is null
  • + *
+ * @throws IllegalStateException + * if set of augmentations from module is 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 String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule()); + final List augmentations = resolveAugmentations(module); + for (AugmentationSchema augment : augmentations) { + augmentationToGenTypes(basePackageName, augment, module); + } + } + + /** + * 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 module is null + * @throws IllegalStateException + * if set of module augmentations is null + */ + private List resolveAugmentations(final Module module) { + checkArgument(module != null, "Module reference cannot be NULL."); + checkState(module.getAugmentations() != null, "Augmentations Set cannot be NULL."); + + final Set augmentations = module.getAugmentations(); + List sortedAugmentations = new ArrayList<>(augmentations); + Collections.sort(sortedAugmentations, Comparators.AUGMENT_COMP); + + return sortedAugmentations; + } + + /** + * Create GeneratedTypeBuilder object from module argument. + * + * @param module + * Module object from which builder will be created + * @return GeneratedTypeBuilder which is internal + * representation of the module + * @throws IllegalArgumentException + * if module is null + */ + private GeneratedTypeBuilder moduleToDataType(final Module module) { + checkArgument(module != null, "Module reference cannot be NULL."); + + final GeneratedTypeBuilder moduleDataTypeBuilder = moduleTypeBuilder(module, "Data"); + addImplementedInterfaceFromUses(module, moduleDataTypeBuilder); + 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 + * @throws IllegalArgumentException + *
    + *
  • if the module is null
  • + *
  • if the name of module is null
  • + *
+ * @throws IllegalStateException + * if set of rpcs from module is null + */ + 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; + } + + final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule()); + final GeneratedTypeBuilder interfaceBuilder = moduleTypeBuilder(module, "Service"); + interfaceBuilder.addImplementsType(Types.typeForClass(RpcService.class)); + interfaceBuilder.setDescription(createDescription(rpcDefinitions, module.getName(), module.getModuleSourcePath())); + + 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) { + final GeneratedTypeBuilder inType = addRawInterfaceDefinition(basePackageName, input, rpcName); + addImplementedInterfaceFromUses(input, inType); + 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 = VOID; + if (output != null) { + final GeneratedTypeBuilder outType = addRawInterfaceDefinition(basePackageName, output, rpcName); + addImplementedInterfaceFromUses(output, outType); + outType.addImplementsType(DATA_OBJECT); + outType.addImplementsType(augmentable(outType)); + resolveDataSchemaNodes(module, basePackageName, outType, outType, output.getChildNodes()); + genCtx.get(module).addChildNodeType(output, outType); + outTypeInstance = outType.toInstance(); + } + + final Type rpcRes = Types.parameterizedTypeFor(Types.typeForClass(RpcResult.class), outTypeInstance); + method.setComment(rpcComment); + method.setReturnType(Types.parameterizedTypeFor(FUTURE, rpcRes)); + } + } + + 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 + * @throws IllegalArgumentException + *
    + *
  • if the module equals null
  • + *
  • if the name of module equals null
  • + *
+ * @throws IllegalStateException + * if set of notifications from module is 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; + } + + final GeneratedTypeBuilder listenerInterface = moduleTypeBuilder(module, "Listener"); + listenerInterface.addImplementsType(BindingTypes.NOTIFICATION_LISTENER); + final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule()); + + + + for (NotificationDefinition notification : notifications) { + if (notification != null) { + processUsesAugments(notification, module); + + final GeneratedTypeBuilder notificationInterface = addDefaultInterfaceDefinition(basePackageName, + notification, BindingTypes.DATA_OBJECT); + notificationInterface.addImplementsType(NOTIFICATION); + genCtx.get(module).addChildNodeType(notification, notificationInterface); + + // Notification object + resolveDataSchemaNodes(module, basePackageName, notificationInterface, notificationInterface, + notification.getChildNodes()); + + listenerInterface.addMethod("on" + notificationInterface.getName()) + .setAccessModifier(AccessModifier.PUBLIC).addParameter(notificationInterface, "notification") + .setComment(notification.getDescription()).setReturnType(Types.VOID); + } + } + 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} + * + */ + private void allIdentitiesToGenTypes(final Module module, final SchemaContext context) { + final Set schemaIdentities = module.getIdentities(); + final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule()); + + if (schemaIdentities != null && !schemaIdentities.isEmpty()) { + for (IdentitySchemaNode identity : schemaIdentities) { + identityToGenType(module, basePackageName, identity, context); + } + } + } + + /** + * 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.BaseIdentity + * BaseIdentity} is added + * + * @param module + * current module + * @param basePackageName + * string contains the module package name + * @param identity + * IdentitySchemaNode which contains data about identity + * @param context + * SchemaContext which is used to get package and name + * information about base of identity + * + */ + private void identityToGenType(final Module module, final String basePackageName, + final IdentitySchemaNode identity, final SchemaContext context) { + if (identity == null) { + return; + } + final String packageName = packageNameForGeneratedType(basePackageName, identity.getPath()); + final String genTypeName = BindingMapping.getClassName(identity.getQName()); + final GeneratedTOBuilderImpl newType = new GeneratedTOBuilderImpl(packageName, genTypeName); + 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 { + 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); + 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 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 + * current module + * @param collection + * of groupings from which types will be generated + * + */ + private void groupingsToGenTypes(final Module module, final Collection groupings) { + final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule()); + final List groupingsSortedByDependencies = new GroupingDefinitionDependencySort() + .sort(groupings); + for (GroupingDefinition grouping : groupingsSortedByDependencies) { + groupingToGenType(basePackageName, grouping, module); + } + } + + /** + * 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 + * @return GeneratedType which is generated from grouping (object of type + * GroupingDefinition) + */ + private void groupingToGenType(final String basePackageName, final GroupingDefinition grouping, final Module module) { + final String packageName = packageNameForGeneratedType(basePackageName, grouping.getPath()); + final GeneratedTypeBuilder genType = addDefaultInterfaceDefinition(packageName, grouping); + 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 + * string contains name which will be assigned to enumeration + * builder + * @param typeBuilder + * GeneratedTypeBuilder to which will be enum builder assigned + * @return enumeration builder which contains data from + * enumTypeDef + */ + 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 = BindingMapping.getClassName(enumName); + final EnumBuilder enumBuilder = typeBuilder.addEnumeration(enumerationName); + 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 + * @param postfix + * string which is added to the module class name representation + * as suffix + * @return instance of GeneratedTypeBuilder which represents + * module. + * @throws IllegalArgumentException + * if module is null + */ + private GeneratedTypeBuilder moduleTypeBuilder(final Module module, final String postfix) { + checkArgument(module != null, "Module reference cannot be NULL."); + final String packageName = BindingMapping.getRootPackageName(module.getQNameModule()); + final String moduleName = BindingMapping.getClassName(module.getName()) + postfix; + + final GeneratedTypeBuilderImpl moduleBuilder = new GeneratedTypeBuilderImpl(packageName, moduleName); + moduleBuilder.setDescription(createDescription(module)); + moduleBuilder.setReference(module.getReference()); + moduleBuilder.setModuleName(moduleName); + + return moduleBuilder; + } + + /** + * Converts augSchema to list of Type which + * contains generated type for augmentation. In addition there are also + * 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 augmentation + * (target path, childs...) + * @param module + * current module + * @param parentUsesNode + * @throws IllegalArgumentException + *
    + *
  • if augmentPackageName equals null
  • + *
  • if augSchema equals null
  • + *
+ * @throws IllegalStateException + * if augment target path is 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 (targetTypeBuilder == null) { + throw new NullPointerException("Target type not yet generated: " + targetSchemaNode); + } + + 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()); + } + } + + 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)."); + + processUsesAugments(augSchema, module); + final SchemaPath targetPath = augSchema.getTargetPath(); + 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(); + } + } + 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 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 + */ + 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()); + + String augTypeName; + if (augIdentifier != null) { + augTypeName = BindingMapping.getClassName(augIdentifier); + } else { + augTypeName = augGenTypeName(augmentBuilders, targetTypeRef.getName()); + } + + final GeneratedTypeBuilder augTypeBuilder = new GeneratedTypeBuilderImpl(augmentPackageName, augTypeName); + + augTypeBuilder.addImplementsType(DATA_OBJECT); + augTypeBuilder.addImplementsType(Types.augmentationTypeFor(targetTypeRef)); + addImplementedInterfaceFromUses(augSchema, augTypeBuilder); + + 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; + } + + /** + * + * @param unknownSchemaNodes + * @return nodeParameter of UnknownSchemaNode + */ + 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 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 + * @param genTypeName + * string with name of augmented node + * @return string with unique name for augmentation builder + */ + private String augGenTypeName(final Map builders, final String genTypeName) { + int index = 1; + if (builders != null) { + while (builders.containsKey(genTypeName + index)) { + index = index + 1; + } + } + return genTypeName + index; + } + + /** + * 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. + */ + 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); + } + } + } + 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 + * 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 augSchemaNodeToMethods(final Module module, final String basePackageName, + final GeneratedTypeBuilder typeBuilder, final GeneratedTypeBuilder childOf, + final Iterable schemaNodes) { + if ((schemaNodes != null) && (typeBuilder != null)) { + for (DataSchemaNode schemaNode : schemaNodes) { + if (!schemaNode.isAugmenting()) { + addSchemaNodeToBuilderAsMethod(basePackageName, schemaNode, typeBuilder, childOf, module); + } + } + } + return 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()); + } + } + } + + /** + * 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."); + + if (!choiceNode.isAddedByUses()) { + final String packageName = packageNameForGeneratedType(basePackageName, choiceNode.getPath()); + 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); + } + } + + /** + * 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."); + + final Set caseNodes = choiceNode.getCases(); + if (caseNodes == null) { + return; + } + + 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); + 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); + } + } + + 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 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 is null
  • + *
  • if targetType is null
  • + *
  • if augmentedNodes is null
  • + *
+ */ + 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(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()); + } + + 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(module, basePackageName, caseTypeBuilder, childOfType, childNodes); + } + genCtx.get(module).addCaseType(caseNode.getPath(), caseTypeBuilder); + genCtx.get(module).addChoiceToCaseMapping(targetType, caseTypeBuilder, node); + } + } + } + + /** + * 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(); + if (leafDesc == null) { + leafDesc = ""; + } + + final Module parentModule = findParentModule(schemaContext, leaf); + if (leafName != null && !leaf.isAddedByUses()) { + final TypeDefinition typeDef = leaf.getType(); + + GeneratedTOBuilder genTOBuilder; + if (typeDef instanceof EnumTypeDefinition) { + returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf); + final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) typeDef; + final EnumBuilder enumBuilder = resolveInnerEnumFromTypeDefinition(enumTypeDef, leaf.getQName(), + typeBuilder); + + if (enumBuilder != null) { + returnType = enumBuilder.toInstance(typeBuilder); + } + ((TypeProviderImpl) typeProvider).putReferencedType(leaf.getPath(), returnType); + } else if (typeDef instanceof UnionType) { + genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, leaf, parentModule); + if (genTOBuilder != null) { + returnType = createReturnTypeForUnion(genTOBuilder, typeDef, typeBuilder, parentModule); + } + } else if (typeDef instanceof BitsTypeDefinition) { + genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, leaf, parentModule); + if (genTOBuilder != null) { + returnType = genTOBuilder.toInstance(); + } + } else { + final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef); + returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf, restrictions); + } + if (returnType != null) { + final MethodSignatureBuilder getter = constructGetter(typeBuilder, leafName, leafDesc, returnType); + processContextRefExtension(leaf, getter, parentModule); + } + } + } + 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, + final boolean isReadOnly, final Module module) { + if ((leaf != null) && (toBuilder != null)) { + final String leafName = leaf.getQName().getLocalName(); + String leafDesc = leaf.getDescription(); + if (leafDesc == null) { + leafDesc = ""; + } + + if (leafName != null) { + Type returnType = null; + final TypeDefinition typeDef = leaf.getType(); + 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 QName nodeName = node.getQName(); + + if (nodeName != null && !node.isAddedByUses()) { + 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); + } + + final ParameterizedType listType = Types.listTypeFor(returnType); + constructGetter(typeBuilder, nodeName.getLocalName(), node.getDescription(), listType); + return true; + } + } + return false; + } + + 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 returnType.toInstance(); + } + + private GeneratedTypeBuilder addDefaultInterfaceDefinition(final String packageName, final SchemaNode schemaNode) { + return addDefaultInterfaceDefinition(packageName, schemaNode, null); + } + + /** + * 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 + * 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) + * @return generated type builder schemaNode + */ + 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)) { + it.addImplementsType(augmentable(it)); + } + + if (schemaNode instanceof DataNodeContainer) { + addImplementedInterfaceFromUses((DataNodeContainer) schemaNode, it); + } + + 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 + * 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) { + checkArgument(schemaNode != null, "Data Schema Node cannot be NULL."); + checkArgument(packageName != null, "Package Name for Generated Type cannot be NULL."); + checkArgument(schemaNode.getQName() != null, "QName for Data Schema Node cannot be NULL."); + final String schemaNodeName = schemaNode.getQName().getLocalName(); + checkArgument(schemaNodeName != null, "Local Name of QName for Data Schema Node cannot be NULL."); + + String genTypeName; + if (prefix == null) { + genTypeName = BindingMapping.getClassName(schemaNodeName); + } else { + genTypeName = prefix + BindingMapping.getClassName(schemaNodeName); + } + + // FIXME: Validation of name conflict + final 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); + genTypeBuilders.put(packageName, builders); + } else { + final Map builders = genTypeBuilders.get(packageName); + if (!builders.containsKey(genTypeName)) { + builders.put(genTypeName, newType); + } + } + return newType; + } + + /** + * 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(); + 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, returnType)); + getMethod.setComment(comment); + getMethod.setReturnType(returnType); + return getMethod; + } + + /** + * 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, + 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; + 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); + } + } + } + + private void typeBuildersToGenTypes(final Module module, final GeneratedTypeBuilder typeBuilder, + final GeneratedTOBuilder genTOBuilder) { + checkArgument(typeBuilder != null, "Generated Type Builder cannot be NULL."); + + if (genTOBuilder != null) { + GeneratedTransferObject genTO = genTOBuilder.toInstance(); + constructGetter(typeBuilder, "key", "Returns Primary Key of Yang List Type", genTO); + genCtx.get(module).addGeneratedTOBuilder(genTOBuilder); + } + } + + /** + * Selects the names of the list keys from list and returns + * them as the list of the strings + * + * @param list + * 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 List listKeys(final ListSchemaNode list) { + final List listKeys = new ArrayList<>(); + + List keyDefinition = list.getKeyDefinition(); + if (keyDefinition != null) { + for (QName keyDef : keyDefinition) { + listKeys.add(keyDef.getLocalName()); + } + } + return listKeys; + } + + /** + * Generates for the list which contains any list keys special + * generated TO builder. + * + * @param packageName + * string with package name to which the list belongs + * @param list + * list schema node which is source of data about the list name + * @return generated TO builder which represents the keys of the + * list or null if list is null or list of + * key definitions is null or empty. + */ + private GeneratedTOBuilder resolveListKeyTOBuilder(final String packageName, final ListSchemaNode list) { + GeneratedTOBuilder genTOBuilder = null; + 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; + } + + /** + * 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) { + genTOBuilders.add((((TypeProviderImpl) typeProvider)).provideGeneratedTOBuilderForBitsTypeDefinition( + packageName, typeDef, classNameFromLeaf, parentModule.getName())); + } + 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 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 with all implemented types + */ + private GeneratedTypeBuilder addImplementedInterfaceFromUses(final DataNodeContainer dataNodeContainer, + final GeneratedTypeBuilder builder) { + for (UsesNode usesNode : dataNodeContainer.getUses()) { + if (usesNode.getGroupingPath() != null) { + 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(); + final String yangSnipet = YangTemplate.generateYangSnipet(schemaNodes); + + 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); + sb.append("
");
+        sb.append(NEW_LINE);
+        sb.append(yangSnipet);
+        sb.append("
"); + sb.append(NEW_LINE); + + return sb.toString(); + } + + private String createDescription(final SchemaNode schemaNode, final String fullyQualifiedName) { + final StringBuilder sb = new StringBuilder(); + final Module module = findParentModule(schemaContext, schemaNode); + final String yangSnipet = YangTemplate.generateYangSnipet(schemaNode); + final String formattedDescription = YangTemplate.formatToParagraph(schemaNode.getDescription(), 0); + 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"); + } + } + + if (!isNullOrEmpty(formattedDescription)) { + sb.append(formattedDescription); + sb.append(NEW_LINE); + } + 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(yangSnipet);
+        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 yangSnipet = YangTemplate.generateYangSnipet(module); + final String formattedDescription = YangTemplate.formatToParagraph(module.getDescription(), 0); + + if (!isNullOrEmpty(formattedDescription)) { + sb.append(formattedDescription); + sb.append(NEW_LINE); + } + 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(yangSnipet);
+        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; + } + +}