2 * Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.mdsal.binding.javav2.generator.impl;
11 import static com.google.common.base.Preconditions.checkArgument;
12 import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.addTOToTypeBuilder;
13 import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.annotateDeprecatedIfNecessary;
14 import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.augGenTypeName;
15 import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.constructGetter;
16 import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.createDescription;
17 import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.createReturnTypeForUnion;
18 import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.getAugmentIdentifier;
19 import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.isInnerType;
20 import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.qNameConstant;
21 import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.resolveInnerEnumFromTypeDefinition;
22 import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.resolveListKeyTOBuilder;
23 import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingGeneratorUtil.computeDefaultSUID;
24 import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingGeneratorUtil.packageNameForGeneratedType;
25 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findParentModule;
27 import com.google.common.annotations.Beta;
28 import com.google.common.base.Preconditions;
29 import java.util.HashMap;
30 import java.util.List;
32 import org.opendaylight.mdsal.binding.javav2.generator.spi.TypeProvider;
33 import org.opendaylight.mdsal.binding.javav2.generator.util.BindingGeneratorUtil;
34 import org.opendaylight.mdsal.binding.javav2.generator.util.BindingTypes;
35 import org.opendaylight.mdsal.binding.javav2.generator.util.Types;
36 import org.opendaylight.mdsal.binding.javav2.generator.util.generated.type.builder.GeneratedPropertyBuilderImpl;
37 import org.opendaylight.mdsal.binding.javav2.generator.util.generated.type.builder.GeneratedTypeBuilderImpl;
38 import org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeProviderImpl;
39 import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedTransferObject;
40 import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedType;
41 import org.opendaylight.mdsal.binding.javav2.model.api.Restrictions;
42 import org.opendaylight.mdsal.binding.javav2.model.api.Type;
43 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.EnumBuilder;
44 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.GeneratedPropertyBuilder;
45 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.GeneratedTOBuilder;
46 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.GeneratedTypeBuilder;
47 import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode;
48 import org.opendaylight.mdsal.binding.javav2.spec.runtime.BindingNamespaceType;
49 import org.opendaylight.mdsal.binding.javav2.spec.structural.Augmentable;
50 import org.opendaylight.mdsal.binding.javav2.util.BindingMapping;
51 import org.opendaylight.yangtools.yang.common.QName;
52 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
53 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
54 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
55 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
56 import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
57 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
58 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
59 import org.opendaylight.yangtools.yang.model.api.Module;
60 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
61 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
62 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
63 import org.opendaylight.yangtools.yang.model.api.Status;
64 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
65 import org.opendaylight.yangtools.yang.model.api.UsesNode;
66 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
67 import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
68 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
69 import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
72 * Helper util class used for generation of types in Binding spec v2.
75 final class GenHelperUtil {
77 private GenHelperUtil() {
78 throw new UnsupportedOperationException("Util class");
82 * Create GeneratedTypeBuilder object from module argument.
85 * Module object from which builder will be created
87 * @param verboseClassComments
89 * @return <code>GeneratedTypeBuilder</code> which is internal
90 * representation of the module
91 * @throws IllegalArgumentException
94 static GeneratedTypeBuilder moduleToDataType(final Module module, final Map<Module, ModuleContext> genCtx, final boolean verboseClassComments) {
95 Preconditions.checkArgument(module != null, "Module reference cannot be NULL.");
97 final GeneratedTypeBuilder moduleDataTypeBuilder = moduleTypeBuilder(module, "Data", verboseClassComments);
98 addImplementedInterfaceFromUses(module, moduleDataTypeBuilder, genCtx);
99 moduleDataTypeBuilder.addImplementsType(BindingTypes.TREE_ROOT);
100 moduleDataTypeBuilder.addComment(module.getDescription());
101 moduleDataTypeBuilder.setDescription(createDescription(module, verboseClassComments));
102 moduleDataTypeBuilder.setReference(module.getReference());
103 return moduleDataTypeBuilder;
107 * Generates type builder for <code>module</code>.
110 * Module which is source of package name for generated type
113 * string which is added to the module class name representation
115 * @param verboseClassComments
116 * @return instance of GeneratedTypeBuilder which represents
117 * <code>module</code>.
118 * @throws IllegalArgumentException
119 * if <code>module</code> is null
121 private static GeneratedTypeBuilder moduleTypeBuilder(final Module module, final String postfix, final boolean
122 verboseClassComments) {
123 Preconditions.checkArgument(module != null, "Module reference cannot be NULL.");
124 final String packageName = BindingMapping.getRootPackageName(module);
125 // underscore used as separator for distinction of module name parts
126 final String moduleName = new StringBuilder(module.getName()).append('_').append(postfix).toString();
128 final GeneratedTypeBuilderImpl moduleBuilder = new GeneratedTypeBuilderImpl(packageName, moduleName);
129 moduleBuilder.setDescription(createDescription(module, verboseClassComments));
130 moduleBuilder.setReference(module.getReference());
131 moduleBuilder.setModuleName(moduleName);
133 return moduleBuilder;
137 * Adds the implemented types to type builder.
139 * The method passes through the list of <i>uses</i> in
140 * {@code dataNodeContainer}. For every <i>use</i> is obtained corresponding
141 * generated type from all groupings
142 * allGroupings} which is added as <i>implements type</i> to
143 * <code>builder</code>
145 * @param dataNodeContainer
146 * element which contains the list of used YANG groupings
148 * builder to which are added implemented types according to
149 * <code>dataNodeContainer</code>
150 * @param genCtx generated context
151 * @return generated type builder with all implemented types
153 private static GeneratedTypeBuilder addImplementedInterfaceFromUses(final DataNodeContainer dataNodeContainer,
154 final GeneratedTypeBuilder builder, final Map<Module, ModuleContext> genCtx) {
155 for (final UsesNode usesNode : dataNodeContainer.getUses()) {
156 final GeneratedType genType = findGroupingByPath(usesNode.getGroupingPath(), genCtx).toInstance();
157 if (genType == null) {
158 throw new IllegalStateException("Grouping " + usesNode.getGroupingPath() + "is not resolved for "
159 + builder.getName());
161 builder.addImplementsType(genType);
166 static GeneratedTypeBuilder findGroupingByPath(final SchemaPath path, final Map<Module, ModuleContext> genCtx) {
167 for (final ModuleContext ctx : genCtx.values()) {
168 final GeneratedTypeBuilder result = ctx.getGrouping(path);
169 if (result != null) {
177 * Adds the methods to <code>typeBuilder</code> which represent subnodes of
178 * node for which <code>typeBuilder</code> was created.
180 * The subnodes aren't mapped to the methods if they are part of grouping or
181 * augment (in this case are already part of them).
185 * @param basePackageName
186 * string contains the module package name
188 * generated type builder which represents any node. The subnodes
189 * of this node are added to the <code>typeBuilder</code> as
190 * methods. The subnode can be of type leaf, leaf-list, list,
195 * set of data schema nodes which are the children of the node
196 * for which <code>typeBuilder</code> was created
197 * @return generated type builder which is the same builder as input
198 * parameter. The getter methods (representing child nodes) could be
201 static GeneratedTypeBuilder resolveDataSchemaNodes(final Module module, final String basePackageName,
202 final GeneratedTypeBuilder parent, final GeneratedTypeBuilder childOf,
203 final Iterable<DataSchemaNode> schemaNodes, final Map<Module, ModuleContext> genCtx,
204 final SchemaContext schemaContext, final boolean verboseClassComments,
205 final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders,
206 final TypeProvider typeProvider) {
208 if (schemaNodes != null && parent != null) {
209 for (final DataSchemaNode schemaNode : schemaNodes) {
210 if (!schemaNode.isAugmenting() && !schemaNode.isAddedByUses()) {
211 addSchemaNodeToBuilderAsMethod(basePackageName, schemaNode, parent, childOf, module, genCtx,
212 schemaContext, verboseClassComments, genTypeBuilders, typeProvider);
219 static GeneratedTypeBuilder addDefaultInterfaceDefinition(final String packageName, final SchemaNode
220 schemaNode, final Module module, final Map<Module, ModuleContext> genCtx, final SchemaContext schemaContext,
221 final boolean verboseClassComments, final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders) {
222 return addDefaultInterfaceDefinition(packageName, schemaNode, null, module, genCtx, schemaContext,
223 verboseClassComments, genTypeBuilders);
226 static Map<Module, ModuleContext> processUsesAugments(final SchemaContext schemaContext, final
227 DataNodeContainer node, final Module module, Map<Module, ModuleContext> genCtx,
228 final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders,
229 final boolean verboseClassComments, final TypeProvider typeProvider) {
230 final String basePackageName = BindingMapping.getRootPackageName(module);
231 for (final UsesNode usesNode : node.getUses()) {
232 for (final AugmentationSchema augment : usesNode.getAugmentations()) {
233 genCtx = AugmentToGenType.usesAugmentationToGenTypes(schemaContext, basePackageName, augment, module,
234 usesNode, node, genCtx, genTypeBuilders, verboseClassComments, typeProvider);
235 genCtx = processUsesAugments(schemaContext, augment, module, genCtx, genTypeBuilders,
236 verboseClassComments, typeProvider);
242 static GeneratedTypeBuilder findChildNodeByPath(final SchemaPath path, final Map<Module, ModuleContext> genCtx) {
243 for (final ModuleContext ctx : genCtx.values()) {
244 final GeneratedTypeBuilder result = ctx.getChildNode(path);
245 if (result != null) {
252 static GeneratedTypeBuilder findCaseByPath(final SchemaPath path, final Map<Module, ModuleContext> genCtx) {
253 for (final ModuleContext ctx : genCtx.values()) {
254 final GeneratedTypeBuilder result = ctx.getCase(path);
255 if (result != null) {
263 * Returns a generated type builder for an augmentation.
265 * The name of the type builder is equal to the name of augmented node with
266 * serial number as suffix.
270 * @param augmentPackageName
271 * string with contains the package name to which the augment
273 * @param basePackageName
274 * string with the package name to which the augmented node
276 * @param targetTypeRef
279 * augmentation schema which contains data about the child nodes
280 * and uses of augment
281 * @return generated type builder for augment in genCtx
283 static Map<Module, ModuleContext> addRawAugmentGenTypeDefinition(final Module module, final String augmentPackageName,
284 final String basePackageName, final Type targetTypeRef, final AugmentationSchema augSchema,
285 final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders, final Map<Module, ModuleContext> genCtx) {
287 Map<String, GeneratedTypeBuilder> augmentBuilders = genTypeBuilders.get(augmentPackageName);
288 if (augmentBuilders == null) {
289 augmentBuilders = new HashMap<>();
290 genTypeBuilders.put(augmentPackageName, augmentBuilders);
292 String augIdentifier = getAugmentIdentifier(augSchema.getUnknownSchemaNodes());
294 if (augIdentifier == null) {
295 augIdentifier = augGenTypeName(augmentBuilders, targetTypeRef.getName());
298 GeneratedTypeBuilder augTypeBuilder = new GeneratedTypeBuilderImpl(augmentPackageName, augIdentifier);
300 augTypeBuilder.addImplementsType(BindingTypes.TREE_NODE);
301 augTypeBuilder.addImplementsType(Types.augmentationTypeFor(targetTypeRef));
302 annotateDeprecatedIfNecessary(augSchema.getStatus(), augTypeBuilder);
303 augTypeBuilder = addImplementedInterfaceFromUses(augSchema, augTypeBuilder, genCtx);
305 augTypeBuilder = augSchemaNodeToMethods(module, basePackageName, augTypeBuilder, augTypeBuilder, augSchema
307 augmentBuilders.put(augTypeBuilder.getName(), augTypeBuilder);
309 if(!augSchema.getChildNodes().isEmpty()) {
310 genCtx.get(module).addTypeToAugmentation(augTypeBuilder, augSchema);
313 genCtx.get(module).addAugmentType(augTypeBuilder);
318 * Adds the methods to <code>typeBuilder</code> what represents subnodes of
319 * node for which <code>typeBuilder</code> was created.
323 * @param basePackageName
324 * string contains the module package name
326 * generated type builder which represents any node. The subnodes
327 * of this node are added to the <code>typeBuilder</code> as
328 * methods. The subnode can be of type leaf, leaf-list, list,
333 * set of data schema nodes which are the children of the node
334 * for which <code>typeBuilder</code> was created
335 * @return generated type builder which is the same object as the input
336 * parameter <code>typeBuilder</code>. The getter method could be
339 private static GeneratedTypeBuilder augSchemaNodeToMethods(final Module module, final String basePackageName,
340 final GeneratedTypeBuilder typeBuilder, final GeneratedTypeBuilder childOf,
341 final Iterable<DataSchemaNode> schemaNodes) {
342 if (schemaNodes != null && typeBuilder != null) {
343 for (final DataSchemaNode schemaNode : schemaNodes) {
344 if (!schemaNode.isAugmenting()) {
345 //TODO: design decomposition and implement it
346 //addSchemaNodeToBuilderAsMethod(basePackageName, schemaNode, typeBuilder, childOf, module);
354 * Instantiates generated type builder with <code>packageName</code> and
355 * <code>schemaNode</code>.
357 * The new builder always implements
358 * {@link TreeNode TreeNode}.<br>
359 * If <code>schemaNode</code> is instance of GroupingDefinition it also
360 * implements {@link Augmentable
362 * If <code>schemaNode</code> is instance of
363 * {@link org.opendaylight.yangtools.yang.model.api.DataNodeContainer
364 * DataNodeContainer} it can also implement nodes which are specified in
368 * string with the name of the package to which
369 * <code>schemaNode</code> belongs.
371 * schema node for which is created generated type builder
373 * parent type (can be null)
374 * @param schemaContext schema context
375 * @return generated type builder <code>schemaNode</code>
377 private static GeneratedTypeBuilder addDefaultInterfaceDefinition(final String packageName, final SchemaNode
378 schemaNode, final Type parent, final Module module, final Map<Module, ModuleContext> genCtx,
379 final SchemaContext schemaContext, final boolean verboseClassComments, final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders) {
381 GeneratedTypeBuilder it = addRawInterfaceDefinition(packageName, schemaNode, schemaContext, "",
382 verboseClassComments, genTypeBuilders);
383 if (parent == null) {
384 it.addImplementsType(BindingTypes.TREE_NODE);
386 it.addImplementsType(BindingTypes.treeChildNode(parent));
388 if (!(schemaNode instanceof GroupingDefinition)) {
389 it.addImplementsType(BindingTypes.augmentable(it));
392 if (schemaNode instanceof DataNodeContainer) {
393 //TODO: design decomposition and implement it
394 //groupingsToGenTypes(module, ((DataNodeContainer) schemaNode).getGroupings());
395 it = addImplementedInterfaceFromUses((DataNodeContainer) schemaNode, it, genCtx);
402 * Returns reference to generated type builder for specified
403 * <code>schemaNode</code> with <code>packageName</code>.
405 * Firstly the generated type builder is searched in
406 * {@link BindingGeneratorImpl#genTypeBuilders genTypeBuilders}. If it isn't
407 * found it is created and added to <code>genTypeBuilders</code>.
410 * string with the package name to which returning generated type
413 * schema node which provide data about the schema node name
414 * @param schemaContext
416 * return type name prefix
417 * @return generated type builder for <code>schemaNode</code>
418 * @throws IllegalArgumentException
420 * <li>if <code>schemaNode</code> is null</li>
421 * <li>if <code>packageName</code> is null</li>
422 * <li>if QName of schema node is null</li>
423 * <li>if schemaNode name is null</li>
427 private static GeneratedTypeBuilder addRawInterfaceDefinition(final String packageName, final SchemaNode schemaNode,
428 final SchemaContext schemaContext, final String prefix, final boolean verboseClassComments,
429 final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders) {
431 Preconditions.checkArgument(schemaNode != null, "Data Schema Node cannot be NULL.");
432 Preconditions.checkArgument(packageName != null, "Package Name for Generated Type cannot be NULL.");
433 String schemaNodeName = schemaNode.getQName().getLocalName();
434 Preconditions.checkArgument(schemaNodeName != null, "Local Name of QName for Data Schema Node cannot be NULL.");
436 if (prefix != null && !prefix.isEmpty()) {
437 // underscore used as separator for distinction of class name parts
438 schemaNodeName = new StringBuilder(prefix).append('_').append(schemaNodeName).toString();
441 final GeneratedTypeBuilderImpl newType = new GeneratedTypeBuilderImpl(packageName, schemaNodeName);
442 final Module module = SchemaContextUtil.findParentModule(schemaContext, schemaNode);
443 qNameConstant(newType, BindingMapping.QNAME_STATIC_FIELD_NAME, schemaNode.getQName());
444 newType.addComment(schemaNode.getDescription());
445 newType.setDescription(createDescription(schemaNode, newType.getFullyQualifiedName(), schemaContext, verboseClassComments));
446 newType.setReference(schemaNode.getReference());
447 newType.setSchemaPath((List<QName>) schemaNode.getPath().getPathFromRoot());
448 newType.setModuleName(module.getName());
450 if (!genTypeBuilders.containsKey(packageName)) {
451 final Map<String, GeneratedTypeBuilder> builders = new HashMap<>();
452 builders.put(newType.getName(), newType);
453 genTypeBuilders.put(packageName, builders);
455 final Map<String, GeneratedTypeBuilder> builders = genTypeBuilders.get(packageName);
456 if (!builders.containsKey(newType.getName())) {
457 builders.put(newType.getName(), newType);
464 private static void addSchemaNodeToBuilderAsMethod(final String basePackageName, final DataSchemaNode node,
465 final GeneratedTypeBuilder typeBuilder, final GeneratedTypeBuilder childOf, final Module module,
466 final Map<Module, ModuleContext> genCtx, final SchemaContext schemaContext, final boolean verboseClassComments,
467 final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders, final TypeProvider typeProvider) {
468 //TODO: implement rest of schema nodes GTO building
469 if (node != null && typeBuilder != null) {
470 if (node instanceof ContainerSchemaNode) {
471 containerToGenType(module, basePackageName, typeBuilder, childOf, (ContainerSchemaNode) node,
472 schemaContext, verboseClassComments, genCtx, genTypeBuilders, typeProvider);
473 } else if (node instanceof LeafSchemaNode) {
474 resolveLeafSchemaNodeAsMethod(schemaContext, typeBuilder, genCtx, (LeafSchemaNode) node, module,
476 } else if (node instanceof ListSchemaNode) {
477 listToGenType(module, basePackageName, typeBuilder, childOf, (ListSchemaNode) node, schemaContext,
478 verboseClassComments, genCtx, genTypeBuilders, typeProvider);
484 private static void containerToGenType(final Module module, final String basePackageName,
485 final GeneratedTypeBuilder parent, final GeneratedTypeBuilder childOf, final ContainerSchemaNode node,
486 final SchemaContext schemaContext, final boolean verboseClassComments, final Map<Module, ModuleContext> genCtx,
487 final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders, final TypeProvider typeProvider) {
489 final GeneratedTypeBuilder genType = processDataSchemaNode(module, basePackageName, childOf, node,
490 schemaContext, verboseClassComments, genCtx, genTypeBuilders, typeProvider);
491 if (genType != null) {
492 constructGetter(parent, node.getQName().getLocalName(), node.getDescription(), genType, node.getStatus());
493 resolveDataSchemaNodes(module, basePackageName, genType, genType, node.getChildNodes(), genCtx,
494 schemaContext, verboseClassComments, genTypeBuilders, typeProvider);
498 private static void listToGenType(final Module module, final String basePackageName, final GeneratedTypeBuilder
499 parent, final GeneratedTypeBuilder childOf, final ListSchemaNode node, final SchemaContext schemaContext,
500 final boolean verboseClassComments, final Map<Module, ModuleContext> genCtx,
501 final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders, final TypeProvider typeProvider) {
502 final GeneratedTypeBuilder genType = processDataSchemaNode(module, basePackageName, childOf, node,
503 schemaContext, verboseClassComments, genCtx, genTypeBuilders, typeProvider);
504 if (genType != null) {
505 final String nodeName = node.getQName().getLocalName();
506 constructGetter(parent, nodeName, node.getDescription(),
507 Types.listTypeFor(genType), node.getStatus());
508 final List<QName> listKeys = node.getKeyDefinition();
509 final String packageName = new StringBuilder(packageNameForGeneratedType(basePackageName, node.getPath(),
510 BindingNamespaceType.Key)).append('.').append(nodeName).toString();
512 final GeneratedTOBuilder genTOBuilder = resolveListKeyTOBuilder(packageName, node);
514 for (final DataSchemaNode schemaNode : node.getChildNodes()) {
515 if (!schemaNode.isAugmenting()) {
516 addSchemaNodeToListBuilders(nodeName, basePackageName, schemaNode, genType, genTOBuilder, listKeys,
517 module, typeProvider, schemaContext, genCtx, genTypeBuilders, verboseClassComments);
522 if (genTOBuilder != null) {
523 final GeneratedPropertyBuilder prop = new GeneratedPropertyBuilderImpl("serialVersionUID");
524 prop.setValue(Long.toString(computeDefaultSUID(genTOBuilder)));
525 genTOBuilder.setSUID(prop);
528 typeBuildersToGenTypes(module, genType, genTOBuilder, genCtx);
532 private static void typeBuildersToGenTypes(final Module module, final GeneratedTypeBuilder typeBuilder,
533 final GeneratedTOBuilder genTOBuilder, final Map<Module, ModuleContext> genCtx) {
534 checkArgument(typeBuilder != null, "Generated Type Builder cannot be NULL.");
535 if (genTOBuilder != null) {
536 final GeneratedTransferObject genTO = genTOBuilder.toInstance();
537 constructGetter(typeBuilder, "key", "Returns Primary Key of Yang List Type", genTO, Status.CURRENT);
538 genCtx.get(module).addGeneratedTOBuilder(genTOBuilder);
543 * Converts <code>leaf</code> to the getter method which is added to
544 * <code>typeBuilder</code>.
547 * generated type builder to which is added getter method as
548 * <code>leaf</code> mapping
550 * leaf schema node which is mapped as getter method which is
551 * added to <code>typeBuilder</code>
553 * Module in which type was defined
554 * @return boolean value
556 * <li>false - if <code>leaf</code> or <code>typeBuilder</code> are
558 * <li>true - in other cases</li>
561 private static Type resolveLeafSchemaNodeAsMethod(final SchemaContext schemaContext, final GeneratedTypeBuilder
562 typeBuilder, final Map<Module, ModuleContext> genCtx, final LeafSchemaNode leaf, final Module module,
563 final TypeProvider typeProvider) {
564 if (leaf == null || typeBuilder == null || leaf.isAddedByUses()) {
568 final String leafName = leaf.getQName().getLocalName();
569 if (leafName == null) {
573 final Module parentModule = findParentModule(schemaContext, leaf);
574 Type returnType = null;
576 final TypeDefinition<?> typeDef = leaf.getType();
577 if (isInnerType(leaf, typeDef)) {
578 if (typeDef instanceof EnumTypeDefinition) {
579 returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf);
580 final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) typeDef;
581 final EnumBuilder enumBuilder = resolveInnerEnumFromTypeDefinition(enumTypeDef, leaf.getQName(),
582 genCtx, typeBuilder, module);
583 if (enumBuilder != null) {
584 returnType = enumBuilder.toInstance(typeBuilder);
586 ((TypeProviderImpl) typeProvider).putReferencedType(leaf.getPath(), returnType);
587 } else if (typeDef instanceof UnionTypeDefinition) {
588 final GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, leaf, parentModule,
589 typeProvider, schemaContext);
590 if (genTOBuilder != null) {
591 //TODO: https://bugs.opendaylight.org/show_bug.cgi?id=2289
592 returnType = createReturnTypeForUnion(genTOBuilder, typeDef, typeBuilder, parentModule, typeProvider);
594 } else if (typeDef instanceof BitsTypeDefinition) {
595 final GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, leaf, parentModule,
596 typeProvider, schemaContext);
597 if (genTOBuilder != null) {
598 returnType = genTOBuilder.toInstance();
601 // It is constrained version of already declared type (inner declared type exists,
602 // onlyfor special cases (Enum, Union, Bits), which were already checked.
603 // In order to get proper class we need to look up closest derived type
604 // and apply restrictions from leaf type
605 final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
606 returnType = typeProvider.javaTypeForSchemaDefinitionType(getBaseOrDeclaredType(typeDef), leaf,
610 final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
611 returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf, restrictions);
614 if (returnType == null) {
618 if (typeDef instanceof EnumTypeDefinition) {
619 ((TypeProviderImpl) typeProvider).putReferencedType(leaf.getPath(), returnType);
622 String leafDesc = leaf.getDescription();
623 if (leafDesc == null) {
627 constructGetter(typeBuilder, leafName, leafDesc, returnType, leaf.getStatus());
628 genCtx.get(module).addChildNodeType(leaf, typeBuilder);
633 * Adds <code>schemaNode</code> to <code>typeBuilder</code> as getter method
634 * or to <code>genTOBuilder</code> as property.
637 * string contains the name of list
638 * @param basePackageName
639 * string contains the module package name
641 * data schema node which should be added as getter method to
642 * <code>typeBuilder</code> or as a property to
643 * <code>genTOBuilder</code> if is part of the list key
645 * generated type builder for the list schema node
646 * @param genTOBuilder
647 * generated TO builder for the list keys
649 * list of string which contains QNames of the list keys
652 * @param typeProvider
653 * provider that defines contract for generated types
654 * @param schemaContext
657 * map of generated entities in context of YANG modules
658 * @param genTypeBuilders
659 * map of generated type builders
660 * @param verboseClassComments
661 * generate verbose comments
662 * @throws IllegalArgumentException
664 * <li>if <code>schemaNode</code> equals null</li>
665 * <li>if <code>typeBuilder</code> equals null</li>
668 private static void addSchemaNodeToListBuilders(final String nodeName, final String basePackageName,
669 final DataSchemaNode schemaNode, final GeneratedTypeBuilder typeBuilder,
670 final GeneratedTOBuilder genTOBuilder, final List<QName> listKeys, final Module module,
671 final TypeProvider typeProvider, final SchemaContext schemaContext, final Map<Module, ModuleContext> genCtx,
672 final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders, final boolean verboseClassComments) {
673 checkArgument(schemaNode != null, "Data Schema Node cannot be NULL.");
674 checkArgument(typeBuilder != null, "Generated Type Builder cannot be NULL.");
676 if (schemaNode instanceof LeafSchemaNode) {
677 final LeafSchemaNode leaf = (LeafSchemaNode) schemaNode;
678 final QName leafQName = leaf.getQName();
679 final String leafName = leafQName.getLocalName();
680 String leafPckgName = basePackageName;
681 boolean isKeyPart = false;
682 if (listKeys.contains(leafQName)) {
683 leafPckgName = new StringBuilder(leafPckgName).append('.').append(BindingNamespaceType.Key).append('.')
684 .append(nodeName).toString();
687 leafPckgName = new StringBuilder(leafPckgName).append('.').append(BindingNamespaceType.Data).append('.')
688 .append(nodeName).toString();
691 final String leafGTOName = new StringBuilder(nodeName).append('_').append(leafName).toString();
692 final GeneratedTypeBuilder leafGTp = new GeneratedTypeBuilderImpl(leafPckgName, leafGTOName);
693 resolveLeafSchemaNodeAsMethod(schemaContext, leafGTp, genCtx, leaf, module,
696 constructGetter(typeBuilder, leafGTOName, schemaNode.getDescription(), leafGTp, Status.CURRENT);
699 AuxiliaryGenUtils.resolveLeafSchemaNodeAsProperty(genTOBuilder, leaf, leafGTp, true);
701 } else if (!schemaNode.isAddedByUses()) {
702 //TODO: implement leaf list to generated type
703 //TODO: implement choice to generated type
704 if (schemaNode instanceof ContainerSchemaNode) {
705 containerToGenType(module, basePackageName, typeBuilder, typeBuilder, (ContainerSchemaNode) schemaNode,
706 schemaContext, verboseClassComments, genCtx, genTypeBuilders, typeProvider);
707 } else if (schemaNode instanceof ListSchemaNode) {
708 listToGenType(module, basePackageName, typeBuilder, typeBuilder, (ListSchemaNode) schemaNode,
709 schemaContext, verboseClassComments, genCtx, genTypeBuilders, typeProvider);
714 private static TypeDefinition<?> getBaseOrDeclaredType(final TypeDefinition<?> typeDef) {
715 final TypeDefinition<?> baseType = typeDef.getBaseType();
716 return (baseType != null && baseType.getBaseType() != null) ? baseType : typeDef;
719 @SuppressWarnings({ "rawtypes", "unchecked" })
720 private static GeneratedTypeBuilder processDataSchemaNode(final Module module, final String basePackageName,
721 final GeneratedTypeBuilder childOf, final DataSchemaNode node, final SchemaContext schemaContext,
722 final boolean verboseClassComments, final Map<Module, ModuleContext> genCtx, final Map<String, Map<String,
723 GeneratedTypeBuilder>> genTypeBuilders, final TypeProvider typeProvider) {
725 if (node.isAugmenting() || node.isAddedByUses()) {
728 final String packageName = packageNameForGeneratedType(basePackageName, node.getPath(), BindingNamespaceType.Data);
729 final GeneratedTypeBuilder genType = addDefaultInterfaceDefinition(packageName, node, childOf, module,
730 genCtx, schemaContext, verboseClassComments, genTypeBuilders);
731 genType.addComment(node.getDescription());
732 annotateDeprecatedIfNecessary(node.getStatus(), genType);
733 genType.setDescription(createDescription(node, genType.getFullyQualifiedName(), schemaContext, verboseClassComments));
734 genType.setModuleName(module.getName());
735 genType.setReference(node.getReference());
736 genType.setSchemaPath((List) node.getPath().getPathFromRoot());
737 if (node instanceof DataNodeContainer) {
738 genCtx.get(module).addChildNodeType(node, genType);
739 //TODO: implement groupings to GTO building first
740 // groupingsToGenTypes(module, ((DataNodeContainer) node).getGroupings());
741 processUsesAugments(schemaContext, (DataNodeContainer) node, module, genCtx, genTypeBuilders,
742 verboseClassComments, typeProvider);