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)
\r
754 genCtx.get(module).addTypeToAugmentation(augTypeBuilder,augSchema);
756 generateTypesFromAugmentedChoiceCases(module, augmentPackageName, targetTypeBuilder.toInstance,
757 targetSchemaNode as ChoiceNode, augSchema.childNodes);
763 * Utility method which search for original node defined in grouping.
\r
765 private def DataSchemaNode findOriginal(DataSchemaNode node) {
766 var DataSchemaNode result = findCorrectTargetFromGrouping(node);
767 if (result == null) {
768 result = findCorrectTargetFromAugment(node);
769 if (result != null) {
770 if (result.addedByUses) {
771 result = findOriginal(result);
778 private def DataSchemaNode findCorrectTargetFromAugment(DataSchemaNode node) {
779 if (!node.augmenting) {
783 var String currentName = node.QName.localName;
784 var tmpPath = new ArrayList<String>();
785 var YangNode parent = node;
786 var AugmentationSchema augment = null;
788 parent = (parent as DataSchemaNode).parent;
789 if (parent instanceof AugmentationTarget) {
790 tmpPath.add(currentName);
791 augment = findNodeInAugment((parent as AugmentationTarget).availableAugmentations, currentName);
792 if (augment == null) {
793 currentName = (parent as DataSchemaNode).QName.localName;
796 } while ((parent as DataSchemaNode).augmenting && augment == null);
798 if (augment == null) {
801 Collections.reverse(tmpPath);
802 var Object actualParent = augment;
803 var DataSchemaNode result = null;
804 for (name : tmpPath) {
805 if (actualParent instanceof DataNodeContainer) {
806 result = (actualParent as DataNodeContainer).getDataChildByName(name);
807 actualParent = (actualParent as DataNodeContainer).getDataChildByName(name);
809 if (actualParent instanceof ChoiceNode) {
810 result = (actualParent as ChoiceNode).getCaseNodeByName(name);
811 actualParent = (actualParent as ChoiceNode).getCaseNodeByName(name);
816 if (result.addedByUses) {
817 result = findCorrectTargetFromGrouping(result);
824 private def AugmentationSchema findNodeInAugment(Collection<AugmentationSchema> augments, String name) {
825 for (augment : augments) {
826 if (augment.getDataChildByName(name) != null) {
833 private def DataSchemaNode findCorrectTargetFromGrouping(DataSchemaNode node) {
834 if (node.path.path.size == 1) {
836 // uses is under module statement
\r
837 val Module m = findParentModule(schemaContext, node);
838 var DataSchemaNode result = null;
840 var SchemaNode targetGrouping = findNodeInSchemaContext(schemaContext, u.groupingPath.path);
841 if (!(targetGrouping instanceof GroupingDefinition)) {
842 throw new IllegalArgumentException("Failed to generate code for augment in " + u);
844 var gr = targetGrouping as GroupingDefinition;
845 result = gr.getDataChildByName(node.QName.localName);
847 if (result == null) {
848 throw new IllegalArgumentException("Failed to generate code for augment");
852 var DataSchemaNode result = null;
853 var String currentName = node.QName.localName;
854 var tmpPath = new ArrayList<String>();
855 var YangNode parent = node.parent;
857 tmpPath.add(currentName);
858 val dataNodeParent = parent as DataNodeContainer;
859 for (u : dataNodeParent.uses) {
860 if (result == null) {
\r
861 var SchemaNode targetGrouping = findNodeInSchemaContext(schemaContext, u.groupingPath.path);
862 if (!(targetGrouping instanceof GroupingDefinition)) {
863 throw new IllegalArgumentException("Failed to generate code for augment in " + u);
865 var gr = targetGrouping as GroupingDefinition;
866 result = gr.getDataChildByName(currentName);
\r
869 if (result == null) {
870 currentName = (parent as SchemaNode).QName.localName;
871 if (parent instanceof DataSchemaNode) {
872 parent = (parent as DataSchemaNode).parent;
874 parent = (parent as DataNodeContainer).parent;
877 } while (result == null && !(parent instanceof Module));
879 if (result != null) {
880 if (tmpPath.size == 1) {
883 var DataSchemaNode newParent = result;
884 Collections.reverse(tmpPath);
886 for (name : tmpPath) {
887 newParent = (newParent as DataNodeContainer).getDataChildByName(name);
898 * Convenient method to find node added by uses statement.
\r
900 private def DataSchemaNode findOriginalTargetFromGrouping(String targetSchemaNodeName, UsesNode parentUsesNode) {
901 var SchemaNode targetGrouping = findNodeInSchemaContext(schemaContext, parentUsesNode.groupingPath.path);
902 if (!(targetGrouping instanceof GroupingDefinition)) {
903 throw new IllegalArgumentException("Failed to generate code for augment in " + parentUsesNode);
906 var grouping = targetGrouping as GroupingDefinition;
907 var result = grouping.getDataChildByName(targetSchemaNodeName);
908 if (result == null) {
911 var boolean fromUses = result.addedByUses;
913 var Iterator<UsesNode> groupingUses = grouping.uses.iterator;
915 if (groupingUses.hasNext()) {
916 grouping = findNodeInSchemaContext(schemaContext, groupingUses.next().groupingPath.path) as GroupingDefinition;
917 result = grouping.getDataChildByName(targetSchemaNodeName);
918 fromUses = result.addedByUses;
920 throw new NullPointerException("Failed to generate code for augment in " + parentUsesNode);
928 * Returns a generated type builder for an augmentation.
\r
930 * The name of the type builder is equal to the name of augmented node with
\r
931 * serial number as suffix.
\r
933 * @param module current module
\r
934 * @param augmentPackageName
\r
935 * string with contains the package name to which the augment
\r
937 * @param basePackageName
\r
938 * string with the package name to which the augmented node
\r
940 * @param targetTypeRef
\r
943 * augmentation schema which contains data about the child nodes
\r
944 * and uses of augment
\r
945 * @return generated type builder for augment
\r
947 private def GeneratedTypeBuilder addRawAugmentGenTypeDefinition(Module module, String augmentPackageName,
948 String basePackageName, Type targetTypeRef, AugmentationSchema augSchema) {
949 var Map<String, GeneratedTypeBuilder> augmentBuilders = genTypeBuilders.get(augmentPackageName);
950 if (augmentBuilders === null) {
951 augmentBuilders = new HashMap();
952 genTypeBuilders.put(augmentPackageName, augmentBuilders);
954 val augIdentifier = getAugmentIdentifier(augSchema.unknownSchemaNodes);
956 val augTypeName = if (augIdentifier !== null) {
957 parseToClassName(augIdentifier)
959 augGenTypeName(augmentBuilders, targetTypeRef.name);
962 val augTypeBuilder = new GeneratedTypeBuilderImpl(augmentPackageName, augTypeName);
964 augTypeBuilder.addImplementsType(DATA_OBJECT);
965 augTypeBuilder.addImplementsType(Types.augmentationTypeFor(targetTypeRef));
966 addImplementedInterfaceFromUses(augSchema, augTypeBuilder);
968 augSchemaNodeToMethods(module, basePackageName, augTypeBuilder, augTypeBuilder, augSchema.childNodes);
969 augmentBuilders.put(augTypeName, augTypeBuilder);
970 return augTypeBuilder;
975 * @param unknownSchemaNodes
\r
976 * @return nodeParameter of UnknownSchemaNode
\r
978 private def String getAugmentIdentifier(List<UnknownSchemaNode> unknownSchemaNodes) {
979 for (unknownSchemaNode : unknownSchemaNodes) {
980 val nodeType = unknownSchemaNode.nodeType;
981 if (AUGMENT_IDENTIFIER_NAME.equals(nodeType.localName) &&
982 YANG_EXT_NAMESPACE.equals(nodeType.namespace.toString())) {
983 return unknownSchemaNode.nodeParameter;
990 * Returns first unique name for the augment generated type builder. The
\r
991 * generated type builder name for augment consists from name of augmented
\r
992 * node and serial number of its augmentation.
\r
995 * map of builders which were created in the package to which the
\r
996 * augmentation belongs
\r
997 * @param genTypeName
\r
998 * string with name of augmented node
\r
999 * @return string with unique name for augmentation builder
\r
1001 private def String augGenTypeName(Map<String, GeneratedTypeBuilder> builders, String genTypeName) {
1003 while ((builders !== null) && builders.containsKey(genTypeName + index)) {
1006 return genTypeName + index;
1010 * Adds the methods to <code>typeBuilder</code> which represent subnodes of
\r
1011 * node for which <code>typeBuilder</code> was created.
\r
1013 * The subnodes aren't mapped to the methods if they are part of grouping or
\r
1014 * augment (in this case are already part of them).
\r
1016 * @param module current module
\r
1017 * @param basePackageName
\r
1018 * string contains the module package name
\r
1020 * generated type builder which represents any node. The subnodes
\r
1021 * of this node are added to the <code>typeBuilder</code> as
\r
1022 * methods. The subnode can be of type leaf, leaf-list, list,
\r
1023 * container, choice.
\r
1024 * @param childOf parent type
\r
1025 * @param schemaNodes
\r
1026 * set of data schema nodes which are the children of the node
\r
1027 * for which <code>typeBuilder</code> was created
\r
1028 * @return generated type builder which is the same builder as input
\r
1029 * parameter. The getter methods (representing child nodes) could be
\r
1032 private def GeneratedTypeBuilder resolveDataSchemaNodes(Module module, String basePackageName,
1033 GeneratedTypeBuilder parent, GeneratedTypeBuilder childOf, Set<DataSchemaNode> schemaNodes) {
1034 if ((schemaNodes !== null) && (parent !== null)) {
1035 for (schemaNode : schemaNodes) {
1036 if (!schemaNode.augmenting && !schemaNode.addedByUses) {
1037 addSchemaNodeToBuilderAsMethod(basePackageName, schemaNode, parent, childOf, module);
1045 * Adds the methods to <code>typeBuilder</code> what represents subnodes of
\r
1046 * node for which <code>typeBuilder</code> was created.
\r
1048 * @param module current module
\r
1049 * @param basePackageName
\r
1050 * string contains the module package name
\r
1051 * @param typeBuilder
\r
1052 * generated type builder which represents any node. The subnodes
\r
1053 * of this node are added to the <code>typeBuilder</code> as
\r
1054 * methods. The subnode can be of type leaf, leaf-list, list,
\r
1055 * container, choice.
\r
1056 * @param childOf parent type
\r
1057 * @param schemaNodes
\r
1058 * set of data schema nodes which are the children of the node
\r
1059 * for which <code>typeBuilder</code> was created
\r
1060 * @return generated type builder which is the same object as the input
\r
1061 * parameter <code>typeBuilder</code>. The getter method could be
\r
1064 private def GeneratedTypeBuilder augSchemaNodeToMethods(Module module, String basePackageName,
1065 GeneratedTypeBuilder typeBuilder, GeneratedTypeBuilder childOf, Set<DataSchemaNode> schemaNodes) {
1066 if ((schemaNodes !== null) && (typeBuilder !== null)) {
1067 for (schemaNode : schemaNodes) {
1068 if (!schemaNode.isAugmenting()) {
1069 addSchemaNodeToBuilderAsMethod(basePackageName, schemaNode, typeBuilder, childOf, module);
1077 * Adds to <code>typeBuilder</code> a method which is derived from
\r
1078 * <code>schemaNode</code>.
\r
1080 * @param basePackageName
\r
1081 * string with the module package name
\r
1083 * data schema node which is added to <code>typeBuilder</code> as
\r
1085 * @param typeBuilder
\r
1086 * generated type builder to which is <code>schemaNode</code>
\r
1087 * added as a method.
\r
1088 * @param childOf parent type
\r
1089 * @param module current module
\r
1091 private def void addSchemaNodeToBuilderAsMethod(String basePackageName, DataSchemaNode node,
1092 GeneratedTypeBuilder typeBuilder, GeneratedTypeBuilder childOf, Module module) {
1093 if (node !== null && typeBuilder !== null) {
1095 case node instanceof LeafSchemaNode:
1096 resolveLeafSchemaNodeAsMethod(typeBuilder, node as LeafSchemaNode)
1097 case node instanceof LeafListSchemaNode:
1098 resolveLeafListSchemaNode(typeBuilder, node as LeafListSchemaNode)
1099 case node instanceof ContainerSchemaNode:
1100 containerToGenType(module, basePackageName, typeBuilder, childOf, node as ContainerSchemaNode)
1101 case node instanceof ListSchemaNode:
1102 listToGenType(module, basePackageName, typeBuilder, childOf, node as ListSchemaNode)
1103 case node instanceof ChoiceNode:
1104 choiceToGeneratedType(module, basePackageName, typeBuilder, node as ChoiceNode)
1110 * Converts <code>choiceNode</code> to the list of generated types for
\r
1111 * choice and its cases.
\r
1113 * The package names for choice and for its cases are created as
\r
1114 * concatenation of the module package (<code>basePackageName</code>) and
\r
1115 * names of all parents node.
\r
1117 * @param module current module
\r
1118 * @param basePackageName
\r
1119 * string with the module package name
\r
1120 * @param parent parent type
\r
1121 * @param childOf concrete parent for case child nodes
\r
1122 * @param choiceNode
\r
1123 * choice node which is mapped to generated type. Also child
\r
1124 * nodes - cases are mapped to generated types.
\r
1125 * @throws IllegalArgumentException
\r
1127 * <li>if <code>basePackageName</code> equals null</li>
\r
1128 * <li>if <code>choiceNode</code> equals null</li>
\r
1132 private def void choiceToGeneratedType(Module module, String basePackageName, GeneratedTypeBuilder parent,
1133 ChoiceNode choiceNode) {
1134 checkArgument(basePackageName !== null, "Base Package Name cannot be NULL.");
1135 checkArgument(choiceNode !== null, "Choice Schema Node cannot be NULL.");
1137 val packageName = packageNameForGeneratedType(basePackageName, choiceNode.path);
1138 val choiceTypeBuilder = addRawInterfaceDefinition(packageName, choiceNode);
1139 constructGetter(parent, choiceNode.QName.localName, choiceNode.description, choiceTypeBuilder);
1140 choiceTypeBuilder.addImplementsType(DataContainer.typeForClass);
1141 genCtx.get(module).addChildNodeType(choiceNode.path, choiceTypeBuilder)
1142 generateTypesFromChoiceCases(module, basePackageName, parent, choiceTypeBuilder.toInstance, choiceNode);
1146 * Converts <code>caseNodes</code> set to list of corresponding generated
\r
1149 * For every <i>case</i> which isn't added through augment or <i>uses</i> is
\r
1150 * created generated type builder. The package names for the builder is
\r
1151 * created as concatenation of the module package (
\r
1152 * <code>basePackageName</code>) and names of all parents nodes of the
\r
1153 * concrete <i>case</i>. There is also relation "<i>implements type</i>"
\r
1154 * between every case builder and <i>choice</i> type
\r
1156 * @param basePackageName
\r
1157 * string with the module package name
\r
1158 * @param refChoiceType
\r
1159 * type which represents superior <i>case</i>
\r
1160 * @param caseNodes
\r
1161 * set of choice case nodes which are mapped to generated types
\r
1162 * @return list of generated types for <code>caseNodes</code>.
\r
1163 * @throws IllegalArgumentException
\r
1165 * <li>if <code>basePackageName</code> equals null</li>
\r
1166 * <li>if <code>refChoiceType</code> equals null</li>
\r
1167 * <li>if <code>caseNodes</code> equals null</li>
\r
1171 private def void generateTypesFromChoiceCases(Module module, String basePackageName,
1172 GeneratedTypeBuilder choiceParent, Type refChoiceType, ChoiceNode choiceNode) {
1173 checkArgument(basePackageName !== null, "Base Package Name cannot be NULL.");
1174 checkArgument(refChoiceType !== null, "Referenced Choice Type cannot be NULL.");
1175 checkArgument(choiceNode !== null, "ChoiceNode cannot be NULL.");
1177 val Set<ChoiceCaseNode> caseNodes = choiceNode.cases;
1178 if (caseNodes == null) {
1182 for (caseNode : caseNodes) {
1183 if (caseNode !== null && !caseNode.isAddedByUses() && !caseNode.isAugmenting()) {
1184 val packageName = packageNameForGeneratedType(basePackageName, caseNode.path);
1185 val caseTypeBuilder = addDefaultInterfaceDefinition(packageName, caseNode);
1186 caseTypeBuilder.addImplementsType(refChoiceType);
1187 genCtx.get(module).addCaseType(caseNode.path, caseTypeBuilder)
1188 val Set<DataSchemaNode> caseChildNodes = caseNode.childNodes;
1189 if (caseChildNodes !== null) {
1190 val parentNode = choiceNode.parent;
1191 var SchemaNode parent;
1192 if (parentNode instanceof AugmentationSchema) {
1193 val augSchema = parentNode as AugmentationSchema;
1194 val targetPath = augSchema.targetPath;
1195 var targetSchemaNode = findDataSchemaNode(schemaContext, targetPath);
1196 if (targetSchemaNode instanceof DataSchemaNode &&
1197 (targetSchemaNode as DataSchemaNode).isAddedByUses()) {
1198 targetSchemaNode = findOriginal(targetSchemaNode as DataSchemaNode);
1199 if (targetSchemaNode == null) {
1200 throw new NullPointerException(
1201 "Failed to find target node from grouping for augmentation " + augSchema +
1202 " in module " + module.name);
1205 parent = targetSchemaNode as SchemaNode
1207 parent = choiceNode.parent as SchemaNode;
1209 var GeneratedTypeBuilder childOfType = findChildNodeByPath(parent.path)
1210 resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, childOfType, caseChildNodes);
1214 processUsesAugments(caseNode, module);
1219 * Generates list of generated types for all the cases of a choice which are
\r
1220 * added to the choice through the augment.
\r
1223 * @param basePackageName
\r
1224 * string contains name of package to which augment belongs. If
\r
1225 * an augmented choice is from an other package (pcg1) than an
\r
1226 * augmenting choice (pcg2) then case's of the augmenting choice
\r
1227 * will belong to pcg2.
\r
1228 * @param refChoiceType
\r
1229 * Type which represents the choice to which case belongs. Every
\r
1230 * case has to contain its choice in extend part.
\r
1231 * @param caseNodes
\r
1232 * set of choice case nodes for which is checked if are/aren't
\r
1233 * added to choice through augmentation
\r
1234 * @return list of generated types which represents augmented cases of
\r
1235 * choice <code>refChoiceType</code>
\r
1236 * @throws IllegalArgumentException
\r
1238 * <li>if <code>basePackageName</code> equals null</li>
\r
1239 * <li>if <code>refChoiceType</code> equals null</li>
\r
1240 * <li>if <code>caseNodes</code> equals null</li>
\r
1243 private def void generateTypesFromAugmentedChoiceCases(Module module, String basePackageName, Type targetType,
1244 ChoiceNode targetNode, Set<DataSchemaNode> augmentedNodes) {
1245 checkArgument(basePackageName !== null, "Base Package Name cannot be NULL.");
1246 checkArgument(targetType !== null, "Referenced Choice Type cannot be NULL.");
1247 checkArgument(augmentedNodes !== null, "Set of Choice Case Nodes cannot be NULL.");
1249 for (caseNode : augmentedNodes) {
1250 if (caseNode !== null) {
1251 val packageName = packageNameForGeneratedType(basePackageName, caseNode.path);
1252 val caseTypeBuilder = addDefaultInterfaceDefinition(packageName, caseNode);
1253 caseTypeBuilder.addImplementsType(targetType);
1255 val SchemaNode parent = targetNode.parent as SchemaNode;
1256 var GeneratedTypeBuilder childOfType = null;
1257 if (parent instanceof Module) {
1258 childOfType = genCtx.get(parent as Module).moduleNode
1259 } else if (parent instanceof ChoiceCaseNode) {
1260 childOfType = findCaseByPath(parent.path)
1261 } else if (parent instanceof DataSchemaNode || parent instanceof NotificationDefinition) {
1262 childOfType = findChildNodeByPath(parent.path)
1263 } else if (parent instanceof GroupingDefinition) {
1264 childOfType = findGroupingByPath(parent.path);
1267 if (childOfType == null) {
1268 throw new IllegalArgumentException("Failed to find parent type of choice " + targetNode);
1271 if (caseNode instanceof DataNodeContainer) {
1272 val DataNodeContainer dataNodeCase = caseNode as DataNodeContainer;
1273 val Set<DataSchemaNode> childNodes = dataNodeCase.childNodes;
1274 if (childNodes !== null) {
1275 resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, childOfType, childNodes);
1278 val ChoiceCaseNode node = targetNode.getCaseNodeByName(caseNode.getQName().getLocalName());
1279 val Set<DataSchemaNode> childNodes = node.childNodes;
1280 if (childNodes !== null) {
1281 resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, childOfType, childNodes);
1285 genCtx.get(module).addCaseType(caseNode.path, caseTypeBuilder)
1292 * Converts <code>leaf</code> to the getter method which is added to
\r
1293 * <code>typeBuilder</code>.
\r
1295 * @param typeBuilder
\r
1296 * generated type builder to which is added getter method as
\r
1297 * <code>leaf</code> mapping
\r
1299 * leaf schema node which is mapped as getter method which is
\r
1300 * added to <code>typeBuilder</code>
\r
1301 * @return boolean value
\r
1303 * <li>false - if <code>leaf</code> or <code>typeBuilder</code> are
\r
1305 * <li>true - in other cases</li>
\r
1308 private def boolean resolveLeafSchemaNodeAsMethod(GeneratedTypeBuilder typeBuilder, LeafSchemaNode leaf) {
1309 if ((leaf !== null) && (typeBuilder !== null)) {
1310 val leafName = leaf.QName.localName;
1311 var String leafDesc = leaf.description;
1312 if (leafDesc === null) {
1316 val parentModule = findParentModule(schemaContext, leaf);
1317 if (leafName !== null && !leaf.isAddedByUses()) {
1318 val TypeDefinition<?> typeDef = leaf.type;
1320 var Type returnType = null;
1321 if (typeDef instanceof EnumTypeDefinition) {
1322 returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf);
1323 val enumTypeDef = typeDef as EnumTypeDefinition;
1324 val enumBuilder = resolveInnerEnumFromTypeDefinition(enumTypeDef, leafName, typeBuilder);
1326 if (enumBuilder !== null) {
1327 returnType = new ReferencedTypeImpl(enumBuilder.packageName, enumBuilder.name);
1329 (typeProvider as TypeProviderImpl).putReferencedType(leaf.path, returnType);
1330 } else if (typeDef instanceof UnionType) {
1331 val genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, leafName, leaf, parentModule);
1332 if (genTOBuilder !== null) {
1333 returnType = new ReferencedTypeImpl(genTOBuilder.packageName, genTOBuilder.name);
1335 } else if (typeDef instanceof BitsTypeDefinition) {
1336 val genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, leafName, leaf, parentModule);
1337 if (genTOBuilder !== null) {
1338 returnType = new ReferencedTypeImpl(genTOBuilder.packageName, genTOBuilder.name);
1341 val Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
\r
1342 returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf, restrictions);
1344 if (returnType !== null) {
1345 val MethodSignatureBuilder getter = constructGetter(typeBuilder, leafName, leafDesc, returnType);
1346 processContextRefExtension(leaf, getter, parentModule);
1354 private def void processContextRefExtension(LeafSchemaNode leaf, MethodSignatureBuilder getter, Module module) {
1355 for (node : leaf.unknownSchemaNodes) {
1356 val nodeType = node.nodeType;
1357 if ("context-reference".equals(nodeType.localName)) {
1358 val nodeParam = node.nodeParameter;
1359 var IdentitySchemaNode identity = null;
1360 var String basePackageName = null;
1361 val String[] splittedElement = nodeParam.split(":");
1362 if (splittedElement.length == 1) {
1363 identity = findIdentityByName(module.identities, splittedElement.get(0));
1364 basePackageName = moduleNamespaceToPackageName(module);
1365 } else if (splittedElement.length == 2) {
1366 var prefix = splittedElement.get(0);
1367 val Module dependentModule = findModuleFromImports(module.imports, prefix)
1368 if (dependentModule == null) {
1369 throw new IllegalArgumentException(
1370 "Failed to process context-reference: unknown prefix " + prefix);
1372 identity = findIdentityByName(dependentModule.identities, splittedElement.get(1));
1373 basePackageName = moduleNamespaceToPackageName(dependentModule);
1375 throw new IllegalArgumentException(
1376 "Failed to process context-reference: unknown identity " + nodeParam);
1378 if (identity == null) {
1379 throw new IllegalArgumentException(
1380 "Failed to process context-reference: unknown identity " + nodeParam);
1383 val Class<RoutingContext> clazz = typeof(RoutingContext);
1384 val AnnotationTypeBuilder rc = getter.addAnnotation(clazz.package.name, clazz.simpleName);
1385 val packageName = packageNameForGeneratedType(basePackageName, identity.path);
1386 val genTypeName = parseToClassName(identity.QName.localName);
1387 rc.addParameter("value", packageName + "." + genTypeName + ".class");
1392 private def IdentitySchemaNode findIdentityByName(Set<IdentitySchemaNode> identities, String name) {
1393 for (id : identities) {
1394 if (id.QName.localName.equals(name)) {
1401 private def Module findModuleFromImports(Set<ModuleImport> imports, String prefix) {
1402 for (imp : imports) {
1403 if (imp.prefix.equals(prefix)) {
1404 return schemaContext.findModuleByName(imp.moduleName, imp.revision);
1411 * Converts <code>leaf</code> schema node to property of generated TO
\r
1414 * @param toBuilder
\r
1415 * generated TO builder to which is <code>leaf</code> added as
\r
1418 * leaf schema node which is added to <code>toBuilder</code> as
\r
1420 * @param isReadOnly
\r
1421 * boolean value which says if leaf property is|isn't read only
\r
1422 * @return boolean value
\r
1424 * <li>false - if <code>leaf</code>, <code>toBuilder</code> or leaf
\r
1425 * name equals null or if leaf is added by <i>uses</i>.</li>
\r
1426 * <li>true - other cases</li>
\r
1429 private def boolean resolveLeafSchemaNodeAsProperty(GeneratedTOBuilder toBuilder, LeafSchemaNode leaf,
1430 boolean isReadOnly) {
1431 if ((leaf !== null) && (toBuilder !== null)) {
1432 val leafName = leaf.QName.localName;
1433 var String leafDesc = leaf.description;
1434 if (leafDesc === null) {
1438 if (leafName !== null) {
1439 val TypeDefinition<?> typeDef = leaf.type;
1441 // TODO: properly resolve enum types
\r
1442 val returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf);
1443 if (returnType !== null) {
1444 val propBuilder = toBuilder.addProperty(parseToValidParamName(leafName));
1445 propBuilder.setReadOnly(isReadOnly);
1446 propBuilder.setReturnType(returnType);
1447 propBuilder.setComment(leafDesc);
1448 toBuilder.addEqualsIdentity(propBuilder);
1449 toBuilder.addHashIdentity(propBuilder);
1450 toBuilder.addToStringProperty(propBuilder);
1459 * Converts <code>node</code> leaf list schema node to getter method of
\r
1460 * <code>typeBuilder</code>.
\r
1462 * @param typeBuilder
\r
1463 * generated type builder to which is <code>node</code> added as
\r
1466 * leaf list schema node which is added to
\r
1467 * <code>typeBuilder</code> as getter method
\r
1468 * @return boolean value
\r
1470 * <li>true - if <code>node</code>, <code>typeBuilder</code>,
\r
1471 * nodeName equal null or <code>node</code> is added by <i>uses</i></li>
\r
1472 * <li>false - other cases</li>
\r
1475 private def boolean resolveLeafListSchemaNode(GeneratedTypeBuilder typeBuilder, LeafListSchemaNode node) {
1476 if ((node !== null) && (typeBuilder !== null)) {
1477 val nodeName = node.QName.localName;
1478 var String nodeDesc = node.description;
1479 if (nodeDesc === null) {
1482 if (nodeName !== null && !node.isAddedByUses()) {
1483 val TypeDefinition<?> type = node.type;
1484 val listType = Types.listTypeFor(typeProvider.javaTypeForSchemaDefinitionType(type, node));
1485 constructGetter(typeBuilder, nodeName, nodeDesc, listType);
1492 private def GeneratedTypeBuilder addDefaultInterfaceDefinition(String packageName, SchemaNode schemaNode) {
1493 return addDefaultInterfaceDefinition(packageName, schemaNode, null);
1497 * Instantiates generated type builder with <code>packageName</code> and
\r
1498 * <code>schemaNode</code>.
\r
1500 * The new builder always implements
\r
1501 * {@link org.opendaylight.yangtools.yang.binding.DataObject DataObject}.<br />
\r
1502 * If <code>schemaNode</code> is instance of GroupingDefinition it also
\r
1503 * implements {@link org.opendaylight.yangtools.yang.binding.Augmentable
\r
1504 * Augmentable}.<br />
\r
1505 * If <code>schemaNode</code> is instance of
\r
1506 * {@link org.opendaylight.yangtools.yang.model.api.DataNodeContainer
\r
1507 * DataNodeContainer} it can also implement nodes which are specified in
\r
1510 * @param packageName
\r
1511 * string with the name of the package to which
\r
1512 * <code>schemaNode</code> belongs.
\r
1513 * @param schemaNode
\r
1514 * schema node for which is created generated type builder
\r
1515 * @param parent parent type (can be null)
\r
1516 * @return generated type builder <code>schemaNode</code>
\r
1518 private def GeneratedTypeBuilder addDefaultInterfaceDefinition(String packageName, SchemaNode schemaNode,
1520 val it = addRawInterfaceDefinition(packageName, schemaNode, "");
\r
1521 val qname = schemaNode.QName;
1522 addConstant(QName.typeForClass,"QNAME",'''
\r
1523 org.opendaylight.yangtools.yang.common.QName.create("«qname.namespace»","«qname.formattedRevision»","«qname.localName»")
\r
1525 if (parent === null) {
1526 addImplementsType(DATA_OBJECT);
1528 addImplementsType(BindingTypes.childOf(parent));
1530 if (!(schemaNode instanceof GroupingDefinition)) {
1531 addImplementsType(augmentable(it));
1534 if (schemaNode instanceof DataNodeContainer) {
1535 addImplementedInterfaceFromUses(schemaNode as DataNodeContainer, it);
1542 * Wraps the calling of the same overloaded method.
\r
1544 * @param packageName
\r
1545 * string with the package name to which returning generated type
\r
1547 * @param schemaNode
\r
1548 * schema node which provide data about the schema node name
\r
1549 * @return generated type builder for <code>schemaNode</code>
\r
1551 private def GeneratedTypeBuilder addRawInterfaceDefinition(String packageName, SchemaNode schemaNode) {
1552 return addRawInterfaceDefinition(packageName, schemaNode, "");
1556 * Returns reference to generated type builder for specified
\r
1557 * <code>schemaNode</code> with <code>packageName</code>.
\r
1559 * Firstly the generated type builder is searched in
\r
1560 * {@link BindingGeneratorImpl#genTypeBuilders genTypeBuilders}. If it isn't
\r
1561 * found it is created and added to <code>genTypeBuilders</code>.
\r
1563 * @param packageName
\r
1564 * string with the package name to which returning generated type
\r
1566 * @param schemaNode
\r
1567 * schema node which provide data about the schema node name
\r
1568 * @param prefix return type name prefix
\r
1569 * @return generated type builder for <code>schemaNode</code>
\r
1570 * @throws IllegalArgumentException
\r
1572 * <li>if <code>schemaNode</code> equals null</li>
\r
1573 * <li>if <code>packageName</code> equals null</li>
\r
1574 * <li>if Q name of schema node is null</li>
\r
1575 * <li>if schema node name is nul</li>
\r
1579 private def GeneratedTypeBuilder addRawInterfaceDefinition(String packageName, SchemaNode schemaNode,
1581 checkArgument(schemaNode !== null, "Data Schema Node cannot be NULL.");
1582 checkArgument(packageName !== null, "Package Name for Generated Type cannot be NULL.");
1583 checkArgument(schemaNode.QName !== null, "QName for Data Schema Node cannot be NULL.");
1584 val schemaNodeName = schemaNode.QName.localName;
1585 checkArgument(schemaNodeName !== null, "Local Name of QName for Data Schema Node cannot be NULL.");
1587 var String genTypeName;
1588 if (prefix === null) {
1589 genTypeName = parseToClassName(schemaNodeName);
1591 genTypeName = prefix + parseToClassName(schemaNodeName);
1594 //FIXME: Validation of name conflict
\r
1595 val newType = new GeneratedTypeBuilderImpl(packageName, genTypeName);
1596 if (!genTypeBuilders.containsKey(packageName)) {
1597 val Map<String, GeneratedTypeBuilder> builders = new HashMap();
1598 builders.put(genTypeName, newType);
1599 genTypeBuilders.put(packageName, builders);
1601 val Map<String, GeneratedTypeBuilder> builders = genTypeBuilders.get(packageName);
1602 if (!builders.containsKey(genTypeName)) {
1603 builders.put(genTypeName, newType);
1610 * Creates the name of the getter method from <code>methodName</code>.
\r
1612 * @param methodName
\r
1613 * string with the name of the getter method
\r
1614 * @param returnType return type
\r
1615 * @return string with the name of the getter method for
\r
1616 * <code>methodName</code> in JAVA method format
\r
1618 public static def String getterMethodName(String localName, Type returnType) {
1619 val method = new StringBuilder();
1620 if (BOOLEAN.equals(returnType)) {
1621 method.append("is");
1623 method.append("get");
1625 method.append(parseToClassName(localName));
1626 return method.toString();
1630 * Created a method signature builder as part of
\r
1631 * <code>interfaceBuilder</code>.
\r
1633 * The method signature builder is created for the getter method of
\r
1634 * <code>schemaNodeName</code>. Also <code>comment</code> and
\r
1635 * <code>returnType</code> information are added to the builder.
\r
1637 * @param interfaceBuilder
\r
1638 * generated type builder for which the getter method should be
\r
1640 * @param schemaNodeName
\r
1641 * string with schema node name. The name will be the part of the
\r
1642 * getter method name.
\r
1644 * string with comment for the getter method
\r
1645 * @param returnType
\r
1646 * type which represents the return type of the getter method
\r
1647 * @return method signature builder which represents the getter method of
\r
1648 * <code>interfaceBuilder</code>
\r
1650 private def MethodSignatureBuilder constructGetter(GeneratedTypeBuilder interfaceBuilder, String schemaNodeName,
1651 String comment, Type returnType) {
1652 val getMethod = interfaceBuilder.addMethod(getterMethodName(schemaNodeName, returnType));
1653 getMethod.setComment(comment);
1654 getMethod.setReturnType(returnType);
1659 * Adds <code>schemaNode</code> to <code>typeBuilder</code> as getter method
\r
1660 * or to <code>genTOBuilder</code> as property.
\r
1662 * @param basePackageName
\r
1663 * string contains the module package name
\r
1664 * @param schemaNode
\r
1665 * data schema node which should be added as getter method to
\r
1666 * <code>typeBuilder</code> or as a property to
\r
1667 * <code>genTOBuilder</code> if is part of the list key
\r
1668 * @param typeBuilder
\r
1669 * generated type builder for the list schema node
\r
1670 * @param genTOBuilder
\r
1671 * generated TO builder for the list keys
\r
1673 * list of string which contains names of the list keys
\r
1674 * @param module current module
\r
1675 * @throws IllegalArgumentException
\r
1677 * <li>if <code>schemaNode</code> equals null</li>
\r
1678 * <li>if <code>typeBuilder</code> equals null</li>
\r
1681 private def void addSchemaNodeToListBuilders(String basePackageName, DataSchemaNode schemaNode,
1682 GeneratedTypeBuilder typeBuilder, GeneratedTOBuilder genTOBuilder, List<String> listKeys, Module module) {
1683 checkArgument(schemaNode !== null, "Data Schema Node cannot be NULL.");
1684 checkArgument(typeBuilder !== null, "Generated Type Builder cannot be NULL.");
1686 if (schemaNode instanceof LeafSchemaNode) {
1687 val leaf = schemaNode as LeafSchemaNode;
1688 val leafName = leaf.QName.localName;
\r
1689 resolveLeafSchemaNodeAsMethod(typeBuilder, leaf);
1690 if (listKeys.contains(leafName)) {
1691 resolveLeafSchemaNodeAsProperty(genTOBuilder, leaf, true);
1693 } else if (!schemaNode.addedByUses) {
1694 if (schemaNode instanceof LeafListSchemaNode) {
1695 resolveLeafListSchemaNode(typeBuilder, schemaNode as LeafListSchemaNode);
1696 } else if (schemaNode instanceof ContainerSchemaNode) {
1697 containerToGenType(module, basePackageName, typeBuilder, typeBuilder, schemaNode as ContainerSchemaNode);
1698 } else if (schemaNode instanceof ChoiceNode) {
1699 choiceToGeneratedType(module, basePackageName, typeBuilder, schemaNode as ChoiceNode);
1700 } else if (schemaNode instanceof ListSchemaNode) {
1701 listToGenType(module, basePackageName, typeBuilder, typeBuilder, schemaNode as ListSchemaNode);
1706 private def typeBuildersToGenTypes(Module module, GeneratedTypeBuilder typeBuilder, GeneratedTOBuilder genTOBuilder) {
1707 checkArgument(typeBuilder !== null, "Generated Type Builder cannot be NULL.");
1709 if (genTOBuilder !== null) {
1710 val genTO = genTOBuilder.toInstance();
1711 constructGetter(typeBuilder, "key", "Returns Primary Key of Yang List Type", genTO);
1712 genCtx.get(module).addGeneratedTOBuilder(genTOBuilder)
1717 * Selects the names of the list keys from <code>list</code> and returns
\r
1718 * them as the list of the strings
\r
1721 * of string with names of the list keys
\r
1722 * @return list of string which represents names of the list keys. If the
\r
1723 * <code>list</code> contains no keys then the empty list is
\r
1726 private def listKeys(ListSchemaNode list) {
1727 val List<String> listKeys = new ArrayList();
1729 if (list.keyDefinition !== null) {
1730 val keyDefinitions = list.keyDefinition;
1731 for (keyDefinition : keyDefinitions) {
1732 listKeys.add(keyDefinition.localName);
1739 * Generates for the <code>list</code> which contains any list keys special
\r
1740 * generated TO builder.
\r
1742 * @param packageName
\r
1743 * string with package name to which the list belongs
\r
1745 * list schema node which is source of data about the list name
\r
1746 * @return generated TO builder which represents the keys of the
\r
1747 * <code>list</code> or null if <code>list</code> is null or list of
\r
1748 * key definitions is null or empty.
\r
1750 private def GeneratedTOBuilder resolveListKeyTOBuilder(String packageName, ListSchemaNode list) {
1751 var GeneratedTOBuilder genTOBuilder = null;
1752 if ((list.keyDefinition !== null) && (!list.keyDefinition.isEmpty())) {
1753 val listName = list.QName.localName + "Key";
1754 val String genTOName = parseToClassName(listName);
1755 genTOBuilder = new GeneratedTOBuilderImpl(packageName, genTOName);
1757 return genTOBuilder;
1761 * Builds generated TO builders for <code>typeDef</code> of type
\r
1762 * {@link org.opendaylight.yangtools.yang.model.util.UnionType UnionType} or
\r
1763 * {@link org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition
\r
1764 * BitsTypeDefinition} which are also added to <code>typeBuilder</code> as
\r
1765 * enclosing transfer object.
\r
1767 * If more then one generated TO builder is created for enclosing then all
\r
1768 * of the generated TO builders are added to <code>typeBuilder</code> as
\r
1769 * enclosing transfer objects.
\r
1772 * type definition which can be of type <code>UnionType</code> or
\r
1773 * <code>BitsTypeDefinition</code>
\r
1774 * @param typeBuilder
\r
1775 * generated type builder to which is added generated TO created
\r
1776 * from <code>typeDef</code>
\r
1778 * string with name for generated TO builder
\r
1780 * @param parentModule
\r
1781 * @return generated TO builder for <code>typeDef</code>
\r
1783 private def GeneratedTOBuilder addTOToTypeBuilder(TypeDefinition<?> typeDef, GeneratedTypeBuilder typeBuilder,
1784 String leafName, LeafSchemaNode leaf, Module parentModule) {
1785 val classNameFromLeaf = parseToClassName(leafName);
1786 val List<GeneratedTOBuilder> genTOBuilders = new ArrayList();
1787 val packageName = typeBuilder.fullyQualifiedName;
1788 if (typeDef instanceof UnionTypeDefinition) {
1789 genTOBuilders.addAll(
1790 (typeProvider as TypeProviderImpl).
1791 provideGeneratedTOBuildersForUnionTypeDef(packageName, (typeDef as UnionTypeDefinition),
1792 classNameFromLeaf, leaf));
1793 } else if (typeDef instanceof BitsTypeDefinition) {
1795 ((typeProvider as TypeProviderImpl) ).
1796 provideGeneratedTOBuilderForBitsTypeDefinition(packageName, typeDef, classNameFromLeaf));
1798 if (genTOBuilders !== null && !genTOBuilders.isEmpty()) {
1799 for (genTOBuilder : genTOBuilders) {
1800 typeBuilder.addEnclosingTransferObject(genTOBuilder);
1802 return genTOBuilders.get(0);
1809 * Adds the implemented types to type builder.
\r
1811 * The method passes through the list of <i>uses</i> in
\r
1812 * {@code dataNodeContainer}. For every <i>use</i> is obtained coresponding
\r
1813 * generated type from {@link BindingGeneratorImpl#allGroupings
\r
1814 * allGroupings} which is added as <i>implements type</i> to
\r
1815 * <code>builder</code>
\r
1817 * @param dataNodeContainer
\r
1818 * element which contains the list of used YANG groupings
\r
1820 * builder to which are added implemented types according to
\r
1821 * <code>dataNodeContainer</code>
\r
1822 * @return generated type builder with all implemented types
\r
1824 private def addImplementedInterfaceFromUses(DataNodeContainer dataNodeContainer, GeneratedTypeBuilder builder) {
1825 for (usesNode : dataNodeContainer.uses) {
1826 if (usesNode.groupingPath !== null) {
1827 val genType = findGroupingByPath(usesNode.groupingPath).toInstance
1828 if (genType === null) {
1829 throw new IllegalStateException(
1830 "Grouping " + usesNode.groupingPath + "is not resolved for " + builder.name);
1832 builder.addImplementsType(genType);
1838 private def GeneratedTypeBuilder findChildNodeByPath(SchemaPath path) {
1839 for (ctx : genCtx.values) {
1840 var result = ctx.getChildNode(path)
1841 if (result !== null) {
1848 private def GeneratedTypeBuilder findGroupingByPath(SchemaPath path) {
1849 for (ctx : genCtx.values) {
1850 var result = ctx.getGrouping(path)
1851 if (result !== null) {
1858 private def GeneratedTypeBuilder findCaseByPath(SchemaPath path) {
1859 for (ctx : genCtx.values) {
1860 var result = ctx.getCase(path)
1861 if (result !== null) {
1869 public def getModuleContexts() {
\r