913d68542a79a8b4c7e63eac7cf4e0994648d626
[mdsal.git] / code-generator / binding-generator-impl / src / main / java / org / opendaylight / yangtools / sal / binding / generator / impl / YangTemplate.xtend
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.yangtools.sal.binding.generator.impl
9
10 import java.util.Collection
11 import java.util.Date
12 import java.util.List
13 import java.util.Map
14 import java.util.Set
15 import java.util.StringTokenizer
16 import org.opendaylight.yangtools.yang.common.QName
17 import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode
18 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema
19 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode
20 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode
21 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
22 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
23 import org.opendaylight.yangtools.yang.model.api.Deviation
24 import org.opendaylight.yangtools.yang.model.api.ExtensionDefinition
25 import org.opendaylight.yangtools.yang.model.api.FeatureDefinition
26 import org.opendaylight.yangtools.yang.model.api.GroupingDefinition
27 import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode
28 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
29 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
30 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
31 import org.opendaylight.yangtools.yang.model.api.Module
32 import org.opendaylight.yangtools.yang.model.api.ModuleImport
33 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition
34 import org.opendaylight.yangtools.yang.model.api.RpcDefinition
35 import org.opendaylight.yangtools.yang.model.api.SchemaNode
36 import org.opendaylight.yangtools.yang.model.api.SchemaPath
37 import org.opendaylight.yangtools.yang.model.api.TypeDefinition
38 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode
39 import org.opendaylight.yangtools.yang.model.api.UsesNode
40 import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition
41 import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition.EnumPair
42 import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil
43 import com.google.common.base.CharMatcher
44
45 class YangTemplate {
46
47     // FIXME: this is not thread-safe and seems to be unused!
48     private static var Module module = null
49
50     private static val CharMatcher NEWLINE_OR_TAB = CharMatcher.anyOf("\n\t")
51
52     def static String generateYangSnipet(SchemaNode schemaNode) {
53         if (schemaNode == null)
54             return ''
55
56         '''
57             «IF schemaNode instanceof DataSchemaNode»
58             «writeDataSchemaNode(schemaNode)»
59             «ENDIF»
60             «IF schemaNode instanceof EnumTypeDefinition.EnumPair»
61             «writeEnumPair(schemaNode)»
62             «ENDIF»
63             «IF schemaNode instanceof ExtensionDefinition»
64             «writeExtension(schemaNode)»
65             «ENDIF»
66             «IF schemaNode instanceof FeatureDefinition»
67             «writeFeature(schemaNode)»
68             «ENDIF»
69             «IF schemaNode instanceof GroupingDefinition»
70             «writeGroupingDef(schemaNode)»
71             «ENDIF»
72             «IF schemaNode instanceof IdentitySchemaNode»
73             «writeIdentity(schemaNode)»
74             «ENDIF»
75             «IF schemaNode instanceof NotificationDefinition»
76             «writeNotification(schemaNode)»
77             «ENDIF»
78             «IF schemaNode instanceof RpcDefinition»
79             «writeRPC(schemaNode)»
80             «ENDIF»
81             «IF schemaNode instanceof TypeDefinition<?>»
82             «writeTypeDefinition(schemaNode)»
83             «ENDIF»
84             «IF schemaNode instanceof UnknownSchemaNode»
85             «writeUnknownSchemaNode(schemaNode)»
86             «ENDIF»
87         '''
88     }
89     
90     def static String generateYangSnipet(Set<? extends SchemaNode> nodes) {
91         if (nodes.nullOrEmpty)
92             return ''
93         
94         '''
95             «FOR node : nodes»
96                 «IF node instanceof NotificationDefinition»
97                 «writeNotification(node)»
98                 «ELSEIF node instanceof RpcDefinition»
99                 «writeRPC(node as RpcDefinition)»
100                 «ENDIF»
101             «ENDFOR»
102         '''
103     }
104
105     def static writeEnumPair(EnumPair pair) {
106         var boolean hasEnumPairValue = pair.value != null
107         '''
108             enum «pair.name»«IF !hasEnumPairValue»;«ELSE»{
109                 value «pair.value»;
110             }
111             «ENDIF»
112         '''
113     }
114
115     def static String writeModuleImports(Set<ModuleImport> moduleImports) {
116         if (moduleImports.nullOrEmpty)
117             return ''
118
119         '''
120             «FOR moduleImport : moduleImports SEPARATOR "\n"»
121                 «IF moduleImport != null && !moduleImport.moduleName.nullOrEmpty»
122                 import «moduleImport.moduleName» { prefix "«moduleImport.prefix»"; }
123                 «ENDIF»
124             «ENDFOR»
125         '''
126     }
127
128     def static writeRevision(Date moduleRevision, String moduleDescription) {
129         val revisionIndent = 12
130
131         '''
132             revision «SimpleDateFormatUtil.getRevisionFormat.format(moduleRevision)» {
133                 description "«formatToParagraph(moduleDescription, revisionIndent)»";
134             }
135         '''
136     }
137
138     def static String generateYangSnipet(Module module) {
139
140         '''
141             module «module.name» {
142                 yang-version «module.yangVersion»;
143                 namespace "«module.QNameModule.namespace.toString»";
144                 prefix "«module.prefix»";
145
146                 «IF !module.imports.nullOrEmpty»
147                 «writeModuleImports(module.imports)»
148                 «ENDIF»
149                 «IF module.revision != null»
150                 «writeRevision(module.revision, module.description)»
151                 «ENDIF»
152                 «IF !module.childNodes.nullOrEmpty»
153
154                 «writeDataSchemaNodes(module.childNodes)»
155                 «ENDIF»
156                 «IF !module.groupings.nullOrEmpty»
157
158                 «writeGroupingDefs(module.groupings)»
159                 «ENDIF»
160                 «IF !module.augmentations.nullOrEmpty»
161
162                 «writeAugments(module.augmentations)»
163                 «ENDIF»
164                 «IF !module.deviations.nullOrEmpty»
165
166                 «writeDeviations(module.deviations)»
167                 «ENDIF»
168                 «IF !module.extensionSchemaNodes.nullOrEmpty»
169
170                 «writeExtensions(module.extensionSchemaNodes)»
171                 «ENDIF»
172                 «IF !module.features.nullOrEmpty»
173
174                 «writeFeatures(module.features)»
175                 «ENDIF»
176                 «IF !module.identities.nullOrEmpty»
177
178                 «writeIdentities(module.identities)»
179                 «ENDIF»
180                 «IF !module.notifications.nullOrEmpty»
181
182                 «writeNotifications(module.notifications)»
183                 «ENDIF»
184                 «IF !module.rpcs.nullOrEmpty»
185
186                 «writeRPCs(module.rpcs)»
187                 «ENDIF»
188                 «IF !module.unknownSchemaNodes.nullOrEmpty»
189
190                 «writeUnknownSchemaNodes(module.unknownSchemaNodes)»
191                 «ENDIF»
192                 «IF !module.uses.nullOrEmpty»
193
194                 «writeUsesNodes(module.uses)»
195                 «ENDIF»
196             }
197         '''
198     }
199
200     def static writeRPCs(Set<RpcDefinition> rpcDefs) {
201         '''
202             «FOR rpc : rpcDefs»
203                 «IF rpc != null»
204                 «writeRPC(rpc)»
205                 «ENDIF»
206             «ENDFOR»
207         '''
208     }
209
210     def static writeRPC(RpcDefinition rpc) {
211         '''
212             rpc «rpc.QName.localName» {
213                 «IF !rpc.description.nullOrEmpty»
214                     "«rpc.description»";
215                 «ENDIF»
216                 «IF !rpc.groupings.nullOrEmpty»
217                     «writeGroupingDefs(rpc.groupings)»
218                 «ENDIF»
219                 «IF rpc.input != null»
220                     «writeRpcInput(rpc.input)»
221                 «ENDIF»
222                 «IF rpc.output != null»
223                     «writeRpcOutput(rpc.output)»
224                 «ENDIF»
225                 «IF !rpc.reference.nullOrEmpty»
226                 reference
227                     "«rpc.reference»";
228                 «ENDIF»
229                 «IF rpc.status != null»
230                 status «rpc.status»;
231                 «ENDIF»
232             }
233         '''
234     }
235
236     def static writeRpcInput(ContainerSchemaNode input) {
237         if(input == null)
238             return ''
239
240         '''
241             input {
242                 «IF !input.childNodes.nullOrEmpty»
243                 «writeDataSchemaNodes(input.childNodes)»
244                 «ENDIF»
245             }
246
247         '''
248     }
249
250     def static writeRpcOutput(ContainerSchemaNode output) {
251         if(output == null)
252             return ''
253
254         '''
255             output {
256                 «IF !output.childNodes.nullOrEmpty»
257                 «writeDataSchemaNodes(output.childNodes)»
258                 «ENDIF»
259             }
260         '''
261     }
262
263     def static writeNotifications(Set<NotificationDefinition> notifications) {
264         '''
265             «FOR notification : notifications»
266                 «IF notification != null»
267                 «writeNotification(notification)»
268                 «ENDIF»
269             «ENDFOR»
270         '''
271     }
272
273     def static writeNotification(NotificationDefinition notification) {
274         '''
275             notification «notification.QName.localName» {
276                 «IF !notification.description.nullOrEmpty»
277                 description
278                     "«notification.description»";
279                 «ENDIF»
280                 «IF !notification.childNodes.nullOrEmpty»
281                     «writeDataSchemaNodes(notification.childNodes)»
282                 «ENDIF»
283                 «IF !notification.availableAugmentations.nullOrEmpty»
284                     «writeAugments(notification.availableAugmentations)»
285                 «ENDIF»
286                 «IF !notification.groupings.nullOrEmpty»
287                     «writeGroupingDefs(notification.groupings)»
288                 «ENDIF»
289                 «IF !notification.uses.nullOrEmpty»
290                     «writeUsesNodes(notification.uses)»
291                 «ENDIF»
292                 «IF !notification.reference.nullOrEmpty»
293                 reference
294                     "«notification.reference»";
295                 «ENDIF»
296                 «IF notification.status != null»
297                 status «notification.status»;
298                 «ENDIF»
299             }
300         '''
301     }
302
303     def static writeUnknownSchemaNodes(List<UnknownSchemaNode> unknownSchemaNodes) {
304         if (unknownSchemaNodes.nullOrEmpty)
305             return ''
306
307         '''
308             «FOR unknownSchemaNode : unknownSchemaNodes»
309                 «writeUnknownSchemaNode(unknownSchemaNode)»
310             «ENDFOR»
311         '''
312     }
313
314     def static writeUnknownSchemaNode(UnknownSchemaNode unknownSchemaNode) {
315         if (unknownSchemaNode == null)
316             return ''
317
318         '''
319             anyxml «unknownSchemaNode.QName.localName» {
320                 «IF !unknownSchemaNode.description.nullOrEmpty»
321                 description
322                     "«unknownSchemaNode.description»";
323                 «ENDIF»
324                 «IF !unknownSchemaNode.reference.nullOrEmpty»
325                 reference
326                     "«unknownSchemaNode.reference»";
327                 «ENDIF»
328                 «IF unknownSchemaNode.status != null»
329                 status «unknownSchemaNode.status»;
330                 «ENDIF»
331             }
332         '''
333     }
334
335     def static writeUsesNodes(Set<UsesNode> usesNodes) {
336         if (usesNodes == null) {
337             return ''
338         }
339
340         '''
341             «FOR usesNode : usesNodes»
342                 «IF usesNode != null»
343                 «writeUsesNode(usesNode)»
344                 «ENDIF»
345             «ENDFOR»
346         '''
347     }
348
349     def static writeUsesNode(UsesNode usesNode) {
350         val hasRefines = !usesNode.refines.empty
351
352         '''
353             uses «usesNode.groupingPath.pathFromRoot.head.localName»«IF !hasRefines»;«ELSE» {«ENDIF»
354             «IF hasRefines»
355                 «writeRefines(usesNode.refines)»
356             }
357             «ENDIF»
358         '''
359     }
360
361     def static writeRefines(Map<SchemaPath, SchemaNode> refines) {
362         '''
363             «FOR path : refines.keySet»
364             «val schemaNode = refines.get(path)»
365             «writeRefine(path, schemaNode)»
366             «ENDFOR»
367         '''
368     }
369
370     def static writeRefine(SchemaPath path, SchemaNode schemaNode) {
371         '''
372             refine «path.pathFromRoot.last» {
373                 «IF schemaNode instanceof DataSchemaNode»
374                 «writeDataSchemaNode(schemaNode)»
375                 «ENDIF»
376             }
377         '''
378     }
379
380     def static writeTypeDefinitions(Set<TypeDefinition<?>> typeDefinitions) {
381         '''
382             «FOR typeDefinition : typeDefinitions»
383                 «IF typeDefinition != null»
384                 «writeTypeDefinition(typeDefinition)»
385                 «ENDIF»
386             «ENDFOR»
387         '''
388     }
389
390     def static writeTypeDefinition(TypeDefinition<?> typeDefinition) {
391         '''
392             type «typeDefinition.QName.localName»;
393         '''
394     }
395
396     def static writeIdentities(Set<IdentitySchemaNode> identities) {
397         if (identities.nullOrEmpty)
398             return ''
399         '''
400             «FOR identity : identities»
401                 «writeIdentity(identity)»
402             «ENDFOR»
403         '''
404     }
405
406     def static writeIdentity(IdentitySchemaNode identity) {
407         if (identity == null)
408             return ''
409         '''
410             identity «identity.QName.localName» {
411                 «IF identity.baseIdentity != null»
412                 base "(«writeIdentityNs(identity.baseIdentity)»)«identity.baseIdentity»";
413                 «ENDIF»
414                 «IF !identity.description.nullOrEmpty»
415                 description
416                     "«identity.description»";
417                 «ENDIF»
418                 «IF !identity.reference.nullOrEmpty»
419                 reference
420                     "«identity.reference»";
421                 «ENDIF»
422                 «IF identity.status != null»
423                 status «identity.status»;
424                 «ENDIF»
425             }
426         '''
427     }
428
429     def static writeIdentityNs(IdentitySchemaNode identity) {
430         if(module == null)
431             return ''
432
433         val identityNs = identity.QName.namespace
434
435         if(!module.namespace.equals(identityNs))
436             return identityNs + ":"
437         return ''
438     }
439
440     def static writeFeatures(Set<FeatureDefinition> features) {
441         '''
442             «FOR feature : features»
443                 «IF feature != null»
444                 «writeFeature(feature)»
445                 «ENDIF»
446             «ENDFOR»
447         '''
448     }
449
450     def static writeFeature(FeatureDefinition featureDef) {
451         '''
452             feature «featureDef.QName.localName» {
453                 «IF !featureDef.description.nullOrEmpty»
454                 description
455                     "«featureDef.description»";
456                 «ENDIF»
457                 «IF !featureDef.reference.nullOrEmpty»
458                 reference
459                     "«featureDef.reference»";
460                 «ENDIF»
461                 «IF featureDef.status != null»
462                 status «featureDef.status»;
463                 «ENDIF»
464             }
465         '''
466     }
467
468     def static writeExtensions(List<ExtensionDefinition> extensions) {
469         '''
470             «FOR anExtension : extensions»
471                 «IF anExtension != null»
472                 «writeExtension(anExtension)»
473                 «ENDIF»
474             «ENDFOR»
475         '''
476     }
477
478     def static writeExtension(ExtensionDefinition extensionDef) {
479         '''
480             extension «extensionDef.QName.localName» {
481                 «IF !extensionDef.description.nullOrEmpty»
482                 description
483                     "«extensionDef.description»";
484                 «ENDIF»
485                 «IF !extensionDef.argument.nullOrEmpty»
486                 argument "«extensionDef.argument»";
487                 «ENDIF»
488                 «IF !extensionDef.reference.nullOrEmpty»
489                 reference
490                     "«extensionDef.reference»";
491                 «ENDIF»
492                 «IF extensionDef.status != null»
493                 status «extensionDef.status»;
494                 «ENDIF»
495             }
496         '''
497     }
498
499     def static writeDeviations(Set<Deviation> deviations) {
500         '''
501             «FOR deviation : deviations»
502                 «IF deviation != null»
503                 «writeDeviation(deviation)»
504                 «ENDIF»
505             «ENDFOR»
506         '''
507     }
508
509     def static writeDeviation(Deviation deviation) {
510         '''
511             deviation «deviation.targetPath» {
512                 «IF !deviation.reference.nullOrEmpty»
513                     reference
514                         "«deviation.reference»";
515                 «ENDIF»
516                 «IF deviation.deviate != null && !deviation.deviate.name.nullOrEmpty»
517                     deviation «deviation.deviate.name»;
518                 «ENDIF»
519             }
520         '''
521     }
522
523     def static writeAugments(Set<AugmentationSchema> augments) {
524         '''
525             «FOR augment : augments»
526                 «IF augment != null»
527                 «writeAugment(augment)»
528                 «ENDIF»
529             «ENDFOR»
530         '''
531     }
532
533     def static writeDataSchemaNodes(Collection<DataSchemaNode> dataSchemaNodes) {
534         '''
535             «FOR schemaNode : dataSchemaNodes»
536                 «writeDataSchemaNode(schemaNode)»
537             «ENDFOR»
538         '''
539     }
540
541     def static CharSequence writeGroupingDefs(Set<GroupingDefinition> groupingDefs) {
542         '''
543             «FOR groupingDef : groupingDefs»
544                 «IF groupingDef != null»
545                 «writeGroupingDef(groupingDef)»
546                 «ENDIF»
547             «ENDFOR»
548         '''
549     }
550
551     def static writeAugment(AugmentationSchema augment) {
552         '''
553             augment «formatToAugmentPath(augment.targetPath.pathFromRoot)» {
554                 «IF augment.whenCondition != null && !augment.whenCondition.toString.nullOrEmpty»
555                 when "«augment.whenCondition.toString»";
556                 «ENDIF»
557                 «IF !augment.description.nullOrEmpty»
558                 description
559                     "«augment.description»";
560                 «ENDIF»
561                 «IF !augment.reference.nullOrEmpty»
562                 reference
563                     "«augment.reference»";
564                 «ENDIF»
565                 «IF augment.status != null»
566                 status «augment.status»;
567                 «ENDIF»
568                 «IF !augment.childNodes.nullOrEmpty»
569                 «writeDataSchemaNodes(augment.childNodes)»
570                 «ENDIF»
571                 «IF !augment.uses.nullOrEmpty»
572                 «writeUsesNodes(augment.uses)»
573                 «ENDIF»
574             }
575         '''
576     }
577
578     def static writeGroupingDef(GroupingDefinition groupingDef) {
579         '''
580             grouping «groupingDef.QName.localName» {
581                 «IF !groupingDef.groupings.nullOrEmpty»
582                     «writeGroupingDefs(groupingDef.groupings)»
583                 «ENDIF»
584                 «IF !groupingDef.childNodes.nullOrEmpty»
585                     «writeDataSchemaNodes(groupingDef.childNodes)»
586                 «ENDIF»
587                 «IF !groupingDef.unknownSchemaNodes.nullOrEmpty»
588                     «writeUnknownSchemaNodes(groupingDef.unknownSchemaNodes)»
589                 «ENDIF»
590             }
591         '''
592     }
593
594     def static writeContSchemaNode(ContainerSchemaNode contSchemaNode) {
595         '''
596             container «contSchemaNode.getQName.localName» {
597                 «IF !contSchemaNode.childNodes.nullOrEmpty»
598                 «writeDataSchemaNodes(contSchemaNode.childNodes)»
599                 «ENDIF»
600                 «IF !contSchemaNode.availableAugmentations.nullOrEmpty»
601                 «writeAugments(contSchemaNode.availableAugmentations)»
602                 «ENDIF»
603                 «IF !contSchemaNode.groupings.nullOrEmpty»
604                 «writeGroupingDefs(contSchemaNode.groupings)»
605                 «ENDIF»
606                 «IF !contSchemaNode.uses.nullOrEmpty»
607                 «writeUsesNodes(contSchemaNode.uses)»
608                 «ENDIF»
609                 «IF !contSchemaNode.unknownSchemaNodes.nullOrEmpty»
610                 «writeUnknownSchemaNodes(contSchemaNode.unknownSchemaNodes)»
611                 «ENDIF»
612             }
613         '''
614     }
615
616     def static writeAnyXmlSchemaNode(AnyXmlSchemaNode anyXmlSchemaNode) {
617         '''
618             anyxml «anyXmlSchemaNode.getQName.localName»;
619         '''
620     }
621
622     def static writeLeafSchemaNode(LeafSchemaNode leafSchemaNode) {
623         '''
624             leaf «leafSchemaNode.getQName.localName» {
625                 type «leafSchemaNode.type.getQName.localName»;
626             }
627         '''
628     }
629
630     def static writeLeafListSchemaNode(LeafListSchemaNode leafListSchemaNode) {
631         '''
632             leaf-list «leafListSchemaNode.getQName.localName» {
633                 type «leafListSchemaNode.type.getQName.localName»;
634             }
635         '''
636     }
637
638     def static writeChoiceCaseNode(ChoiceCaseNode choiceCaseNode) {
639         '''
640             case «choiceCaseNode.getQName.localName» {
641                 «FOR childNode : choiceCaseNode.childNodes»
642                     «writeDataSchemaNode(childNode)»
643                 «ENDFOR»
644             }
645         '''
646     }
647
648     def static writeChoiceNode(ChoiceSchemaNode choiceNode) {
649         '''
650             choice «choiceNode.getQName.localName» {
651                 «FOR child : choiceNode.cases»
652                     «writeDataSchemaNode(child)»
653                 «ENDFOR»
654             }
655         '''
656     }
657
658     def static writeListSchemaNode(ListSchemaNode listSchemaNode) {
659         '''
660             list «listSchemaNode.getQName.localName» {
661                 key «FOR listKey : listSchemaNode.keyDefinition SEPARATOR " "»"«listKey.localName»"
662                 «ENDFOR»
663                 «IF !listSchemaNode.childNodes.nullOrEmpty»
664                     «writeDataSchemaNodes(listSchemaNode.childNodes)»
665                 «ENDIF»
666                 «IF !listSchemaNode.availableAugmentations.nullOrEmpty»
667                     «writeAugments(listSchemaNode.availableAugmentations)»
668                 «ENDIF»
669                 «IF !listSchemaNode.groupings.nullOrEmpty»
670                     «writeGroupingDefs(listSchemaNode.groupings)»
671                 «ENDIF»
672                 «IF !listSchemaNode.uses.nullOrEmpty»
673                     «writeUsesNodes(listSchemaNode.uses)»
674                 «ENDIF»
675                 «IF !listSchemaNode.unknownSchemaNodes.nullOrEmpty»
676                     «writeUnknownSchemaNodes(listSchemaNode.unknownSchemaNodes)»
677                 «ENDIF»
678             }
679         '''
680     }
681
682     def static CharSequence writeDataSchemaNode(DataSchemaNode child) {
683         '''
684             «IF child instanceof ContainerSchemaNode»
685                 «writeContSchemaNode(child)»
686             «ENDIF»
687             «IF child instanceof AnyXmlSchemaNode»
688                 «writeAnyXmlSchemaNode(child)»
689             «ENDIF»
690             «IF child instanceof LeafSchemaNode»
691                 «writeLeafSchemaNode(child)»
692             «ENDIF»
693             «IF child instanceof LeafListSchemaNode»
694                 «writeLeafListSchemaNode(child)»
695             «ENDIF»
696             «IF child instanceof ChoiceCaseNode»
697                 «writeChoiceCaseNode(child)»
698             «ENDIF»
699             «IF child instanceof ChoiceSchemaNode»
700                 «writeChoiceNode(child)»
701             «ENDIF»
702             «IF child instanceof ListSchemaNode»
703                 «writeListSchemaNode(child)»
704             «ENDIF»
705         '''
706     }
707     
708     static def String formatSchemaPath(String moduleName, Iterable<QName> schemaPath) {
709         var currentElement = schemaPath.head
710         val StringBuilder sb = new StringBuilder()
711         sb.append(moduleName)
712
713         for(pathElement : schemaPath) {
714             if(!currentElement.namespace.equals(pathElement.namespace)) {
715                 currentElement = pathElement
716                 sb.append('/')
717                 sb.append(pathElement)
718             }
719             else {
720                 sb.append('/')
721                 sb.append(pathElement.localName)
722             }
723         }
724         return sb.toString
725     }
726
727     static def String formatToParagraph(String text, int nextLineIndent) {
728         if (text == null || text.isEmpty())
729             return '';
730
731         var String formattedText = text;
732         val StringBuilder sb = new StringBuilder();
733         val StringBuilder lineBuilder = new StringBuilder();
734         var boolean isFirstElementOnNewLineEmptyChar = false;
735         val lineIndent = computeNextLineIndent(nextLineIndent);
736
737         formattedText = formattedText.replace("*/", "&#42;&#47;");
738         formattedText = NEWLINE_OR_TAB.removeFrom(formattedText);
739         formattedText = formattedText.replaceAll(" +", " ");
740
741         val StringTokenizer tokenizer = new StringTokenizer(formattedText, " ", true);
742
743         while (tokenizer.hasMoreElements()) {
744             val String nextElement = tokenizer.nextElement().toString();
745
746             if (lineBuilder.length() + nextElement.length() > 80) {
747                 if (lineBuilder.charAt(lineBuilder.length() - 1) == ' ') {
748                     lineBuilder.setLength(0);
749                     lineBuilder.append(lineBuilder.substring(0, lineBuilder.length() - 1));
750                 }
751                 if (lineBuilder.charAt(0) == ' ') {
752                     lineBuilder.setLength(0);
753                     lineBuilder.append(lineBuilder.substring(1));
754                 }
755
756                 sb.append(lineBuilder);
757                 lineBuilder.setLength(0);
758                 sb.append("\n");
759
760                 if (nextLineIndent > 0) {
761                     sb.append(lineIndent)
762                 }
763
764                 if (nextElement.toString().equals(" "))
765                     isFirstElementOnNewLineEmptyChar = !isFirstElementOnNewLineEmptyChar;
766             }
767             if (isFirstElementOnNewLineEmptyChar) {
768                 isFirstElementOnNewLineEmptyChar = !isFirstElementOnNewLineEmptyChar;
769             } else {
770                 lineBuilder.append(nextElement);
771             }
772         }
773         sb.append(lineBuilder);
774         sb.append("\n");
775
776         return sb.toString();
777     }
778
779     def private static formatToAugmentPath(Iterable<QName> schemaPath) {
780         val StringBuilder sb = new StringBuilder();
781
782         for(pathElement : schemaPath) {
783             val ns = pathElement.namespace
784             val localName = pathElement.localName
785
786             sb.append("\\(")
787             sb.append(ns)
788             sb.append(')')
789             sb.append(localName)
790         }
791         return sb.toString
792     }
793
794     private static def computeNextLineIndent(int nextLineIndent) {
795         val StringBuilder sb = new StringBuilder()
796         var i = 0
797         while (i < nextLineIndent) {
798             sb.append(' ')
799             i = i + 1
800         }
801         return sb.toString
802     }
803 }