/* * 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.api.type.UnionTypeDefinition; import org.opendaylight.yangtools.yang.model.util.DataNodeIterator; import org.opendaylight.yangtools.yang.model.util.ExtendedType; import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil; import org.opendaylight.yangtools.yang.model.util.UnionType; 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 contains the module package name * @param identity * IdentitySchemaNode which contains data about identity * @param context * SchemaContext which is used to get package and name * information about base of identity * * @return GeneratedType which is generated from identity (object of type * IdentitySchemaNode * */ private GeneratedType identityToGenType(final String basePackageName, final IdentitySchemaNode identity, final SchemaContext context) { 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 contains the module package name * @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 contains the module package name * @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(); } /** * 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 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 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 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; } /** * Adds the methods to typeBuilder what represents subnodes of * node for which typeBuilder was created. * * @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 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 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; } /** * Adds to typeBuilder a method which is derived from * schemaNode. * * @param basePackageName * string with the module package name * @param schemaNode * data schema node which is added to typeBuilder as * a method * @param typeBuilder * generated type builder to which is schemaNode * added as a method. */ 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); } } } /** * Creates a getter method for a choice node. * * Firstly generated type builder for choice is created or found in * {@link BindingGeneratorImpl#allGroupings allGroupings}. The package name * in the builder is created as concatenation of module package name and * names of all parent nodes. In the end the getter method for choice is * added to typeBuilder and return type is set to choice * builder. * * @param basePackageName * string with the module package name * @param typeBuilder * generated type builder to which is choiceNode * added as getter method * @param choiceNode * choice node which is mapped as a getter method * @throws IllegalArgumentException *
    *
  • if basePackageName equals null
  • *
  • if typeBuilder equals null
  • *
  • if choiceNode equals null
  • *
* */ 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); } } /** * 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 basePackageName * string with the module package name * @param choiceNode * choice node which is mapped to generated type. Also child * nodes - cases are mapped to generated types. * @return list of generated types which contains generated type for choice * and generated types for all cases which aren't added do choice * through uses. * @throws IllegalArgumentException *
    *
  • if basePackageName equals null
  • *
  • if choiceNode equals null
  • *
* */ 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; } /** * 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 basePackageName * string with the module package name * @param refChoiceType * type which represents superior case * @param caseNodes * set of choice case nodes which are mapped to generated types * @return list of generated types for caseNodes. * @throws IllegalArgumentException *
    *
  • if basePackageName equals null
  • *
  • if refChoiceType equals null
  • *
  • if caseNodes equals null
  • *
* * */ 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; } /** * 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 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 = addTOToTypeBuilder(typeDef, typeBuilder, leafName); if (genTOBuilder != null) { returnType = new ReferencedTypeImpl(genTOBuilder.getPackageName(), genTOBuilder.getName()); } } else if (typeDef instanceof BitsTypeDefinition) { GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(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; } /** * 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 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, 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; } /** * Converts node leaf list schema node to getter method of * typeBuilder. * * @param typeBuilder * generated type builder to which is node added as * getter method * @param node * leaf list schema node which is added to * typeBuilder as getter method * @return boolean value *
    *
  • true - if node, typeBuilder, * nodeName equal null or node is added by uses
  • *
  • false - other cases
  • *
*/ private boolean resolveLeafListSchemaNode(final GeneratedTypeBuilder typeBuilder, final LeafListSchemaNode node) { if ((node != null) && (typeBuilder != null)) { final String nodeName = node.getQName().getLocalName(); String nodeDesc = node.getDescription(); if (nodeDesc == null) { nodeDesc = ""; } 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; } /** * Creates a getter method for a container node. * * Firstly generated type builder for container is created or found in * {@link BindingGeneratorImpl#allGroupings allGroupings}. The package name * in the builder is created as concatenation of module package name and * names of all parent nodes. In the end the getter method for container is * added to typeBuilder and return type is set to container * type builder. * * @param basePackageName * string with the module package name * @param typeBuilder * generated type builder to which is containerNode * added as getter method * @param containerNode * container schema node which is mapped as getter method to * typeBuilder * @return boolean value *
    *
  • false - if containerNode, * typeBuilder, container node name equal null or * containerNode is added by uses
  • *
  • true - other cases
  • *
*/ 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; } /** * Creates a getter method for a list node. * * Firstly generated type builder for list is created or found in * {@link BindingGeneratorImpl#allGroupings allGroupings}. The package name * in the builder is created as concatenation of module package name and * names of all parent nodes. In the end the getter method for list is added * to typeBuilder and return type is set to list type builder. * * @param basePackageName * string with the module package name * @param typeBuilder * generated type builder to which is added as * getter method * @param listNode * list schema node which is mapped as getter method to * typeBuilder * @return boolean value *
    *
  • false - if listNode, typeBuilder, * list node name equal null or listNode is added by * uses
  • *
  • true - other cases
  • *
*/ private boolean resolveListSchemaNode(final String basePackageName, final GeneratedTypeBuilder typeBuilder, final ListSchemaNode listNode) { if ((listNode != null) && (typeBuilder != null)) { final String listName = listNode.getQName().getLocalName(); if (listName != null && !listNode.isAddedByUses()) { final String packageName = packageNameForGeneratedType(basePackageName, listNode.getPath()); final GeneratedTypeBuilder rawGenType = addDefaultInterfaceDefinition(packageName, listNode); constructGetter(typeBuilder, listName, listNode.getDescription(), Types.listTypeFor(rawGenType)); return true; } } return false; } /** * 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 * @return generated type builder schemaNode */ private GeneratedTypeBuilder addDefaultInterfaceDefinition(final String packageName, final SchemaNode schemaNode) { final GeneratedTypeBuilder builder = addRawInterfaceDefinition(packageName, schemaNode, ""); builder.addImplementsType(Types.DATA_OBJECT); if (!(schemaNode instanceof GroupingDefinition)) { builder.addImplementsType(Types.augmentableTypeFor(builder)); } if (schemaNode instanceof DataNodeContainer) { addImplementedInterfaceFromUses((DataNodeContainer) schemaNode, builder); } return builder; } /** * 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 * @return generated type builder for schemaNode * @throws IllegalArgumentException *
    *
  • if schemaNode equals null
  • *
  • if packageName equals null
  • *
  • if Q name of schema node is null
  • *
  • if schema node name is nul
  • *
* */ 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; } /** * Creates the name of the getter method from methodName. * * @param methodName * string with the name of the getter method * @return string with the name of the getter method for * methodName in JAVA method format */ private String getterMethodName(final String methodName) { final StringBuilder method = new StringBuilder(); method.append("get"); method.append(parseToClassName(methodName)); return method.toString(); } /** * Creates the name of the setter method from methodName. * * @param methodName * string with the name of the setter method * @return string with the name of the setter method for * methodName in JAVA method format */ private String setterMethodName(final String methodName) { final StringBuilder method = new StringBuilder(); method.append("set"); method.append(parseToClassName(methodName)); 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)); getMethod.setComment(comment); getMethod.setReturnType(returnType); return getMethod; } /** * Creates a method signature builder as a part of * interfaceBuilder for schemaNodeName * * The method signature builder is created for the setter method of * schemaNodeName. Also comment * parameterType data are added to the builder. The return type * of the method is set to void. * * @param interfaceBuilder * generated type builder for which the setter method should be * created * @param schemaNodeName * string with schema node name. The name will be the part of the * setter method name. * @param comment * string with comment for the setter method * @param parameterType * type which represents the type of the setter method input * parameter * @return method signature builder which represents the setter method of * interfaceBuilder */ 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 GeneratedTypeBuilder typeBuilder = addDefaultInterfaceDefinition(packageName, list); final List listKeys = listKeys(list); GeneratedTOBuilder genTOBuilder = resolveListKeyTOBuilder(packageName, list); 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); } /** * 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 * @throws IllegalArgumentException *
    *
  • if schemaNode equals null
  • *
  • if typeBuilder equals null
  • *
*/ private void addSchemaNodeToListBuilders(final String basePackageName, final DataSchemaNode schemaNode, final GeneratedTypeBuilder typeBuilder, final GeneratedTOBuilder genTOBuilder, final List listKeys) { if (schemaNode == null) { throw new IllegalArgumentException("Data Schema Node cannot be NULL!"); } if (typeBuilder == null) { throw new IllegalArgumentException("Generated Type Builder cannot be NULL!"); } if (schemaNode instanceof LeafSchemaNode) { final LeafSchemaNode leaf = (LeafSchemaNode) schemaNode; final String leafName = leaf.getQName().getLocalName(); if (!listKeys.contains(leafName)) { 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; } /** * 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<>(); if (list.getKeyDefinition() != null) { final List keyDefinitions = list.getKeyDefinition(); for (final QName keyDefinition : keyDefinitions) { listKeys.add(keyDefinition.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())) { if (list != null) { final String listName = list.getQName().getLocalName() + "Key"; genTOBuilder = schemaNodeToTransferObjectBuilder(packageName, listName); } } 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. * * @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 * @return generated TO builder for typeDef */ private GeneratedTOBuilder addTOToTypeBuilder(TypeDefinition typeDef, GeneratedTypeBuilder typeBuilder, String leafName) { final String classNameFromLeaf = parseToClassName(leafName); GeneratedTOBuilder genTOBuilder = null; final String packageName = typeBuilder.getFullyQualifiedName(); if (typeDef instanceof UnionTypeDefinition) { genTOBuilder = ((TypeProviderImpl) typeProvider).provideGeneratedTOBuilderForUnionTypeDefinition(packageName, typeDef, classNameFromLeaf); } else if (typeDef instanceof BitsTypeDefinition) { genTOBuilder = ((TypeProviderImpl) typeProvider).provideGeneratedTOBuilderForBitsTypeDefinition(packageName, typeDef, classNameFromLeaf); } if (genTOBuilder != null) { typeBuilder.addEnclosingTransferObject(genTOBuilder); return genTOBuilder; } 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 coresponding * generated type from {@link BindingGeneratorImpl#allGroupings * allGroupings} which is adde 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) { 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; } }