2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
\r
4 * This program and the accompanying materials are made available under the
\r
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
\r
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
\r
8 package org.opendaylight.yangtools.sal.binding.generator.impl;
10 import java.util.ArrayList;
11 import java.util.Collections;
12 import java.util.HashMap;
13 import java.util.List;
16 import org.opendaylight.yangtools.binding.generator.util.BindingTypes;
17 import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl;
18 import org.opendaylight.yangtools.binding.generator.util.Types;
19 import org.opendaylight.yangtools.binding.generator.util.generated.type.builder.GeneratedTOBuilderImpl;
20 import org.opendaylight.yangtools.binding.generator.util.generated.type.builder.GeneratedTypeBuilderImpl;
21 import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator;
22 import org.opendaylight.yangtools.sal.binding.generator.spi.TypeProvider;
23 import org.opendaylight.yangtools.sal.binding.model.api.AccessModifier;
24 import org.opendaylight.yangtools.sal.binding.model.api.Type;
25 import org.opendaylight.yangtools.sal.binding.model.api.type.builder.EnumBuilder;
26 import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTOBuilder;
27 import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder;
28 import org.opendaylight.yangtools.sal.binding.model.api.type.builder.MethodSignatureBuilder;
29 import org.opendaylight.yangtools.sal.binding.yang.types.GroupingDefinitionDependencySort;
30 import org.opendaylight.yangtools.sal.binding.yang.types.TypeProviderImpl;
31 import org.opendaylight.yangtools.yang.binding.RpcService;
32 import org.opendaylight.yangtools.yang.common.RpcResult;
33 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
34 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
35 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
36 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
37 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
38 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
39 import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
40 import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
41 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
42 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
43 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
44 import org.opendaylight.yangtools.yang.model.api.Module;
45 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
46 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
47 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
48 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
49 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
50 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
51 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
52 import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
53 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
54 import org.opendaylight.yangtools.yang.model.util.DataNodeIterator;
55 import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
56 import org.opendaylight.yangtools.yang.model.util.UnionType;
57 import static com.google.common.base.Preconditions.*;
58 import static extension org.opendaylight.yangtools.binding.generator.util.Types.*;
59 import static org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil.*;
60 import static org.opendaylight.yangtools.binding.generator.util.BindingTypes.*;
61 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.*;
62 import org.opendaylight.yangtools.yang.parser.util.ModuleDependencySort
63 import org.opendaylight.yangtools.yang.model.util.ExtendedType;
64 import org.opendaylight.yangtools.yang.model.api.UsesNode
65 import org.opendaylight.yangtools.yang.binding.annotations.RoutingContext
66 import org.opendaylight.yangtools.sal.binding.model.api.type.builder.AnnotationTypeBuilder
67 import org.opendaylight.yangtools.yang.model.api.ModuleImport
68 import org.opendaylight.yangtools.yang.binding.DataContainer
69 import java.util.Iterator
70 import org.opendaylight.yangtools.yang.model.api.AugmentationTarget
71 import java.util.Collection
72 import org.opendaylight.yangtools.yang.model.api.YangNode
73 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition
74 import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil
75 import org.opendaylight.yangtools.sal.binding.model.api.Restrictions
76 import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedPropertyBuilder
77 import org.opendaylight.yangtools.binding.generator.util.generated.type.builder.GeneratedPropertyBuilderImpl
79 public class BindingGeneratorImpl implements BindingGenerator {
81 private final Map<Module, ModuleContext> genCtx = new HashMap()
84 * Outter key represents the package name. Outter value represents map of
\r
85 * all builders in the same package. Inner key represents the schema node
\r
86 * name (in JAVA class/interface name format). Inner value represents
\r
87 * instance of builder for schema node specified in key part.
\r
89 private Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders;
92 * Provide methods for converting YANG types to JAVA types.
\r
94 private var TypeProvider typeProvider;
97 * Holds reference to schema context to resolve data of augmented elemnt
\r
98 * when creating augmentation builder
\r
100 private var SchemaContext schemaContext;
103 * Constant with the concrete name of namespace.
\r
105 private val static String YANG_EXT_NAMESPACE = "urn:opendaylight:yang:extension:yang-ext";
108 * Constant with the concrete name of identifier.
\r
110 private val static String AUGMENT_IDENTIFIER_NAME = "augment-identifier";
113 * Resolves generated types from <code>context</code> schema nodes of all
\r
116 * Generated types are created for modules, groupings, types, containers,
\r
117 * lists, choices, augments, rpcs, notification, identities.
\r
120 * schema context which contains data about all schema nodes
\r
122 * @return list of types (usually <code>GeneratedType</code>
\r
123 * <code>GeneratedTransferObject</code>which are generated from
\r
124 * <code>context</code> data.
\r
125 * @throws IllegalArgumentException
\r
126 * if param <code>context</code> is null
\r
127 * @throws IllegalStateException
\r
128 * if <code>context</code> contain no modules
\r
130 override generateTypes(SchemaContext context) {
131 checkArgument(context !== null, "Schema Context reference cannot be NULL.");
132 checkState(context.modules !== null, "Schema Context does not contain defined modules.");
133 schemaContext = context;
134 typeProvider = new TypeProviderImpl(context);
135 val Set<Module> modules = context.modules;
136 return generateTypes(context, modules);
140 * Resolves generated types from <code>context</code> schema nodes only for
\r
141 * modules specified in <code>modules</code>
\r
143 * Generated types are created for modules, groupings, types, containers,
\r
144 * lists, choices, augments, rpcs, notification, identities.
\r
147 * schema context which contains data about all schema nodes
\r
150 * set of modules for which schema nodes should be generated
\r
152 * @return list of types (usually <code>GeneratedType</code> or
\r
153 * <code>GeneratedTransferObject</code>) which:
\r
155 * <li>are generated from <code>context</code> schema nodes and</li>
\r
156 * <li>are also part of some of the module in <code>modules</code>
\r
159 * @throws IllegalArgumentException
\r
161 * <li>if param <code>context</code> is null or</li>
\r
162 * <li>if param <code>modules</code> is null</li>
\r
164 * @throws IllegalStateException
\r
165 * if <code>context</code> contain no modules
\r
167 override generateTypes(SchemaContext context, Set<Module> modules) {
168 checkArgument(context !== null, "Schema Context reference cannot be NULL.");
169 checkState(context.modules !== null, "Schema Context does not contain defined modules.");
170 checkArgument(modules !== null, "Set of Modules cannot be NULL.");
172 schemaContext = context;
173 typeProvider = new TypeProviderImpl(context);
174 val contextModules = ModuleDependencySort.sort(context.modules);
175 genTypeBuilders = new HashMap();
177 for (contextModule : contextModules) {
178 moduleToGenTypes(contextModule, context);
180 for (contextModule : contextModules) {
181 allAugmentsToGenTypes(contextModule);
184 val List<Type> filteredGenTypes = new ArrayList();
185 for (Module m : modules) {
186 filteredGenTypes.addAll(genCtx.get(m).generatedTypes);
191 return filteredGenTypes;
194 private def void moduleToGenTypes(Module m, SchemaContext context) {
195 genCtx.put(m, new ModuleContext)
196 allTypeDefinitionsToGenTypes(m)
197 groupingsToGenTypes(m, m.groupings)
198 rpcMethodsToGenType(m)
199 allIdentitiesToGenTypes(m, context)
200 notificationsToGenType(m)
202 if (!m.childNodes.isEmpty()) {
203 val moduleType = moduleToDataType(m)
204 genCtx.get(m).addModuleNode(moduleType)
205 val basePackageName = moduleNamespaceToPackageName(m);
206 resolveDataSchemaNodes(m, basePackageName, moduleType, moduleType, m.childNodes)
211 * Converts all extended type definitions of module to the list of
\r
212 * <code>Type</code> objects.
\r
215 * module from which is obtained set of type definitions
\r
216 * @throws IllegalArgumentException
\r
218 * <li>if module equals null</li>
\r
219 * <li>if name of module equals null</li>
\r
220 * <li>if type definitions of module equal null</li>
\r
224 private def void allTypeDefinitionsToGenTypes(Module module) {
225 checkArgument(module !== null, "Module reference cannot be NULL.");
226 checkArgument(module.name !== null, "Module name cannot be NULL.");
227 val it = new DataNodeIterator(module);
228 val List<TypeDefinition<?>> typeDefinitions = it.allTypedefs;
229 checkState(typeDefinitions !== null, '''Type Definitions for module «module.name» cannot be NULL.''');
231 for (TypeDefinition<?> typedef : typeDefinitions) {
232 if (typedef !== null) {
233 val type = (typeProvider as TypeProviderImpl).generatedTypeForExtendedDefinitionType(typedef, typedef);
235 genCtx.get(module).addTypedefType(typedef.path, type)
241 private def void containerToGenType(Module module, String basePackageName, GeneratedTypeBuilder parent,
242 GeneratedTypeBuilder childOf, ContainerSchemaNode node) {
243 if (node.augmenting || node.addedByUses) {
246 val packageName = packageNameForGeneratedType(basePackageName, node.path)
247 val genType = addDefaultInterfaceDefinition(packageName, node, childOf)
248 constructGetter(parent, node.QName.localName, node.description, genType)
249 genCtx.get(module).addChildNodeType(node.path, genType)
250 resolveDataSchemaNodes(module, basePackageName, genType, genType, node.childNodes)
251 groupingsToGenTypes(module, node.groupings)
252 processUsesAugments(node, module)
255 private def void listToGenType(Module module, String basePackageName, GeneratedTypeBuilder parent,
256 GeneratedTypeBuilder childOf, ListSchemaNode node) {
257 if (node.augmenting || node.addedByUses) {
260 val packageName = packageNameForGeneratedType(basePackageName, (node).path)
261 val genType = addDefaultInterfaceDefinition(packageName, node, childOf)
262 constructGetter(parent, node.QName.localName, node.description, Types.listTypeFor(genType))
263 genCtx.get(module).addChildNodeType(node.path, genType)
264 groupingsToGenTypes(module, node.groupings)
265 processUsesAugments(node, module)
267 val List<String> listKeys = listKeys(node);
268 val genTOBuilder = resolveListKeyTOBuilder(packageName, node);
\r
270 if (genTOBuilder !== null) {
271 val identifierMarker = IDENTIFIER.parameterizedTypeFor(genType);
272 val identifiableMarker = IDENTIFIABLE.parameterizedTypeFor(genTOBuilder);
273 genTOBuilder.addImplementsType(identifierMarker);
274 genType.addImplementsType(identifiableMarker);
277 for (schemaNode : node.childNodes) {
278 if (!schemaNode.augmenting) {
279 addSchemaNodeToListBuilders(basePackageName, schemaNode, genType, genTOBuilder, listKeys, module);
283 // serialVersionUID
\r
284 if (genTOBuilder !== null) {
\r
285 val GeneratedPropertyBuilder prop = new GeneratedPropertyBuilderImpl("serialVersionUID");
\r
286 prop.setValue(Long.toString(computeDefaultSUID(genTOBuilder as GeneratedTOBuilderImpl)));
\r
287 genTOBuilder.setSUID(prop);
\r
290 typeBuildersToGenTypes(module, genType, genTOBuilder);
293 private def void processUsesAugments(DataNodeContainer node, Module module) {
294 val basePackageName = moduleNamespaceToPackageName(module);
295 for (usesNode : node.uses) {
296 for (augment : usesNode.augmentations) {
297 augmentationToGenTypes(basePackageName, augment, module, usesNode);
298 processUsesAugments(augment, module);
304 * Converts all <b>augmentation</b> of the module to the list
\r
305 * <code>Type</code> objects.
\r
308 * module from which is obtained list of all augmentation objects
\r
309 * to iterate over them
\r
310 * @throws IllegalArgumentException
\r
312 * <li>if the module equals null</li>
\r
313 * <li>if the name of module equals null</li>
\r
314 * <li>if the set of child nodes equals null</li>
\r
318 private def void allAugmentsToGenTypes(Module module) {
319 checkArgument(module !== null, "Module reference cannot be NULL.");
320 checkArgument(module.name !== null, "Module name cannot be NULL.");
321 if (module.childNodes === null) {
322 throw new IllegalArgumentException(
323 "Reference to Set of Augmentation Definitions in module " + module.name + " cannot be NULL.");
326 val basePackageName = moduleNamespaceToPackageName(module);
327 val List<AugmentationSchema> augmentations = resolveAugmentations(module);
328 for (augment : augmentations) {
329 augmentationToGenTypes(basePackageName, augment, module, null);
334 * Returns list of <code>AugmentationSchema</code> objects. The objects are
\r
335 * sorted according to the length of their target path from the shortest to
\r
339 * module from which is obtained list of all augmentation objects
\r
340 * @return list of sorted <code>AugmentationSchema</code> objects obtained
\r
341 * from <code>module</code>
\r
342 * @throws IllegalArgumentException
\r
344 * <li>if the module equals null</li>
\r
345 * <li>if the set of augmentation equals null</li>
\r
349 private def List<AugmentationSchema> resolveAugmentations(Module module) {
350 checkArgument(module !== null, "Module reference cannot be NULL.");
351 checkState(module.augmentations !== null, "Augmentations Set cannot be NULL.");
353 val Set<AugmentationSchema> augmentations = module.augmentations;
354 val List<AugmentationSchema> sortedAugmentations = new ArrayList(augmentations);
355 Collections.sort(sortedAugmentations,
356 [ augSchema1, augSchema2 |
357 if (augSchema1.targetPath.path.size() > augSchema2.targetPath.path.size()) {
359 } else if (augSchema1.targetPath.path.size() < augSchema2.targetPath.path.size()) {
364 return sortedAugmentations;
368 * Converts whole <b>module</b> to <code>GeneratedType</code> object.
\r
369 * Firstly is created the module builder object from which is vally
\r
370 * obtained reference to <code>GeneratedType</code> object.
\r
373 * module from which are obtained the module name, child nodes,
\r
374 * uses and is derived package name
\r
375 * @return <code>GeneratedType</code> which is internal representation of
\r
377 * @throws IllegalArgumentException
\r
378 * if the module equals null
\r
381 private def GeneratedTypeBuilder moduleToDataType(Module module) {
382 checkArgument(module !== null, "Module reference cannot be NULL.");
384 val moduleDataTypeBuilder = moduleTypeBuilder(module, "Data");
385 addImplementedInterfaceFromUses(module, moduleDataTypeBuilder);
386 moduleDataTypeBuilder.addImplementsType(DATA_ROOT);
387 return moduleDataTypeBuilder;
391 * Converts all <b>rpcs</b> inputs and outputs substatements of the module
\r
392 * to the list of <code>Type</code> objects. In addition are to containers
\r
393 * and lists which belong to input or output also part of returning list.
\r
396 * module from which is obtained set of all rpc objects to
\r
397 * iterate over them
\r
398 * @throws IllegalArgumentException
\r
400 * <li>if the module equals null</li>
\r
401 * <li>if the name of module equals null</li>
\r
402 * <li>if the set of child nodes equals null</li>
\r
406 private def void rpcMethodsToGenType(Module module) {
407 checkArgument(module !== null, "Module reference cannot be NULL.");
408 checkArgument(module.name !== null, "Module name cannot be NULL.");
409 checkArgument(module.childNodes !== null,
410 "Reference to Set of RPC Method Definitions in module " + module.name + " cannot be NULL.");
412 val basePackageName = moduleNamespaceToPackageName(module);
413 val Set<RpcDefinition> rpcDefinitions = module.rpcs;
414 if (rpcDefinitions.isEmpty()) {
418 val interfaceBuilder = moduleTypeBuilder(module, "Service");
419 interfaceBuilder.addImplementsType(Types.typeForClass(RpcService));
420 for (rpc : rpcDefinitions) {
422 val rpcName = parseToClassName(rpc.QName.localName);
423 val rpcMethodName = parseToValidParamName(rpcName);
424 val method = interfaceBuilder.addMethod(rpcMethodName);
425 val input = rpc.input;
426 val output = rpc.output;
428 if (input !== null) {
429 val inType = addRawInterfaceDefinition(basePackageName, input, rpcName);
430 addImplementedInterfaceFromUses(input, inType);
431 inType.addImplementsType(DATA_OBJECT);
432 inType.addImplementsType(augmentable(inType));
433 resolveDataSchemaNodes(module, basePackageName, inType, inType, input.childNodes);
434 genCtx.get(module).addChildNodeType(input.path, inType)
435 val inTypeInstance = inType.toInstance();
436 method.addParameter(inTypeInstance, "input");
439 var Type outTypeInstance = VOID;
440 if (output !== null) {
441 val outType = addRawInterfaceDefinition(basePackageName, output, rpcName);
442 addImplementedInterfaceFromUses(output, outType);
443 outType.addImplementsType(DATA_OBJECT);
444 outType.addImplementsType(augmentable(outType));
445 resolveDataSchemaNodes(module, basePackageName, outType, outType, output.childNodes);
446 genCtx.get(module).addChildNodeType(output.path, outType)
447 outTypeInstance = outType.toInstance();
450 val rpcRes = Types.parameterizedTypeFor(Types.typeForClass(RpcResult), outTypeInstance);
451 method.setReturnType(Types.parameterizedTypeFor(FUTURE, rpcRes));
455 genCtx.get(module).addTopLevelNodeType(interfaceBuilder)
459 * Converts all <b>notifications</b> of the module to the list of
\r
460 * <code>Type</code> objects. In addition are to this list added containers
\r
461 * and lists which are part of this notification.
\r
464 * module from which is obtained set of all notification objects
\r
465 * to iterate over them
\r
466 * @throws IllegalArgumentException
\r
468 * <li>if the module equals null</li>
\r
469 * <li>if the name of module equals null</li>
\r
470 * <li>if the set of child nodes equals null</li>
\r
474 private def void notificationsToGenType(Module module) {
475 checkArgument(module !== null, "Module reference cannot be NULL.");
476 checkArgument(module.name !== null, "Module name cannot be NULL.");
478 if (module.childNodes === null) {
479 throw new IllegalArgumentException(
480 "Reference to Set of Notification Definitions in module " + module.name + " cannot be NULL.");
482 val notifications = module.notifications;
483 if(notifications.empty) return;
485 val listenerInterface = moduleTypeBuilder(module, "Listener");
486 listenerInterface.addImplementsType(BindingTypes.NOTIFICATION_LISTENER);
487 val basePackageName = moduleNamespaceToPackageName(module);
489 for (notification : notifications) {
490 if (notification !== null) {
491 processUsesAugments(notification, module);
493 val notificationInterface = addDefaultInterfaceDefinition(basePackageName, notification,
494 BindingTypes.DATA_OBJECT);
495 notificationInterface.addImplementsType(NOTIFICATION);
496 genCtx.get(module).addChildNodeType(notification.path, notificationInterface)
498 // Notification object
\r
499 resolveDataSchemaNodes(module, basePackageName, notificationInterface, notificationInterface,
500 notification.childNodes);
502 listenerInterface.addMethod("on" + notificationInterface.name) //
\r
503 .setAccessModifier(AccessModifier.PUBLIC).addParameter(notificationInterface, "notification").
504 setReturnType(Types.VOID);
508 genCtx.get(module).addTopLevelNodeType(listenerInterface)
512 * Converts all <b>identities</b> of the module to the list of
\r
513 * <code>Type</code> objects.
\r
516 * module from which is obtained set of all identity objects to
\r
517 * iterate over them
\r
519 * schema context only used as input parameter for method
\r
520 * {@link identityToGenType}
\r
523 private def void allIdentitiesToGenTypes(Module module, SchemaContext context) {
524 val Set<IdentitySchemaNode> schemaIdentities = module.identities;
525 val basePackageName = moduleNamespaceToPackageName(module);
527 if (schemaIdentities !== null && !schemaIdentities.isEmpty()) {
528 for (identity : schemaIdentities) {
529 identityToGenType(module, basePackageName, identity, context);
535 * Converts the <b>identity</b> object to GeneratedType. Firstly it is
\r
536 * created transport object builder. If identity contains base identity then
\r
537 * reference to base identity is added to superior identity as its extend.
\r
538 * If identity doesn't contain base identity then only reference to abstract
\r
539 * class {@link org.opendaylight.yangtools.yang.model.api.BaseIdentity
\r
540 * BaseIdentity} is added
\r
542 * @param module current module
\r
543 * @param basePackageName
\r
544 * string contains the module package name
\r
546 * IdentitySchemaNode which contains data about identity
\r
548 * SchemaContext which is used to get package and name
\r
549 * information about base of identity
\r
552 private def void identityToGenType(Module module, String basePackageName, IdentitySchemaNode identity,
553 SchemaContext context) {
554 if (identity === null) {
557 val packageName = packageNameForGeneratedType(basePackageName, identity.path);
558 val genTypeName = parseToClassName(identity.QName.localName);
559 val newType = new GeneratedTOBuilderImpl(packageName, genTypeName);
560 val baseIdentity = identity.baseIdentity;
561 if (baseIdentity === null) {
562 newType.setExtendsType(Types.baseIdentityTO);
564 val baseIdentityParentModule = SchemaContextUtil.findParentModule(context, baseIdentity);
565 val returnTypePkgName = moduleNamespaceToPackageName(baseIdentityParentModule);
566 val returnTypeName = parseToClassName(baseIdentity.QName.localName);
567 val gto = new GeneratedTOBuilderImpl(returnTypePkgName, returnTypeName).toInstance();
568 newType.setExtendsType(gto);
570 newType.setAbstract(true);
571 genCtx.get(module).addIdentityType(newType)
575 * Converts all <b>groupings</b> of the module to the list of
\r
576 * <code>Type</code> objects. Firstly are groupings sorted according mutual
\r
577 * dependencies. At least dependend (indepedent) groupings are in the list
\r
578 * saved at first positions. For every grouping the record is added to map
\r
579 * {@link BindingGeneratorImpl#allGroupings allGroupings}
\r
583 * @param collection of groupings from which types will be generated
\r
586 private def void groupingsToGenTypes(Module module, Collection<GroupingDefinition> groupings) {
587 val basePackageName = moduleNamespaceToPackageName(module);
588 val List<GroupingDefinition> groupingsSortedByDependencies = new GroupingDefinitionDependencySort().sort(
590 for (grouping : groupingsSortedByDependencies) {
591 groupingToGenType(basePackageName, grouping, module);
596 * Converts individual grouping to GeneratedType. Firstly generated type
\r
597 * builder is created and every child node of grouping is resolved to the
\r
600 * @param basePackageName
\r
601 * string contains the module package name
\r
603 * GroupingDefinition which contains data about grouping
\r
604 * @param module current module
\r
605 * @return GeneratedType which is generated from grouping (object of type
\r
606 * <code>GroupingDefinition</code>)
\r
608 private def void groupingToGenType(String basePackageName, GroupingDefinition grouping, Module module) {
609 val packageName = packageNameForGeneratedType(basePackageName, grouping.path);
610 val genType = addDefaultInterfaceDefinition(packageName, grouping);
611 genCtx.get(module).addGroupingType(grouping.path, genType)
612 resolveDataSchemaNodes(module, basePackageName, genType, genType, grouping.childNodes);
613 groupingsToGenTypes(module, grouping.groupings);
614 processUsesAugments(grouping, module);
618 * Tries to find EnumTypeDefinition in <code>typeDefinition</code>. If base
\r
619 * type of <code>typeDefinition</code> is of the type ExtendedType then this
\r
620 * method is recursivelly called with this base type.
\r
622 * @param typeDefinition
\r
623 * TypeDefinition in which should be EnumTypeDefinition found as
\r
625 * @return EnumTypeDefinition if it is found inside
\r
626 * <code>typeDefinition</code> or <code>null</code> in other case
\r
628 private def EnumTypeDefinition enumTypeDefFromExtendedType(TypeDefinition<?> typeDefinition) {
629 if (typeDefinition !== null) {
630 if (typeDefinition.baseType instanceof EnumTypeDefinition) {
631 return typeDefinition.baseType as EnumTypeDefinition;
632 } else if (typeDefinition.baseType instanceof ExtendedType) {
633 return enumTypeDefFromExtendedType(typeDefinition.baseType);
640 * Adds enumeration builder created from <code>enumTypeDef</code> to
\r
641 * <code>typeBuilder</code>.
\r
643 * Each <code>enumTypeDef</code> item is added to builder with its name and
\r
646 * @param enumTypeDef
\r
647 * EnumTypeDefinition contains enum data
\r
649 * string contains name which will be assigned to enumeration
\r
651 * @param typeBuilder
\r
652 * GeneratedTypeBuilder to which will be enum builder assigned
\r
653 * @return enumeration builder which contais data from
\r
654 * <code>enumTypeDef</code>
\r
656 private def EnumBuilder resolveInnerEnumFromTypeDefinition(EnumTypeDefinition enumTypeDef, String enumName,
657 GeneratedTypeBuilder typeBuilder) {
658 if ((enumTypeDef !== null) && (typeBuilder !== null) && (enumTypeDef.QName !== null) &&
659 (enumTypeDef.QName.localName !== null)) {
660 val enumerationName = parseToClassName(enumName);
661 val enumBuilder = typeBuilder.addEnumeration(enumerationName);
662 enumBuilder.updateEnumPairsFromEnumTypeDef(enumTypeDef);
669 * Generates type builder for <code>module</code>.
\r
672 * Module which is source of package name for generated type
\r
675 * string which is added to the module class name representation
\r
677 * @return instance of GeneratedTypeBuilder which represents
\r
678 * <code>module</code>.
\r
679 * @throws IllegalArgumentException
\r
680 * if <code>module</code> equals null
\r
682 private def GeneratedTypeBuilder moduleTypeBuilder(Module module, String postfix) {
683 checkArgument(module !== null, "Module reference cannot be NULL.");
684 val packageName = moduleNamespaceToPackageName(module);
685 val moduleName = parseToClassName(module.name) + postfix;
686 return new GeneratedTypeBuilderImpl(packageName, moduleName);
690 * Converts <code>augSchema</code> to list of <code>Type</code> which
\r
691 * contains generated type for augmentation. In addition there are also
\r
692 * generated types for all containers, list and choices which are child of
\r
693 * <code>augSchema</code> node or a generated types for cases are added if
\r
694 * augmented node is choice.
\r
696 * @param augmentPackageName
\r
697 * string with the name of the package to which the augmentation
\r
700 * AugmentationSchema which is contains data about agumentation
\r
701 * (target path, childs...)
\r
702 * @param module current module
\r
703 * @param parentUsesNode parent uses node of this augment (can be null if this augment is not defined under uses statement)
\r
704 * @throws IllegalArgumentException
\r
706 * <li>if <code>augmentPackageName</code> equals null</li>
\r
707 * <li>if <code>augSchema</code> equals null</li>
\r
708 * <li>if target path of <code>augSchema</code> equals null</li>
\r
711 private def void augmentationToGenTypes(String augmentPackageName, AugmentationSchema augSchema, Module module,
712 UsesNode parentUsesNode) {
713 checkArgument(augmentPackageName !== null, "Package Name cannot be NULL.");
714 checkArgument(augSchema !== null, "Augmentation Schema cannot be NULL.");
715 checkState(augSchema.targetPath !== null,
716 "Augmentation Schema does not contain Target Path (Target Path is NULL).");
718 processUsesAugments(augSchema, module);
720 // EVERY augmented interface will extends Augmentation<T> interface
\r
721 // and DataObject interface
\r
722 val targetPath = augSchema.targetPath;
723 var targetSchemaNode = findDataSchemaNode(schemaContext, targetPath);
724 if (targetSchemaNode instanceof DataSchemaNode && (targetSchemaNode as DataSchemaNode).isAddedByUses()) {
725 if (parentUsesNode == null) {
726 targetSchemaNode = findOriginal(targetSchemaNode as DataSchemaNode);
728 targetSchemaNode = findOriginalTargetFromGrouping(targetSchemaNode.QName.localName, parentUsesNode);
730 if (targetSchemaNode == null) {
731 throw new NullPointerException(
732 "Failed to find target node from grouping for augmentation " + augSchema + " in module " +
737 if (targetSchemaNode !== null) {
738 var targetTypeBuilder = findChildNodeByPath(targetSchemaNode.path)
739 if (targetTypeBuilder === null) {
740 targetTypeBuilder = findCaseByPath(targetSchemaNode.path)
742 if (targetTypeBuilder === null) {
743 throw new NullPointerException("Target type not yet generated: " + targetSchemaNode);
745 if (!(targetSchemaNode instanceof ChoiceNode)) {
746 var packageName = augmentPackageName;
747 if (parentUsesNode != null) {
748 packageName = packageNameForGeneratedType(augmentPackageName, augSchema.targetPath);
750 val augTypeBuilder = addRawAugmentGenTypeDefinition(module, packageName, augmentPackageName,
751 targetTypeBuilder.toInstance, augSchema);
752 genCtx.get(module).addAugmentType(augTypeBuilder)
754 generateTypesFromAugmentedChoiceCases(module, augmentPackageName, targetTypeBuilder.toInstance,
755 targetSchemaNode as ChoiceNode, augSchema.childNodes);
761 * Utility method which search for original node defined in grouping.
\r
763 private def DataSchemaNode findOriginal(DataSchemaNode node) {
764 var DataSchemaNode result = findCorrectTargetFromGrouping(node);
765 if (result == null) {
766 result = findCorrectTargetFromAugment(node);
767 if (result != null) {
768 if (result.addedByUses) {
769 result = findOriginal(result);
776 private def DataSchemaNode findCorrectTargetFromAugment(DataSchemaNode node) {
777 if (!node.augmenting) {
781 var String currentName = node.QName.localName;
782 var tmpPath = new ArrayList<String>();
783 var YangNode parent = node;
784 var AugmentationSchema augment = null;
786 parent = (parent as DataSchemaNode).parent;
787 if (parent instanceof AugmentationTarget) {
788 tmpPath.add(currentName);
789 augment = findNodeInAugment((parent as AugmentationTarget).availableAugmentations, currentName);
790 if (augment == null) {
791 currentName = (parent as DataSchemaNode).QName.localName;
794 } while ((parent as DataSchemaNode).augmenting && augment == null);
796 if (augment == null) {
799 Collections.reverse(tmpPath);
800 var Object actualParent = augment;
801 var DataSchemaNode result = null;
802 for (name : tmpPath) {
803 if (actualParent instanceof DataNodeContainer) {
804 result = (actualParent as DataNodeContainer).getDataChildByName(name);
805 actualParent = (actualParent as DataNodeContainer).getDataChildByName(name);
807 if (actualParent instanceof ChoiceNode) {
808 result = (actualParent as ChoiceNode).getCaseNodeByName(name);
809 actualParent = (actualParent as ChoiceNode).getCaseNodeByName(name);
814 if (result.addedByUses) {
815 result = findCorrectTargetFromGrouping(result);
822 private def AugmentationSchema findNodeInAugment(Collection<AugmentationSchema> augments, String name) {
823 for (augment : augments) {
824 if (augment.getDataChildByName(name) != null) {
831 private def DataSchemaNode findCorrectTargetFromGrouping(DataSchemaNode node) {
832 if (node.path.path.size == 1) {
834 // uses is under module statement
\r
835 val Module m = findParentModule(schemaContext, node);
836 var DataSchemaNode result = null;
838 var SchemaNode targetGrouping = findNodeInSchemaContext(schemaContext, u.groupingPath.path);
839 if (!(targetGrouping instanceof GroupingDefinition)) {
840 throw new IllegalArgumentException("Failed to generate code for augment in " + u);
842 var gr = targetGrouping as GroupingDefinition;
843 result = gr.getDataChildByName(node.QName.localName);
845 if (result == null) {
846 throw new IllegalArgumentException("Failed to generate code for augment");
850 var DataSchemaNode result = null;
851 var String currentName = node.QName.localName;
852 var tmpPath = new ArrayList<String>();
853 var YangNode parent = node.parent;
855 tmpPath.add(currentName);
856 val dataNodeParent = parent as DataNodeContainer;
857 for (u : dataNodeParent.uses) {
858 if (result == null) {
\r
859 var SchemaNode targetGrouping = findNodeInSchemaContext(schemaContext, u.groupingPath.path);
860 if (!(targetGrouping instanceof GroupingDefinition)) {
861 throw new IllegalArgumentException("Failed to generate code for augment in " + u);
863 var gr = targetGrouping as GroupingDefinition;
864 result = gr.getDataChildByName(currentName);
\r
867 if (result == null) {
868 currentName = (parent as SchemaNode).QName.localName;
869 if (parent instanceof DataSchemaNode) {
870 parent = (parent as DataSchemaNode).parent;
872 parent = (parent as DataNodeContainer).parent;
875 } while (result == null && !(parent instanceof Module));
877 if (result != null) {
878 if (tmpPath.size == 1) {
881 var DataSchemaNode newParent = result;
882 Collections.reverse(tmpPath);
884 for (name : tmpPath) {
885 newParent = (newParent as DataNodeContainer).getDataChildByName(name);
896 * Convenient method to find node added by uses statement.
\r
898 private def DataSchemaNode findOriginalTargetFromGrouping(String targetSchemaNodeName, UsesNode parentUsesNode) {
899 var SchemaNode targetGrouping = findNodeInSchemaContext(schemaContext, parentUsesNode.groupingPath.path);
900 if (!(targetGrouping instanceof GroupingDefinition)) {
901 throw new IllegalArgumentException("Failed to generate code for augment in " + parentUsesNode);
904 var grouping = targetGrouping as GroupingDefinition;
905 var result = grouping.getDataChildByName(targetSchemaNodeName);
906 if (result == null) {
909 var boolean fromUses = result.addedByUses;
911 var Iterator<UsesNode> groupingUses = grouping.uses.iterator;
913 if (groupingUses.hasNext()) {
914 grouping = findNodeInSchemaContext(schemaContext, groupingUses.next().groupingPath.path) as GroupingDefinition;
915 result = grouping.getDataChildByName(targetSchemaNodeName);
916 fromUses = result.addedByUses;
918 throw new NullPointerException("Failed to generate code for augment in " + parentUsesNode);
926 * Returns a generated type builder for an augmentation.
\r
928 * The name of the type builder is equal to the name of augmented node with
\r
929 * serial number as suffix.
\r
931 * @param module current module
\r
932 * @param augmentPackageName
\r
933 * string with contains the package name to which the augment
\r
935 * @param basePackageName
\r
936 * string with the package name to which the augmented node
\r
938 * @param targetTypeRef
\r
941 * augmentation schema which contains data about the child nodes
\r
942 * and uses of augment
\r
943 * @return generated type builder for augment
\r
945 private def GeneratedTypeBuilder addRawAugmentGenTypeDefinition(Module module, String augmentPackageName,
946 String basePackageName, Type targetTypeRef, AugmentationSchema augSchema) {
947 var Map<String, GeneratedTypeBuilder> augmentBuilders = genTypeBuilders.get(augmentPackageName);
948 if (augmentBuilders === null) {
949 augmentBuilders = new HashMap();
950 genTypeBuilders.put(augmentPackageName, augmentBuilders);
952 val augIdentifier = getAugmentIdentifier(augSchema.unknownSchemaNodes);
954 val augTypeName = if (augIdentifier !== null) {
955 parseToClassName(augIdentifier)
957 augGenTypeName(augmentBuilders, targetTypeRef.name);
960 val augTypeBuilder = new GeneratedTypeBuilderImpl(augmentPackageName, augTypeName);
962 augTypeBuilder.addImplementsType(DATA_OBJECT);
963 augTypeBuilder.addImplementsType(Types.augmentationTypeFor(targetTypeRef));
964 addImplementedInterfaceFromUses(augSchema, augTypeBuilder);
966 augSchemaNodeToMethods(module, basePackageName, augTypeBuilder, augTypeBuilder, augSchema.childNodes);
967 augmentBuilders.put(augTypeName, augTypeBuilder);
968 return augTypeBuilder;
973 * @param unknownSchemaNodes
\r
974 * @return nodeParameter of UnknownSchemaNode
\r
976 private def String getAugmentIdentifier(List<UnknownSchemaNode> unknownSchemaNodes) {
977 for (unknownSchemaNode : unknownSchemaNodes) {
978 val nodeType = unknownSchemaNode.nodeType;
979 if (AUGMENT_IDENTIFIER_NAME.equals(nodeType.localName) &&
980 YANG_EXT_NAMESPACE.equals(nodeType.namespace.toString())) {
981 return unknownSchemaNode.nodeParameter;
988 * Returns first unique name for the augment generated type builder. The
\r
989 * generated type builder name for augment consists from name of augmented
\r
990 * node and serial number of its augmentation.
\r
993 * map of builders which were created in the package to which the
\r
994 * augmentation belongs
\r
995 * @param genTypeName
\r
996 * string with name of augmented node
\r
997 * @return string with unique name for augmentation builder
\r
999 private def String augGenTypeName(Map<String, GeneratedTypeBuilder> builders, String genTypeName) {
1001 while ((builders !== null) && builders.containsKey(genTypeName + index)) {
1004 return genTypeName + index;
1008 * Adds the methods to <code>typeBuilder</code> which represent subnodes of
\r
1009 * node for which <code>typeBuilder</code> was created.
\r
1011 * The subnodes aren't mapped to the methods if they are part of grouping or
\r
1012 * augment (in this case are already part of them).
\r
1014 * @param module current module
\r
1015 * @param basePackageName
\r
1016 * string contains the module package name
\r
1018 * generated type builder which represents any node. The subnodes
\r
1019 * of this node are added to the <code>typeBuilder</code> as
\r
1020 * methods. The subnode can be of type leaf, leaf-list, list,
\r
1021 * container, choice.
\r
1022 * @param childOf parent type
\r
1023 * @param schemaNodes
\r
1024 * set of data schema nodes which are the children of the node
\r
1025 * for which <code>typeBuilder</code> was created
\r
1026 * @return generated type builder which is the same builder as input
\r
1027 * parameter. The getter methods (representing child nodes) could be
\r
1030 private def GeneratedTypeBuilder resolveDataSchemaNodes(Module module, String basePackageName,
1031 GeneratedTypeBuilder parent, GeneratedTypeBuilder childOf, Set<DataSchemaNode> schemaNodes) {
1032 if ((schemaNodes !== null) && (parent !== null)) {
1033 for (schemaNode : schemaNodes) {
1034 if (!schemaNode.augmenting && !schemaNode.addedByUses) {
1035 addSchemaNodeToBuilderAsMethod(basePackageName, schemaNode, parent, childOf, module);
1043 * Adds the methods to <code>typeBuilder</code> what represents subnodes of
\r
1044 * node for which <code>typeBuilder</code> was created.
\r
1046 * @param module current module
\r
1047 * @param basePackageName
\r
1048 * string contains the module package name
\r
1049 * @param typeBuilder
\r
1050 * generated type builder which represents any node. The subnodes
\r
1051 * of this node are added to the <code>typeBuilder</code> as
\r
1052 * methods. The subnode can be of type leaf, leaf-list, list,
\r
1053 * container, choice.
\r
1054 * @param childOf parent type
\r
1055 * @param schemaNodes
\r
1056 * set of data schema nodes which are the children of the node
\r
1057 * for which <code>typeBuilder</code> was created
\r
1058 * @return generated type builder which is the same object as the input
\r
1059 * parameter <code>typeBuilder</code>. The getter method could be
\r
1062 private def GeneratedTypeBuilder augSchemaNodeToMethods(Module module, String basePackageName,
1063 GeneratedTypeBuilder typeBuilder, GeneratedTypeBuilder childOf, Set<DataSchemaNode> schemaNodes) {
1064 if ((schemaNodes !== null) && (typeBuilder !== null)) {
1065 for (schemaNode : schemaNodes) {
1066 if (!schemaNode.isAugmenting()) {
1067 addSchemaNodeToBuilderAsMethod(basePackageName, schemaNode, typeBuilder, childOf, module);
1075 * Adds to <code>typeBuilder</code> a method which is derived from
\r
1076 * <code>schemaNode</code>.
\r
1078 * @param basePackageName
\r
1079 * string with the module package name
\r
1081 * data schema node which is added to <code>typeBuilder</code> as
\r
1083 * @param typeBuilder
\r
1084 * generated type builder to which is <code>schemaNode</code>
\r
1085 * added as a method.
\r
1086 * @param childOf parent type
\r
1087 * @param module current module
\r
1089 private def void addSchemaNodeToBuilderAsMethod(String basePackageName, DataSchemaNode node,
1090 GeneratedTypeBuilder typeBuilder, GeneratedTypeBuilder childOf, Module module) {
1091 if (node !== null && typeBuilder !== null) {
1093 case node instanceof LeafSchemaNode:
1094 resolveLeafSchemaNodeAsMethod(typeBuilder, node as LeafSchemaNode)
1095 case node instanceof LeafListSchemaNode:
1096 resolveLeafListSchemaNode(typeBuilder, node as LeafListSchemaNode)
1097 case node instanceof ContainerSchemaNode:
1098 containerToGenType(module, basePackageName, typeBuilder, childOf, node as ContainerSchemaNode)
1099 case node instanceof ListSchemaNode:
1100 listToGenType(module, basePackageName, typeBuilder, childOf, node as ListSchemaNode)
1101 case node instanceof ChoiceNode:
1102 choiceToGeneratedType(module, basePackageName, typeBuilder, node as ChoiceNode)
1108 * Converts <code>choiceNode</code> to the list of generated types for
\r
1109 * choice and its cases.
\r
1111 * The package names for choice and for its cases are created as
\r
1112 * concatenation of the module package (<code>basePackageName</code>) and
\r
1113 * names of all parents node.
\r
1115 * @param module current module
\r
1116 * @param basePackageName
\r
1117 * string with the module package name
\r
1118 * @param parent parent type
\r
1119 * @param childOf concrete parent for case child nodes
\r
1120 * @param choiceNode
\r
1121 * choice node which is mapped to generated type. Also child
\r
1122 * nodes - cases are mapped to generated types.
\r
1123 * @throws IllegalArgumentException
\r
1125 * <li>if <code>basePackageName</code> equals null</li>
\r
1126 * <li>if <code>choiceNode</code> equals null</li>
\r
1130 private def void choiceToGeneratedType(Module module, String basePackageName, GeneratedTypeBuilder parent,
1131 ChoiceNode choiceNode) {
1132 checkArgument(basePackageName !== null, "Base Package Name cannot be NULL.");
1133 checkArgument(choiceNode !== null, "Choice Schema Node cannot be NULL.");
1135 val packageName = packageNameForGeneratedType(basePackageName, choiceNode.path);
1136 val choiceTypeBuilder = addRawInterfaceDefinition(packageName, choiceNode);
1137 constructGetter(parent, choiceNode.QName.localName, choiceNode.description, choiceTypeBuilder);
1138 choiceTypeBuilder.addImplementsType(DataContainer.typeForClass);
1139 genCtx.get(module).addChildNodeType(choiceNode.path, choiceTypeBuilder)
1140 generateTypesFromChoiceCases(module, basePackageName, parent, choiceTypeBuilder.toInstance, choiceNode);
1144 * Converts <code>caseNodes</code> set to list of corresponding generated
\r
1147 * For every <i>case</i> which isn't added through augment or <i>uses</i> is
\r
1148 * created generated type builder. The package names for the builder is
\r
1149 * created as concatenation of the module package (
\r
1150 * <code>basePackageName</code>) and names of all parents nodes of the
\r
1151 * concrete <i>case</i>. There is also relation "<i>implements type</i>"
\r
1152 * between every case builder and <i>choice</i> type
\r
1154 * @param basePackageName
\r
1155 * string with the module package name
\r
1156 * @param refChoiceType
\r
1157 * type which represents superior <i>case</i>
\r
1158 * @param caseNodes
\r
1159 * set of choice case nodes which are mapped to generated types
\r
1160 * @return list of generated types for <code>caseNodes</code>.
\r
1161 * @throws IllegalArgumentException
\r
1163 * <li>if <code>basePackageName</code> equals null</li>
\r
1164 * <li>if <code>refChoiceType</code> equals null</li>
\r
1165 * <li>if <code>caseNodes</code> equals null</li>
\r
1169 private def void generateTypesFromChoiceCases(Module module, String basePackageName,
1170 GeneratedTypeBuilder choiceParent, Type refChoiceType, ChoiceNode choiceNode) {
1171 checkArgument(basePackageName !== null, "Base Package Name cannot be NULL.");
1172 checkArgument(refChoiceType !== null, "Referenced Choice Type cannot be NULL.");
1173 checkArgument(choiceNode !== null, "ChoiceNode cannot be NULL.");
1175 val Set<ChoiceCaseNode> caseNodes = choiceNode.cases;
1176 if (caseNodes == null) {
1180 for (caseNode : caseNodes) {
1181 if (caseNode !== null && !caseNode.isAddedByUses() && !caseNode.isAugmenting()) {
1182 val packageName = packageNameForGeneratedType(basePackageName, caseNode.path);
1183 val caseTypeBuilder = addDefaultInterfaceDefinition(packageName, caseNode);
1184 caseTypeBuilder.addImplementsType(refChoiceType);
1185 genCtx.get(module).addCaseType(caseNode.path, caseTypeBuilder)
1186 val Set<DataSchemaNode> caseChildNodes = caseNode.childNodes;
1187 if (caseChildNodes !== null) {
1188 val parentNode = choiceNode.parent;
1189 var SchemaNode parent;
1190 if (parentNode instanceof AugmentationSchema) {
1191 val augSchema = parentNode as AugmentationSchema;
1192 val targetPath = augSchema.targetPath;
1193 var targetSchemaNode = findDataSchemaNode(schemaContext, targetPath);
1194 if (targetSchemaNode instanceof DataSchemaNode &&
1195 (targetSchemaNode as DataSchemaNode).isAddedByUses()) {
1196 targetSchemaNode = findOriginal(targetSchemaNode as DataSchemaNode);
1197 if (targetSchemaNode == null) {
1198 throw new NullPointerException(
1199 "Failed to find target node from grouping for augmentation " + augSchema +
1200 " in module " + module.name);
1203 parent = targetSchemaNode as SchemaNode
1205 parent = choiceNode.parent as SchemaNode;
1207 var GeneratedTypeBuilder childOfType = findChildNodeByPath(parent.path)
1208 resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, childOfType, caseChildNodes);
1212 processUsesAugments(caseNode, module);
1217 * Generates list of generated types for all the cases of a choice which are
\r
1218 * added to the choice through the augment.
\r
1221 * @param basePackageName
\r
1222 * string contains name of package to which augment belongs. If
\r
1223 * an augmented choice is from an other package (pcg1) than an
\r
1224 * augmenting choice (pcg2) then case's of the augmenting choice
\r
1225 * will belong to pcg2.
\r
1226 * @param refChoiceType
\r
1227 * Type which represents the choice to which case belongs. Every
\r
1228 * case has to contain its choice in extend part.
\r
1229 * @param caseNodes
\r
1230 * set of choice case nodes for which is checked if are/aren't
\r
1231 * added to choice through augmentation
\r
1232 * @return list of generated types which represents augmented cases of
\r
1233 * choice <code>refChoiceType</code>
\r
1234 * @throws IllegalArgumentException
\r
1236 * <li>if <code>basePackageName</code> equals null</li>
\r
1237 * <li>if <code>refChoiceType</code> equals null</li>
\r
1238 * <li>if <code>caseNodes</code> equals null</li>
\r
1241 private def void generateTypesFromAugmentedChoiceCases(Module module, String basePackageName, Type targetType,
1242 ChoiceNode targetNode, Set<DataSchemaNode> augmentedNodes) {
1243 checkArgument(basePackageName !== null, "Base Package Name cannot be NULL.");
1244 checkArgument(targetType !== null, "Referenced Choice Type cannot be NULL.");
1245 checkArgument(augmentedNodes !== null, "Set of Choice Case Nodes cannot be NULL.");
1247 for (caseNode : augmentedNodes) {
1248 if (caseNode !== null) {
1249 val packageName = packageNameForGeneratedType(basePackageName, caseNode.path);
1250 val caseTypeBuilder = addDefaultInterfaceDefinition(packageName, caseNode);
1251 caseTypeBuilder.addImplementsType(targetType);
1253 val SchemaNode parent = targetNode.parent as SchemaNode;
1254 var GeneratedTypeBuilder childOfType = null;
1255 if (parent instanceof Module) {
1256 childOfType = genCtx.get(parent as Module).moduleNode
1257 } else if (parent instanceof ChoiceCaseNode) {
1258 childOfType = findCaseByPath(parent.path)
1259 } else if (parent instanceof DataSchemaNode || parent instanceof NotificationDefinition) {
1260 childOfType = findChildNodeByPath(parent.path)
1261 } else if (parent instanceof GroupingDefinition) {
1262 childOfType = findGroupingByPath(parent.path);
1265 if (childOfType == null) {
1266 throw new IllegalArgumentException("Failed to find parent type of choice " + targetNode);
1269 if (caseNode instanceof DataNodeContainer) {
1270 val DataNodeContainer dataNodeCase = caseNode as DataNodeContainer;
1271 val Set<DataSchemaNode> childNodes = dataNodeCase.childNodes;
1272 if (childNodes !== null) {
1273 resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, childOfType, childNodes);
1276 val ChoiceCaseNode node = targetNode.getCaseNodeByName(caseNode.getQName().getLocalName());
1277 val Set<DataSchemaNode> childNodes = node.childNodes;
1278 if (childNodes !== null) {
1279 resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, childOfType, childNodes);
1283 genCtx.get(module).addCaseType(caseNode.path, caseTypeBuilder)
1290 * Converts <code>leaf</code> to the getter method which is added to
\r
1291 * <code>typeBuilder</code>.
\r
1293 * @param typeBuilder
\r
1294 * generated type builder to which is added getter method as
\r
1295 * <code>leaf</code> mapping
\r
1297 * leaf schema node which is mapped as getter method which is
\r
1298 * added to <code>typeBuilder</code>
\r
1299 * @return boolean value
\r
1301 * <li>false - if <code>leaf</code> or <code>typeBuilder</code> are
\r
1303 * <li>true - in other cases</li>
\r
1306 private def boolean resolveLeafSchemaNodeAsMethod(GeneratedTypeBuilder typeBuilder, LeafSchemaNode leaf) {
1307 if ((leaf !== null) && (typeBuilder !== null)) {
1308 val leafName = leaf.QName.localName;
1309 var String leafDesc = leaf.description;
1310 if (leafDesc === null) {
1314 val parentModule = findParentModule(schemaContext, leaf);
1315 if (leafName !== null && !leaf.isAddedByUses()) {
1316 val TypeDefinition<?> typeDef = leaf.type;
1318 var Type returnType = null;
1319 if (typeDef instanceof EnumTypeDefinition) {
1320 returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf);
1321 val enumTypeDef = typeDef as EnumTypeDefinition;
1322 val enumBuilder = resolveInnerEnumFromTypeDefinition(enumTypeDef, leafName, typeBuilder);
1324 if (enumBuilder !== null) {
1325 returnType = new ReferencedTypeImpl(enumBuilder.packageName, enumBuilder.name);
1327 (typeProvider as TypeProviderImpl).putReferencedType(leaf.path, returnType);
1328 } else if (typeDef instanceof UnionType) {
1329 val genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, leafName, leaf, parentModule);
1330 if (genTOBuilder !== null) {
1331 returnType = new ReferencedTypeImpl(genTOBuilder.packageName, genTOBuilder.name);
1333 } else if (typeDef instanceof BitsTypeDefinition) {
1334 val genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, leafName, leaf, parentModule);
1335 if (genTOBuilder !== null) {
1336 returnType = new ReferencedTypeImpl(genTOBuilder.packageName, genTOBuilder.name);
1339 val Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
\r
1340 returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf, restrictions);
1342 if (returnType !== null) {
1343 val MethodSignatureBuilder getter = constructGetter(typeBuilder, leafName, leafDesc, returnType);
1344 processContextRefExtension(leaf, getter, parentModule);
1352 private def void processContextRefExtension(LeafSchemaNode leaf, MethodSignatureBuilder getter, Module module) {
1353 for (node : leaf.unknownSchemaNodes) {
1354 val nodeType = node.nodeType;
1355 if ("context-reference".equals(nodeType.localName)) {
1356 val nodeParam = node.nodeParameter;
1357 var IdentitySchemaNode identity = null;
1358 var String basePackageName = null;
1359 val String[] splittedElement = nodeParam.split(":");
1360 if (splittedElement.length == 1) {
1361 identity = findIdentityByName(module.identities, splittedElement.get(0));
1362 basePackageName = moduleNamespaceToPackageName(module);
1363 } else if (splittedElement.length == 2) {
1364 var prefix = splittedElement.get(0);
1365 val Module dependentModule = findModuleFromImports(module.imports, prefix)
1366 if (dependentModule == null) {
1367 throw new IllegalArgumentException(
1368 "Failed to process context-reference: unknown prefix " + prefix);
1370 identity = findIdentityByName(dependentModule.identities, splittedElement.get(1));
1371 basePackageName = moduleNamespaceToPackageName(dependentModule);
1373 throw new IllegalArgumentException(
1374 "Failed to process context-reference: unknown identity " + nodeParam);
1376 if (identity == null) {
1377 throw new IllegalArgumentException(
1378 "Failed to process context-reference: unknown identity " + nodeParam);
1381 val Class<RoutingContext> clazz = typeof(RoutingContext);
1382 val AnnotationTypeBuilder rc = getter.addAnnotation(clazz.package.name, clazz.simpleName);
1383 val packageName = packageNameForGeneratedType(basePackageName, identity.path);
1384 val genTypeName = parseToClassName(identity.QName.localName);
1385 rc.addParameter("value", packageName + "." + genTypeName + ".class");
1390 private def IdentitySchemaNode findIdentityByName(Set<IdentitySchemaNode> identities, String name) {
1391 for (id : identities) {
1392 if (id.QName.localName.equals(name)) {
1399 private def Module findModuleFromImports(Set<ModuleImport> imports, String prefix) {
1400 for (imp : imports) {
1401 if (imp.prefix.equals(prefix)) {
1402 return schemaContext.findModuleByName(imp.moduleName, imp.revision);
1409 * Converts <code>leaf</code> schema node to property of generated TO
\r
1412 * @param toBuilder
\r
1413 * generated TO builder to which is <code>leaf</code> added as
\r
1416 * leaf schema node which is added to <code>toBuilder</code> as
\r
1418 * @param isReadOnly
\r
1419 * boolean value which says if leaf property is|isn't read only
\r
1420 * @return boolean value
\r
1422 * <li>false - if <code>leaf</code>, <code>toBuilder</code> or leaf
\r
1423 * name equals null or if leaf is added by <i>uses</i>.</li>
\r
1424 * <li>true - other cases</li>
\r
1427 private def boolean resolveLeafSchemaNodeAsProperty(GeneratedTOBuilder toBuilder, LeafSchemaNode leaf,
1428 boolean isReadOnly) {
1429 if ((leaf !== null) && (toBuilder !== null)) {
1430 val leafName = leaf.QName.localName;
1431 var String leafDesc = leaf.description;
1432 if (leafDesc === null) {
1436 if (leafName !== null) {
1437 val TypeDefinition<?> typeDef = leaf.type;
1439 // TODO: properly resolve enum types
\r
1440 val returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf);
1441 if (returnType !== null) {
1442 val propBuilder = toBuilder.addProperty(parseToValidParamName(leafName));
1443 propBuilder.setReadOnly(isReadOnly);
1444 propBuilder.setReturnType(returnType);
1445 propBuilder.setComment(leafDesc);
1446 toBuilder.addEqualsIdentity(propBuilder);
1447 toBuilder.addHashIdentity(propBuilder);
1448 toBuilder.addToStringProperty(propBuilder);
1457 * Converts <code>node</code> leaf list schema node to getter method of
\r
1458 * <code>typeBuilder</code>.
\r
1460 * @param typeBuilder
\r
1461 * generated type builder to which is <code>node</code> added as
\r
1464 * leaf list schema node which is added to
\r
1465 * <code>typeBuilder</code> as getter method
\r
1466 * @return boolean value
\r
1468 * <li>true - if <code>node</code>, <code>typeBuilder</code>,
\r
1469 * nodeName equal null or <code>node</code> is added by <i>uses</i></li>
\r
1470 * <li>false - other cases</li>
\r
1473 private def boolean resolveLeafListSchemaNode(GeneratedTypeBuilder typeBuilder, LeafListSchemaNode node) {
1474 if ((node !== null) && (typeBuilder !== null)) {
1475 val nodeName = node.QName.localName;
1476 var String nodeDesc = node.description;
1477 if (nodeDesc === null) {
1480 if (nodeName !== null && !node.isAddedByUses()) {
1481 val TypeDefinition<?> type = node.type;
1482 val listType = Types.listTypeFor(typeProvider.javaTypeForSchemaDefinitionType(type, node));
1483 constructGetter(typeBuilder, nodeName, nodeDesc, listType);
1490 private def GeneratedTypeBuilder addDefaultInterfaceDefinition(String packageName, SchemaNode schemaNode) {
1491 return addDefaultInterfaceDefinition(packageName, schemaNode, null);
1495 * Instantiates generated type builder with <code>packageName</code> and
\r
1496 * <code>schemaNode</code>.
\r
1498 * The new builder always implements
\r
1499 * {@link org.opendaylight.yangtools.yang.binding.DataObject DataObject}.<br />
\r
1500 * If <code>schemaNode</code> is instance of GroupingDefinition it also
\r
1501 * implements {@link org.opendaylight.yangtools.yang.binding.Augmentable
\r
1502 * Augmentable}.<br />
\r
1503 * If <code>schemaNode</code> is instance of
\r
1504 * {@link org.opendaylight.yangtools.yang.model.api.DataNodeContainer
\r
1505 * DataNodeContainer} it can also implement nodes which are specified in
\r
1508 * @param packageName
\r
1509 * string with the name of the package to which
\r
1510 * <code>schemaNode</code> belongs.
\r
1511 * @param schemaNode
\r
1512 * schema node for which is created generated type builder
\r
1513 * @param parent parent type (can be null)
\r
1514 * @return generated type builder <code>schemaNode</code>
\r
1516 private def GeneratedTypeBuilder addDefaultInterfaceDefinition(String packageName, SchemaNode schemaNode,
1518 val it = addRawInterfaceDefinition(packageName, schemaNode, "");
\r
1519 val qname = schemaNode.QName;
1520 //addConstant(QName.typeForClass,"QNAME",'''
\r
1521 // org.opendaylight.yangtools.yang.common.QName.create("«qname.namespace»","«qname.formattedRevision»","«qname.localName»");
\r
1523 if (parent === null) {
1524 addImplementsType(DATA_OBJECT);
1526 addImplementsType(BindingTypes.childOf(parent));
1528 if (!(schemaNode instanceof GroupingDefinition)) {
1529 addImplementsType(augmentable(it));
1532 if (schemaNode instanceof DataNodeContainer) {
1533 addImplementedInterfaceFromUses(schemaNode as DataNodeContainer, it);
1540 * Wraps the calling of the same overloaded method.
\r
1542 * @param packageName
\r
1543 * string with the package name to which returning generated type
\r
1545 * @param schemaNode
\r
1546 * schema node which provide data about the schema node name
\r
1547 * @return generated type builder for <code>schemaNode</code>
\r
1549 private def GeneratedTypeBuilder addRawInterfaceDefinition(String packageName, SchemaNode schemaNode) {
1550 return addRawInterfaceDefinition(packageName, schemaNode, "");
1554 * Returns reference to generated type builder for specified
\r
1555 * <code>schemaNode</code> with <code>packageName</code>.
\r
1557 * Firstly the generated type builder is searched in
\r
1558 * {@link BindingGeneratorImpl#genTypeBuilders genTypeBuilders}. If it isn't
\r
1559 * found it is created and added to <code>genTypeBuilders</code>.
\r
1561 * @param packageName
\r
1562 * string with the package name to which returning generated type
\r
1564 * @param schemaNode
\r
1565 * schema node which provide data about the schema node name
\r
1566 * @param prefix return type name prefix
\r
1567 * @return generated type builder for <code>schemaNode</code>
\r
1568 * @throws IllegalArgumentException
\r
1570 * <li>if <code>schemaNode</code> equals null</li>
\r
1571 * <li>if <code>packageName</code> equals null</li>
\r
1572 * <li>if Q name of schema node is null</li>
\r
1573 * <li>if schema node name is nul</li>
\r
1577 private def GeneratedTypeBuilder addRawInterfaceDefinition(String packageName, SchemaNode schemaNode,
1579 checkArgument(schemaNode !== null, "Data Schema Node cannot be NULL.");
1580 checkArgument(packageName !== null, "Package Name for Generated Type cannot be NULL.");
1581 checkArgument(schemaNode.QName !== null, "QName for Data Schema Node cannot be NULL.");
1582 val schemaNodeName = schemaNode.QName.localName;
1583 checkArgument(schemaNodeName !== null, "Local Name of QName for Data Schema Node cannot be NULL.");
1585 var String genTypeName;
1586 if (prefix === null) {
1587 genTypeName = parseToClassName(schemaNodeName);
1589 genTypeName = prefix + parseToClassName(schemaNodeName);
1592 //FIXME: Validation of name conflict
\r
1593 val newType = new GeneratedTypeBuilderImpl(packageName, genTypeName);
1594 if (!genTypeBuilders.containsKey(packageName)) {
1595 val Map<String, GeneratedTypeBuilder> builders = new HashMap();
1596 builders.put(genTypeName, newType);
1597 genTypeBuilders.put(packageName, builders);
1599 val Map<String, GeneratedTypeBuilder> builders = genTypeBuilders.get(packageName);
1600 if (!builders.containsKey(genTypeName)) {
1601 builders.put(genTypeName, newType);
1608 * Creates the name of the getter method from <code>methodName</code>.
\r
1610 * @param methodName
\r
1611 * string with the name of the getter method
\r
1612 * @param returnType return type
\r
1613 * @return string with the name of the getter method for
\r
1614 * <code>methodName</code> in JAVA method format
\r
1616 public static def String getterMethodName(String localName, Type returnType) {
1617 val method = new StringBuilder();
1618 if (BOOLEAN.equals(returnType)) {
1619 method.append("is");
1621 method.append("get");
1623 method.append(parseToClassName(localName));
1624 return method.toString();
1628 * Created a method signature builder as part of
\r
1629 * <code>interfaceBuilder</code>.
\r
1631 * The method signature builder is created for the getter method of
\r
1632 * <code>schemaNodeName</code>. Also <code>comment</code> and
\r
1633 * <code>returnType</code> information are added to the builder.
\r
1635 * @param interfaceBuilder
\r
1636 * generated type builder for which the getter method should be
\r
1638 * @param schemaNodeName
\r
1639 * string with schema node name. The name will be the part of the
\r
1640 * getter method name.
\r
1642 * string with comment for the getter method
\r
1643 * @param returnType
\r
1644 * type which represents the return type of the getter method
\r
1645 * @return method signature builder which represents the getter method of
\r
1646 * <code>interfaceBuilder</code>
\r
1648 private def MethodSignatureBuilder constructGetter(GeneratedTypeBuilder interfaceBuilder, String schemaNodeName,
1649 String comment, Type returnType) {
1650 val getMethod = interfaceBuilder.addMethod(getterMethodName(schemaNodeName, returnType));
1651 getMethod.setComment(comment);
1652 getMethod.setReturnType(returnType);
1657 * Adds <code>schemaNode</code> to <code>typeBuilder</code> as getter method
\r
1658 * or to <code>genTOBuilder</code> as property.
\r
1660 * @param basePackageName
\r
1661 * string contains the module package name
\r
1662 * @param schemaNode
\r
1663 * data schema node which should be added as getter method to
\r
1664 * <code>typeBuilder</code> or as a property to
\r
1665 * <code>genTOBuilder</code> if is part of the list key
\r
1666 * @param typeBuilder
\r
1667 * generated type builder for the list schema node
\r
1668 * @param genTOBuilder
\r
1669 * generated TO builder for the list keys
\r
1671 * list of string which contains names of the list keys
\r
1672 * @param module current module
\r
1673 * @throws IllegalArgumentException
\r
1675 * <li>if <code>schemaNode</code> equals null</li>
\r
1676 * <li>if <code>typeBuilder</code> equals null</li>
\r
1679 private def void addSchemaNodeToListBuilders(String basePackageName, DataSchemaNode schemaNode,
1680 GeneratedTypeBuilder typeBuilder, GeneratedTOBuilder genTOBuilder, List<String> listKeys, Module module) {
1681 checkArgument(schemaNode !== null, "Data Schema Node cannot be NULL.");
1682 checkArgument(typeBuilder !== null, "Generated Type Builder cannot be NULL.");
1684 if (schemaNode instanceof LeafSchemaNode) {
1685 val leaf = schemaNode as LeafSchemaNode;
1686 val leafName = leaf.QName.localName;
\r
1687 resolveLeafSchemaNodeAsMethod(typeBuilder, leaf);
1688 if (listKeys.contains(leafName)) {
1689 resolveLeafSchemaNodeAsProperty(genTOBuilder, leaf, true);
1691 } else if (!schemaNode.addedByUses) {
1692 if (schemaNode instanceof LeafListSchemaNode) {
1693 resolveLeafListSchemaNode(typeBuilder, schemaNode as LeafListSchemaNode);
1694 } else if (schemaNode instanceof ContainerSchemaNode) {
1695 containerToGenType(module, basePackageName, typeBuilder, typeBuilder, schemaNode as ContainerSchemaNode);
1696 } else if (schemaNode instanceof ChoiceNode) {
1697 choiceToGeneratedType(module, basePackageName, typeBuilder, schemaNode as ChoiceNode);
1698 } else if (schemaNode instanceof ListSchemaNode) {
1699 listToGenType(module, basePackageName, typeBuilder, typeBuilder, schemaNode as ListSchemaNode);
1704 private def typeBuildersToGenTypes(Module module, GeneratedTypeBuilder typeBuilder, GeneratedTOBuilder genTOBuilder) {
1705 checkArgument(typeBuilder !== null, "Generated Type Builder cannot be NULL.");
1707 if (genTOBuilder !== null) {
1708 val genTO = genTOBuilder.toInstance();
1709 constructGetter(typeBuilder, "key", "Returns Primary Key of Yang List Type", genTO);
1710 genCtx.get(module).addGeneratedTOBuilder(genTOBuilder)
1715 * Selects the names of the list keys from <code>list</code> and returns
\r
1716 * them as the list of the strings
\r
1719 * of string with names of the list keys
\r
1720 * @return list of string which represents names of the list keys. If the
\r
1721 * <code>list</code> contains no keys then the empty list is
\r
1724 private def listKeys(ListSchemaNode list) {
1725 val List<String> listKeys = new ArrayList();
1727 if (list.keyDefinition !== null) {
1728 val keyDefinitions = list.keyDefinition;
1729 for (keyDefinition : keyDefinitions) {
1730 listKeys.add(keyDefinition.localName);
1737 * Generates for the <code>list</code> which contains any list keys special
\r
1738 * generated TO builder.
\r
1740 * @param packageName
\r
1741 * string with package name to which the list belongs
\r
1743 * list schema node which is source of data about the list name
\r
1744 * @return generated TO builder which represents the keys of the
\r
1745 * <code>list</code> or null if <code>list</code> is null or list of
\r
1746 * key definitions is null or empty.
\r
1748 private def GeneratedTOBuilder resolveListKeyTOBuilder(String packageName, ListSchemaNode list) {
1749 var GeneratedTOBuilder genTOBuilder = null;
1750 if ((list.keyDefinition !== null) && (!list.keyDefinition.isEmpty())) {
1751 val listName = list.QName.localName + "Key";
1752 val String genTOName = parseToClassName(listName);
1753 genTOBuilder = new GeneratedTOBuilderImpl(packageName, genTOName);
1755 return genTOBuilder;
1759 * Builds generated TO builders for <code>typeDef</code> of type
\r
1760 * {@link org.opendaylight.yangtools.yang.model.util.UnionType UnionType} or
\r
1761 * {@link org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition
\r
1762 * BitsTypeDefinition} which are also added to <code>typeBuilder</code> as
\r
1763 * enclosing transfer object.
\r
1765 * If more then one generated TO builder is created for enclosing then all
\r
1766 * of the generated TO builders are added to <code>typeBuilder</code> as
\r
1767 * enclosing transfer objects.
\r
1770 * type definition which can be of type <code>UnionType</code> or
\r
1771 * <code>BitsTypeDefinition</code>
\r
1772 * @param typeBuilder
\r
1773 * generated type builder to which is added generated TO created
\r
1774 * from <code>typeDef</code>
\r
1776 * string with name for generated TO builder
\r
1778 * @param parentModule
\r
1779 * @return generated TO builder for <code>typeDef</code>
\r
1781 private def GeneratedTOBuilder addTOToTypeBuilder(TypeDefinition<?> typeDef, GeneratedTypeBuilder typeBuilder,
1782 String leafName, LeafSchemaNode leaf, Module parentModule) {
1783 val classNameFromLeaf = parseToClassName(leafName);
1784 val List<GeneratedTOBuilder> genTOBuilders = new ArrayList();
1785 val packageName = typeBuilder.fullyQualifiedName;
1786 if (typeDef instanceof UnionTypeDefinition) {
1787 genTOBuilders.addAll(
1788 (typeProvider as TypeProviderImpl).
1789 provideGeneratedTOBuildersForUnionTypeDef(packageName, (typeDef as UnionTypeDefinition),
1790 classNameFromLeaf, leaf));
1791 } else if (typeDef instanceof BitsTypeDefinition) {
1793 ((typeProvider as TypeProviderImpl) ).
1794 provideGeneratedTOBuilderForBitsTypeDefinition(packageName, typeDef, classNameFromLeaf));
1796 if (genTOBuilders !== null && !genTOBuilders.isEmpty()) {
1797 for (genTOBuilder : genTOBuilders) {
1798 typeBuilder.addEnclosingTransferObject(genTOBuilder);
1800 return genTOBuilders.get(0);
1807 * Adds the implemented types to type builder.
\r
1809 * The method passes through the list of <i>uses</i> in
\r
1810 * {@code dataNodeContainer}. For every <i>use</i> is obtained coresponding
\r
1811 * generated type from {@link BindingGeneratorImpl#allGroupings
\r
1812 * allGroupings} which is added as <i>implements type</i> to
\r
1813 * <code>builder</code>
\r
1815 * @param dataNodeContainer
\r
1816 * element which contains the list of used YANG groupings
\r
1818 * builder to which are added implemented types according to
\r
1819 * <code>dataNodeContainer</code>
\r
1820 * @return generated type builder with all implemented types
\r
1822 private def addImplementedInterfaceFromUses(DataNodeContainer dataNodeContainer, GeneratedTypeBuilder builder) {
1823 for (usesNode : dataNodeContainer.uses) {
1824 if (usesNode.groupingPath !== null) {
1825 val genType = findGroupingByPath(usesNode.groupingPath).toInstance
1826 if (genType === null) {
1827 throw new IllegalStateException(
1828 "Grouping " + usesNode.groupingPath + "is not resolved for " + builder.name);
1830 builder.addImplementsType(genType);
1836 private def GeneratedTypeBuilder findChildNodeByPath(SchemaPath path) {
1837 for (ctx : genCtx.values) {
1838 var result = ctx.getChildNode(path)
1839 if (result !== null) {
1846 private def GeneratedTypeBuilder findGroupingByPath(SchemaPath path) {
1847 for (ctx : genCtx.values) {
1848 var result = ctx.getGrouping(path)
1849 if (result !== null) {
1856 private def GeneratedTypeBuilder findCaseByPath(SchemaPath path) {
1857 for (ctx : genCtx.values) {
1858 var result = ctx.getCase(path)
1859 if (result !== null) {
1867 public def getModuleContexts() {
\r