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
78 import org.opendaylight.yangtools.yang.common.QName
\r
80 public class BindingGeneratorImpl implements BindingGenerator {
82 private final Map<Module, ModuleContext> genCtx = new HashMap()
85 * Outter key represents the package name. Outter value represents map of
\r
86 * all builders in the same package. Inner key represents the schema node
\r
87 * name (in JAVA class/interface name format). Inner value represents
\r
88 * instance of builder for schema node specified in key part.
\r
90 private Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders;
93 * Provide methods for converting YANG types to JAVA types.
\r
95 private var TypeProvider typeProvider;
98 * Holds reference to schema context to resolve data of augmented elemnt
\r
99 * when creating augmentation builder
\r
101 private var SchemaContext schemaContext;
104 * Constant with the concrete name of namespace.
\r
106 private val static String YANG_EXT_NAMESPACE = "urn:opendaylight:yang:extension:yang-ext";
109 * Constant with the concrete name of identifier.
\r
111 private val static String AUGMENT_IDENTIFIER_NAME = "augment-identifier";
114 * Resolves generated types from <code>context</code> schema nodes of all
\r
117 * Generated types are created for modules, groupings, types, containers,
\r
118 * lists, choices, augments, rpcs, notification, identities.
\r
121 * schema context which contains data about all schema nodes
\r
123 * @return list of types (usually <code>GeneratedType</code>
\r
124 * <code>GeneratedTransferObject</code>which are generated from
\r
125 * <code>context</code> data.
\r
126 * @throws IllegalArgumentException
\r
127 * if param <code>context</code> is null
\r
128 * @throws IllegalStateException
\r
129 * if <code>context</code> contain no modules
\r
131 override generateTypes(SchemaContext context) {
132 checkArgument(context !== null, "Schema Context reference cannot be NULL.");
133 checkState(context.modules !== null, "Schema Context does not contain defined modules.");
134 schemaContext = context;
135 typeProvider = new TypeProviderImpl(context);
136 val Set<Module> modules = context.modules;
137 return generateTypes(context, modules);
141 * Resolves generated types from <code>context</code> schema nodes only for
\r
142 * modules specified in <code>modules</code>
\r
144 * Generated types are created for modules, groupings, types, containers,
\r
145 * lists, choices, augments, rpcs, notification, identities.
\r
148 * schema context which contains data about all schema nodes
\r
151 * set of modules for which schema nodes should be generated
\r
153 * @return list of types (usually <code>GeneratedType</code> or
\r
154 * <code>GeneratedTransferObject</code>) which:
\r
156 * <li>are generated from <code>context</code> schema nodes and</li>
\r
157 * <li>are also part of some of the module in <code>modules</code>
\r
160 * @throws IllegalArgumentException
\r
162 * <li>if param <code>context</code> is null or</li>
\r
163 * <li>if param <code>modules</code> is null</li>
\r
165 * @throws IllegalStateException
\r
166 * if <code>context</code> contain no modules
\r
168 override generateTypes(SchemaContext context, Set<Module> modules) {
169 checkArgument(context !== null, "Schema Context reference cannot be NULL.");
170 checkState(context.modules !== null, "Schema Context does not contain defined modules.");
171 checkArgument(modules !== null, "Set of Modules cannot be NULL.");
173 schemaContext = context;
174 typeProvider = new TypeProviderImpl(context);
175 val contextModules = ModuleDependencySort.sort(context.modules);
176 genTypeBuilders = new HashMap();
178 for (contextModule : contextModules) {
179 moduleToGenTypes(contextModule, context);
181 for (contextModule : contextModules) {
182 allAugmentsToGenTypes(contextModule);
185 val List<Type> filteredGenTypes = new ArrayList();
186 for (Module m : modules) {
187 filteredGenTypes.addAll(genCtx.get(m).generatedTypes);
192 return filteredGenTypes;
195 private def void moduleToGenTypes(Module m, SchemaContext context) {
196 genCtx.put(m, new ModuleContext)
197 allTypeDefinitionsToGenTypes(m)
198 groupingsToGenTypes(m, m.groupings)
199 rpcMethodsToGenType(m)
200 allIdentitiesToGenTypes(m, context)
201 notificationsToGenType(m)
203 if (!m.childNodes.isEmpty()) {
204 val moduleType = moduleToDataType(m)
205 genCtx.get(m).addModuleNode(moduleType)
206 val basePackageName = moduleNamespaceToPackageName(m);
207 resolveDataSchemaNodes(m, basePackageName, moduleType, moduleType, m.childNodes)
212 * Converts all extended type definitions of module to the list of
\r
213 * <code>Type</code> objects.
\r
216 * module from which is obtained set of type definitions
\r
217 * @throws IllegalArgumentException
\r
219 * <li>if module equals null</li>
\r
220 * <li>if name of module equals null</li>
\r
221 * <li>if type definitions of module equal null</li>
\r
225 private def void allTypeDefinitionsToGenTypes(Module module) {
226 checkArgument(module !== null, "Module reference cannot be NULL.");
227 checkArgument(module.name !== null, "Module name cannot be NULL.");
228 val it = new DataNodeIterator(module);
229 val List<TypeDefinition<?>> typeDefinitions = it.allTypedefs;
230 checkState(typeDefinitions !== null, '''Type Definitions for module «module.name» cannot be NULL.''');
232 for (TypeDefinition<?> typedef : typeDefinitions) {
233 if (typedef !== null) {
234 val type = (typeProvider as TypeProviderImpl).generatedTypeForExtendedDefinitionType(typedef, typedef);
236 genCtx.get(module).addTypedefType(typedef.path, type)
242 private def void containerToGenType(Module module, String basePackageName, GeneratedTypeBuilder parent,
243 GeneratedTypeBuilder childOf, ContainerSchemaNode node) {
244 if (node.augmenting || node.addedByUses) {
247 val packageName = packageNameForGeneratedType(basePackageName, node.path)
248 val genType = addDefaultInterfaceDefinition(packageName, node, childOf)
249 constructGetter(parent, node.QName.localName, node.description, genType)
250 genCtx.get(module).addChildNodeType(node.path, genType)
251 resolveDataSchemaNodes(module, basePackageName, genType, genType, node.childNodes)
252 groupingsToGenTypes(module, node.groupings)
253 processUsesAugments(node, module)
256 private def void listToGenType(Module module, String basePackageName, GeneratedTypeBuilder parent,
257 GeneratedTypeBuilder childOf, ListSchemaNode node) {
258 if (node.augmenting || node.addedByUses) {
261 val packageName = packageNameForGeneratedType(basePackageName, (node).path)
262 val genType = addDefaultInterfaceDefinition(packageName, node, childOf)
263 constructGetter(parent, node.QName.localName, node.description, Types.listTypeFor(genType))
264 genCtx.get(module).addChildNodeType(node.path, genType)
265 groupingsToGenTypes(module, node.groupings)
266 processUsesAugments(node, module)
268 val List<String> listKeys = listKeys(node);
269 val genTOBuilder = resolveListKeyTOBuilder(packageName, node);
\r
271 if (genTOBuilder !== null) {
272 val identifierMarker = IDENTIFIER.parameterizedTypeFor(genType);
273 val identifiableMarker = IDENTIFIABLE.parameterizedTypeFor(genTOBuilder);
274 genTOBuilder.addImplementsType(identifierMarker);
275 genType.addImplementsType(identifiableMarker);
278 for (schemaNode : node.childNodes) {
279 if (!schemaNode.augmenting) {
280 addSchemaNodeToListBuilders(basePackageName, schemaNode, genType, genTOBuilder, listKeys, module);
284 // serialVersionUID
\r
285 if (genTOBuilder !== null) {
\r
286 val GeneratedPropertyBuilder prop = new GeneratedPropertyBuilderImpl("serialVersionUID");
\r
287 prop.setValue(Long.toString(computeDefaultSUID(genTOBuilder as GeneratedTOBuilderImpl)));
\r
288 genTOBuilder.setSUID(prop);
\r
291 typeBuildersToGenTypes(module, genType, genTOBuilder);
294 private def void processUsesAugments(DataNodeContainer node, Module module) {
295 val basePackageName = moduleNamespaceToPackageName(module);
296 for (usesNode : node.uses) {
297 for (augment : usesNode.augmentations) {
298 augmentationToGenTypes(basePackageName, augment, module, usesNode);
299 processUsesAugments(augment, module);
305 * Converts all <b>augmentation</b> of the module to the list
\r
306 * <code>Type</code> objects.
\r
309 * module from which is obtained list of all augmentation objects
\r
310 * to iterate over them
\r
311 * @throws IllegalArgumentException
\r
313 * <li>if the module equals null</li>
\r
314 * <li>if the name of module equals null</li>
\r
315 * <li>if the set of child nodes equals null</li>
\r
319 private def void allAugmentsToGenTypes(Module module) {
320 checkArgument(module !== null, "Module reference cannot be NULL.");
321 checkArgument(module.name !== null, "Module name cannot be NULL.");
322 if (module.childNodes === null) {
323 throw new IllegalArgumentException(
324 "Reference to Set of Augmentation Definitions in module " + module.name + " cannot be NULL.");
327 val basePackageName = moduleNamespaceToPackageName(module);
328 val List<AugmentationSchema> augmentations = resolveAugmentations(module);
329 for (augment : augmentations) {
330 augmentationToGenTypes(basePackageName, augment, module, null);
335 * Returns list of <code>AugmentationSchema</code> objects. The objects are
\r
336 * sorted according to the length of their target path from the shortest to
\r
340 * module from which is obtained list of all augmentation objects
\r
341 * @return list of sorted <code>AugmentationSchema</code> objects obtained
\r
342 * from <code>module</code>
\r
343 * @throws IllegalArgumentException
\r
345 * <li>if the module equals null</li>
\r
346 * <li>if the set of augmentation equals null</li>
\r
350 private def List<AugmentationSchema> resolveAugmentations(Module module) {
351 checkArgument(module !== null, "Module reference cannot be NULL.");
352 checkState(module.augmentations !== null, "Augmentations Set cannot be NULL.");
354 val Set<AugmentationSchema> augmentations = module.augmentations;
355 val List<AugmentationSchema> sortedAugmentations = new ArrayList(augmentations);
356 Collections.sort(sortedAugmentations,
357 [ augSchema1, augSchema2 |
358 if (augSchema1.targetPath.path.size() > augSchema2.targetPath.path.size()) {
360 } else if (augSchema1.targetPath.path.size() < augSchema2.targetPath.path.size()) {
365 return sortedAugmentations;
369 * Converts whole <b>module</b> to <code>GeneratedType</code> object.
\r
370 * Firstly is created the module builder object from which is vally
\r
371 * obtained reference to <code>GeneratedType</code> object.
\r
374 * module from which are obtained the module name, child nodes,
\r
375 * uses and is derived package name
\r
376 * @return <code>GeneratedType</code> which is internal representation of
\r
378 * @throws IllegalArgumentException
\r
379 * if the module equals null
\r
382 private def GeneratedTypeBuilder moduleToDataType(Module module) {
383 checkArgument(module !== null, "Module reference cannot be NULL.");
385 val moduleDataTypeBuilder = moduleTypeBuilder(module, "Data");
386 addImplementedInterfaceFromUses(module, moduleDataTypeBuilder);
387 moduleDataTypeBuilder.addImplementsType(DATA_ROOT);
388 return moduleDataTypeBuilder;
392 * Converts all <b>rpcs</b> inputs and outputs substatements of the module
\r
393 * to the list of <code>Type</code> objects. In addition are to containers
\r
394 * and lists which belong to input or output also part of returning list.
\r
397 * module from which is obtained set of all rpc objects to
\r
398 * iterate over them
\r
399 * @throws IllegalArgumentException
\r
401 * <li>if the module equals null</li>
\r
402 * <li>if the name of module equals null</li>
\r
403 * <li>if the set of child nodes equals null</li>
\r
407 private def void rpcMethodsToGenType(Module module) {
408 checkArgument(module !== null, "Module reference cannot be NULL.");
409 checkArgument(module.name !== null, "Module name cannot be NULL.");
410 checkArgument(module.childNodes !== null,
411 "Reference to Set of RPC Method Definitions in module " + module.name + " cannot be NULL.");
413 val basePackageName = moduleNamespaceToPackageName(module);
414 val Set<RpcDefinition> rpcDefinitions = module.rpcs;
415 if (rpcDefinitions.isEmpty()) {
419 val interfaceBuilder = moduleTypeBuilder(module, "Service");
420 interfaceBuilder.addImplementsType(Types.typeForClass(RpcService));
421 for (rpc : rpcDefinitions) {
423 val rpcName = parseToClassName(rpc.QName.localName);
424 val rpcMethodName = parseToValidParamName(rpcName);
425 val method = interfaceBuilder.addMethod(rpcMethodName);
426 val input = rpc.input;
427 val output = rpc.output;
429 if (input !== null) {
430 val inType = addRawInterfaceDefinition(basePackageName, input, rpcName);
431 addImplementedInterfaceFromUses(input, inType);
432 inType.addImplementsType(DATA_OBJECT);
433 inType.addImplementsType(augmentable(inType));
434 resolveDataSchemaNodes(module, basePackageName, inType, inType, input.childNodes);
435 genCtx.get(module).addChildNodeType(input.path, inType)
436 val inTypeInstance = inType.toInstance();
437 method.addParameter(inTypeInstance, "input");
440 var Type outTypeInstance = VOID;
441 if (output !== null) {
442 val outType = addRawInterfaceDefinition(basePackageName, output, rpcName);
443 addImplementedInterfaceFromUses(output, outType);
444 outType.addImplementsType(DATA_OBJECT);
445 outType.addImplementsType(augmentable(outType));
446 resolveDataSchemaNodes(module, basePackageName, outType, outType, output.childNodes);
447 genCtx.get(module).addChildNodeType(output.path, outType)
448 outTypeInstance = outType.toInstance();
451 val rpcRes = Types.parameterizedTypeFor(Types.typeForClass(RpcResult), outTypeInstance);
452 method.setReturnType(Types.parameterizedTypeFor(FUTURE, rpcRes));
456 genCtx.get(module).addTopLevelNodeType(interfaceBuilder)
460 * Converts all <b>notifications</b> of the module to the list of
\r
461 * <code>Type</code> objects. In addition are to this list added containers
\r
462 * and lists which are part of this notification.
\r
465 * module from which is obtained set of all notification objects
\r
466 * to iterate over them
\r
467 * @throws IllegalArgumentException
\r
469 * <li>if the module equals null</li>
\r
470 * <li>if the name of module equals null</li>
\r
471 * <li>if the set of child nodes equals null</li>
\r
475 private def void notificationsToGenType(Module module) {
476 checkArgument(module !== null, "Module reference cannot be NULL.");
477 checkArgument(module.name !== null, "Module name cannot be NULL.");
479 if (module.childNodes === null) {
480 throw new IllegalArgumentException(
481 "Reference to Set of Notification Definitions in module " + module.name + " cannot be NULL.");
483 val notifications = module.notifications;
484 if(notifications.empty) return;
486 val listenerInterface = moduleTypeBuilder(module, "Listener");
487 listenerInterface.addImplementsType(BindingTypes.NOTIFICATION_LISTENER);
488 val basePackageName = moduleNamespaceToPackageName(module);
490 for (notification : notifications) {
491 if (notification !== null) {
492 processUsesAugments(notification, module);
494 val notificationInterface = addDefaultInterfaceDefinition(basePackageName, notification,
495 BindingTypes.DATA_OBJECT);
496 notificationInterface.addImplementsType(NOTIFICATION);
497 genCtx.get(module).addChildNodeType(notification.path, notificationInterface)
499 // Notification object
\r
500 resolveDataSchemaNodes(module, basePackageName, notificationInterface, notificationInterface,
501 notification.childNodes);
503 listenerInterface.addMethod("on" + notificationInterface.name) //
\r
504 .setAccessModifier(AccessModifier.PUBLIC).addParameter(notificationInterface, "notification").
505 setReturnType(Types.VOID);
509 genCtx.get(module).addTopLevelNodeType(listenerInterface)
513 * Converts all <b>identities</b> of the module to the list of
\r
514 * <code>Type</code> objects.
\r
517 * module from which is obtained set of all identity objects to
\r
518 * iterate over them
\r
520 * schema context only used as input parameter for method
\r
521 * {@link identityToGenType}
\r
524 private def void allIdentitiesToGenTypes(Module module, SchemaContext context) {
525 val Set<IdentitySchemaNode> schemaIdentities = module.identities;
526 val basePackageName = moduleNamespaceToPackageName(module);
528 if (schemaIdentities !== null && !schemaIdentities.isEmpty()) {
529 for (identity : schemaIdentities) {
530 identityToGenType(module, basePackageName, identity, context);
536 * Converts the <b>identity</b> object to GeneratedType. Firstly it is
\r
537 * created transport object builder. If identity contains base identity then
\r
538 * reference to base identity is added to superior identity as its extend.
\r
539 * If identity doesn't contain base identity then only reference to abstract
\r
540 * class {@link org.opendaylight.yangtools.yang.model.api.BaseIdentity
\r
541 * BaseIdentity} is added
\r
543 * @param module current module
\r
544 * @param basePackageName
\r
545 * string contains the module package name
\r
547 * IdentitySchemaNode which contains data about identity
\r
549 * SchemaContext which is used to get package and name
\r
550 * information about base of identity
\r
553 private def void identityToGenType(Module module, String basePackageName, IdentitySchemaNode identity,
554 SchemaContext context) {
555 if (identity === null) {
558 val packageName = packageNameForGeneratedType(basePackageName, identity.path);
559 val genTypeName = parseToClassName(identity.QName.localName);
560 val newType = new GeneratedTOBuilderImpl(packageName, genTypeName);
561 val baseIdentity = identity.baseIdentity;
562 if (baseIdentity === null) {
563 newType.setExtendsType(Types.baseIdentityTO);
565 val baseIdentityParentModule = SchemaContextUtil.findParentModule(context, baseIdentity);
566 val returnTypePkgName = moduleNamespaceToPackageName(baseIdentityParentModule);
567 val returnTypeName = parseToClassName(baseIdentity.QName.localName);
568 val gto = new GeneratedTOBuilderImpl(returnTypePkgName, returnTypeName).toInstance();
569 newType.setExtendsType(gto);
571 newType.setAbstract(true);
572 genCtx.get(module).addIdentityType(newType)
576 * Converts all <b>groupings</b> of the module to the list of
\r
577 * <code>Type</code> objects. Firstly are groupings sorted according mutual
\r
578 * dependencies. At least dependend (indepedent) groupings are in the list
\r
579 * saved at first positions. For every grouping the record is added to map
\r
580 * {@link BindingGeneratorImpl#allGroupings allGroupings}
\r
584 * @param collection of groupings from which types will be generated
\r
587 private def void groupingsToGenTypes(Module module, Collection<GroupingDefinition> groupings) {
588 val basePackageName = moduleNamespaceToPackageName(module);
589 val List<GroupingDefinition> groupingsSortedByDependencies = new GroupingDefinitionDependencySort().sort(
591 for (grouping : groupingsSortedByDependencies) {
592 groupingToGenType(basePackageName, grouping, module);
597 * Converts individual grouping to GeneratedType. Firstly generated type
\r
598 * builder is created and every child node of grouping is resolved to the
\r
601 * @param basePackageName
\r
602 * string contains the module package name
\r
604 * GroupingDefinition which contains data about grouping
\r
605 * @param module current module
\r
606 * @return GeneratedType which is generated from grouping (object of type
\r
607 * <code>GroupingDefinition</code>)
\r
609 private def void groupingToGenType(String basePackageName, GroupingDefinition grouping, Module module) {
610 val packageName = packageNameForGeneratedType(basePackageName, grouping.path);
611 val genType = addDefaultInterfaceDefinition(packageName, grouping);
612 genCtx.get(module).addGroupingType(grouping.path, genType)
613 resolveDataSchemaNodes(module, basePackageName, genType, genType, grouping.childNodes);
614 groupingsToGenTypes(module, grouping.groupings);
615 processUsesAugments(grouping, module);
619 * Tries to find EnumTypeDefinition in <code>typeDefinition</code>. If base
\r
620 * type of <code>typeDefinition</code> is of the type ExtendedType then this
\r
621 * method is recursivelly called with this base type.
\r
623 * @param typeDefinition
\r
624 * TypeDefinition in which should be EnumTypeDefinition found as
\r
626 * @return EnumTypeDefinition if it is found inside
\r
627 * <code>typeDefinition</code> or <code>null</code> in other case
\r
629 private def EnumTypeDefinition enumTypeDefFromExtendedType(TypeDefinition<?> typeDefinition) {
630 if (typeDefinition !== null) {
631 if (typeDefinition.baseType instanceof EnumTypeDefinition) {
632 return typeDefinition.baseType as EnumTypeDefinition;
633 } else if (typeDefinition.baseType instanceof ExtendedType) {
634 return enumTypeDefFromExtendedType(typeDefinition.baseType);
641 * Adds enumeration builder created from <code>enumTypeDef</code> to
\r
642 * <code>typeBuilder</code>.
\r
644 * Each <code>enumTypeDef</code> item is added to builder with its name and
\r
647 * @param enumTypeDef
\r
648 * EnumTypeDefinition contains enum data
\r
650 * string contains name which will be assigned to enumeration
\r
652 * @param typeBuilder
\r
653 * GeneratedTypeBuilder to which will be enum builder assigned
\r
654 * @return enumeration builder which contais data from
\r
655 * <code>enumTypeDef</code>
\r
657 private def EnumBuilder resolveInnerEnumFromTypeDefinition(EnumTypeDefinition enumTypeDef, String enumName,
658 GeneratedTypeBuilder typeBuilder) {
659 if ((enumTypeDef !== null) && (typeBuilder !== null) && (enumTypeDef.QName !== null) &&
660 (enumTypeDef.QName.localName !== null)) {
661 val enumerationName = parseToClassName(enumName);
662 val enumBuilder = typeBuilder.addEnumeration(enumerationName);
663 enumBuilder.updateEnumPairsFromEnumTypeDef(enumTypeDef);
670 * Generates type builder for <code>module</code>.
\r
673 * Module which is source of package name for generated type
\r
676 * string which is added to the module class name representation
\r
678 * @return instance of GeneratedTypeBuilder which represents
\r
679 * <code>module</code>.
\r
680 * @throws IllegalArgumentException
\r
681 * if <code>module</code> equals null
\r
683 private def GeneratedTypeBuilder moduleTypeBuilder(Module module, String postfix) {
684 checkArgument(module !== null, "Module reference cannot be NULL.");
685 val packageName = moduleNamespaceToPackageName(module);
686 val moduleName = parseToClassName(module.name) + postfix;
687 return new GeneratedTypeBuilderImpl(packageName, moduleName);
691 * Converts <code>augSchema</code> to list of <code>Type</code> which
\r
692 * contains generated type for augmentation. In addition there are also
\r
693 * generated types for all containers, list and choices which are child of
\r
694 * <code>augSchema</code> node or a generated types for cases are added if
\r
695 * augmented node is choice.
\r
697 * @param augmentPackageName
\r
698 * string with the name of the package to which the augmentation
\r
701 * AugmentationSchema which is contains data about agumentation
\r
702 * (target path, childs...)
\r
703 * @param module current module
\r
704 * @param parentUsesNode parent uses node of this augment (can be null if this augment is not defined under uses statement)
\r
705 * @throws IllegalArgumentException
\r
707 * <li>if <code>augmentPackageName</code> equals null</li>
\r
708 * <li>if <code>augSchema</code> equals null</li>
\r
709 * <li>if target path of <code>augSchema</code> equals null</li>
\r
712 private def void augmentationToGenTypes(String augmentPackageName, AugmentationSchema augSchema, Module module,
713 UsesNode parentUsesNode) {
714 checkArgument(augmentPackageName !== null, "Package Name cannot be NULL.");
715 checkArgument(augSchema !== null, "Augmentation Schema cannot be NULL.");
716 checkState(augSchema.targetPath !== null,
717 "Augmentation Schema does not contain Target Path (Target Path is NULL).");
719 processUsesAugments(augSchema, module);
721 // EVERY augmented interface will extends Augmentation<T> interface
\r
722 // and DataObject interface
\r
723 val targetPath = augSchema.targetPath;
724 var targetSchemaNode = findDataSchemaNode(schemaContext, targetPath);
725 if (targetSchemaNode instanceof DataSchemaNode && (targetSchemaNode as DataSchemaNode).isAddedByUses()) {
726 if (parentUsesNode == null) {
727 targetSchemaNode = findOriginal(targetSchemaNode as DataSchemaNode);
729 targetSchemaNode = findOriginalTargetFromGrouping(targetSchemaNode.QName.localName, parentUsesNode);
731 if (targetSchemaNode == null) {
732 throw new NullPointerException(
733 "Failed to find target node from grouping for augmentation " + augSchema + " in module " +
738 if (targetSchemaNode !== null) {
739 var targetTypeBuilder = findChildNodeByPath(targetSchemaNode.path)
740 if (targetTypeBuilder === null) {
741 targetTypeBuilder = findCaseByPath(targetSchemaNode.path)
743 if (targetTypeBuilder === null) {
744 throw new NullPointerException("Target type not yet generated: " + targetSchemaNode);
746 if (!(targetSchemaNode instanceof ChoiceNode)) {
747 var packageName = augmentPackageName;
748 if (parentUsesNode != null) {
749 packageName = packageNameForGeneratedType(augmentPackageName, augSchema.targetPath);
751 val augTypeBuilder = addRawAugmentGenTypeDefinition(module, packageName, augmentPackageName,
752 targetTypeBuilder.toInstance, augSchema);
753 genCtx.get(module).addAugmentType(augTypeBuilder)
755 generateTypesFromAugmentedChoiceCases(module, augmentPackageName, targetTypeBuilder.toInstance,
756 targetSchemaNode as ChoiceNode, augSchema.childNodes);
762 * Utility method which search for original node defined in grouping.
\r
764 private def DataSchemaNode findOriginal(DataSchemaNode node) {
765 var DataSchemaNode result = findCorrectTargetFromGrouping(node);
766 if (result == null) {
767 result = findCorrectTargetFromAugment(node);
768 if (result != null) {
769 if (result.addedByUses) {
770 result = findOriginal(result);
777 private def DataSchemaNode findCorrectTargetFromAugment(DataSchemaNode node) {
778 if (!node.augmenting) {
782 var String currentName = node.QName.localName;
783 var tmpPath = new ArrayList<String>();
784 var YangNode parent = node;
785 var AugmentationSchema augment = null;
787 parent = (parent as DataSchemaNode).parent;
788 if (parent instanceof AugmentationTarget) {
789 tmpPath.add(currentName);
790 augment = findNodeInAugment((parent as AugmentationTarget).availableAugmentations, currentName);
791 if (augment == null) {
792 currentName = (parent as DataSchemaNode).QName.localName;
795 } while ((parent as DataSchemaNode).augmenting && augment == null);
797 if (augment == null) {
800 Collections.reverse(tmpPath);
801 var Object actualParent = augment;
802 var DataSchemaNode result = null;
803 for (name : tmpPath) {
804 if (actualParent instanceof DataNodeContainer) {
805 result = (actualParent as DataNodeContainer).getDataChildByName(name);
806 actualParent = (actualParent as DataNodeContainer).getDataChildByName(name);
808 if (actualParent instanceof ChoiceNode) {
809 result = (actualParent as ChoiceNode).getCaseNodeByName(name);
810 actualParent = (actualParent as ChoiceNode).getCaseNodeByName(name);
815 if (result.addedByUses) {
816 result = findCorrectTargetFromGrouping(result);
823 private def AugmentationSchema findNodeInAugment(Collection<AugmentationSchema> augments, String name) {
824 for (augment : augments) {
825 if (augment.getDataChildByName(name) != null) {
832 private def DataSchemaNode findCorrectTargetFromGrouping(DataSchemaNode node) {
833 if (node.path.path.size == 1) {
835 // uses is under module statement
\r
836 val Module m = findParentModule(schemaContext, node);
837 var DataSchemaNode result = null;
839 var SchemaNode targetGrouping = findNodeInSchemaContext(schemaContext, u.groupingPath.path);
840 if (!(targetGrouping instanceof GroupingDefinition)) {
841 throw new IllegalArgumentException("Failed to generate code for augment in " + u);
843 var gr = targetGrouping as GroupingDefinition;
844 result = gr.getDataChildByName(node.QName.localName);
846 if (result == null) {
847 throw new IllegalArgumentException("Failed to generate code for augment");
851 var DataSchemaNode result = null;
852 var String currentName = node.QName.localName;
853 var tmpPath = new ArrayList<String>();
854 var YangNode parent = node.parent;
856 tmpPath.add(currentName);
857 val dataNodeParent = parent as DataNodeContainer;
858 for (u : dataNodeParent.uses) {
859 if (result == null) {
\r
860 var SchemaNode targetGrouping = findNodeInSchemaContext(schemaContext, u.groupingPath.path);
861 if (!(targetGrouping instanceof GroupingDefinition)) {
862 throw new IllegalArgumentException("Failed to generate code for augment in " + u);
864 var gr = targetGrouping as GroupingDefinition;
865 result = gr.getDataChildByName(currentName);
\r
868 if (result == null) {
869 currentName = (parent as SchemaNode).QName.localName;
870 if (parent instanceof DataSchemaNode) {
871 parent = (parent as DataSchemaNode).parent;
873 parent = (parent as DataNodeContainer).parent;
876 } while (result == null && !(parent instanceof Module));
878 if (result != null) {
879 if (tmpPath.size == 1) {
882 var DataSchemaNode newParent = result;
883 Collections.reverse(tmpPath);
885 for (name : tmpPath) {
886 newParent = (newParent as DataNodeContainer).getDataChildByName(name);
897 * Convenient method to find node added by uses statement.
\r
899 private def DataSchemaNode findOriginalTargetFromGrouping(String targetSchemaNodeName, UsesNode parentUsesNode) {
900 var SchemaNode targetGrouping = findNodeInSchemaContext(schemaContext, parentUsesNode.groupingPath.path);
901 if (!(targetGrouping instanceof GroupingDefinition)) {
902 throw new IllegalArgumentException("Failed to generate code for augment in " + parentUsesNode);
905 var grouping = targetGrouping as GroupingDefinition;
906 var result = grouping.getDataChildByName(targetSchemaNodeName);
907 if (result == null) {
910 var boolean fromUses = result.addedByUses;
912 var Iterator<UsesNode> groupingUses = grouping.uses.iterator;
914 if (groupingUses.hasNext()) {
915 grouping = findNodeInSchemaContext(schemaContext, groupingUses.next().groupingPath.path) as GroupingDefinition;
916 result = grouping.getDataChildByName(targetSchemaNodeName);
917 fromUses = result.addedByUses;
919 throw new NullPointerException("Failed to generate code for augment in " + parentUsesNode);
927 * Returns a generated type builder for an augmentation.
\r
929 * The name of the type builder is equal to the name of augmented node with
\r
930 * serial number as suffix.
\r
932 * @param module current module
\r
933 * @param augmentPackageName
\r
934 * string with contains the package name to which the augment
\r
936 * @param basePackageName
\r
937 * string with the package name to which the augmented node
\r
939 * @param targetTypeRef
\r
942 * augmentation schema which contains data about the child nodes
\r
943 * and uses of augment
\r
944 * @return generated type builder for augment
\r
946 private def GeneratedTypeBuilder addRawAugmentGenTypeDefinition(Module module, String augmentPackageName,
947 String basePackageName, Type targetTypeRef, AugmentationSchema augSchema) {
948 var Map<String, GeneratedTypeBuilder> augmentBuilders = genTypeBuilders.get(augmentPackageName);
949 if (augmentBuilders === null) {
950 augmentBuilders = new HashMap();
951 genTypeBuilders.put(augmentPackageName, augmentBuilders);
953 val augIdentifier = getAugmentIdentifier(augSchema.unknownSchemaNodes);
955 val augTypeName = if (augIdentifier !== null) {
956 parseToClassName(augIdentifier)
958 augGenTypeName(augmentBuilders, targetTypeRef.name);
961 val augTypeBuilder = new GeneratedTypeBuilderImpl(augmentPackageName, augTypeName);
963 augTypeBuilder.addImplementsType(DATA_OBJECT);
964 augTypeBuilder.addImplementsType(Types.augmentationTypeFor(targetTypeRef));
965 addImplementedInterfaceFromUses(augSchema, augTypeBuilder);
967 augSchemaNodeToMethods(module, basePackageName, augTypeBuilder, augTypeBuilder, augSchema.childNodes);
968 augmentBuilders.put(augTypeName, augTypeBuilder);
969 return augTypeBuilder;
974 * @param unknownSchemaNodes
\r
975 * @return nodeParameter of UnknownSchemaNode
\r
977 private def String getAugmentIdentifier(List<UnknownSchemaNode> unknownSchemaNodes) {
978 for (unknownSchemaNode : unknownSchemaNodes) {
979 val nodeType = unknownSchemaNode.nodeType;
980 if (AUGMENT_IDENTIFIER_NAME.equals(nodeType.localName) &&
981 YANG_EXT_NAMESPACE.equals(nodeType.namespace.toString())) {
982 return unknownSchemaNode.nodeParameter;
989 * Returns first unique name for the augment generated type builder. The
\r
990 * generated type builder name for augment consists from name of augmented
\r
991 * node and serial number of its augmentation.
\r
994 * map of builders which were created in the package to which the
\r
995 * augmentation belongs
\r
996 * @param genTypeName
\r
997 * string with name of augmented node
\r
998 * @return string with unique name for augmentation builder
\r
1000 private def String augGenTypeName(Map<String, GeneratedTypeBuilder> builders, String genTypeName) {
1002 while ((builders !== null) && builders.containsKey(genTypeName + index)) {
1005 return genTypeName + index;
1009 * Adds the methods to <code>typeBuilder</code> which represent subnodes of
\r
1010 * node for which <code>typeBuilder</code> was created.
\r
1012 * The subnodes aren't mapped to the methods if they are part of grouping or
\r
1013 * augment (in this case are already part of them).
\r
1015 * @param module current module
\r
1016 * @param basePackageName
\r
1017 * string contains the module package name
\r
1019 * generated type builder which represents any node. The subnodes
\r
1020 * of this node are added to the <code>typeBuilder</code> as
\r
1021 * methods. The subnode can be of type leaf, leaf-list, list,
\r
1022 * container, choice.
\r
1023 * @param childOf parent type
\r
1024 * @param schemaNodes
\r
1025 * set of data schema nodes which are the children of the node
\r
1026 * for which <code>typeBuilder</code> was created
\r
1027 * @return generated type builder which is the same builder as input
\r
1028 * parameter. The getter methods (representing child nodes) could be
\r
1031 private def GeneratedTypeBuilder resolveDataSchemaNodes(Module module, String basePackageName,
1032 GeneratedTypeBuilder parent, GeneratedTypeBuilder childOf, Set<DataSchemaNode> schemaNodes) {
1033 if ((schemaNodes !== null) && (parent !== null)) {
1034 for (schemaNode : schemaNodes) {
1035 if (!schemaNode.augmenting && !schemaNode.addedByUses) {
1036 addSchemaNodeToBuilderAsMethod(basePackageName, schemaNode, parent, childOf, module);
1044 * Adds the methods to <code>typeBuilder</code> what represents subnodes of
\r
1045 * node for which <code>typeBuilder</code> was created.
\r
1047 * @param module current module
\r
1048 * @param basePackageName
\r
1049 * string contains the module package name
\r
1050 * @param typeBuilder
\r
1051 * generated type builder which represents any node. The subnodes
\r
1052 * of this node are added to the <code>typeBuilder</code> as
\r
1053 * methods. The subnode can be of type leaf, leaf-list, list,
\r
1054 * container, choice.
\r
1055 * @param childOf parent type
\r
1056 * @param schemaNodes
\r
1057 * set of data schema nodes which are the children of the node
\r
1058 * for which <code>typeBuilder</code> was created
\r
1059 * @return generated type builder which is the same object as the input
\r
1060 * parameter <code>typeBuilder</code>. The getter method could be
\r
1063 private def GeneratedTypeBuilder augSchemaNodeToMethods(Module module, String basePackageName,
1064 GeneratedTypeBuilder typeBuilder, GeneratedTypeBuilder childOf, Set<DataSchemaNode> schemaNodes) {
1065 if ((schemaNodes !== null) && (typeBuilder !== null)) {
1066 for (schemaNode : schemaNodes) {
1067 if (!schemaNode.isAugmenting()) {
1068 addSchemaNodeToBuilderAsMethod(basePackageName, schemaNode, typeBuilder, childOf, module);
1076 * Adds to <code>typeBuilder</code> a method which is derived from
\r
1077 * <code>schemaNode</code>.
\r
1079 * @param basePackageName
\r
1080 * string with the module package name
\r
1082 * data schema node which is added to <code>typeBuilder</code> as
\r
1084 * @param typeBuilder
\r
1085 * generated type builder to which is <code>schemaNode</code>
\r
1086 * added as a method.
\r
1087 * @param childOf parent type
\r
1088 * @param module current module
\r
1090 private def void addSchemaNodeToBuilderAsMethod(String basePackageName, DataSchemaNode node,
1091 GeneratedTypeBuilder typeBuilder, GeneratedTypeBuilder childOf, Module module) {
1092 if (node !== null && typeBuilder !== null) {
1094 case node instanceof LeafSchemaNode:
1095 resolveLeafSchemaNodeAsMethod(typeBuilder, node as LeafSchemaNode)
1096 case node instanceof LeafListSchemaNode:
1097 resolveLeafListSchemaNode(typeBuilder, node as LeafListSchemaNode)
1098 case node instanceof ContainerSchemaNode:
1099 containerToGenType(module, basePackageName, typeBuilder, childOf, node as ContainerSchemaNode)
1100 case node instanceof ListSchemaNode:
1101 listToGenType(module, basePackageName, typeBuilder, childOf, node as ListSchemaNode)
1102 case node instanceof ChoiceNode:
1103 choiceToGeneratedType(module, basePackageName, typeBuilder, node as ChoiceNode)
1109 * Converts <code>choiceNode</code> to the list of generated types for
\r
1110 * choice and its cases.
\r
1112 * The package names for choice and for its cases are created as
\r
1113 * concatenation of the module package (<code>basePackageName</code>) and
\r
1114 * names of all parents node.
\r
1116 * @param module current module
\r
1117 * @param basePackageName
\r
1118 * string with the module package name
\r
1119 * @param parent parent type
\r
1120 * @param childOf concrete parent for case child nodes
\r
1121 * @param choiceNode
\r
1122 * choice node which is mapped to generated type. Also child
\r
1123 * nodes - cases are mapped to generated types.
\r
1124 * @throws IllegalArgumentException
\r
1126 * <li>if <code>basePackageName</code> equals null</li>
\r
1127 * <li>if <code>choiceNode</code> equals null</li>
\r
1131 private def void choiceToGeneratedType(Module module, String basePackageName, GeneratedTypeBuilder parent,
1132 ChoiceNode choiceNode) {
1133 checkArgument(basePackageName !== null, "Base Package Name cannot be NULL.");
1134 checkArgument(choiceNode !== null, "Choice Schema Node cannot be NULL.");
1136 val packageName = packageNameForGeneratedType(basePackageName, choiceNode.path);
1137 val choiceTypeBuilder = addRawInterfaceDefinition(packageName, choiceNode);
1138 constructGetter(parent, choiceNode.QName.localName, choiceNode.description, choiceTypeBuilder);
1139 choiceTypeBuilder.addImplementsType(DataContainer.typeForClass);
1140 genCtx.get(module).addChildNodeType(choiceNode.path, choiceTypeBuilder)
1141 generateTypesFromChoiceCases(module, basePackageName, parent, choiceTypeBuilder.toInstance, choiceNode);
1145 * Converts <code>caseNodes</code> set to list of corresponding generated
\r
1148 * For every <i>case</i> which isn't added through augment or <i>uses</i> is
\r
1149 * created generated type builder. The package names for the builder is
\r
1150 * created as concatenation of the module package (
\r
1151 * <code>basePackageName</code>) and names of all parents nodes of the
\r
1152 * concrete <i>case</i>. There is also relation "<i>implements type</i>"
\r
1153 * between every case builder and <i>choice</i> type
\r
1155 * @param basePackageName
\r
1156 * string with the module package name
\r
1157 * @param refChoiceType
\r
1158 * type which represents superior <i>case</i>
\r
1159 * @param caseNodes
\r
1160 * set of choice case nodes which are mapped to generated types
\r
1161 * @return list of generated types for <code>caseNodes</code>.
\r
1162 * @throws IllegalArgumentException
\r
1164 * <li>if <code>basePackageName</code> equals null</li>
\r
1165 * <li>if <code>refChoiceType</code> equals null</li>
\r
1166 * <li>if <code>caseNodes</code> equals null</li>
\r
1170 private def void generateTypesFromChoiceCases(Module module, String basePackageName,
1171 GeneratedTypeBuilder choiceParent, Type refChoiceType, ChoiceNode choiceNode) {
1172 checkArgument(basePackageName !== null, "Base Package Name cannot be NULL.");
1173 checkArgument(refChoiceType !== null, "Referenced Choice Type cannot be NULL.");
1174 checkArgument(choiceNode !== null, "ChoiceNode cannot be NULL.");
1176 val Set<ChoiceCaseNode> caseNodes = choiceNode.cases;
1177 if (caseNodes == null) {
1181 for (caseNode : caseNodes) {
1182 if (caseNode !== null && !caseNode.isAddedByUses() && !caseNode.isAugmenting()) {
1183 val packageName = packageNameForGeneratedType(basePackageName, caseNode.path);
1184 val caseTypeBuilder = addDefaultInterfaceDefinition(packageName, caseNode);
1185 caseTypeBuilder.addImplementsType(refChoiceType);
1186 genCtx.get(module).addCaseType(caseNode.path, caseTypeBuilder)
1187 val Set<DataSchemaNode> caseChildNodes = caseNode.childNodes;
1188 if (caseChildNodes !== null) {
1189 val parentNode = choiceNode.parent;
1190 var SchemaNode parent;
1191 if (parentNode instanceof AugmentationSchema) {
1192 val augSchema = parentNode as AugmentationSchema;
1193 val targetPath = augSchema.targetPath;
1194 var targetSchemaNode = findDataSchemaNode(schemaContext, targetPath);
1195 if (targetSchemaNode instanceof DataSchemaNode &&
1196 (targetSchemaNode as DataSchemaNode).isAddedByUses()) {
1197 targetSchemaNode = findOriginal(targetSchemaNode as DataSchemaNode);
1198 if (targetSchemaNode == null) {
1199 throw new NullPointerException(
1200 "Failed to find target node from grouping for augmentation " + augSchema +
1201 " in module " + module.name);
1204 parent = targetSchemaNode as SchemaNode
1206 parent = choiceNode.parent as SchemaNode;
1208 var GeneratedTypeBuilder childOfType = findChildNodeByPath(parent.path)
1209 resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, childOfType, caseChildNodes);
1213 processUsesAugments(caseNode, module);
1218 * Generates list of generated types for all the cases of a choice which are
\r
1219 * added to the choice through the augment.
\r
1222 * @param basePackageName
\r
1223 * string contains name of package to which augment belongs. If
\r
1224 * an augmented choice is from an other package (pcg1) than an
\r
1225 * augmenting choice (pcg2) then case's of the augmenting choice
\r
1226 * will belong to pcg2.
\r
1227 * @param refChoiceType
\r
1228 * Type which represents the choice to which case belongs. Every
\r
1229 * case has to contain its choice in extend part.
\r
1230 * @param caseNodes
\r
1231 * set of choice case nodes for which is checked if are/aren't
\r
1232 * added to choice through augmentation
\r
1233 * @return list of generated types which represents augmented cases of
\r
1234 * choice <code>refChoiceType</code>
\r
1235 * @throws IllegalArgumentException
\r
1237 * <li>if <code>basePackageName</code> equals null</li>
\r
1238 * <li>if <code>refChoiceType</code> equals null</li>
\r
1239 * <li>if <code>caseNodes</code> equals null</li>
\r
1242 private def void generateTypesFromAugmentedChoiceCases(Module module, String basePackageName, Type targetType,
1243 ChoiceNode targetNode, Set<DataSchemaNode> augmentedNodes) {
1244 checkArgument(basePackageName !== null, "Base Package Name cannot be NULL.");
1245 checkArgument(targetType !== null, "Referenced Choice Type cannot be NULL.");
1246 checkArgument(augmentedNodes !== null, "Set of Choice Case Nodes cannot be NULL.");
1248 for (caseNode : augmentedNodes) {
1249 if (caseNode !== null) {
1250 val packageName = packageNameForGeneratedType(basePackageName, caseNode.path);
1251 val caseTypeBuilder = addDefaultInterfaceDefinition(packageName, caseNode);
1252 caseTypeBuilder.addImplementsType(targetType);
1254 val SchemaNode parent = targetNode.parent as SchemaNode;
1255 var GeneratedTypeBuilder childOfType = null;
1256 if (parent instanceof Module) {
1257 childOfType = genCtx.get(parent as Module).moduleNode
1258 } else if (parent instanceof ChoiceCaseNode) {
1259 childOfType = findCaseByPath(parent.path)
1260 } else if (parent instanceof DataSchemaNode || parent instanceof NotificationDefinition) {
1261 childOfType = findChildNodeByPath(parent.path)
1262 } else if (parent instanceof GroupingDefinition) {
1263 childOfType = findGroupingByPath(parent.path);
1266 if (childOfType == null) {
1267 throw new IllegalArgumentException("Failed to find parent type of choice " + targetNode);
1270 if (caseNode instanceof DataNodeContainer) {
1271 val DataNodeContainer dataNodeCase = caseNode as DataNodeContainer;
1272 val Set<DataSchemaNode> childNodes = dataNodeCase.childNodes;
1273 if (childNodes !== null) {
1274 resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, childOfType, childNodes);
1277 val ChoiceCaseNode node = targetNode.getCaseNodeByName(caseNode.getQName().getLocalName());
1278 val Set<DataSchemaNode> childNodes = node.childNodes;
1279 if (childNodes !== null) {
1280 resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, childOfType, childNodes);
1284 genCtx.get(module).addCaseType(caseNode.path, caseTypeBuilder)
1291 * Converts <code>leaf</code> to the getter method which is added to
\r
1292 * <code>typeBuilder</code>.
\r
1294 * @param typeBuilder
\r
1295 * generated type builder to which is added getter method as
\r
1296 * <code>leaf</code> mapping
\r
1298 * leaf schema node which is mapped as getter method which is
\r
1299 * added to <code>typeBuilder</code>
\r
1300 * @return boolean value
\r
1302 * <li>false - if <code>leaf</code> or <code>typeBuilder</code> are
\r
1304 * <li>true - in other cases</li>
\r
1307 private def boolean resolveLeafSchemaNodeAsMethod(GeneratedTypeBuilder typeBuilder, LeafSchemaNode leaf) {
1308 if ((leaf !== null) && (typeBuilder !== null)) {
1309 val leafName = leaf.QName.localName;
1310 var String leafDesc = leaf.description;
1311 if (leafDesc === null) {
1315 val parentModule = findParentModule(schemaContext, leaf);
1316 if (leafName !== null && !leaf.isAddedByUses()) {
1317 val TypeDefinition<?> typeDef = leaf.type;
1319 var Type returnType = null;
1320 if (typeDef instanceof EnumTypeDefinition) {
1321 returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf);
1322 val enumTypeDef = typeDef as EnumTypeDefinition;
1323 val enumBuilder = resolveInnerEnumFromTypeDefinition(enumTypeDef, leafName, typeBuilder);
1325 if (enumBuilder !== null) {
1326 returnType = new ReferencedTypeImpl(enumBuilder.packageName, enumBuilder.name);
1328 (typeProvider as TypeProviderImpl).putReferencedType(leaf.path, returnType);
1329 } else if (typeDef instanceof UnionType) {
1330 val genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, leafName, leaf, parentModule);
1331 if (genTOBuilder !== null) {
1332 returnType = new ReferencedTypeImpl(genTOBuilder.packageName, genTOBuilder.name);
1334 } else if (typeDef instanceof BitsTypeDefinition) {
1335 val genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, leafName, leaf, parentModule);
1336 if (genTOBuilder !== null) {
1337 returnType = new ReferencedTypeImpl(genTOBuilder.packageName, genTOBuilder.name);
1340 val Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
\r
1341 returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf, restrictions);
1343 if (returnType !== null) {
1344 val MethodSignatureBuilder getter = constructGetter(typeBuilder, leafName, leafDesc, returnType);
1345 processContextRefExtension(leaf, getter, parentModule);
1353 private def void processContextRefExtension(LeafSchemaNode leaf, MethodSignatureBuilder getter, Module module) {
1354 for (node : leaf.unknownSchemaNodes) {
1355 val nodeType = node.nodeType;
1356 if ("context-reference".equals(nodeType.localName)) {
1357 val nodeParam = node.nodeParameter;
1358 var IdentitySchemaNode identity = null;
1359 var String basePackageName = null;
1360 val String[] splittedElement = nodeParam.split(":");
1361 if (splittedElement.length == 1) {
1362 identity = findIdentityByName(module.identities, splittedElement.get(0));
1363 basePackageName = moduleNamespaceToPackageName(module);
1364 } else if (splittedElement.length == 2) {
1365 var prefix = splittedElement.get(0);
1366 val Module dependentModule = findModuleFromImports(module.imports, prefix)
1367 if (dependentModule == null) {
1368 throw new IllegalArgumentException(
1369 "Failed to process context-reference: unknown prefix " + prefix);
1371 identity = findIdentityByName(dependentModule.identities, splittedElement.get(1));
1372 basePackageName = moduleNamespaceToPackageName(dependentModule);
1374 throw new IllegalArgumentException(
1375 "Failed to process context-reference: unknown identity " + nodeParam);
1377 if (identity == null) {
1378 throw new IllegalArgumentException(
1379 "Failed to process context-reference: unknown identity " + nodeParam);
1382 val Class<RoutingContext> clazz = typeof(RoutingContext);
1383 val AnnotationTypeBuilder rc = getter.addAnnotation(clazz.package.name, clazz.simpleName);
1384 val packageName = packageNameForGeneratedType(basePackageName, identity.path);
1385 val genTypeName = parseToClassName(identity.QName.localName);
1386 rc.addParameter("value", packageName + "." + genTypeName + ".class");
1391 private def IdentitySchemaNode findIdentityByName(Set<IdentitySchemaNode> identities, String name) {
1392 for (id : identities) {
1393 if (id.QName.localName.equals(name)) {
1400 private def Module findModuleFromImports(Set<ModuleImport> imports, String prefix) {
1401 for (imp : imports) {
1402 if (imp.prefix.equals(prefix)) {
1403 return schemaContext.findModuleByName(imp.moduleName, imp.revision);
1410 * Converts <code>leaf</code> schema node to property of generated TO
\r
1413 * @param toBuilder
\r
1414 * generated TO builder to which is <code>leaf</code> added as
\r
1417 * leaf schema node which is added to <code>toBuilder</code> as
\r
1419 * @param isReadOnly
\r
1420 * boolean value which says if leaf property is|isn't read only
\r
1421 * @return boolean value
\r
1423 * <li>false - if <code>leaf</code>, <code>toBuilder</code> or leaf
\r
1424 * name equals null or if leaf is added by <i>uses</i>.</li>
\r
1425 * <li>true - other cases</li>
\r
1428 private def boolean resolveLeafSchemaNodeAsProperty(GeneratedTOBuilder toBuilder, LeafSchemaNode leaf,
1429 boolean isReadOnly) {
1430 if ((leaf !== null) && (toBuilder !== null)) {
1431 val leafName = leaf.QName.localName;
1432 var String leafDesc = leaf.description;
1433 if (leafDesc === null) {
1437 if (leafName !== null) {
1438 val TypeDefinition<?> typeDef = leaf.type;
1440 // TODO: properly resolve enum types
\r
1441 val returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf);
1442 if (returnType !== null) {
1443 val propBuilder = toBuilder.addProperty(parseToValidParamName(leafName));
1444 propBuilder.setReadOnly(isReadOnly);
1445 propBuilder.setReturnType(returnType);
1446 propBuilder.setComment(leafDesc);
1447 toBuilder.addEqualsIdentity(propBuilder);
1448 toBuilder.addHashIdentity(propBuilder);
1449 toBuilder.addToStringProperty(propBuilder);
1458 * Converts <code>node</code> leaf list schema node to getter method of
\r
1459 * <code>typeBuilder</code>.
\r
1461 * @param typeBuilder
\r
1462 * generated type builder to which is <code>node</code> added as
\r
1465 * leaf list schema node which is added to
\r
1466 * <code>typeBuilder</code> as getter method
\r
1467 * @return boolean value
\r
1469 * <li>true - if <code>node</code>, <code>typeBuilder</code>,
\r
1470 * nodeName equal null or <code>node</code> is added by <i>uses</i></li>
\r
1471 * <li>false - other cases</li>
\r
1474 private def boolean resolveLeafListSchemaNode(GeneratedTypeBuilder typeBuilder, LeafListSchemaNode node) {
1475 if ((node !== null) && (typeBuilder !== null)) {
1476 val nodeName = node.QName.localName;
1477 var String nodeDesc = node.description;
1478 if (nodeDesc === null) {
1481 if (nodeName !== null && !node.isAddedByUses()) {
1482 val TypeDefinition<?> type = node.type;
1483 val listType = Types.listTypeFor(typeProvider.javaTypeForSchemaDefinitionType(type, node));
1484 constructGetter(typeBuilder, nodeName, nodeDesc, listType);
1491 private def GeneratedTypeBuilder addDefaultInterfaceDefinition(String packageName, SchemaNode schemaNode) {
1492 return addDefaultInterfaceDefinition(packageName, schemaNode, null);
1496 * Instantiates generated type builder with <code>packageName</code> and
\r
1497 * <code>schemaNode</code>.
\r
1499 * The new builder always implements
\r
1500 * {@link org.opendaylight.yangtools.yang.binding.DataObject DataObject}.<br />
\r
1501 * If <code>schemaNode</code> is instance of GroupingDefinition it also
\r
1502 * implements {@link org.opendaylight.yangtools.yang.binding.Augmentable
\r
1503 * Augmentable}.<br />
\r
1504 * If <code>schemaNode</code> is instance of
\r
1505 * {@link org.opendaylight.yangtools.yang.model.api.DataNodeContainer
\r
1506 * DataNodeContainer} it can also implement nodes which are specified in
\r
1509 * @param packageName
\r
1510 * string with the name of the package to which
\r
1511 * <code>schemaNode</code> belongs.
\r
1512 * @param schemaNode
\r
1513 * schema node for which is created generated type builder
\r
1514 * @param parent parent type (can be null)
\r
1515 * @return generated type builder <code>schemaNode</code>
\r
1517 private def GeneratedTypeBuilder addDefaultInterfaceDefinition(String packageName, SchemaNode schemaNode,
1519 val it = addRawInterfaceDefinition(packageName, schemaNode, "");
\r
1520 val qname = schemaNode.QName;
1521 addConstant(QName.typeForClass,"QNAME",'''
\r
1522 org.opendaylight.yangtools.yang.common.QName.create("«qname.namespace»","«qname.formattedRevision»","«qname.localName»")
\r
1524 if (parent === null) {
1525 addImplementsType(DATA_OBJECT);
1527 addImplementsType(BindingTypes.childOf(parent));
1529 if (!(schemaNode instanceof GroupingDefinition)) {
1530 addImplementsType(augmentable(it));
1533 if (schemaNode instanceof DataNodeContainer) {
1534 addImplementedInterfaceFromUses(schemaNode as DataNodeContainer, it);
1541 * Wraps the calling of the same overloaded method.
\r
1543 * @param packageName
\r
1544 * string with the package name to which returning generated type
\r
1546 * @param schemaNode
\r
1547 * schema node which provide data about the schema node name
\r
1548 * @return generated type builder for <code>schemaNode</code>
\r
1550 private def GeneratedTypeBuilder addRawInterfaceDefinition(String packageName, SchemaNode schemaNode) {
1551 return addRawInterfaceDefinition(packageName, schemaNode, "");
1555 * Returns reference to generated type builder for specified
\r
1556 * <code>schemaNode</code> with <code>packageName</code>.
\r
1558 * Firstly the generated type builder is searched in
\r
1559 * {@link BindingGeneratorImpl#genTypeBuilders genTypeBuilders}. If it isn't
\r
1560 * found it is created and added to <code>genTypeBuilders</code>.
\r
1562 * @param packageName
\r
1563 * string with the package name to which returning generated type
\r
1565 * @param schemaNode
\r
1566 * schema node which provide data about the schema node name
\r
1567 * @param prefix return type name prefix
\r
1568 * @return generated type builder for <code>schemaNode</code>
\r
1569 * @throws IllegalArgumentException
\r
1571 * <li>if <code>schemaNode</code> equals null</li>
\r
1572 * <li>if <code>packageName</code> equals null</li>
\r
1573 * <li>if Q name of schema node is null</li>
\r
1574 * <li>if schema node name is nul</li>
\r
1578 private def GeneratedTypeBuilder addRawInterfaceDefinition(String packageName, SchemaNode schemaNode,
1580 checkArgument(schemaNode !== null, "Data Schema Node cannot be NULL.");
1581 checkArgument(packageName !== null, "Package Name for Generated Type cannot be NULL.");
1582 checkArgument(schemaNode.QName !== null, "QName for Data Schema Node cannot be NULL.");
1583 val schemaNodeName = schemaNode.QName.localName;
1584 checkArgument(schemaNodeName !== null, "Local Name of QName for Data Schema Node cannot be NULL.");
1586 var String genTypeName;
1587 if (prefix === null) {
1588 genTypeName = parseToClassName(schemaNodeName);
1590 genTypeName = prefix + parseToClassName(schemaNodeName);
1593 //FIXME: Validation of name conflict
\r
1594 val newType = new GeneratedTypeBuilderImpl(packageName, genTypeName);
1595 if (!genTypeBuilders.containsKey(packageName)) {
1596 val Map<String, GeneratedTypeBuilder> builders = new HashMap();
1597 builders.put(genTypeName, newType);
1598 genTypeBuilders.put(packageName, builders);
1600 val Map<String, GeneratedTypeBuilder> builders = genTypeBuilders.get(packageName);
1601 if (!builders.containsKey(genTypeName)) {
1602 builders.put(genTypeName, newType);
1609 * Creates the name of the getter method from <code>methodName</code>.
\r
1611 * @param methodName
\r
1612 * string with the name of the getter method
\r
1613 * @param returnType return type
\r
1614 * @return string with the name of the getter method for
\r
1615 * <code>methodName</code> in JAVA method format
\r
1617 public static def String getterMethodName(String localName, Type returnType) {
1618 val method = new StringBuilder();
1619 if (BOOLEAN.equals(returnType)) {
1620 method.append("is");
1622 method.append("get");
1624 method.append(parseToClassName(localName));
1625 return method.toString();
1629 * Created a method signature builder as part of
\r
1630 * <code>interfaceBuilder</code>.
\r
1632 * The method signature builder is created for the getter method of
\r
1633 * <code>schemaNodeName</code>. Also <code>comment</code> and
\r
1634 * <code>returnType</code> information are added to the builder.
\r
1636 * @param interfaceBuilder
\r
1637 * generated type builder for which the getter method should be
\r
1639 * @param schemaNodeName
\r
1640 * string with schema node name. The name will be the part of the
\r
1641 * getter method name.
\r
1643 * string with comment for the getter method
\r
1644 * @param returnType
\r
1645 * type which represents the return type of the getter method
\r
1646 * @return method signature builder which represents the getter method of
\r
1647 * <code>interfaceBuilder</code>
\r
1649 private def MethodSignatureBuilder constructGetter(GeneratedTypeBuilder interfaceBuilder, String schemaNodeName,
1650 String comment, Type returnType) {
1651 val getMethod = interfaceBuilder.addMethod(getterMethodName(schemaNodeName, returnType));
1652 getMethod.setComment(comment);
1653 getMethod.setReturnType(returnType);
1658 * Adds <code>schemaNode</code> to <code>typeBuilder</code> as getter method
\r
1659 * or to <code>genTOBuilder</code> as property.
\r
1661 * @param basePackageName
\r
1662 * string contains the module package name
\r
1663 * @param schemaNode
\r
1664 * data schema node which should be added as getter method to
\r
1665 * <code>typeBuilder</code> or as a property to
\r
1666 * <code>genTOBuilder</code> if is part of the list key
\r
1667 * @param typeBuilder
\r
1668 * generated type builder for the list schema node
\r
1669 * @param genTOBuilder
\r
1670 * generated TO builder for the list keys
\r
1672 * list of string which contains names of the list keys
\r
1673 * @param module current module
\r
1674 * @throws IllegalArgumentException
\r
1676 * <li>if <code>schemaNode</code> equals null</li>
\r
1677 * <li>if <code>typeBuilder</code> equals null</li>
\r
1680 private def void addSchemaNodeToListBuilders(String basePackageName, DataSchemaNode schemaNode,
1681 GeneratedTypeBuilder typeBuilder, GeneratedTOBuilder genTOBuilder, List<String> listKeys, Module module) {
1682 checkArgument(schemaNode !== null, "Data Schema Node cannot be NULL.");
1683 checkArgument(typeBuilder !== null, "Generated Type Builder cannot be NULL.");
1685 if (schemaNode instanceof LeafSchemaNode) {
1686 val leaf = schemaNode as LeafSchemaNode;
1687 val leafName = leaf.QName.localName;
\r
1688 resolveLeafSchemaNodeAsMethod(typeBuilder, leaf);
1689 if (listKeys.contains(leafName)) {
1690 resolveLeafSchemaNodeAsProperty(genTOBuilder, leaf, true);
1692 } else if (!schemaNode.addedByUses) {
1693 if (schemaNode instanceof LeafListSchemaNode) {
1694 resolveLeafListSchemaNode(typeBuilder, schemaNode as LeafListSchemaNode);
1695 } else if (schemaNode instanceof ContainerSchemaNode) {
1696 containerToGenType(module, basePackageName, typeBuilder, typeBuilder, schemaNode as ContainerSchemaNode);
1697 } else if (schemaNode instanceof ChoiceNode) {
1698 choiceToGeneratedType(module, basePackageName, typeBuilder, schemaNode as ChoiceNode);
1699 } else if (schemaNode instanceof ListSchemaNode) {
1700 listToGenType(module, basePackageName, typeBuilder, typeBuilder, schemaNode as ListSchemaNode);
1705 private def typeBuildersToGenTypes(Module module, GeneratedTypeBuilder typeBuilder, GeneratedTOBuilder genTOBuilder) {
1706 checkArgument(typeBuilder !== null, "Generated Type Builder cannot be NULL.");
1708 if (genTOBuilder !== null) {
1709 val genTO = genTOBuilder.toInstance();
1710 constructGetter(typeBuilder, "key", "Returns Primary Key of Yang List Type", genTO);
1711 genCtx.get(module).addGeneratedTOBuilder(genTOBuilder)
1716 * Selects the names of the list keys from <code>list</code> and returns
\r
1717 * them as the list of the strings
\r
1720 * of string with names of the list keys
\r
1721 * @return list of string which represents names of the list keys. If the
\r
1722 * <code>list</code> contains no keys then the empty list is
\r
1725 private def listKeys(ListSchemaNode list) {
1726 val List<String> listKeys = new ArrayList();
1728 if (list.keyDefinition !== null) {
1729 val keyDefinitions = list.keyDefinition;
1730 for (keyDefinition : keyDefinitions) {
1731 listKeys.add(keyDefinition.localName);
1738 * Generates for the <code>list</code> which contains any list keys special
\r
1739 * generated TO builder.
\r
1741 * @param packageName
\r
1742 * string with package name to which the list belongs
\r
1744 * list schema node which is source of data about the list name
\r
1745 * @return generated TO builder which represents the keys of the
\r
1746 * <code>list</code> or null if <code>list</code> is null or list of
\r
1747 * key definitions is null or empty.
\r
1749 private def GeneratedTOBuilder resolveListKeyTOBuilder(String packageName, ListSchemaNode list) {
1750 var GeneratedTOBuilder genTOBuilder = null;
1751 if ((list.keyDefinition !== null) && (!list.keyDefinition.isEmpty())) {
1752 val listName = list.QName.localName + "Key";
1753 val String genTOName = parseToClassName(listName);
1754 genTOBuilder = new GeneratedTOBuilderImpl(packageName, genTOName);
1756 return genTOBuilder;
1760 * Builds generated TO builders for <code>typeDef</code> of type
\r
1761 * {@link org.opendaylight.yangtools.yang.model.util.UnionType UnionType} or
\r
1762 * {@link org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition
\r
1763 * BitsTypeDefinition} which are also added to <code>typeBuilder</code> as
\r
1764 * enclosing transfer object.
\r
1766 * If more then one generated TO builder is created for enclosing then all
\r
1767 * of the generated TO builders are added to <code>typeBuilder</code> as
\r
1768 * enclosing transfer objects.
\r
1771 * type definition which can be of type <code>UnionType</code> or
\r
1772 * <code>BitsTypeDefinition</code>
\r
1773 * @param typeBuilder
\r
1774 * generated type builder to which is added generated TO created
\r
1775 * from <code>typeDef</code>
\r
1777 * string with name for generated TO builder
\r
1779 * @param parentModule
\r
1780 * @return generated TO builder for <code>typeDef</code>
\r
1782 private def GeneratedTOBuilder addTOToTypeBuilder(TypeDefinition<?> typeDef, GeneratedTypeBuilder typeBuilder,
1783 String leafName, LeafSchemaNode leaf, Module parentModule) {
1784 val classNameFromLeaf = parseToClassName(leafName);
1785 val List<GeneratedTOBuilder> genTOBuilders = new ArrayList();
1786 val packageName = typeBuilder.fullyQualifiedName;
1787 if (typeDef instanceof UnionTypeDefinition) {
1788 genTOBuilders.addAll(
1789 (typeProvider as TypeProviderImpl).
1790 provideGeneratedTOBuildersForUnionTypeDef(packageName, (typeDef as UnionTypeDefinition),
1791 classNameFromLeaf, leaf));
1792 } else if (typeDef instanceof BitsTypeDefinition) {
1794 ((typeProvider as TypeProviderImpl) ).
1795 provideGeneratedTOBuilderForBitsTypeDefinition(packageName, typeDef, classNameFromLeaf));
1797 if (genTOBuilders !== null && !genTOBuilders.isEmpty()) {
1798 for (genTOBuilder : genTOBuilders) {
1799 typeBuilder.addEnclosingTransferObject(genTOBuilder);
1801 return genTOBuilders.get(0);
1808 * Adds the implemented types to type builder.
\r
1810 * The method passes through the list of <i>uses</i> in
\r
1811 * {@code dataNodeContainer}. For every <i>use</i> is obtained coresponding
\r
1812 * generated type from {@link BindingGeneratorImpl#allGroupings
\r
1813 * allGroupings} which is added as <i>implements type</i> to
\r
1814 * <code>builder</code>
\r
1816 * @param dataNodeContainer
\r
1817 * element which contains the list of used YANG groupings
\r
1819 * builder to which are added implemented types according to
\r
1820 * <code>dataNodeContainer</code>
\r
1821 * @return generated type builder with all implemented types
\r
1823 private def addImplementedInterfaceFromUses(DataNodeContainer dataNodeContainer, GeneratedTypeBuilder builder) {
1824 for (usesNode : dataNodeContainer.uses) {
1825 if (usesNode.groupingPath !== null) {
1826 val genType = findGroupingByPath(usesNode.groupingPath).toInstance
1827 if (genType === null) {
1828 throw new IllegalStateException(
1829 "Grouping " + usesNode.groupingPath + "is not resolved for " + builder.name);
1831 builder.addImplementsType(genType);
1837 private def GeneratedTypeBuilder findChildNodeByPath(SchemaPath path) {
1838 for (ctx : genCtx.values) {
1839 var result = ctx.getChildNode(path)
1840 if (result !== null) {
1847 private def GeneratedTypeBuilder findGroupingByPath(SchemaPath path) {
1848 for (ctx : genCtx.values) {
1849 var result = ctx.getGrouping(path)
1850 if (result !== null) {
1857 private def GeneratedTypeBuilder findCaseByPath(SchemaPath path) {
1858 for (ctx : genCtx.values) {
1859 var result = ctx.getCase(path)
1860 if (result !== null) {
1868 public def getModuleContexts() {
\r