2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.yangtools.yang.unified.doc.generator
\r
10 import org.opendaylight.yangtools.yang.model.api.SchemaContext
\r
12 import java.util.Set
\r
13 import org.opendaylight.yangtools.yang.model.api.Module
\r
14 import java.io.IOException
\r
15 import java.util.HashSet
\r
16 import java.io.BufferedWriter
\r
17 import java.io.OutputStreamWriter;
\r
18 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
\r
19 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
\r
20 import org.opendaylight.yangtools.yang.model.api.TypeDefinition
\r
21 import org.opendaylight.yangtools.yang.model.api.SchemaNode
\r
22 import org.opendaylight.yangtools.yang.model.util.ExtendedType
\r
23 import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition
\r
24 import java.text.SimpleDateFormat
\r
25 import java.util.Collection
\r
26 import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint
\r
27 import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition
\r
28 import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition
\r
29 import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint
\r
30 import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition
\r
31 import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition
\r
32 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition
\r
33 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
\r
34 import org.slf4j.LoggerFactory
\r
35 import org.slf4j.Logger
\r
36 import java.util.List
\r
37 import org.opendaylight.yangtools.yang.common.QName
\r
38 import org.opendaylight.yangtools.yang.model.api.RpcDefinition
\r
39 import org.opendaylight.yangtools.yang.model.api.ExtensionDefinition
\r
40 import java.util.ArrayList
\r
41 import java.util.Map
\r
42 import org.opendaylight.yangtools.yang.model.api.SchemaPath
\r
44 import org.sonatype.plexus.build.incremental.BuildContext;
\r
45 import org.sonatype.plexus.build.incremental.DefaultBuildContext;
\r
47 import org.opendaylight.yangtools.yang.model.api.ChoiceNode
\r
48 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode
\r
49 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
\r
50 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
\r
51 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates
\r
52 import java.util.LinkedHashMap
\r
53 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier
\r
54 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
\r
55 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
\rimport java.util.HashMap
56 import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode
58 class GeneratorImpl {
\r
61 static val REVISION_FORMAT = new SimpleDateFormat("yyyy-MM-dd")
\r
62 static val Logger LOG = LoggerFactory.getLogger(GeneratorImpl)
\r
63 static val BuildContext CTX = new DefaultBuildContext();
\r
64 var Module currentModule;
\r
67 def generate(SchemaContext context, File targetPath, Set<Module> modulesToGen) throws IOException {
\r
70 val it = new HashSet;
\r
71 for (module : modulesToGen) {
\r
72 add(generateDocumentation(module, context));
\r
77 def generateDocumentation(Module module, SchemaContext ctx) {
\r
78 val destination = new File(path, '''«module.name».html''')
\r
80 val fw = new OutputStreamWriter(CTX.newFileOutputStream(destination))
\r
81 val bw = new BufferedWriter(fw)
\r
82 currentModule = module;
\r
83 bw.append(generate(module, ctx));
\r
86 } catch (IOException e) {
\r
87 LOG.error(e.getMessage());
\r
92 def generate(Module module, SchemaContext ctx) '''
\r
96 <title>«module.name»</title>
\r
104 def body(Module module, SchemaContext ctx) '''
\r
107 «typeDefinitions(module)»
\r
109 «identities(module)»
\r
111 «groupings(module)»
\r
113 «dataStore(module)»
\r
115 «childNodes(module)»
\r
117 «notifications(module)»
\r
119 «augmentations(module, ctx)»
\r
123 «extensions(module)»
\r
130 def typeDefinitions(Module module) {
\r
131 val Set<TypeDefinition<?>> typedefs = module.typeDefinitions
\r
132 if (typedefs.empty) {
\r
136 <h2>Type Definitions</h2>
\r
138 «FOR typedef : typedefs»
\r
140 «strong("typedef " + typedef.QName.localName)»
\r
142 «typedef.descAndRefLi»
\r
143 «typedef.restrictions»
\r
151 private def identities(Module module) {
\r
152 if (module.identities.empty) {
\r
156 <h2>Identities</h2>
\r
158 «FOR identity : module.identities»
\r
160 «strong("identity " + identity.QName.localName)»
\r
162 «identity.descAndRefLi»
\r
163 «IF identity.baseIdentity != null»
\r
164 «listItem("base", identity.baseIdentity.QName.localName)»
\r
173 private def groupings(Module module) {
\r
174 if (module.groupings.empty) {
\r
180 «FOR grouping : module.groupings»
\r
182 «strong("grouping " + grouping.QName.localName)»
\r
184 «grouping.descAndRefLi»
\r
192 def dataStore(Module module) {
\r
193 if (module.childNodes.empty) {
\r
197 <h2>Datastore Structure</h2>
\r
202 def augmentations(Module module, SchemaContext context) {
\r
203 if (module.augmentations.empty) {
\r
207 <h2>Augmentations</h2>
\r
210 «FOR augment : module.augmentations»
\r
212 <h3>Target [«schemaPathAsRestconfPath(module, augment.targetPath, context)»]</h3>
\r
213 «augment.description»
\r
214 «IF augment.reference !== null»
\r
215 Reference «augment.reference»
\r
217 «IF augment.whenCondition !== null»
\r
218 When «augment.whenCondition.toString»
\r
220 «augment.childNodes.printChildren(3,InstanceIdentifier.builder().toInstance())»
\r
227 def notifications(Module module) {
\r
228 val Set<NotificationDefinition> notificationdefs = module.notifications
\r
229 if (notificationdefs.empty) {
\r
234 <h2>Notifications</h2>
\r
235 «FOR notificationdef : notificationdefs»
\r
237 <h3>«notificationdef.nodeName»</h3>
\r
238 «notificationdef.descAndRef»
\r
239 «notificationdef.childNodes.printChildren(3,InstanceIdentifier.builder().toInstance())»
\r
244 def rpcs(Module module) {
\r
245 if (module.rpcs.empty) {
\r
250 <h2>RPC Definitions</h2>
\r
251 «FOR rpc : module.rpcs»
\r
252 <h3>«rpc.nodeName»</h3>
\r
253 «rpc.rpcInfo(InstanceIdentifier.builder().node(rpc.QName).toInstance())»
\r
259 def extensions(Module module) {
\r
260 if (module.extensionSchemaNodes.empty) {
\r
264 <h2>Extensions</h2>
\r
265 «FOR ext : module.extensionSchemaNodes»
\r
267 <h3>«ext.nodeName»</h3>
\r
269 «extensionInfo(ext)»
\r
274 def features(Module module) {
\r
275 if (module.features.empty) {
\r
282 «FOR feature : module.features»
\r
284 «strong("feature " + feature.QName.localName)»
\r
286 «feature.descAndRefLi»
\r
294 def header(Module module) '''
\r
295 <h1>«module.name»</h1>
\r
297 <h2>Base Information</h2>
\r
300 <dd>«pre(module.prefix)»</dd>
\r
302 <dd>«pre(module.namespace.toString)»</dd>
\r
304 <dd>«pre(REVISION_FORMAT.format(module.revision))»</dd>
\r
306 «FOR imp : module.imports BEFORE "<dt>Imports</dt>" »
\r
307 <dd>«code(imp.prefix)» = «code(imp.moduleName)»</dd>
\r
312 def code(String string) '''<code>«string»</code>'''
\r
314 def process(Module module) {
\r
315 throw new UnsupportedOperationException("TODO: auto-generated method stub")
\r
318 def CharSequence tree(Module module) '''
\r
319 «strong("module " + module.name)»
\r
320 «module.childNodes.treeSet(InstanceIdentifier.builder.toInstance())»
\r
323 private def dispatch CharSequence tree(ChoiceNode node,InstanceIdentifier path) '''
\r
324 «node.nodeName» (choice)
\r
325 «casesTree(node.cases,path)»
\r
328 def casesTree(Set<ChoiceCaseNode> nodes,InstanceIdentifier path) '''
\r
333 «node.childNodes.treeSet(path)»
\r
339 private def dispatch CharSequence tree(DataSchemaNode node,InstanceIdentifier path) '''
\r
343 private def dispatch CharSequence tree(ListSchemaNode node,InstanceIdentifier path) '''
\r
344 «val newPath = path.append(node)»
\r
345 «localLink(newPath,node.nodeName)»
\r
346 «node.childNodes.treeSet(newPath)»
\r
349 private def dispatch CharSequence tree(ContainerSchemaNode node,InstanceIdentifier path) '''
\r
350 «val newPath = path.append(node)»
\r
351 «localLink(newPath,node.nodeName)»
\r
352 «node.childNodes.treeSet(newPath)»
\r
355 def CharSequence childNodes(Module module) '''
\r
356 «val childNodes = module.childNodes»
\r
357 «IF childNodes !== null && !childNodes.empty»
\r
358 <h2>Child nodes</h2>
\r
360 «childNodes.printChildren(3,InstanceIdentifier.builder().toInstance())»
\r
364 def CharSequence printChildren(Set<DataSchemaNode> nodes, int level, InstanceIdentifier path) {
\r
365 val anyxmlNodes = nodes.filter(AnyXmlSchemaNode)
\r
366 val leafNodes = nodes.filter(LeafSchemaNode)
\r
367 val leafListNodes = nodes.filter(LeafListSchemaNode)
\r
368 val choices = nodes.filter(ChoiceNode)
\r
369 val cases = nodes.filter(ChoiceCaseNode)
\r
370 val containers = nodes.filter(ContainerSchemaNode)
\r
371 val lists = nodes.filter(ListSchemaNode)
\r
373 «IF ((anyxmlNodes.size + leafNodes.size + leafListNodes.size + containers.size + lists.size) > 0)»
\r
374 <h3>Direct children</h3>
\r
376 «FOR childNode : anyxmlNodes»
\r
377 «childNode.printShortInfo(level,path)»
\r
379 «FOR childNode : leafNodes»
\r
380 «childNode.printShortInfo(level,path)»
\r
382 «FOR childNode : leafListNodes»
\r
383 «childNode.printShortInfo(level,path)»
\r
385 «FOR childNode : containers»
\r
386 «childNode.printShortInfo(level,path)»
\r
388 «FOR childNode : lists»
\r
389 «childNode.printShortInfo(level,path)»
\r
394 «IF !path.path.empty»
\r
395 <h3>XML example</h3>
\r
396 «nodes.xmlExample(path.path.last.nodeType,path)»
\r
399 «FOR childNode : containers»
\r
400 «childNode.printInfo(level,path)»
\r
402 «FOR childNode : lists»
\r
403 «childNode.printInfo(level,path)»
\r
405 «FOR childNode : choices»
\r
406 «childNode.printInfo(level,path)»
\r
408 «FOR childNode : cases»
\r
409 «childNode.printInfo(level,path)»
\r
415 def CharSequence xmlExample(Set<DataSchemaNode> nodes, QName name,InstanceIdentifier path) '''
\r
417 «xmlExampleTag(name,nodes.xmplExampleTags(path))»
\r
421 def CharSequence xmplExampleTags(Set<DataSchemaNode> nodes, InstanceIdentifier identifier) '''
\r
422 <!-- Child nodes -->
\r
424 <!-- «node.QName.localName» -->
\r
425 «node.asXmlExampleTag(identifier)»
\r
430 private def dispatch CharSequence asXmlExampleTag(LeafSchemaNode node, InstanceIdentifier identifier) '''
\r
431 «node.QName.xmlExampleTag("...")»
\r
434 private def dispatch CharSequence asXmlExampleTag(LeafListSchemaNode node, InstanceIdentifier identifier) '''
\r
435 <!-- This node could appear multiple times -->
\r
436 «node.QName.xmlExampleTag("...")»
\r
439 private def dispatch CharSequence asXmlExampleTag(ContainerSchemaNode node, InstanceIdentifier identifier) '''
\r
440 <!-- See «localLink(identifier.append(node),"definition")» for child nodes. -->
\r
441 «node.QName.xmlExampleTag("...")»
\r
445 private def dispatch CharSequence asXmlExampleTag(ListSchemaNode node, InstanceIdentifier identifier) '''
\r
446 <!-- See «localLink(identifier.append(node),"definition")» for child nodes. -->
\r
447 <!-- This node could appear multiple times -->
\r
448 «node.QName.xmlExampleTag("...")»
\r
452 private def dispatch CharSequence asXmlExampleTag(DataSchemaNode node, InstanceIdentifier identifier) '''
\r
457 def xmlExampleTag(QName name, CharSequence data) {
\r
458 return '''<«name.localName» xmlns="«name.namespace»">«data»</«name.localName»>'''
\r
461 def header(int level,QName name) '''<h«level»>«name.localName»</h«level»>'''
\r
464 def header(int level,InstanceIdentifier name) '''
\r
465 <h«level» id="«FOR cmp : name.path SEPARATOR "/"»«cmp.nodeType.localName»«ENDFOR»">
\r
466 «FOR cmp : name.path SEPARATOR "/"»«cmp.nodeType.localName»«ENDFOR»
\r
472 private def dispatch CharSequence printInfo(DataSchemaNode node, int level, InstanceIdentifier path) '''
\r
473 «header(level+1,node.QName)»
\r
476 private def dispatch CharSequence printInfo(ContainerSchemaNode node, int level, InstanceIdentifier path) '''
\r
477 «val newPath = path.append(node)»
\r
478 «header(level,newPath)»
\r
481 <dd>«newPath.asXmlPath»</dd>
\r
482 <dt>Restconf path</dt>
\r
483 <dd>«code(newPath.asRestconfPath)»</dd>
\r
485 «node.childNodes.printChildren(level,newPath)»
\r
488 private def dispatch CharSequence printInfo(ListSchemaNode node, int level, InstanceIdentifier path) '''
\r
489 «val newPath = path.append(node)»
\r
490 «header(level,newPath)»
\r
493 <dd>«newPath.asXmlPath»</dd>
\r
494 <dt>Restconf path</dt>
\r
495 <dd>«code(newPath.asRestconfPath)»</dd>
\r
497 «node.childNodes.printChildren(level,newPath)»
\r
500 private def dispatch CharSequence printInfo(ChoiceNode node, int level, InstanceIdentifier path) '''
\r
501 «val Set<DataSchemaNode> choiceCases = new HashSet(node.cases)»
\r
502 «choiceCases.printChildren(level,path)»
\r
505 private def dispatch CharSequence printInfo(ChoiceCaseNode node, int level, InstanceIdentifier path) '''
\r
506 «node.childNodes.printChildren(level,path)»
\r
511 def CharSequence printShortInfo(ContainerSchemaNode node, int level, InstanceIdentifier path) {
\r
512 val newPath = path.append(node);
\r
514 <li>«strong(localLink(newPath,node.QName.localName))» (container)</li>
\r
518 def CharSequence printShortInfo(ListSchemaNode node, int level, InstanceIdentifier path) {
\r
519 val newPath = path.append(node);
\r
521 <li>«strong(localLink(newPath,node.QName.localName))» (list)</li>
\r
525 def CharSequence printShortInfo(AnyXmlSchemaNode node, int level, InstanceIdentifier path) {
\r
527 <li>«strong((node.QName.localName))» (anyxml)</li>
\r
531 def CharSequence printShortInfo(LeafSchemaNode node, int level, InstanceIdentifier path) {
\r
533 <li>«strong((node.QName.localName))» (leaf)</li>
\r
537 def CharSequence printShortInfo(LeafListSchemaNode node, int level, InstanceIdentifier path) {
\r
539 <li>«strong((node.QName.localName))» (leaf-list)</li>
\r
543 def CharSequence localLink(InstanceIdentifier identifier, CharSequence text) '''
\r
544 <a href="#«FOR cmp : identifier.path SEPARATOR "/"»«cmp.nodeType.localName»«ENDFOR»">«text»</a>
\r
548 private def dispatch InstanceIdentifier append(InstanceIdentifier identifier, ContainerSchemaNode node) {
\r
549 val pathArguments = new ArrayList(identifier.path)
\r
550 pathArguments.add(new NodeIdentifier(node.QName));
\r
551 return new InstanceIdentifier(pathArguments);
\r
554 private def dispatch InstanceIdentifier append(InstanceIdentifier identifier, ListSchemaNode node) {
\r
555 val pathArguments = new ArrayList(identifier.path)
\r
556 val keyValues = new LinkedHashMap<QName,Object>();
\r
557 if(node.keyDefinition != null) {
\r
558 for(definition : node.keyDefinition) {
\r
559 keyValues.put(definition,new Object);
\r
562 pathArguments.add(new NodeIdentifierWithPredicates(node.QName,keyValues));
\r
563 return new InstanceIdentifier(pathArguments);
\r
567 def asXmlPath(InstanceIdentifier identifier) {
\r
571 def asRestconfPath(InstanceIdentifier identifier) {
\r
572 val it = new StringBuilder();
\r
573 append(currentModule.name)
\r
575 var previous = false;
\r
576 for(arg : identifier.path) {
\r
577 if(previous) append("/")
\r
578 append(arg.nodeType.localName);
\r
580 if(arg instanceof NodeIdentifierWithPredicates) {
\r
581 val nodeIdentifier = arg as NodeIdentifierWithPredicates;
\r
582 for(qname : nodeIdentifier.keyValues.keySet) {
\r
584 append(qname.localName)
\r
590 return it.toString;
\r
593 private def String schemaPathAsRestconfPath(Module module, SchemaPath schemaPath, SchemaContext ctx) {
\r
594 val Map<String, String> imports = new HashMap();
\r
595 for (mImport : module.imports) {
\r
596 imports.put(mImport.prefix, mImport.moduleName)
\r
599 val List<QName> path = schemaPath.path
\r
600 val StringBuilder pathString = new StringBuilder()
\r
601 if (schemaPath.absolute) {
\r
602 pathString.append("/")
\r
605 val QName qname = path.get(0)
\r
606 var Object parent = ctx.findModuleByNamespaceAndRevision(qname.namespace, qname.revision)
\r
608 for (name : path) {
\r
609 if (parent instanceof DataNodeContainer) {
\r
610 var SchemaNode node = (parent as DataNodeContainer).getDataChildByName(name)
\r
611 if (node == null && (parent instanceof Module)) {
\r
612 val notifications = (parent as Module).notifications;
\r
613 for (notification : notifications) {
\r
614 if (notification.QName.localName.equals(name.localName)) {
\r
615 node = notification
\r
620 if (!(node instanceof ChoiceNode) && !(node instanceof ChoiceCaseNode)) {
\r
621 var String prefix = node.QName.prefix
\r
622 var String moduleName
\r
623 if (prefix == null || "".equals(prefix) || prefix.equals(module.prefix)) {
\r
624 moduleName = module.name
\r
626 moduleName = imports.get(prefix)
\r
628 pathString.append(moduleName)
\r
629 pathString.append(":")
\r
630 pathString.append(node.QName.localName)
\r
631 pathString.append("/")
\r
634 } else if (parent instanceof ChoiceNode) {
\r
635 parent = (parent as ChoiceNode).getCaseNodeByName(qname.localName)
\r
638 return pathString.toString;
\r
642 def CharSequence childNodesInfoTree(Map<SchemaPath, DataSchemaNode> childNodes) '''
\r
643 «IF childNodes !== null && !childNodes.empty»
\r
644 «FOR child : childNodes.values»
\r
645 «childInfo(child, childNodes)»
\r
650 def CharSequence childInfo(DataSchemaNode node, Map<SchemaPath, DataSchemaNode> childNodes) '''
\r
651 «val String path = nodeSchemaPathToPath(node, childNodes)»
\r
656 «node.descAndRefLi»
\r
662 private def CharSequence treeSet(Collection<DataSchemaNode> childNodes, InstanceIdentifier path) '''
\r
663 «IF childNodes !== null && !childNodes.empty»
\r
665 «FOR child : childNodes»
\r
674 def listKeys(ListSchemaNode node) '''
\r
675 [«FOR key : node.keyDefinition SEPARATOR " "»«key.localName»«ENDFOR»]
\r
678 private def CharSequence rpcInfo(RpcDefinition rpc,InstanceIdentifier path) '''
\r
682 «rpc.input.tree(path)»
\r
685 «rpc.output.tree(path)»
\r
690 private def CharSequence extensionInfo(ExtensionDefinition ext) '''
\r
693 «listItem("Argument", ext.argument)»
\r
697 private def dispatch CharSequence tree(Void obj, InstanceIdentifier path) '''
\r
702 /* #################### RESTRICTIONS #################### */
\r
703 private def restrictions(TypeDefinition<?> type) '''
\r
708 private def dispatch toLength(TypeDefinition<?> type) {
\r
711 private def dispatch toLength(BinaryTypeDefinition type) '''
\r
712 «type.lengthConstraints.toLengthStmt»
\r
715 private def dispatch toLength(StringTypeDefinition type) '''
\r
716 «type.lengthConstraints.toLengthStmt»
\r
719 private def dispatch toLength(ExtendedType type) '''
\r
720 «type.lengthConstraints.toLengthStmt»
\r
723 private def dispatch toRange(TypeDefinition<?> type) {
\r
726 private def dispatch toRange(DecimalTypeDefinition type) '''
\r
727 «type.rangeConstraints.toRangeStmt»
\r
730 private def dispatch toRange(IntegerTypeDefinition type) '''
\r
731 «type.rangeConstraints.toRangeStmt»
\r
734 private def dispatch toRange(UnsignedIntegerTypeDefinition type) '''
\r
735 «type.rangeConstraints.toRangeStmt»
\r
738 private def dispatch toRange(ExtendedType type) '''
\r
739 «type.rangeConstraints.toRangeStmt»
\r
742 def toLengthStmt(Collection<LengthConstraint> lengths) '''
\r
743 «IF lengths != null && !lengths.empty»
\r
744 «listItem("Length restrictions")»
\r
746 «FOR length : lengths»
\r
748 «IF length.min == length.max»
\r
751 <«length.min», «length.max»>
\r
759 def toRangeStmt(Collection<RangeConstraint> ranges) '''
\r
760 «IF ranges != null && !ranges.empty»
\r
761 «listItem("Range restrictions")»
\r
763 «FOR range : ranges»
\r
765 «IF range.min == range.max»
\r
768 <«range.min», «range.max»>
\r
778 /* #################### UTILITY #################### */
\r
779 private def String strong(CharSequence str) '''<strong>«str»</strong>'''
\r
780 private def italic(CharSequence str) '''<i>«str»</i>'''
\r
781 private def pre(CharSequence str) '''<pre>«str»</pre>'''
\r
783 def CharSequence descAndRefLi(SchemaNode node) '''
\r
784 «listItem(node.description)»
\r
785 «listItem("Reference", node.reference)»
\r
788 def CharSequence descAndRef(SchemaNode node) '''
\r
790 «IF node.reference !== null»
\r
791 Reference «node.reference»
\r
795 private def listItem(String value) '''
\r
796 «IF value !== null && !value.empty»
\r
803 private def listItem(String name, String value) '''
\r
804 «IF value !== null && !value.empty»
\r
811 private def String nodeSchemaPathToPath(DataSchemaNode node, Map<SchemaPath, DataSchemaNode> childNodes) {
\r
812 if (node instanceof ChoiceNode || node instanceof ChoiceCaseNode) {
\r
816 val path = node.path.path
\r
817 val absolute = node.path.absolute;
\r
818 var StringBuilder result = new StringBuilder
\r
822 if (path !== null && !path.empty) {
\r
823 val List<QName> actual = new ArrayList()
\r
825 for (pathElement : path) {
\r
826 actual.add(pathElement)
\r
827 val DataSchemaNode nodeByPath = childNodes.get(new SchemaPath(actual, absolute))
\r
828 if (!(nodeByPath instanceof ChoiceNode) && !(nodeByPath instanceof ChoiceCaseNode)) {
\r
829 result.append(pathElement.localName)
\r
830 if (i != path.size - 1) {
\r
837 return result.toString
\r
840 private def void collectChildNodes(Collection<DataSchemaNode> source, Map<SchemaPath, DataSchemaNode> destination) {
\r
841 for (node : source) {
\r
842 destination.put(node.path, node)
\r
843 if (node instanceof DataNodeContainer) {
\r
844 collectChildNodes((node as DataNodeContainer).childNodes, destination)
\r
846 if (node instanceof ChoiceNode) {
\r
847 val List<DataSchemaNode> choiceCases = new ArrayList()
\r
848 for (caseNode : (node as ChoiceNode).cases) {
\r
849 choiceCases.add(caseNode)
\r
851 collectChildNodes(choiceCases, destination)
\r
856 private def dispatch addedByInfo(SchemaNode node) '''
\r
859 private def dispatch addedByInfo(DataSchemaNode node) '''
\r
860 «IF node.augmenting»(A)«ENDIF»«IF node.addedByUses»(U)«ENDIF»
\r
863 private def dispatch isAddedBy(SchemaNode node) {
\r
867 private def dispatch isAddedBy(DataSchemaNode node) {
\r
868 if (node.augmenting || node.addedByUses) {
\r
875 private def dispatch nodeName(SchemaNode node) '''
\r
876 «IF node.isAddedBy»
\r
877 «italic(node.QName.localName)»«node.addedByInfo»
\r
879 «node.QName.localName»«node.addedByInfo»
\r
883 private def dispatch nodeName(ContainerSchemaNode node) '''
\r
884 «IF node.isAddedBy»
\r
885 «strong(italic(node.QName.localName))»«node.addedByInfo»
\r
887 «strong(node.QName.localName)»«node.addedByInfo»
\r
891 private def dispatch nodeName(ListSchemaNode node) '''
\r
892 «IF node.isAddedBy»
\r
893 «strong(italic(node.QName.localName))» «IF node.keyDefinition !== null && !node.keyDefinition.empty»«node.listKeys»«ENDIF»«node.addedByInfo»
\r
895 «strong(node.QName.localName)» «IF node.keyDefinition !== null && !node.keyDefinition.empty»«node.listKeys»«ENDIF»
\r