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) {
\r
271 val GeneratedPropertyBuilder prop = new GeneratedPropertyBuilderImpl("serialVersionUID");
\r
272 prop.setValue(Long.toString(computeDefaultSUID(genTOBuilder as GeneratedTOBuilderImpl)));
\r
273 genTOBuilder.setSUID(prop);
274 val identifierMarker = IDENTIFIER.parameterizedTypeFor(genType);
275 val identifiableMarker = IDENTIFIABLE.parameterizedTypeFor(genTOBuilder);
276 genTOBuilder.addImplementsType(identifierMarker);
277 genType.addImplementsType(identifiableMarker);
280 for (schemaNode : node.childNodes) {
281 if (!schemaNode.augmenting) {
282 addSchemaNodeToListBuilders(basePackageName, schemaNode, genType, genTOBuilder, listKeys, module);
286 typeBuildersToGenTypes(module, genType, genTOBuilder);
289 private def void processUsesAugments(DataNodeContainer node, Module module) {
290 val basePackageName = moduleNamespaceToPackageName(module);
291 for (usesNode : node.uses) {
292 for (augment : usesNode.augmentations) {
293 augmentationToGenTypes(basePackageName, augment, module, usesNode);
294 processUsesAugments(augment, module);
300 * Converts all <b>augmentation</b> of the module to the list
\r
301 * <code>Type</code> objects.
\r
304 * module from which is obtained list of all augmentation objects
\r
305 * to iterate over them
\r
306 * @throws IllegalArgumentException
\r
308 * <li>if the module equals null</li>
\r
309 * <li>if the name of module equals null</li>
\r
310 * <li>if the set of child nodes equals null</li>
\r
314 private def void allAugmentsToGenTypes(Module module) {
315 checkArgument(module !== null, "Module reference cannot be NULL.");
316 checkArgument(module.name !== null, "Module name cannot be NULL.");
317 if (module.childNodes === null) {
318 throw new IllegalArgumentException(
319 "Reference to Set of Augmentation Definitions in module " + module.name + " cannot be NULL.");
322 val basePackageName = moduleNamespaceToPackageName(module);
323 val List<AugmentationSchema> augmentations = resolveAugmentations(module);
324 for (augment : augmentations) {
325 augmentationToGenTypes(basePackageName, augment, module, null);
330 * Returns list of <code>AugmentationSchema</code> objects. The objects are
\r
331 * sorted according to the length of their target path from the shortest to
\r
335 * module from which is obtained list of all augmentation objects
\r
336 * @return list of sorted <code>AugmentationSchema</code> objects obtained
\r
337 * from <code>module</code>
\r
338 * @throws IllegalArgumentException
\r
340 * <li>if the module equals null</li>
\r
341 * <li>if the set of augmentation equals null</li>
\r
345 private def List<AugmentationSchema> resolveAugmentations(Module module) {
346 checkArgument(module !== null, "Module reference cannot be NULL.");
347 checkState(module.augmentations !== null, "Augmentations Set cannot be NULL.");
349 val Set<AugmentationSchema> augmentations = module.augmentations;
350 val List<AugmentationSchema> sortedAugmentations = new ArrayList(augmentations);
351 Collections.sort(sortedAugmentations,
352 [ augSchema1, augSchema2 |
353 if (augSchema1.targetPath.path.size() > augSchema2.targetPath.path.size()) {
355 } else if (augSchema1.targetPath.path.size() < augSchema2.targetPath.path.size()) {
360 return sortedAugmentations;
364 * Converts whole <b>module</b> to <code>GeneratedType</code> object.
\r
365 * Firstly is created the module builder object from which is vally
\r
366 * obtained reference to <code>GeneratedType</code> object.
\r
369 * module from which are obtained the module name, child nodes,
\r
370 * uses and is derived package name
\r
371 * @return <code>GeneratedType</code> which is internal representation of
\r
373 * @throws IllegalArgumentException
\r
374 * if the module equals null
\r
377 private def GeneratedTypeBuilder moduleToDataType(Module module) {
378 checkArgument(module !== null, "Module reference cannot be NULL.");
380 val moduleDataTypeBuilder = moduleTypeBuilder(module, "Data");
381 addImplementedInterfaceFromUses(module, moduleDataTypeBuilder);
382 moduleDataTypeBuilder.addImplementsType(DATA_ROOT);
383 return moduleDataTypeBuilder;
387 * Converts all <b>rpcs</b> inputs and outputs substatements of the module
\r
388 * to the list of <code>Type</code> objects. In addition are to containers
\r
389 * and lists which belong to input or output also part of returning list.
\r
392 * module from which is obtained set of all rpc objects to
\r
393 * iterate over them
\r
394 * @throws IllegalArgumentException
\r
396 * <li>if the module equals null</li>
\r
397 * <li>if the name of module equals null</li>
\r
398 * <li>if the set of child nodes equals null</li>
\r
402 private def void rpcMethodsToGenType(Module module) {
403 checkArgument(module !== null, "Module reference cannot be NULL.");
404 checkArgument(module.name !== null, "Module name cannot be NULL.");
405 checkArgument(module.childNodes !== null,
406 "Reference to Set of RPC Method Definitions in module " + module.name + " cannot be NULL.");
408 val basePackageName = moduleNamespaceToPackageName(module);
409 val Set<RpcDefinition> rpcDefinitions = module.rpcs;
410 if (rpcDefinitions.isEmpty()) {
414 val interfaceBuilder = moduleTypeBuilder(module, "Service");
415 interfaceBuilder.addImplementsType(Types.typeForClass(RpcService));
416 for (rpc : rpcDefinitions) {
418 val rpcName = parseToClassName(rpc.QName.localName);
419 val rpcMethodName = parseToValidParamName(rpcName);
420 val method = interfaceBuilder.addMethod(rpcMethodName);
421 val input = rpc.input;
422 val output = rpc.output;
424 if (input !== null) {
425 val inType = addRawInterfaceDefinition(basePackageName, input, rpcName);
426 addImplementedInterfaceFromUses(input, inType);
427 inType.addImplementsType(DATA_OBJECT);
428 inType.addImplementsType(augmentable(inType));
429 resolveDataSchemaNodes(module, basePackageName, inType, inType, input.childNodes);
430 genCtx.get(module).addChildNodeType(input.path, inType)
431 val inTypeInstance = inType.toInstance();
432 method.addParameter(inTypeInstance, "input");
435 var Type outTypeInstance = VOID;
436 if (output !== null) {
437 val outType = addRawInterfaceDefinition(basePackageName, output, rpcName);
438 addImplementedInterfaceFromUses(output, outType);
439 outType.addImplementsType(DATA_OBJECT);
440 outType.addImplementsType(augmentable(outType));
441 resolveDataSchemaNodes(module, basePackageName, outType, outType, output.childNodes);
442 genCtx.get(module).addChildNodeType(output.path, outType)
443 outTypeInstance = outType.toInstance();
446 val rpcRes = Types.parameterizedTypeFor(Types.typeForClass(RpcResult), outTypeInstance);
447 method.setReturnType(Types.parameterizedTypeFor(FUTURE, rpcRes));
451 genCtx.get(module).addTopLevelNodeType(interfaceBuilder)
455 * Converts all <b>notifications</b> of the module to the list of
\r
456 * <code>Type</code> objects. In addition are to this list added containers
\r
457 * and lists which are part of this notification.
\r
460 * module from which is obtained set of all notification objects
\r
461 * to iterate over them
\r
462 * @throws IllegalArgumentException
\r
464 * <li>if the module equals null</li>
\r
465 * <li>if the name of module equals null</li>
\r
466 * <li>if the set of child nodes equals null</li>
\r
470 private def void notificationsToGenType(Module module) {
471 checkArgument(module !== null, "Module reference cannot be NULL.");
472 checkArgument(module.name !== null, "Module name cannot be NULL.");
474 if (module.childNodes === null) {
475 throw new IllegalArgumentException(
476 "Reference to Set of Notification Definitions in module " + module.name + " cannot be NULL.");
478 val notifications = module.notifications;
479 if(notifications.empty) return;
481 val listenerInterface = moduleTypeBuilder(module, "Listener");
482 listenerInterface.addImplementsType(BindingTypes.NOTIFICATION_LISTENER);
483 val basePackageName = moduleNamespaceToPackageName(module);
485 for (notification : notifications) {
486 if (notification !== null) {
487 processUsesAugments(notification, module);
489 val notificationInterface = addDefaultInterfaceDefinition(basePackageName, notification,
490 BindingTypes.DATA_OBJECT);
491 notificationInterface.addImplementsType(NOTIFICATION);
492 genCtx.get(module).addChildNodeType(notification.path, notificationInterface)
494 // Notification object
\r
495 resolveDataSchemaNodes(module, basePackageName, notificationInterface, notificationInterface,
496 notification.childNodes);
498 listenerInterface.addMethod("on" + notificationInterface.name) //
\r
499 .setAccessModifier(AccessModifier.PUBLIC).addParameter(notificationInterface, "notification").
500 setReturnType(Types.VOID);
504 genCtx.get(module).addTopLevelNodeType(listenerInterface)
508 * Converts all <b>identities</b> of the module to the list of
\r
509 * <code>Type</code> objects.
\r
512 * module from which is obtained set of all identity objects to
\r
513 * iterate over them
\r
515 * schema context only used as input parameter for method
\r
516 * {@link identityToGenType}
\r
519 private def void allIdentitiesToGenTypes(Module module, SchemaContext context) {
520 val Set<IdentitySchemaNode> schemaIdentities = module.identities;
521 val basePackageName = moduleNamespaceToPackageName(module);
523 if (schemaIdentities !== null && !schemaIdentities.isEmpty()) {
524 for (identity : schemaIdentities) {
525 identityToGenType(module, basePackageName, identity, context);
531 * Converts the <b>identity</b> object to GeneratedType. Firstly it is
\r
532 * created transport object builder. If identity contains base identity then
\r
533 * reference to base identity is added to superior identity as its extend.
\r
534 * If identity doesn't contain base identity then only reference to abstract
\r
535 * class {@link org.opendaylight.yangtools.yang.model.api.BaseIdentity
\r
536 * BaseIdentity} is added
\r
538 * @param module current module
\r
539 * @param basePackageName
\r
540 * string contains the module package name
\r
542 * IdentitySchemaNode which contains data about identity
\r
544 * SchemaContext which is used to get package and name
\r
545 * information about base of identity
\r
548 private def void identityToGenType(Module module, String basePackageName, IdentitySchemaNode identity,
549 SchemaContext context) {
550 if (identity === null) {
553 val packageName = packageNameForGeneratedType(basePackageName, identity.path);
554 val genTypeName = parseToClassName(identity.QName.localName);
555 val newType = new GeneratedTOBuilderImpl(packageName, genTypeName);
556 val baseIdentity = identity.baseIdentity;
557 if (baseIdentity === null) {
558 newType.setExtendsType(Types.baseIdentityTO);
560 val baseIdentityParentModule = SchemaContextUtil.findParentModule(context, baseIdentity);
561 val returnTypePkgName = moduleNamespaceToPackageName(baseIdentityParentModule);
562 val returnTypeName = parseToClassName(baseIdentity.QName.localName);
563 val gto = new GeneratedTOBuilderImpl(returnTypePkgName, returnTypeName).toInstance();
564 newType.setExtendsType(gto);
566 newType.setAbstract(true);
567 genCtx.get(module).addIdentityType(newType)
571 * Converts all <b>groupings</b> of the module to the list of
\r
572 * <code>Type</code> objects. Firstly are groupings sorted according mutual
\r
573 * dependencies. At least dependend (indepedent) groupings are in the list
\r
574 * saved at first positions. For every grouping the record is added to map
\r
575 * {@link BindingGeneratorImpl#allGroupings allGroupings}
\r
579 * @param collection of groupings from which types will be generated
\r
582 private def void groupingsToGenTypes(Module module, Collection<GroupingDefinition> groupings) {
583 val basePackageName = moduleNamespaceToPackageName(module);
584 val List<GroupingDefinition> groupingsSortedByDependencies = new GroupingDefinitionDependencySort().sort(
586 for (grouping : groupingsSortedByDependencies) {
587 groupingToGenType(basePackageName, grouping, module);
592 * Converts individual grouping to GeneratedType. Firstly generated type
\r
593 * builder is created and every child node of grouping is resolved to the
\r
596 * @param basePackageName
\r
597 * string contains the module package name
\r
599 * GroupingDefinition which contains data about grouping
\r
600 * @param module current module
\r
601 * @return GeneratedType which is generated from grouping (object of type
\r
602 * <code>GroupingDefinition</code>)
\r
604 private def void groupingToGenType(String basePackageName, GroupingDefinition grouping, Module module) {
605 val packageName = packageNameForGeneratedType(basePackageName, grouping.path);
606 val genType = addDefaultInterfaceDefinition(packageName, grouping);
607 genCtx.get(module).addGroupingType(grouping.path, genType)
608 resolveDataSchemaNodes(module, basePackageName, genType, genType, grouping.childNodes);
609 groupingsToGenTypes(module, grouping.groupings);
610 processUsesAugments(grouping, module);
614 * Tries to find EnumTypeDefinition in <code>typeDefinition</code>. If base
\r
615 * type of <code>typeDefinition</code> is of the type ExtendedType then this
\r
616 * method is recursivelly called with this base type.
\r
618 * @param typeDefinition
\r
619 * TypeDefinition in which should be EnumTypeDefinition found as
\r
621 * @return EnumTypeDefinition if it is found inside
\r
622 * <code>typeDefinition</code> or <code>null</code> in other case
\r
624 private def EnumTypeDefinition enumTypeDefFromExtendedType(TypeDefinition<?> typeDefinition) {
625 if (typeDefinition !== null) {
626 if (typeDefinition.baseType instanceof EnumTypeDefinition) {
627 return typeDefinition.baseType as EnumTypeDefinition;
628 } else if (typeDefinition.baseType instanceof ExtendedType) {
629 return enumTypeDefFromExtendedType(typeDefinition.baseType);
636 * Adds enumeration builder created from <code>enumTypeDef</code> to
\r
637 * <code>typeBuilder</code>.
\r
639 * Each <code>enumTypeDef</code> item is added to builder with its name and
\r
642 * @param enumTypeDef
\r
643 * EnumTypeDefinition contains enum data
\r
645 * string contains name which will be assigned to enumeration
\r
647 * @param typeBuilder
\r
648 * GeneratedTypeBuilder to which will be enum builder assigned
\r
649 * @return enumeration builder which contais data from
\r
650 * <code>enumTypeDef</code>
\r
652 private def EnumBuilder resolveInnerEnumFromTypeDefinition(EnumTypeDefinition enumTypeDef, String enumName,
653 GeneratedTypeBuilder typeBuilder) {
654 if ((enumTypeDef !== null) && (typeBuilder !== null) && (enumTypeDef.QName !== null) &&
655 (enumTypeDef.QName.localName !== null)) {
656 val enumerationName = parseToClassName(enumName);
657 val enumBuilder = typeBuilder.addEnumeration(enumerationName);
658 enumBuilder.updateEnumPairsFromEnumTypeDef(enumTypeDef);
665 * Generates type builder for <code>module</code>.
\r
668 * Module which is source of package name for generated type
\r
671 * string which is added to the module class name representation
\r
673 * @return instance of GeneratedTypeBuilder which represents
\r
674 * <code>module</code>.
\r
675 * @throws IllegalArgumentException
\r
676 * if <code>module</code> equals null
\r
678 private def GeneratedTypeBuilder moduleTypeBuilder(Module module, String postfix) {
679 checkArgument(module !== null, "Module reference cannot be NULL.");
680 val packageName = moduleNamespaceToPackageName(module);
681 val moduleName = parseToClassName(module.name) + postfix;
682 return new GeneratedTypeBuilderImpl(packageName, moduleName);
686 * Converts <code>augSchema</code> to list of <code>Type</code> which
\r
687 * contains generated type for augmentation. In addition there are also
\r
688 * generated types for all containers, list and choices which are child of
\r
689 * <code>augSchema</code> node or a generated types for cases are added if
\r
690 * augmented node is choice.
\r
692 * @param augmentPackageName
\r
693 * string with the name of the package to which the augmentation
\r
696 * AugmentationSchema which is contains data about agumentation
\r
697 * (target path, childs...)
\r
698 * @param module current module
\r
699 * @param parentUsesNode parent uses node of this augment (can be null if this augment is not defined under uses statement)
\r
700 * @throws IllegalArgumentException
\r
702 * <li>if <code>augmentPackageName</code> equals null</li>
\r
703 * <li>if <code>augSchema</code> equals null</li>
\r
704 * <li>if target path of <code>augSchema</code> equals null</li>
\r
707 private def void augmentationToGenTypes(String augmentPackageName, AugmentationSchema augSchema, Module module,
708 UsesNode parentUsesNode) {
709 checkArgument(augmentPackageName !== null, "Package Name cannot be NULL.");
710 checkArgument(augSchema !== null, "Augmentation Schema cannot be NULL.");
711 checkState(augSchema.targetPath !== null,
712 "Augmentation Schema does not contain Target Path (Target Path is NULL).");
714 processUsesAugments(augSchema, module);
716 // EVERY augmented interface will extends Augmentation<T> interface
\r
717 // and DataObject interface
\r
718 val targetPath = augSchema.targetPath;
719 var targetSchemaNode = findDataSchemaNode(schemaContext, targetPath);
720 if (targetSchemaNode instanceof DataSchemaNode && (targetSchemaNode as DataSchemaNode).isAddedByUses()) {
721 if (parentUsesNode == null) {
722 targetSchemaNode = findOriginal(targetSchemaNode as DataSchemaNode);
724 targetSchemaNode = findOriginalTargetFromGrouping(targetSchemaNode.QName.localName, parentUsesNode);
726 if (targetSchemaNode == null) {
727 throw new NullPointerException(
728 "Failed to find target node from grouping for augmentation " + augSchema + " in module " +
733 if (targetSchemaNode !== null) {
734 var targetTypeBuilder = findChildNodeByPath(targetSchemaNode.path)
735 if (targetTypeBuilder === null) {
736 targetTypeBuilder = findCaseByPath(targetSchemaNode.path)
738 if (targetTypeBuilder === null) {
739 throw new NullPointerException("Target type not yet generated: " + targetSchemaNode);
741 if (!(targetSchemaNode instanceof ChoiceNode)) {
742 var packageName = augmentPackageName;
743 if (parentUsesNode != null) {
744 packageName = packageNameForGeneratedType(augmentPackageName, augSchema.targetPath);
746 val augTypeBuilder = addRawAugmentGenTypeDefinition(module, packageName, augmentPackageName,
747 targetTypeBuilder.toInstance, augSchema);
748 genCtx.get(module).addAugmentType(augTypeBuilder)
750 generateTypesFromAugmentedChoiceCases(module, augmentPackageName, targetTypeBuilder.toInstance,
751 targetSchemaNode as ChoiceNode, augSchema.childNodes);
757 * Utility method which search for original node defined in grouping.
\r
759 private def DataSchemaNode findOriginal(DataSchemaNode node) {
760 var DataSchemaNode result = findCorrectTargetFromGrouping(node);
761 if (result == null) {
762 result = findCorrectTargetFromAugment(node);
763 if (result != null) {
764 if (result.addedByUses) {
765 result = findOriginal(result);
772 private def DataSchemaNode findCorrectTargetFromAugment(DataSchemaNode node) {
773 if (!node.augmenting) {
777 var String currentName = node.QName.localName;
778 var tmpPath = new ArrayList<String>();
779 var YangNode parent = node;
780 var AugmentationSchema augment = null;
782 parent = (parent as DataSchemaNode).parent;
783 if (parent instanceof AugmentationTarget) {
784 tmpPath.add(currentName);
785 augment = findNodeInAugment((parent as AugmentationTarget).availableAugmentations, currentName);
786 if (augment == null) {
787 currentName = (parent as DataSchemaNode).QName.localName;
790 } while ((parent as DataSchemaNode).augmenting && augment == null);
792 if (augment == null) {
795 Collections.reverse(tmpPath);
796 var Object actualParent = augment;
797 var DataSchemaNode result = null;
798 for (name : tmpPath) {
799 if (actualParent instanceof DataNodeContainer) {
800 result = (actualParent as DataNodeContainer).getDataChildByName(name);
801 actualParent = (actualParent as DataNodeContainer).getDataChildByName(name);
803 if (actualParent instanceof ChoiceNode) {
804 result = (actualParent as ChoiceNode).getCaseNodeByName(name);
805 actualParent = (actualParent as ChoiceNode).getCaseNodeByName(name);
810 if (result.addedByUses) {
811 result = findCorrectTargetFromGrouping(result);
818 private def AugmentationSchema findNodeInAugment(Collection<AugmentationSchema> augments, String name) {
819 for (augment : augments) {
820 if (augment.getDataChildByName(name) != null) {
827 private def DataSchemaNode findCorrectTargetFromGrouping(DataSchemaNode node) {
828 if (node.path.path.size == 1) {
830 // uses is under module statement
\r
831 val Module m = findParentModule(schemaContext, node);
832 var DataSchemaNode result = null;
834 var SchemaNode targetGrouping = findNodeInSchemaContext(schemaContext, u.groupingPath.path);
835 if (!(targetGrouping instanceof GroupingDefinition)) {
836 throw new IllegalArgumentException("Failed to generate code for augment in " + u);
838 var gr = targetGrouping as GroupingDefinition;
839 result = gr.getDataChildByName(node.QName.localName);
841 if (result == null) {
842 throw new IllegalArgumentException("Failed to generate code for augment");
846 var DataSchemaNode result = null;
847 var String currentName = node.QName.localName;
848 var tmpPath = new ArrayList<String>();
849 var YangNode parent = node.parent;
851 tmpPath.add(currentName);
852 val dataNodeParent = parent as DataNodeContainer;
853 for (u : dataNodeParent.uses) {
854 if (result == null) {
\r
855 var SchemaNode targetGrouping = findNodeInSchemaContext(schemaContext, u.groupingPath.path);
856 if (!(targetGrouping instanceof GroupingDefinition)) {
857 throw new IllegalArgumentException("Failed to generate code for augment in " + u);
859 var gr = targetGrouping as GroupingDefinition;
860 result = gr.getDataChildByName(currentName);
\r
863 if (result == null) {
864 currentName = (parent as SchemaNode).QName.localName;
865 if (parent instanceof DataSchemaNode) {
866 parent = (parent as DataSchemaNode).parent;
868 parent = (parent as DataNodeContainer).parent;
871 } while (result == null && !(parent instanceof Module));
873 if (result != null) {
874 if (tmpPath.size == 1) {
877 var DataSchemaNode newParent = result;
878 Collections.reverse(tmpPath);
880 for (name : tmpPath) {
881 newParent = (newParent as DataNodeContainer).getDataChildByName(name);
892 * Convenient method to find node added by uses statement.
\r
894 private def DataSchemaNode findOriginalTargetFromGrouping(String targetSchemaNodeName, UsesNode parentUsesNode) {
895 var SchemaNode targetGrouping = findNodeInSchemaContext(schemaContext, parentUsesNode.groupingPath.path);
896 if (!(targetGrouping instanceof GroupingDefinition)) {
897 throw new IllegalArgumentException("Failed to generate code for augment in " + parentUsesNode);
900 var grouping = targetGrouping as GroupingDefinition;
901 var result = grouping.getDataChildByName(targetSchemaNodeName);
902 if (result == null) {
905 var boolean fromUses = result.addedByUses;
907 var Iterator<UsesNode> groupingUses = grouping.uses.iterator;
909 if (groupingUses.hasNext()) {
910 grouping = findNodeInSchemaContext(schemaContext, groupingUses.next().groupingPath.path) as GroupingDefinition;
911 result = grouping.getDataChildByName(targetSchemaNodeName);
912 fromUses = result.addedByUses;
914 throw new NullPointerException("Failed to generate code for augment in " + parentUsesNode);
922 * Returns a generated type builder for an augmentation.
\r
924 * The name of the type builder is equal to the name of augmented node with
\r
925 * serial number as suffix.
\r
927 * @param module current module
\r
928 * @param augmentPackageName
\r
929 * string with contains the package name to which the augment
\r
931 * @param basePackageName
\r
932 * string with the package name to which the augmented node
\r
934 * @param targetTypeRef
\r
937 * augmentation schema which contains data about the child nodes
\r
938 * and uses of augment
\r
939 * @return generated type builder for augment
\r
941 private def GeneratedTypeBuilder addRawAugmentGenTypeDefinition(Module module, String augmentPackageName,
942 String basePackageName, Type targetTypeRef, AugmentationSchema augSchema) {
943 var Map<String, GeneratedTypeBuilder> augmentBuilders = genTypeBuilders.get(augmentPackageName);
944 if (augmentBuilders === null) {
945 augmentBuilders = new HashMap();
946 genTypeBuilders.put(augmentPackageName, augmentBuilders);
948 val augIdentifier = getAugmentIdentifier(augSchema.unknownSchemaNodes);
950 val augTypeName = if (augIdentifier !== null) {
951 parseToClassName(augIdentifier)
953 augGenTypeName(augmentBuilders, targetTypeRef.name);
956 val augTypeBuilder = new GeneratedTypeBuilderImpl(augmentPackageName, augTypeName);
958 augTypeBuilder.addImplementsType(DATA_OBJECT);
959 augTypeBuilder.addImplementsType(Types.augmentationTypeFor(targetTypeRef));
960 addImplementedInterfaceFromUses(augSchema, augTypeBuilder);
962 augSchemaNodeToMethods(module, basePackageName, augTypeBuilder, augTypeBuilder, augSchema.childNodes);
963 augmentBuilders.put(augTypeName, augTypeBuilder);
964 return augTypeBuilder;
969 * @param unknownSchemaNodes
\r
970 * @return nodeParameter of UnknownSchemaNode
\r
972 private def String getAugmentIdentifier(List<UnknownSchemaNode> unknownSchemaNodes) {
973 for (unknownSchemaNode : unknownSchemaNodes) {
974 val nodeType = unknownSchemaNode.nodeType;
975 if (AUGMENT_IDENTIFIER_NAME.equals(nodeType.localName) &&
976 YANG_EXT_NAMESPACE.equals(nodeType.namespace.toString())) {
977 return unknownSchemaNode.nodeParameter;
984 * Returns first unique name for the augment generated type builder. The
\r
985 * generated type builder name for augment consists from name of augmented
\r
986 * node and serial number of its augmentation.
\r
989 * map of builders which were created in the package to which the
\r
990 * augmentation belongs
\r
991 * @param genTypeName
\r
992 * string with name of augmented node
\r
993 * @return string with unique name for augmentation builder
\r
995 private def String augGenTypeName(Map<String, GeneratedTypeBuilder> builders, String genTypeName) {
997 while ((builders !== null) && builders.containsKey(genTypeName + index)) {
1000 return genTypeName + index;
1004 * Adds the methods to <code>typeBuilder</code> which represent subnodes of
\r
1005 * node for which <code>typeBuilder</code> was created.
\r
1007 * The subnodes aren't mapped to the methods if they are part of grouping or
\r
1008 * augment (in this case are already part of them).
\r
1010 * @param module current module
\r
1011 * @param basePackageName
\r
1012 * string contains the module package name
\r
1014 * generated type builder which represents any node. The subnodes
\r
1015 * of this node are added to the <code>typeBuilder</code> as
\r
1016 * methods. The subnode can be of type leaf, leaf-list, list,
\r
1017 * container, choice.
\r
1018 * @param childOf parent type
\r
1019 * @param schemaNodes
\r
1020 * set of data schema nodes which are the children of the node
\r
1021 * for which <code>typeBuilder</code> was created
\r
1022 * @return generated type builder which is the same builder as input
\r
1023 * parameter. The getter methods (representing child nodes) could be
\r
1026 private def GeneratedTypeBuilder resolveDataSchemaNodes(Module module, String basePackageName,
1027 GeneratedTypeBuilder parent, GeneratedTypeBuilder childOf, Set<DataSchemaNode> schemaNodes) {
1028 if ((schemaNodes !== null) && (parent !== null)) {
1029 for (schemaNode : schemaNodes) {
1030 if (!schemaNode.augmenting && !schemaNode.addedByUses) {
1031 addSchemaNodeToBuilderAsMethod(basePackageName, schemaNode, parent, childOf, module);
1039 * Adds the methods to <code>typeBuilder</code> what represents subnodes of
\r
1040 * node for which <code>typeBuilder</code> was created.
\r
1042 * @param module current module
\r
1043 * @param basePackageName
\r
1044 * string contains the module package name
\r
1045 * @param typeBuilder
\r
1046 * generated type builder which represents any node. The subnodes
\r
1047 * of this node are added to the <code>typeBuilder</code> as
\r
1048 * methods. The subnode can be of type leaf, leaf-list, list,
\r
1049 * container, choice.
\r
1050 * @param childOf parent type
\r
1051 * @param schemaNodes
\r
1052 * set of data schema nodes which are the children of the node
\r
1053 * for which <code>typeBuilder</code> was created
\r
1054 * @return generated type builder which is the same object as the input
\r
1055 * parameter <code>typeBuilder</code>. The getter method could be
\r
1058 private def GeneratedTypeBuilder augSchemaNodeToMethods(Module module, String basePackageName,
1059 GeneratedTypeBuilder typeBuilder, GeneratedTypeBuilder childOf, Set<DataSchemaNode> schemaNodes) {
1060 if ((schemaNodes !== null) && (typeBuilder !== null)) {
1061 for (schemaNode : schemaNodes) {
1062 if (!schemaNode.isAugmenting()) {
1063 addSchemaNodeToBuilderAsMethod(basePackageName, schemaNode, typeBuilder, childOf, module);
1071 * Adds to <code>typeBuilder</code> a method which is derived from
\r
1072 * <code>schemaNode</code>.
\r
1074 * @param basePackageName
\r
1075 * string with the module package name
\r
1077 * data schema node which is added to <code>typeBuilder</code> as
\r
1079 * @param typeBuilder
\r
1080 * generated type builder to which is <code>schemaNode</code>
\r
1081 * added as a method.
\r
1082 * @param childOf parent type
\r
1083 * @param module current module
\r
1085 private def void addSchemaNodeToBuilderAsMethod(String basePackageName, DataSchemaNode node,
1086 GeneratedTypeBuilder typeBuilder, GeneratedTypeBuilder childOf, Module module) {
1087 if (node !== null && typeBuilder !== null) {
1089 case node instanceof LeafSchemaNode:
1090 resolveLeafSchemaNodeAsMethod(typeBuilder, node as LeafSchemaNode)
1091 case node instanceof LeafListSchemaNode:
1092 resolveLeafListSchemaNode(typeBuilder, node as LeafListSchemaNode)
1093 case node instanceof ContainerSchemaNode:
1094 containerToGenType(module, basePackageName, typeBuilder, childOf, node as ContainerSchemaNode)
1095 case node instanceof ListSchemaNode:
1096 listToGenType(module, basePackageName, typeBuilder, childOf, node as ListSchemaNode)
1097 case node instanceof ChoiceNode:
1098 choiceToGeneratedType(module, basePackageName, typeBuilder, node as ChoiceNode)
1104 * Converts <code>choiceNode</code> to the list of generated types for
\r
1105 * choice and its cases.
\r
1107 * The package names for choice and for its cases are created as
\r
1108 * concatenation of the module package (<code>basePackageName</code>) and
\r
1109 * names of all parents node.
\r
1111 * @param module current module
\r
1112 * @param basePackageName
\r
1113 * string with the module package name
\r
1114 * @param parent parent type
\r
1115 * @param childOf concrete parent for case child nodes
\r
1116 * @param choiceNode
\r
1117 * choice node which is mapped to generated type. Also child
\r
1118 * nodes - cases are mapped to generated types.
\r
1119 * @throws IllegalArgumentException
\r
1121 * <li>if <code>basePackageName</code> equals null</li>
\r
1122 * <li>if <code>choiceNode</code> equals null</li>
\r
1126 private def void choiceToGeneratedType(Module module, String basePackageName, GeneratedTypeBuilder parent,
1127 ChoiceNode choiceNode) {
1128 checkArgument(basePackageName !== null, "Base Package Name cannot be NULL.");
1129 checkArgument(choiceNode !== null, "Choice Schema Node cannot be NULL.");
1131 val packageName = packageNameForGeneratedType(basePackageName, choiceNode.path);
1132 val choiceTypeBuilder = addRawInterfaceDefinition(packageName, choiceNode);
1133 constructGetter(parent, choiceNode.QName.localName, choiceNode.description, choiceTypeBuilder);
1134 choiceTypeBuilder.addImplementsType(DataContainer.typeForClass);
1135 genCtx.get(module).addChildNodeType(choiceNode.path, choiceTypeBuilder)
1136 generateTypesFromChoiceCases(module, basePackageName, parent, choiceTypeBuilder.toInstance, choiceNode);
1140 * Converts <code>caseNodes</code> set to list of corresponding generated
\r
1143 * For every <i>case</i> which isn't added through augment or <i>uses</i> is
\r
1144 * created generated type builder. The package names for the builder is
\r
1145 * created as concatenation of the module package (
\r
1146 * <code>basePackageName</code>) and names of all parents nodes of the
\r
1147 * concrete <i>case</i>. There is also relation "<i>implements type</i>"
\r
1148 * between every case builder and <i>choice</i> type
\r
1150 * @param basePackageName
\r
1151 * string with the module package name
\r
1152 * @param refChoiceType
\r
1153 * type which represents superior <i>case</i>
\r
1154 * @param caseNodes
\r
1155 * set of choice case nodes which are mapped to generated types
\r
1156 * @return list of generated types for <code>caseNodes</code>.
\r
1157 * @throws IllegalArgumentException
\r
1159 * <li>if <code>basePackageName</code> equals null</li>
\r
1160 * <li>if <code>refChoiceType</code> equals null</li>
\r
1161 * <li>if <code>caseNodes</code> equals null</li>
\r
1165 private def void generateTypesFromChoiceCases(Module module, String basePackageName,
1166 GeneratedTypeBuilder choiceParent, Type refChoiceType, ChoiceNode choiceNode) {
1167 checkArgument(basePackageName !== null, "Base Package Name cannot be NULL.");
1168 checkArgument(refChoiceType !== null, "Referenced Choice Type cannot be NULL.");
1169 checkArgument(choiceNode !== null, "ChoiceNode cannot be NULL.");
1171 val Set<ChoiceCaseNode> caseNodes = choiceNode.cases;
1172 if (caseNodes == null) {
1176 for (caseNode : caseNodes) {
1177 if (caseNode !== null && !caseNode.isAddedByUses() && !caseNode.isAugmenting()) {
1178 val packageName = packageNameForGeneratedType(basePackageName, caseNode.path);
1179 val caseTypeBuilder = addDefaultInterfaceDefinition(packageName, caseNode);
1180 caseTypeBuilder.addImplementsType(refChoiceType);
1181 genCtx.get(module).addCaseType(caseNode.path, caseTypeBuilder)
1182 val Set<DataSchemaNode> caseChildNodes = caseNode.childNodes;
1183 if (caseChildNodes !== null) {
1184 val parentNode = choiceNode.parent;
1185 var SchemaNode parent;
1186 if (parentNode instanceof AugmentationSchema) {
1187 val augSchema = parentNode as AugmentationSchema;
1188 val targetPath = augSchema.targetPath;
1189 var targetSchemaNode = findDataSchemaNode(schemaContext, targetPath);
1190 if (targetSchemaNode instanceof DataSchemaNode &&
1191 (targetSchemaNode as DataSchemaNode).isAddedByUses()) {
1192 targetSchemaNode = findOriginal(targetSchemaNode as DataSchemaNode);
1193 if (targetSchemaNode == null) {
1194 throw new NullPointerException(
1195 "Failed to find target node from grouping for augmentation " + augSchema +
1196 " in module " + module.name);
1199 parent = targetSchemaNode as SchemaNode
1201 parent = choiceNode.parent as SchemaNode;
1203 var GeneratedTypeBuilder childOfType = findChildNodeByPath(parent.path)
1204 resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, childOfType, caseChildNodes);
1208 processUsesAugments(caseNode, module);
1213 * Generates list of generated types for all the cases of a choice which are
\r
1214 * added to the choice through the augment.
\r
1217 * @param basePackageName
\r
1218 * string contains name of package to which augment belongs. If
\r
1219 * an augmented choice is from an other package (pcg1) than an
\r
1220 * augmenting choice (pcg2) then case's of the augmenting choice
\r
1221 * will belong to pcg2.
\r
1222 * @param refChoiceType
\r
1223 * Type which represents the choice to which case belongs. Every
\r
1224 * case has to contain its choice in extend part.
\r
1225 * @param caseNodes
\r
1226 * set of choice case nodes for which is checked if are/aren't
\r
1227 * added to choice through augmentation
\r
1228 * @return list of generated types which represents augmented cases of
\r
1229 * choice <code>refChoiceType</code>
\r
1230 * @throws IllegalArgumentException
\r
1232 * <li>if <code>basePackageName</code> equals null</li>
\r
1233 * <li>if <code>refChoiceType</code> equals null</li>
\r
1234 * <li>if <code>caseNodes</code> equals null</li>
\r
1237 private def void generateTypesFromAugmentedChoiceCases(Module module, String basePackageName, Type targetType,
1238 ChoiceNode targetNode, Set<DataSchemaNode> augmentedNodes) {
1239 checkArgument(basePackageName !== null, "Base Package Name cannot be NULL.");
1240 checkArgument(targetType !== null, "Referenced Choice Type cannot be NULL.");
1241 checkArgument(augmentedNodes !== null, "Set of Choice Case Nodes cannot be NULL.");
1243 for (caseNode : augmentedNodes) {
1244 if (caseNode !== null) {
1245 val packageName = packageNameForGeneratedType(basePackageName, caseNode.path);
1246 val caseTypeBuilder = addDefaultInterfaceDefinition(packageName, caseNode);
1247 caseTypeBuilder.addImplementsType(targetType);
1249 val SchemaNode parent = targetNode.parent as SchemaNode;
1250 var GeneratedTypeBuilder childOfType = null;
1251 if (parent instanceof Module) {
1252 childOfType = genCtx.get(parent as Module).moduleNode
1253 } else if (parent instanceof ChoiceCaseNode) {
1254 childOfType = findCaseByPath(parent.path)
1255 } else if (parent instanceof DataSchemaNode || parent instanceof NotificationDefinition) {
1256 childOfType = findChildNodeByPath(parent.path)
1257 } else if (parent instanceof GroupingDefinition) {
1258 childOfType = findGroupingByPath(parent.path);
1261 if (childOfType == null) {
1262 throw new IllegalArgumentException("Failed to find parent type of choice " + targetNode);
1265 if (caseNode instanceof DataNodeContainer) {
1266 val DataNodeContainer dataNodeCase = caseNode as DataNodeContainer;
1267 val Set<DataSchemaNode> childNodes = dataNodeCase.childNodes;
1268 if (childNodes !== null) {
1269 resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, childOfType, childNodes);
1272 val ChoiceCaseNode node = targetNode.getCaseNodeByName(caseNode.getQName().getLocalName());
1273 val Set<DataSchemaNode> childNodes = node.childNodes;
1274 if (childNodes !== null) {
1275 resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, childOfType, childNodes);
1279 genCtx.get(module).addCaseType(caseNode.path, caseTypeBuilder)
1286 * Converts <code>leaf</code> to the getter method which is added to
\r
1287 * <code>typeBuilder</code>.
\r
1289 * @param typeBuilder
\r
1290 * generated type builder to which is added getter method as
\r
1291 * <code>leaf</code> mapping
\r
1293 * leaf schema node which is mapped as getter method which is
\r
1294 * added to <code>typeBuilder</code>
\r
1295 * @return boolean value
\r
1297 * <li>false - if <code>leaf</code> or <code>typeBuilder</code> are
\r
1299 * <li>true - in other cases</li>
\r
1302 private def boolean resolveLeafSchemaNodeAsMethod(GeneratedTypeBuilder typeBuilder, LeafSchemaNode leaf) {
1303 if ((leaf !== null) && (typeBuilder !== null)) {
1304 val leafName = leaf.QName.localName;
1305 var String leafDesc = leaf.description;
1306 if (leafDesc === null) {
1310 val parentModule = findParentModule(schemaContext, leaf);
1311 if (leafName !== null && !leaf.isAddedByUses()) {
1312 val TypeDefinition<?> typeDef = leaf.type;
1314 var Type returnType = null;
1315 if (typeDef instanceof EnumTypeDefinition) {
1316 returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf);
1317 val enumTypeDef = typeDef as EnumTypeDefinition;
1318 val enumBuilder = resolveInnerEnumFromTypeDefinition(enumTypeDef, leafName, typeBuilder);
1320 if (enumBuilder !== null) {
1321 returnType = new ReferencedTypeImpl(enumBuilder.packageName, enumBuilder.name);
1323 (typeProvider as TypeProviderImpl).putReferencedType(leaf.path, returnType);
1324 } else if (typeDef instanceof UnionType) {
1325 val genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, leafName, leaf, parentModule);
1326 if (genTOBuilder !== null) {
1327 returnType = new ReferencedTypeImpl(genTOBuilder.packageName, genTOBuilder.name);
1329 } else if (typeDef instanceof BitsTypeDefinition) {
1330 val genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, leafName, leaf, parentModule);
1331 if (genTOBuilder !== null) {
1332 returnType = new ReferencedTypeImpl(genTOBuilder.packageName, genTOBuilder.name);
1335 val Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
\r
1336 returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf, restrictions);
1338 if (returnType !== null) {
1339 val MethodSignatureBuilder getter = constructGetter(typeBuilder, leafName, leafDesc, returnType);
1340 processContextRefExtension(leaf, getter, parentModule);
1348 private def void processContextRefExtension(LeafSchemaNode leaf, MethodSignatureBuilder getter, Module module) {
1349 for (node : leaf.unknownSchemaNodes) {
1350 val nodeType = node.nodeType;
1351 if ("context-reference".equals(nodeType.localName)) {
1352 val nodeParam = node.nodeParameter;
1353 var IdentitySchemaNode identity = null;
1354 var String basePackageName = null;
1355 val String[] splittedElement = nodeParam.split(":");
1356 if (splittedElement.length == 1) {
1357 identity = findIdentityByName(module.identities, splittedElement.get(0));
1358 basePackageName = moduleNamespaceToPackageName(module);
1359 } else if (splittedElement.length == 2) {
1360 var prefix = splittedElement.get(0);
1361 val Module dependentModule = findModuleFromImports(module.imports, prefix)
1362 if (dependentModule == null) {
1363 throw new IllegalArgumentException(
1364 "Failed to process context-reference: unknown prefix " + prefix);
1366 identity = findIdentityByName(dependentModule.identities, splittedElement.get(1));
1367 basePackageName = moduleNamespaceToPackageName(dependentModule);
1369 throw new IllegalArgumentException(
1370 "Failed to process context-reference: unknown identity " + nodeParam);
1372 if (identity == null) {
1373 throw new IllegalArgumentException(
1374 "Failed to process context-reference: unknown identity " + nodeParam);
1377 val Class<RoutingContext> clazz = typeof(RoutingContext);
1378 val AnnotationTypeBuilder rc = getter.addAnnotation(clazz.package.name, clazz.simpleName);
1379 val packageName = packageNameForGeneratedType(basePackageName, identity.path);
1380 val genTypeName = parseToClassName(identity.QName.localName);
1381 rc.addParameter("value", packageName + "." + genTypeName + ".class");
1386 private def IdentitySchemaNode findIdentityByName(Set<IdentitySchemaNode> identities, String name) {
1387 for (id : identities) {
1388 if (id.QName.localName.equals(name)) {
1395 private def Module findModuleFromImports(Set<ModuleImport> imports, String prefix) {
1396 for (imp : imports) {
1397 if (imp.prefix.equals(prefix)) {
1398 return schemaContext.findModuleByName(imp.moduleName, imp.revision);
1405 * Converts <code>leaf</code> schema node to property of generated TO
\r
1408 * @param toBuilder
\r
1409 * generated TO builder to which is <code>leaf</code> added as
\r
1412 * leaf schema node which is added to <code>toBuilder</code> as
\r
1414 * @param isReadOnly
\r
1415 * boolean value which says if leaf property is|isn't read only
\r
1416 * @return boolean value
\r
1418 * <li>false - if <code>leaf</code>, <code>toBuilder</code> or leaf
\r
1419 * name equals null or if leaf is added by <i>uses</i>.</li>
\r
1420 * <li>true - other cases</li>
\r
1423 private def boolean resolveLeafSchemaNodeAsProperty(GeneratedTOBuilder toBuilder, LeafSchemaNode leaf,
1424 boolean isReadOnly) {
1425 if ((leaf !== null) && (toBuilder !== null)) {
1426 val leafName = leaf.QName.localName;
1427 var String leafDesc = leaf.description;
1428 if (leafDesc === null) {
1432 if (leafName !== null) {
1433 val TypeDefinition<?> typeDef = leaf.type;
1435 // TODO: properly resolve enum types
\r
1436 val returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf);
1438 if (returnType !== null) {
1439 val propBuilder = toBuilder.addProperty(parseToClassName(leafName));
1441 propBuilder.setReadOnly(isReadOnly);
1442 propBuilder.setReturnType(returnType);
1443 propBuilder.setComment(leafDesc);
1445 toBuilder.addEqualsIdentity(propBuilder);
1446 toBuilder.addHashIdentity(propBuilder);
1447 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;
1687 if (!listKeys.contains(leafName)) {
1688 resolveLeafSchemaNodeAsMethod(typeBuilder, leaf);
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