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.sal.binding.generator.impl
10 import java.text.SimpleDateFormat
11 import java.util.Collection
16 import java.util.StringTokenizer
17 import org.opendaylight.yangtools.yang.common.QName
18 import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode
19 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema
20 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode
21 import org.opendaylight.yangtools.yang.model.api.ChoiceNode
22 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
23 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
24 import org.opendaylight.yangtools.yang.model.api.Deviation
25 import org.opendaylight.yangtools.yang.model.api.ExtensionDefinition
26 import org.opendaylight.yangtools.yang.model.api.FeatureDefinition
27 import org.opendaylight.yangtools.yang.model.api.GroupingDefinition
28 import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode
29 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
30 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
31 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
32 import org.opendaylight.yangtools.yang.model.api.Module
33 import org.opendaylight.yangtools.yang.model.api.ModuleImport
34 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition
35 import org.opendaylight.yangtools.yang.model.api.RpcDefinition
36 import org.opendaylight.yangtools.yang.model.api.SchemaNode
37 import org.opendaylight.yangtools.yang.model.api.SchemaPath
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
46 private static var Module module = null
48 def static String generateYangSnipet(SchemaNode schemaNode) {
49 if (schemaNode == null)
53 «IF schemaNode instanceof DataSchemaNode»
54 «writeDataSchemaNode(schemaNode as DataSchemaNode)»
56 «IF schemaNode instanceof EnumTypeDefinition.EnumPair»
57 «writeEnumPair(schemaNode as EnumTypeDefinition.EnumPair)»
59 «IF schemaNode instanceof ExtensionDefinition»
60 «writeExtension(schemaNode as ExtensionDefinition)»
62 «IF schemaNode instanceof FeatureDefinition»
63 «writeFeature(schemaNode as FeatureDefinition)»
65 «IF schemaNode instanceof GroupingDefinition»
66 «writeGroupingDef(schemaNode as GroupingDefinition)»
68 «IF schemaNode instanceof IdentitySchemaNode»
69 «writeIdentity(schemaNode as IdentitySchemaNode)»
71 «IF schemaNode instanceof NotificationDefinition»
72 «writeNotification(schemaNode as NotificationDefinition)»
74 «IF schemaNode instanceof RpcDefinition»
75 «writeRPC(schemaNode as RpcDefinition)»
77 «IF schemaNode instanceof TypeDefinition<?>»
78 «writeTypeDefinition(schemaNode as TypeDefinition<?>)»
80 «IF schemaNode instanceof UnknownSchemaNode»
81 «writeUnknownSchemaNode(schemaNode as UnknownSchemaNode)»
86 def static String generateYangSnipet(Set<? extends SchemaNode> nodes) {
87 if (nodes.nullOrEmpty)
92 «IF node instanceof NotificationDefinition»
93 «writeNotification(node as NotificationDefinition)»
94 «ELSEIF node instanceof RpcDefinition»
95 «writeRPC(node as RpcDefinition)»
101 def static writeEnumPair(EnumPair pair) {
102 var boolean hasEnumPairValue = pair.value != null
104 enum «pair.name»«IF !hasEnumPairValue»;«ELSE»{
111 def static String writeModuleImports(Set<ModuleImport> moduleImports) {
112 if (moduleImports.nullOrEmpty)
116 «FOR moduleImport : moduleImports SEPARATOR "\n"»
117 «IF moduleImport != null && !moduleImport.moduleName.nullOrEmpty»
118 import «moduleImport.moduleName» { prefix "«moduleImport.prefix»"; }
124 def static formatDate(Date moduleRevision) {
125 val SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-mm-dd")
126 return dateFormat.format(moduleRevision)
129 def static writeRevision(Date moduleRevision, String moduleDescription) {
130 val revisionIndent = 12
133 revision «formatDate(moduleRevision)» {
134 description "«formatToParagraph(moduleDescription, revisionIndent)»";
139 def static String generateYangSnipet(Module module) {
142 module «module.name» {
143 yang-version «module.yangVersion»;
144 namespace "«module.QNameModule.namespace.toString»";
145 prefix "«module.prefix»";
147 «IF !module.imports.nullOrEmpty»
148 «writeModuleImports(module.imports)»
150 «IF module.revision != null»
151 «writeRevision(module.revision, module.description)»
153 «IF !module.childNodes.nullOrEmpty»
155 «writeDataSchemaNodes(module.childNodes)»
157 «IF !module.groupings.nullOrEmpty»
159 «writeGroupingDefs(module.groupings)»
161 «IF !module.augmentations.nullOrEmpty»
163 «writeAugments(module.augmentations)»
165 «IF !module.deviations.nullOrEmpty»
167 «writeDeviations(module.deviations)»
169 «IF !module.extensionSchemaNodes.nullOrEmpty»
171 «writeExtensions(module.extensionSchemaNodes)»
173 «IF !module.features.nullOrEmpty»
175 «writeFeatures(module.features)»
177 «IF !module.identities.nullOrEmpty»
179 «writeIdentities(module.identities)»
181 «IF !module.notifications.nullOrEmpty»
183 «writeNotifications(module.notifications)»
185 «IF !module.rpcs.nullOrEmpty»
187 «writeRPCs(module.rpcs)»
189 «IF !module.unknownSchemaNodes.nullOrEmpty»
191 «writeUnknownSchemaNodes(module.unknownSchemaNodes)»
193 «IF !module.uses.nullOrEmpty»
195 «writeUsesNodes(module.uses)»
201 def static writeRPCs(Set<RpcDefinition> rpcDefs) {
211 def static writeRPC(RpcDefinition rpc) {
213 rpc «rpc.QName.localName» {
214 «IF !rpc.description.nullOrEmpty»
217 «IF !rpc.groupings.nullOrEmpty»
218 «writeGroupingDefs(rpc.groupings)»
220 «IF rpc.input != null»
221 «writeRpcInput(rpc.input)»
223 «IF rpc.output != null»
224 «writeRpcOutput(rpc.output)»
226 «IF !rpc.reference.nullOrEmpty»
230 «IF rpc.status != null»
237 def static writeRpcInput(ContainerSchemaNode input) {
243 «IF input instanceof DataSchemaNode && !input.childNodes.nullOrEmpty»
244 «writeDataSchemaNodes(input.childNodes)»
251 def static writeRpcOutput(ContainerSchemaNode output) {
257 «IF output instanceof DataSchemaNode && !output.childNodes.nullOrEmpty»
258 «writeDataSchemaNodes(output.childNodes)»
264 def static writeNotifications(Set<NotificationDefinition> notifications) {
266 «FOR notification : notifications»
267 «IF notification != null»
268 «writeNotification(notification)»
274 def static writeNotification(NotificationDefinition notification) {
276 notification «notification.QName.localName» {
277 «IF !notification.description.nullOrEmpty»
279 "«notification.description»";
281 «IF !notification.childNodes.nullOrEmpty»
282 «writeDataSchemaNodes(notification.childNodes)»
284 «IF !notification.availableAugmentations.nullOrEmpty»
285 «writeAugments(notification.availableAugmentations)»
287 «IF !notification.groupings.nullOrEmpty»
288 «writeGroupingDefs(notification.groupings)»
290 «IF !notification.uses.nullOrEmpty»
291 «writeUsesNodes(notification.uses)»
293 «IF !notification.reference.nullOrEmpty»
295 "«notification.reference»";
297 «IF notification.status != null»
298 status «notification.status»;
304 def static writeUnknownSchemaNodes(List<UnknownSchemaNode> unknownSchemaNodes) {
305 if (unknownSchemaNodes.nullOrEmpty)
309 «FOR unknownSchemaNode : unknownSchemaNodes»
310 «writeUnknownSchemaNode(unknownSchemaNode)»
315 def static writeUnknownSchemaNode(UnknownSchemaNode unknownSchemaNode) {
316 if (unknownSchemaNode == null)
320 anyxml «unknownSchemaNode.QName.localName» {
321 «IF !unknownSchemaNode.description.nullOrEmpty»
323 "«unknownSchemaNode.description»";
325 «IF !unknownSchemaNode.reference.nullOrEmpty»
327 "«unknownSchemaNode.reference»";
329 «IF unknownSchemaNode.status != null»
330 status «unknownSchemaNode.status»;
336 def static writeUsesNodes(Set<UsesNode> usesNodes) {
337 if (usesNodes == null) {
342 «FOR usesNode : usesNodes»
343 «IF usesNode != null»
344 «writeUsesNode(usesNode)»
350 def static writeUsesNode(UsesNode usesNode) {
351 val hasRefines = !usesNode.refines.empty
354 uses «usesNode.groupingPath.pathFromRoot.head.localName»«IF !hasRefines»;«ELSE» {«ENDIF»
356 «writeRefines(usesNode.refines)»
362 def static writeRefines(Map<SchemaPath, SchemaNode> refines) {
364 «FOR path : refines.keySet»
365 «val schemaNode = refines.get(path)»
366 «writeRefine(path, schemaNode)»
371 def static writeRefine(SchemaPath path, SchemaNode schemaNode) {
373 refine «path.pathFromRoot.last» {
374 «IF schemaNode instanceof DataSchemaNode»
375 «writeDataSchemaNode(schemaNode as DataSchemaNode)»
381 def static writeTypeDefinitions(Set<TypeDefinition<?>> typeDefinitions) {
383 «FOR typeDefinition : typeDefinitions»
384 «IF typeDefinition != null»
385 «writeTypeDefinition(typeDefinition)»
391 def static writeTypeDefinition(TypeDefinition<?> typeDefinition) {
393 type «typeDefinition.QName.localName»;
397 def static writeIdentities(Set<IdentitySchemaNode> identities) {
398 if (identities.nullOrEmpty)
401 «FOR identity : identities»
402 «writeIdentity(identity)»
407 def static writeIdentity(IdentitySchemaNode identity) {
408 if (identity == null)
411 identity «identity.QName.localName» {
412 «IF identity.baseIdentity != null»
413 base "(«writeIdentityNs(identity.baseIdentity)»)«identity.baseIdentity»";
415 «IF !identity.description.nullOrEmpty»
417 "«identity.description»";
419 «IF !identity.reference.nullOrEmpty»
421 "«identity.reference»";
423 «IF identity.status != null»
424 status «identity.status»;
430 def static writeIdentityNs(IdentitySchemaNode identity) {
434 val identityNs = identity.QName.namespace
436 if(!module.namespace.equals(identityNs))
437 return identityNs + ":"
441 def static writeFeatures(Set<FeatureDefinition> features) {
443 «FOR feature : features»
445 «writeFeature(feature)»
451 def static writeFeature(FeatureDefinition featureDef) {
453 feature «featureDef.QName.localName» {
454 «IF !featureDef.description.nullOrEmpty»
456 "«featureDef.description»";
458 «IF !featureDef.reference.nullOrEmpty»
460 "«featureDef.reference»";
462 «IF featureDef.status != null»
463 status «featureDef.status»;
469 def static writeExtensions(List<ExtensionDefinition> extensions) {
471 «FOR anExtension : extensions»
472 «IF anExtension != null»
473 «writeExtension(anExtension)»
479 def static writeExtension(ExtensionDefinition extensionDef) {
481 extension «extensionDef.QName.localName» {
482 «IF !extensionDef.description.nullOrEmpty»
484 "«extensionDef.description»";
486 «IF !extensionDef.argument.nullOrEmpty»
487 argument "«extensionDef.argument»";
489 «IF !extensionDef.reference.nullOrEmpty»
491 "«extensionDef.reference»";
493 «IF extensionDef.status != null»
494 status «extensionDef.status»;
500 def static writeDeviations(Set<Deviation> deviations) {
502 «FOR deviation : deviations»
503 «IF deviation != null»
504 «writeDeviation(deviation)»
510 def static writeDeviation(Deviation deviation) {
512 deviation «deviation.targetPath» {
513 «IF !deviation.reference.nullOrEmpty»
515 "«deviation.reference»";
517 «IF deviation.deviate != null && !deviation.deviate.name.nullOrEmpty»
518 deviation «deviation.deviate.name»;
524 def static writeAugments(Set<AugmentationSchema> augments) {
526 «FOR augment : augments»
528 «writeAugment(augment)»
534 def static writeDataSchemaNodes(Collection<DataSchemaNode> dataSchemaNodes) {
536 «FOR schemaNode : dataSchemaNodes»
537 «writeDataSchemaNode(schemaNode)»
542 def static CharSequence writeGroupingDefs(Set<GroupingDefinition> groupingDefs) {
544 «FOR groupingDef : groupingDefs»
545 «IF groupingDef != null»
546 «writeGroupingDef(groupingDef)»
552 def static writeAugment(AugmentationSchema augment) {
554 augment «formatToAugmentPath(augment.targetPath.pathFromRoot)» {
555 «IF augment.whenCondition != null && !augment.whenCondition.toString.nullOrEmpty»
556 when "«augment.whenCondition.toString»";
558 «IF !augment.description.nullOrEmpty»
560 "«augment.description»";
562 «IF !augment.reference.nullOrEmpty»
564 "«augment.reference»";
566 «IF augment.status != null»
567 status «augment.status»;
569 «IF !augment.childNodes.nullOrEmpty»
570 «writeDataSchemaNodes(augment.childNodes)»
572 «IF !augment.uses.nullOrEmpty»
573 «writeUsesNodes(augment.uses)»
579 def static writeGroupingDef(GroupingDefinition groupingDef) {
581 grouping «groupingDef.QName.localName» {
582 «IF !groupingDef.groupings.nullOrEmpty»
583 «writeGroupingDefs(groupingDef.groupings)»
585 «IF !groupingDef.childNodes.nullOrEmpty»
586 «writeDataSchemaNodes(groupingDef.childNodes)»
588 «IF !groupingDef.unknownSchemaNodes.nullOrEmpty»
589 «writeUnknownSchemaNodes(groupingDef.unknownSchemaNodes)»
595 def static writeContSchemaNode(ContainerSchemaNode contSchemaNode) {
597 container «contSchemaNode.getQName.localName» {
598 «IF !contSchemaNode.childNodes.nullOrEmpty»
599 «writeDataSchemaNodes(contSchemaNode.childNodes)»
601 «IF !contSchemaNode.availableAugmentations.nullOrEmpty»
602 «writeAugments(contSchemaNode.availableAugmentations)»
604 «IF !contSchemaNode.groupings.nullOrEmpty»
605 «writeGroupingDefs(contSchemaNode.groupings)»
607 «IF !contSchemaNode.uses.nullOrEmpty»
608 «writeUsesNodes(contSchemaNode.uses)»
610 «IF !contSchemaNode.unknownSchemaNodes.nullOrEmpty»
611 «writeUnknownSchemaNodes(contSchemaNode.unknownSchemaNodes)»
617 def static writeAnyXmlSchemaNode(AnyXmlSchemaNode anyXmlSchemaNode) {
619 anyxml «anyXmlSchemaNode.getQName.localName»;
623 def static writeLeafSchemaNode(LeafSchemaNode leafSchemaNode) {
625 leaf «leafSchemaNode.getQName.localName» {
626 type «leafSchemaNode.type.getQName.localName»;
631 def static writeLeafListSchemaNode(LeafListSchemaNode leafListSchemaNode) {
633 leaf-list «leafListSchemaNode.getQName.localName» {
634 type «leafListSchemaNode.type.getQName.localName»;
639 def static writeChoiceCaseNode(ChoiceCaseNode choiceCaseNode) {
641 case «choiceCaseNode.getQName.localName» {
642 «FOR childNode : choiceCaseNode.childNodes»
643 «writeDataSchemaNode(childNode)»
649 def static writeChoiceNode(ChoiceNode choiceNode) {
651 choice «choiceNode.getQName.localName» {
652 «FOR child : choiceNode.cases»
653 «writeDataSchemaNode(child)»
659 def static writeListSchemaNode(ListSchemaNode listSchemaNode) {
661 list «listSchemaNode.getQName.localName» {
662 key «FOR listKey : listSchemaNode.keyDefinition SEPARATOR " "»"«listKey.localName»"
664 «IF !listSchemaNode.childNodes.nullOrEmpty»
665 «writeDataSchemaNodes(listSchemaNode.childNodes)»
667 «IF !listSchemaNode.availableAugmentations.nullOrEmpty»
668 «writeAugments(listSchemaNode.availableAugmentations)»
670 «IF !listSchemaNode.groupings.nullOrEmpty»
671 «writeGroupingDefs(listSchemaNode.groupings)»
673 «IF !listSchemaNode.uses.nullOrEmpty»
674 «writeUsesNodes(listSchemaNode.uses)»
676 «IF !listSchemaNode.unknownSchemaNodes.nullOrEmpty»
677 «writeUnknownSchemaNodes(listSchemaNode.unknownSchemaNodes)»
683 def static CharSequence writeDataSchemaNode(DataSchemaNode child) {
685 «IF child instanceof ContainerSchemaNode»
686 «writeContSchemaNode(child as ContainerSchemaNode)»
688 «IF child instanceof AnyXmlSchemaNode»
689 «writeAnyXmlSchemaNode(child as AnyXmlSchemaNode)»
691 «IF child instanceof LeafSchemaNode»
692 «writeLeafSchemaNode(child as LeafSchemaNode)»
694 «IF child instanceof LeafListSchemaNode»
695 «writeLeafListSchemaNode(child as LeafListSchemaNode)»
697 «IF child instanceof ChoiceCaseNode»
698 «writeChoiceCaseNode(child as ChoiceCaseNode)»
700 «IF child instanceof ChoiceNode»
701 «writeChoiceNode(child as ChoiceNode)»
703 «IF child instanceof ListSchemaNode»
704 «writeListSchemaNode(child as ListSchemaNode)»
709 static def String formatSchemaPath(String moduleName, Iterable<QName> schemaPath) {
710 var currentElement = schemaPath.head
711 val StringBuilder sb = new StringBuilder()
712 sb.append(moduleName)
714 for(pathElement : schemaPath) {
715 if(!currentElement.namespace.equals(pathElement.namespace)) {
716 currentElement = pathElement
718 sb.append(pathElement)
722 sb.append(pathElement.localName)
728 static def String formatToParagraph(String text, int nextLineIndent) {
729 if (text == null || text.isEmpty())
732 var String formattedText = text;
733 val StringBuilder sb = new StringBuilder();
734 val StringBuilder lineBuilder = new StringBuilder();
735 var boolean isFirstElementOnNewLineEmptyChar = false;
736 val lineIndent = computeNextLineIndent(nextLineIndent);
738 formattedText = formattedText.replace("*/", "*/");
739 formattedText = formattedText.replace("\n", "");
740 formattedText = formattedText.replace("\t", "");
741 formattedText = formattedText.replaceAll(" +", " ");
743 val StringTokenizer tokenizer = new StringTokenizer(formattedText, " ", true);
745 while (tokenizer.hasMoreElements()) {
746 val String nextElement = tokenizer.nextElement().toString();
748 if (lineBuilder.length() + nextElement.length() > 80) {
749 if (lineBuilder.charAt(lineBuilder.length() - 1) == ' ') {
750 lineBuilder.setLength(0);
751 lineBuilder.append(lineBuilder.substring(0, lineBuilder.length() - 1));
753 if (lineBuilder.charAt(0) == ' ') {
754 lineBuilder.setLength(0);
755 lineBuilder.append(lineBuilder.substring(1));
758 sb.append(lineBuilder);
759 lineBuilder.setLength(0);
762 if (nextLineIndent > 0) {
763 sb.append(lineIndent)
766 if (nextElement.toString().equals(" "))
767 isFirstElementOnNewLineEmptyChar = !isFirstElementOnNewLineEmptyChar;
769 if (isFirstElementOnNewLineEmptyChar) {
770 isFirstElementOnNewLineEmptyChar = !isFirstElementOnNewLineEmptyChar;
772 lineBuilder.append(nextElement);
775 sb.append(lineBuilder);
778 return sb.toString();
781 def private static formatToAugmentPath(Iterable<QName> schemaPath) {
782 val StringBuilder sb = new StringBuilder();
784 for(pathElement : schemaPath) {
785 val ns = pathElement.namespace
786 val localName = pathElement.localName
797 private static def computeNextLineIndent(int nextLineIndent) {
798 val StringBuilder sb = new StringBuilder()
800 while (i < nextLineIndent) {