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