-package org.opendaylight.yangtools.yang.unified.doc.generator
-
-import org.opendaylight.yangtools.yang.model.api.SchemaContext
-import java.io.File
-import java.util.Set
-import org.opendaylight.yangtools.yang.model.api.Module
-import java.io.IOException
-import java.util.HashSet
-import java.io.FileWriter
-import java.io.BufferedWriter
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
-import org.opendaylight.yangtools.yang.model.api.TypeDefinition
-import org.opendaylight.yangtools.yang.model.api.SchemaNode
-import org.opendaylight.yangtools.yang.model.util.ExtendedType
-import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition
-import java.text.SimpleDateFormat
-import java.util.Collection
-import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint
-import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition
-import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition
-import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint
-import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition
-import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition
-import org.opendaylight.yangtools.yang.model.api.NotificationDefinition
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
-import org.slf4j.LoggerFactory
-import org.slf4j.Logger
-import org.opendaylight.yangtools.yang.model.api.AugmentationSchema
-import java.util.List
-import org.opendaylight.yangtools.yang.common.QName
-import org.opendaylight.yangtools.yang.model.api.RpcDefinition
-import org.opendaylight.yangtools.yang.model.api.ExtensionDefinition
-import java.util.ArrayList
-import java.util.Map
-import org.opendaylight.yangtools.yang.model.api.SchemaPath
-import java.util.LinkedHashMap
-import org.opendaylight.yangtools.yang.model.api.ChoiceNode
-import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode
-
-class GeneratorImpl {
-
- File path
- static val REVISION_FORMAT = new SimpleDateFormat("yyyy-MM-dd")
- static val Logger LOG = LoggerFactory.getLogger(GeneratorImpl)
-
-
- def generate(SchemaContext context, File targetPath, Set<Module> modulesToGen) throws IOException {
- path = targetPath;
- path.mkdirs();
- val it = new HashSet;
- for (module : modulesToGen) {
- add(module.generateDocumentation());
- }
- return it;
- }
-
- def generateDocumentation(Module module) {
- val destination = new File(path, '''«module.name».html''')
- try {
- val fw = new FileWriter(destination)
- destination.createNewFile();
- val bw = new BufferedWriter(fw)
-
- bw.append(module.generate);
- bw.close();
- fw.close();
- } catch (IOException e) {
- LOG.error(e.getMessage());
- }
- return destination;
- }
-
- def generate(Module module) '''
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <title>«module.name»</title>
- </head>
- <body>
- «module.body»
- </body>
- </html>
- '''
-
- def body(Module module) '''
- «header(module)»
-
- «typeDefinitions(module)»
-
- «identities(module)»
-
- «groupings(module)»
-
- «childNodes(module)»
-
- «dataStore(module)»
-
- «notifications(module)»
-
- «augmentations(module)»
-
- «rpcs(module)»
-
- «extensions(module)»
-
- «features(module)»
-
- '''
-
-
- def typeDefinitions(Module module) {
- val Set<TypeDefinition<?>> typedefs = module.typeDefinitions
- if (typedefs.empty) {
- return '';
- }
- return '''
- <h2>Type Definitions</h2>
- <ul>
- «FOR typedef : typedefs»
- <li>
- «strong("typedef " + typedef.QName.localName)»
- <ul>
- «typedef.descAndRef»
- «typedef.restrictions»
- </ul>
- </li>
- «ENDFOR»
- </ul>
- '''
- }
-
- private def identities(Module module) {
- if (module.identities.empty) {
- return '';
- }
- return '''
- <h2>Identities</h2>
- <ul>
- «FOR identity : module.identities»
- <li>
- «strong("identity " + identity.QName.localName)»
- <ul>
- «identity.descAndRef»
- «IF identity.baseIdentity != null»
- «listItem("base", identity.baseIdentity.QName.localName)»
- «ENDIF»
- </ul>
- </li>
- «ENDFOR»
- </ul>
- '''
- }
-
- private def groupings(Module module) {
- if (module.groupings.empty) {
- return '';
- }
- return '''
- <h2>Groupings</h2>
- <ul>
- «FOR grouping : module.groupings»
- <li>
- «strong("grouping " + grouping.QName.localName)»
- <ul>
- «grouping.descAndRef»
- </ul>
- </li>
- «ENDFOR»
- </ul>
- '''
- }
-
- def dataStore(Module module) {
- if (module.childNodes.empty) {
- return '';
- }
- return '''
- <h2>Datastore Structure</h2>
- «tree(module)»
- '''
- }
-
- def augmentations(Module module) {
- if (module.augmentations.empty) {
- return '';
- }
- return '''
- <h2>Augmentations</h2>
-
- <ul>
- «FOR augment : module.augmentations»
- <li>
- augment
- «augment.tree»
- </li>
- «ENDFOR»
- </ul>
- '''
- }
-
- def notifications(Module module) {
- val Set<NotificationDefinition> notificationdefs = module.notifications
- if (notificationdefs.empty) {
- return '';
- }
- return '''
- <h2>Notifications</h2>
-
- <ul>
- «FOR notificationdef : notificationdefs»
- <li>
- «notificationdef.nodeName»
- «notificationdef.tree»
- </li>
- «ENDFOR»
- </ul>
- '''
- }
-
- def rpcs(Module module) {
- if (module.rpcs.empty) {
- return '';
- }
- return '''
- <h2>RPC Definitions</h2>
-
- <ul>
- «FOR rpc : module.rpcs»
- <li>
- «rpc.nodeName»
- «rpc.tree»
- </li>
- «ENDFOR»
- </ul>
- '''
- }
-
- def extensions(Module module) {
- if (module.extensionSchemaNodes.empty) {
- return '';
- }
- return '''
- <h2>Extensions</h2>
-
- <ul>
- «FOR ext : module.extensionSchemaNodes»
- <li>
- «ext.nodeName»
- «ext.tree»
- </li>
- «ENDFOR»
- </ul>
- '''
- }
-
- def features(Module module) {
- if (module.features.empty) {
- return '';
- }
- return '''
- <h2>Features</h2>
-
- <ul>
- «FOR feature : module.features»
- <li>
- «strong("feature " + feature.QName.localName)»
- <ul>
- «feature.descAndRef»
- </ul>
- </li>
- «ENDFOR»
- </ul>
- '''
- }
-
- def header(Module module) '''
- <h1>«module.name»</h1>
-
- <h2>Base Information</h2>
- <dl>
- <dt>Prefix</dt>
- <dd>«pre(module.prefix)»</dd>
- <dt>Namespace</dt>
- <dd>«pre(module.namespace.toString)»</dd>
- <dt>Revision</dt>
- <dd>«pre(REVISION_FORMAT.format(module.revision))»</dd>
-
- «FOR imp : module.imports BEFORE "<dt>Imports</dt>" »
- <dd>«pre(imp.prefix)» = «pre(imp.moduleName)»</dd>
- «ENDFOR»
- </dl>
- '''
-
- def process(Module module) {
- throw new UnsupportedOperationException("TODO: auto-generated method stub")
- }
-
-
-
- /* #################### TREE STRUCTURE #################### */
- def dispatch CharSequence tree(Module module) '''
- «strong("module " + module.name)»
- «module.childNodes.tree»
- '''
-
- def dispatch CharSequence tree(DataNodeContainer node) '''
- «IF node instanceof SchemaNode»
- «(node as SchemaNode).nodeName»
- «ENDIF»
- «node.childNodes.tree»
- '''
-
- def dispatch CharSequence tree(DataSchemaNode node) '''
- «node.nodeName»
- '''
-
- def dispatch CharSequence tree(ListSchemaNode node) '''
- «node.nodeName»
- «node.childNodes.tree»
- '''
-
- def CharSequence childNodes(Module module) '''
- «val Map<SchemaPath, DataSchemaNode> childNodes = new LinkedHashMap()»
- «collectChildNodes(module.childNodes, childNodes)»
- «IF childNodes !== null && !childNodes.empty»
- <h2>Child nodes</h2>
-
- «childNodes.childNodesInfoTree»
- «ENDIF»
- '''
-
- def CharSequence childNodesInfoTree(Map<SchemaPath, DataSchemaNode> childNodes) '''
- «IF childNodes !== null && !childNodes.empty»
- <ul>
- «FOR child : childNodes.values»
- «childInfo(child, childNodes)»
- «ENDFOR»
- </ul>
- «ENDIF»
- '''
-
- def CharSequence childInfo(DataSchemaNode node, Map<SchemaPath, DataSchemaNode> childNodes) '''
- «val String path = nodeSchemaPathToPath(node, childNodes)»
- «IF path != null»
- «listItem(strong(path))»
- «IF node !== null»
- <ul>
- «node.descAndRef»
- </ul>
- «ENDIF»
- «ENDIF»
- '''
-
- def dispatch CharSequence tree(Collection<DataSchemaNode> childNodes) '''
- «IF childNodes !== null && !childNodes.empty»
- <ul>
- «FOR child : childNodes»
- <li>
- «child.tree»
- </li>
- «ENDFOR»
- </ul>
- «ENDIF»
- '''
-
- def listKeys(ListSchemaNode node) '''
- [«FOR key : node.keyDefinition SEPARATOR " "»«key.localName»«ENDFOR»]
- '''
-
- def dispatch CharSequence tree(AugmentationSchema augment) '''
- <ul>
- «listItem(augment.description)»
- «listItem("Reference", augment.reference)»
- «IF augment.whenCondition !== null»
- «listItem("When", augment.whenCondition.toString)»
- «ENDIF»
- <li>
- Path «augment.targetPath.path.pathToTree»
- </li>
- <li>
- Child nodes
- «augment.childNodes.tree»
- </li>
- </ul>
- '''
-
- def dispatch CharSequence tree(NotificationDefinition notification) '''
- <ul>
- «notification.descAndRef»
- <li>
- Child nodes
- «notification.childNodes.tree»
- </li>
- </ul>
- '''
-
- def dispatch CharSequence tree(RpcDefinition rpc) '''
- <ul>
- «rpc.descAndRef»
- <li>
- «rpc.input.tree»
- </li>
- <li>
- «rpc.output.tree»
- </li>
- </ul>
- '''
-
- def dispatch CharSequence tree(ExtensionDefinition ext) '''
- <ul>
- «ext.descAndRef»
- «listItem("Argument", ext.argument)»
- </ul>
- '''
-
- def dispatch CharSequence tree(Void obj) '''
- '''
-
-
-
- /* #################### RESTRICTIONS #################### */
- private def restrictions(TypeDefinition<?> type) '''
- «type.toLength»
- «type.toRange»
- '''
-
- def dispatch toLength(TypeDefinition<?> type) {
- }
-
- def dispatch toLength(BinaryTypeDefinition type) '''
- «type.lengthConstraints.toLengthStmt»
- '''
-
- def dispatch toLength(StringTypeDefinition type) '''
- «type.lengthConstraints.toLengthStmt»
- '''
-
- def dispatch toLength(ExtendedType type) '''
- «type.lengthConstraints.toLengthStmt»
- '''
-
- def dispatch toRange(TypeDefinition<?> type) {
- }
-
- def dispatch toRange(DecimalTypeDefinition type) '''
- «type.rangeConstraints.toRangeStmt»
- '''
-
- def dispatch toRange(IntegerTypeDefinition type) '''
- «type.rangeConstraints.toRangeStmt»
- '''
-
- def dispatch toRange(UnsignedIntegerTypeDefinition type) '''
- «type.rangeConstraints.toRangeStmt»
- '''
-
- def dispatch toRange(ExtendedType type) '''
- «type.rangeConstraints.toRangeStmt»
- '''
-
- def toLengthStmt(Collection<LengthConstraint> lengths) '''
- «IF lengths != null && !lengths.empty»
- «listItem("Length restrictions")»
- <ul>
- «FOR length : lengths»
- <li>
- «IF length.min == length.max»
- «length.min»
- «ELSE»
- <«length.min», «length.max»>
- «ENDIF»
- </li>
- «ENDFOR»
- </ul>
- «ENDIF»
- '''
-
- def toRangeStmt(Collection<RangeConstraint> ranges) '''
- «IF ranges != null && !ranges.empty»
- «listItem("Range restrictions")»
- <ul>
- «FOR range : ranges»
- <li>
- «IF range.min == range.max»
- «range.min»
- «ELSE»
- <«range.min», «range.max»>
- «ENDIF»
- </li>
- «ENDFOR»
- </ul>
- «ENDIF»
- '''
-
-
-
- /* #################### UTILITY #################### */
- private def String strong(String str) '''<strong>«str»</strong>'''
- private def italic(String str) '''<i>«str»</i>'''
- private def pre(String str) '''<pre>«str»</pre>'''
-
- def CharSequence descAndRef(SchemaNode node) '''
- «listItem(node.description)»
- «listItem("Reference", node.reference)»
- '''
-
- private def listItem(String value) '''
- «IF value !== null && !value.empty»
- <li>
- «value»
- </li>
- «ENDIF»
- '''
-
- private def listItem(String name, String value) '''
- «IF value !== null && !value.empty»
- <li>
- «name»
- <ul>
- <li>
- «value»
- </li>
- </ul>
- </li>
- «ENDIF»
- '''
-
- private def String nodeSchemaPathToPath(DataSchemaNode node, Map<SchemaPath, DataSchemaNode> childNodes) {
- if (node instanceof ChoiceNode || node instanceof ChoiceCaseNode) {
- return null
- }
-
- val path = node.path.path
- val absolute = node.path.absolute;
- var StringBuilder result = new StringBuilder
- if (absolute) {
- result.append("/")
- }
- if (path !== null && !path.empty) {
- val List<QName> actual = new ArrayList()
- var i = 0;
- for (pathElement : path) {
- actual.add(pathElement)
- val DataSchemaNode nodeByPath = childNodes.get(new SchemaPath(actual, absolute))
- if (!(nodeByPath instanceof ChoiceNode) && !(nodeByPath instanceof ChoiceCaseNode)) {
- result.append(pathElement.localName)
- if (i != path.size - 1) {
- result.append("/")
- }
- }
- i = i + 1
- }
- }
- return result.toString
- }
-
- private def void collectChildNodes(Collection<DataSchemaNode> source, Map<SchemaPath, DataSchemaNode> destination) {
- for (node : source) {
- destination.put(node.path, node)
- if (node instanceof DataNodeContainer) {
- collectChildNodes((node as DataNodeContainer).childNodes, destination)
- }
- if (node instanceof ChoiceNode) {
- val List<DataSchemaNode> choiceCases = new ArrayList()
- for (caseNode : (node as ChoiceNode).cases) {
- choiceCases.add(caseNode)
- }
- collectChildNodes(choiceCases, destination)
- }
- }
- }
-
- private def CharSequence pathToTree(List<QName> path) '''
- «IF path !== null && !path.empty»
- <ul>
- «FOR pathElement : path»
- <li>
- «pathElement.namespace» «pathElement.localName»
- </li>
- «ENDFOR»
- </ul>
- «ENDIF»
- '''
-
- def dispatch addedByInfo(SchemaNode node) '''
- '''
-
- def dispatch addedByInfo(DataSchemaNode node) '''
- «IF node.augmenting»(A)«ENDIF»«IF node.addedByUses»(U)«ENDIF»
- '''
-
- def dispatch isAddedBy(SchemaNode node) {
- return false;
- }
-
- def dispatch isAddedBy(DataSchemaNode node) {
- if (node.augmenting || node.addedByUses) {
- return true
- } else {
- return false;
- }
- }
-
- def dispatch nodeName(SchemaNode node) '''
- «IF node.isAddedBy»
- «italic(node.QName.localName)»«node.addedByInfo»
- «ELSE»
- «strong(node.QName.localName)»«node.addedByInfo»
- «ENDIF»
- '''
-
- def dispatch nodeName(ListSchemaNode node) '''
- «IF node.isAddedBy»
- «italic(node.QName.localName)» «IF node.keyDefinition !== null && !node.keyDefinition.empty»«node.listKeys»«ENDIF»«node.addedByInfo»
- «ELSE»
- «strong(node.QName.localName)» «IF node.keyDefinition !== null && !node.keyDefinition.empty»«node.listKeys»«ENDIF»
- «ENDIF»
- '''
-
-}
+package org.opendaylight.yangtools.yang.unified.doc.generator\r
+\r
+import org.opendaylight.yangtools.yang.model.api.SchemaContext\r
+import java.io.File\r
+import java.util.Set\r
+import org.opendaylight.yangtools.yang.model.api.Module\r
+import java.io.IOException\r
+import java.util.HashSet\r
+import java.io.FileWriter\r
+import java.io.BufferedWriter\r
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode\r
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode\r
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition\r
+import org.opendaylight.yangtools.yang.model.api.SchemaNode\r
+import org.opendaylight.yangtools.yang.model.util.ExtendedType\r
+import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition\r
+import java.text.SimpleDateFormat\r
+import java.util.Collection\r
+import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint\r
+import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition\r
+import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition\r
+import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint\r
+import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition\r
+import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition\r
+import org.opendaylight.yangtools.yang.model.api.NotificationDefinition\r
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer\r
+import org.slf4j.LoggerFactory\r
+import org.slf4j.Logger\r
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema\r
+import java.util.List\r
+import org.opendaylight.yangtools.yang.common.QName\r
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition\r
+import org.opendaylight.yangtools.yang.model.api.ExtensionDefinition\r
+import java.util.ArrayList\r
+import java.util.Map\r
+import org.opendaylight.yangtools.yang.model.api.SchemaPath\r
+\r
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode\r
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode\r
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode\r
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier\r
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates\r
+import java.util.LinkedHashMap\r
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier\r
+import com.google.common.collect.FluentIterable\r
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode\r
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode\r
+import java.net.URLEncoder\r
+import javax.swing.text.StyledEditorKit.ForegroundAction\r
+\r
+class GeneratorImpl {\r
+\r
+ File path\r
+ static val REVISION_FORMAT = new SimpleDateFormat("yyyy-MM-dd")\r
+ static val Logger LOG = LoggerFactory.getLogger(GeneratorImpl)\r
+ var Module currentModule;\r
+\r
+\r
+ def generate(SchemaContext context, File targetPath, Set<Module> modulesToGen) throws IOException {\r
+ path = targetPath;\r
+ path.mkdirs();\r
+ val it = new HashSet;\r
+ for (module : modulesToGen) {\r
+ add(module.generateDocumentation());\r
+ }\r
+ return it;\r
+ }\r
+\r
+ def generateDocumentation(Module module) {\r
+ val destination = new File(path, '''«module.name».html''')\r
+ try {\r
+ val fw = new FileWriter(destination)\r
+ destination.createNewFile();\r
+ val bw = new BufferedWriter(fw)\r
+ currentModule = module;\r
+ bw.append(module.generate);\r
+ bw.close();\r
+ fw.close();\r
+ } catch (IOException e) {\r
+ LOG.error(e.getMessage());\r
+ }\r
+ return destination;\r
+ }\r
+\r
+ def generate(Module module) '''\r
+ <!DOCTYPE html>\r
+ <html lang="en">\r
+ <head>\r
+ <title>«module.name»</title>\r
+ </head>\r
+ <body>\r
+ «module.body»\r
+ </body>\r
+ </html>\r
+ '''\r
+\r
+ def body(Module module) '''\r
+ «header(module)»\r
+\r
+ «typeDefinitions(module)»\r
+\r
+ «identities(module)»\r
+\r
+ «groupings(module)»\r
+\r
+ «dataStore(module)»\r
+\r
+ «childNodes(module)»\r
+\r
+ «notifications(module)»\r
+\r
+ «augmentations(module)»\r
+\r
+ «rpcs(module)»\r
+\r
+ «extensions(module)»\r
+\r
+ «features(module)»\r
+\r
+ '''\r
+\r
+\r
+ def typeDefinitions(Module module) {\r
+ val Set<TypeDefinition<?>> typedefs = module.typeDefinitions\r
+ if (typedefs.empty) {\r
+ return '';\r
+ }\r
+ return '''\r
+ <h2>Type Definitions</h2>\r
+ <ul>\r
+ «FOR typedef : typedefs»\r
+ <li>\r
+ «strong("typedef " + typedef.QName.localName)»\r
+ <ul>\r
+ «typedef.descAndRef»\r
+ «typedef.restrictions»\r
+ </ul>\r
+ </li>\r
+ «ENDFOR»\r
+ </ul>\r
+ '''\r
+ }\r
+\r
+ private def identities(Module module) {\r
+ if (module.identities.empty) {\r
+ return '';\r
+ }\r
+ return '''\r
+ <h2>Identities</h2>\r
+ <ul>\r
+ «FOR identity : module.identities»\r
+ <li>\r
+ «strong("identity " + identity.QName.localName)»\r
+ <ul>\r
+ «identity.descAndRef»\r
+ «IF identity.baseIdentity != null»\r
+ «listItem("base", identity.baseIdentity.QName.localName)»\r
+ «ENDIF»\r
+ </ul>\r
+ </li>\r
+ «ENDFOR»\r
+ </ul>\r
+ '''\r
+ }\r
+\r
+ private def groupings(Module module) {\r
+ if (module.groupings.empty) {\r
+ return '';\r
+ }\r
+ return '''\r
+ <h2>Groupings</h2>\r
+ <ul>\r
+ «FOR grouping : module.groupings»\r
+ <li>\r
+ «strong("grouping " + grouping.QName.localName)»\r
+ <ul>\r
+ «grouping.descAndRef»\r
+ </ul>\r
+ </li>\r
+ «ENDFOR»\r
+ </ul>\r
+ '''\r
+ }\r
+\r
+ def dataStore(Module module) {\r
+ if (module.childNodes.empty) {\r
+ return '';\r
+ }\r
+ return '''\r
+ <h2>Datastore Structure</h2>\r
+ «tree(module)»\r
+ '''\r
+ }\r
+\r
+ def augmentations(Module module) {\r
+ if (module.augmentations.empty) {\r
+ return '';\r
+ }\r
+ return '''\r
+ <h2>Augmentations</h2>\r
+\r
+ <ul>\r
+ «FOR augment : module.augmentations»\r
+ <li>\r
+ augment\r
+ «augment.augmentationInfo(InstanceIdentifier.builder().toInstance())»\r
+ </li>\r
+ «ENDFOR»\r
+ </ul>\r
+ '''\r
+ }\r
+\r
+ def notifications(Module module) {\r
+ val Set<NotificationDefinition> notificationdefs = module.notifications\r
+ if (notificationdefs.empty) {\r
+ return '';\r
+ }\r
+ \r
+ return '''\r
+ <h2>Notifications</h2>\r
+ «FOR notificationdef : notificationdefs»\r
+ \r
+ <h3>«notificationdef.nodeName»</h3>\r
+ «notificationdef.notificationInfo(InstanceIdentifier.builder().node(notificationdef.QName).toInstance())»\r
+ «ENDFOR»\r
+ '''\r
+ }\r
+\r
+ def rpcs(Module module) {\r
+ if (module.rpcs.empty) {\r
+ return '';\r
+ }\r
+ \r
+ return '''\r
+ <h2>RPC Definitions</h2>\r
+ «FOR rpc : module.rpcs»\r
+ <h3>«rpc.nodeName»</h3>\r
+ «rpc.rpcInfo(InstanceIdentifier.builder().node(rpc.QName).toInstance())»\r
+ «ENDFOR»\r
+ </ul>\r
+ '''\r
+ }\r
+\r
+ def extensions(Module module) {\r
+ if (module.extensionSchemaNodes.empty) {\r
+ return '';\r
+ }\r
+ return '''\r
+ <h2>Extensions</h2>\r
+ «FOR ext : module.extensionSchemaNodes»\r
+ <li>\r
+ <h3>«ext.nodeName»</h3>\r
+ </li>\r
+ «ENDFOR»\r
+ '''\r
+ }\r
+\r
+ def features(Module module) {\r
+ if (module.features.empty) {\r
+ return '';\r
+ }\r
+ return '''\r
+ <h2>Features</h2>\r
+\r
+ <ul>\r
+ «FOR feature : module.features»\r
+ <li>\r
+ «strong("feature " + feature.QName.localName)»\r
+ <ul>\r
+ «feature.descAndRef»\r
+ </ul>\r
+ </li>\r
+ «ENDFOR»\r
+ </ul>\r
+ '''\r
+ }\r
+\r
+ def header(Module module) '''\r
+ <h1>«module.name»</h1>\r
+ \r
+ <h2>Base Information</h2>\r
+ <dl>\r
+ <dt>Prefix</dt>\r
+ <dd>«pre(module.prefix)»</dd>\r
+ <dt>Namespace</dt>\r
+ <dd>«pre(module.namespace.toString)»</dd>\r
+ <dt>Revision</dt>\r
+ <dd>«pre(REVISION_FORMAT.format(module.revision))»</dd>\r
+ \r
+ «FOR imp : module.imports BEFORE "<dt>Imports</dt>" »\r
+ <dd>«code(imp.prefix)» = «code(imp.moduleName)»</dd>\r
+ «ENDFOR»\r
+ </dl>\r
+ '''\r
+ \r
+ def code(String string) '''<code>«string»</code>'''\r
+ \r
+ def process(Module module) {\r
+ throw new UnsupportedOperationException("TODO: auto-generated method stub")\r
+ }\r
+\r
+ def CharSequence tree(Module module) '''\r
+ «strong("module " + module.name)»\r
+ «module.childNodes.treeSet(InstanceIdentifier.builder.toInstance())»\r
+ '''\r
+ \r
+ private def dispatch CharSequence tree(ChoiceNode node,InstanceIdentifier path) '''\r
+ «node.nodeName» (choice)\r
+ «casesTree(node.cases,path)»\r
+ '''\r
+ \r
+ def casesTree(Set<ChoiceCaseNode> nodes,InstanceIdentifier path) '''\r
+ <ul>\r
+ «FOR node : nodes»\r
+ <li>\r
+ «node.nodeName»\r
+ «node.childNodes.treeSet(path)»\r
+ </li>\r
+ «ENDFOR»\r
+ </ul>\r
+ '''\r
+\r
+ private def dispatch CharSequence tree(DataSchemaNode node,InstanceIdentifier path) '''\r
+ «node.nodeName»\r
+ '''\r
+\r
+ private def dispatch CharSequence tree(ListSchemaNode node,InstanceIdentifier path) '''\r
+ «val newPath = path.append(node)»\r
+ «localLink(newPath,node.nodeName)»\r
+ «node.childNodes.treeSet(newPath)»\r
+ '''\r
+ \r
+ private def dispatch CharSequence tree(ContainerSchemaNode node,InstanceIdentifier path) '''\r
+ «val newPath = path.append(node)»\r
+ «localLink(newPath,node.nodeName)»\r
+ «node.childNodes.treeSet(newPath)»\r
+ '''\r
+\r
+ def CharSequence childNodes(Module module) '''\r
+ «val childNodes = module.childNodes»\r
+ «IF childNodes !== null && !childNodes.empty»\r
+ <h2>Child nodes</h2>\r
+\r
+ «childNodes.printChildren(2,InstanceIdentifier.builder().toInstance())»\r
+ «ENDIF»\r
+ '''\r
+ \r
+ def CharSequence printChildren(Set<DataSchemaNode> nodes, int level, InstanceIdentifier path) {\r
+ val leafNodes = nodes.filter(LeafSchemaNode)\r
+ val leafListNodes = nodes.filter(LeafListSchemaNode)\r
+ val choices = nodes.filter(ChoiceNode)\r
+ val containers = nodes.filter(ContainerSchemaNode)\r
+ val lists = nodes.filter(ListSchemaNode)\r
+ return '''\r
+ <h3>Direct children</h3>\r
+ <ul>\r
+ «FOR childNode : leafNodes»\r
+ «childNode.printShortInfo(level,path)»\r
+ «ENDFOR»\r
+ «FOR childNode : leafListNodes»\r
+ «childNode.printShortInfo(level,path)»\r
+ «ENDFOR»\r
+ «FOR childNode : containers»\r
+ «childNode.printShortInfo(level,path)»\r
+ «ENDFOR»\r
+ «FOR childNode : lists»\r
+ «childNode.printShortInfo(level,path)»\r
+ «ENDFOR»\r
+ </ul>\r
+ \r
+ «IF !path.path.empty»\r
+ <h3>XML example</h3>\r
+ «nodes.xmlExample(path.path.last.nodeType,path)»\r
+ </h3>\r
+ «ENDIF»\r
+ «FOR childNode : containers»\r
+ «childNode.printInfo(level,path)»\r
+ «ENDFOR»\r
+ «FOR childNode : lists»\r
+ «childNode.printInfo(level,path)»\r
+ «ENDFOR»\r
+ \r
+ '''\r
+ }\r
+ \r
+ def CharSequence xmlExample(Set<DataSchemaNode> nodes, QName name,InstanceIdentifier path) '''\r
+ <pre>\r
+ «xmlExampleTag(name,nodes.xmplExampleTags(path))»\r
+ </pre>\r
+ '''\r
+ \r
+ def CharSequence xmplExampleTags(Set<DataSchemaNode> nodes, InstanceIdentifier identifier) '''\r
+ <!-- Child nodes -->\r
+ «FOR node : nodes»\r
+ <!-- «node.QName.localName» -->\r
+ «node.asXmlExampleTag(identifier)»\r
+ «ENDFOR»\r
+ \r
+ '''\r
+ \r
+ private def dispatch CharSequence asXmlExampleTag(LeafSchemaNode node, InstanceIdentifier identifier) '''\r
+ «node.QName.xmlExampleTag("...")»\r
+ '''\r
+ \r
+ private def dispatch CharSequence asXmlExampleTag(LeafListSchemaNode node, InstanceIdentifier identifier) '''\r
+ <!-- This node could appear multiple times -->\r
+ «node.QName.xmlExampleTag("...")»\r
+ '''\r
+ \r
+ private def dispatch CharSequence asXmlExampleTag(ContainerSchemaNode node, InstanceIdentifier identifier) '''\r
+ <!-- See «localLink(identifier.append(node),"definition")» for child nodes. -->\r
+ «node.QName.xmlExampleTag("...")»\r
+ '''\r
+ \r
+ \r
+ private def dispatch CharSequence asXmlExampleTag(ListSchemaNode node, InstanceIdentifier identifier) '''\r
+ <!-- See «localLink(identifier.append(node),"definition")» for child nodes. -->\r
+ <!-- This node could appear multiple times -->\r
+ «node.QName.xmlExampleTag("...")»\r
+ '''\r
+ \r
+ \r
+ private def dispatch CharSequence asXmlExampleTag(DataSchemaNode node, InstanceIdentifier identifier) '''\r
+ <!-- noop -->\r
+ '''\r
+ \r
+ \r
+ def xmlExampleTag(QName name, CharSequence data) {\r
+ return '''<«name.localName» xmlns="«name.namespace»">«data»</«name.localName»>'''\r
+ }\r
+ \r
+ private def dispatch CharSequence printInfo(ContainerSchemaNode node, int level, InstanceIdentifier path) '''\r
+ «val newPath = path.append(node)»\r
+ «header(level,newPath)»\r
+ <dl>\r
+ <dt>XML Path</dt>\r
+ <dd>«newPath.asXmlPath»</dd>\r
+ <dt>Restconf path</dt>\r
+ <dd>«code(newPath.asRestconfPath)»</dd>\r
+ </dl>\r
+ «node.childNodes.printChildren(level,newPath)»\r
+ '''\r
+ \r
+ def header(int level,QName name) '''<h«level»>«name.localName»</h«level»>'''\r
+ \r
+ \r
+ def header(int level,InstanceIdentifier name) \r
+ '''\r
+ <h«level» id="«FOR cmp : name.path SEPARATOR "/"»«cmp.nodeType.localName»«ENDFOR»">\r
+ «FOR cmp : name.path SEPARATOR "/"»«cmp.nodeType.localName»«ENDFOR»\r
+ </h«level»>'''\r
+ \r
+ \r
+ private def dispatch CharSequence printInfo(ListSchemaNode node, int level, InstanceIdentifier path) '''\r
+ «val newPath = path.append(node)»\r
+ «header(level,newPath)»\r
+ <dl>\r
+ <dt>XML Path</dt>\r
+ <dd>«newPath.asXmlPath»</dd>\r
+ <dt>Restconf path</dt>\r
+ <dd>«code(newPath.asRestconfPath)»</dd>\r
+ </dl>\r
+ «node.childNodes.printChildren(level,newPath)»\r
+ '''\r
+ \r
+ def CharSequence printShortInfo(ContainerSchemaNode node, int level, InstanceIdentifier path) {\r
+ val newPath = path.append(node);\r
+ return '''\r
+ <li>«strong(localLink(newPath,node.QName.localName))» (container)</li>\r
+ '''\r
+ }\r
+ \r
+ def CharSequence printShortInfo(ListSchemaNode node, int level, InstanceIdentifier path) {\r
+ val newPath = path.append(node);\r
+ return '''\r
+ <li>«strong(localLink(newPath,node.QName.localName))» (list)</li>\r
+ '''\r
+ }\r
+ \r
+ def CharSequence printShortInfo(LeafSchemaNode node, int level, InstanceIdentifier path) {\r
+ return '''\r
+ <li>«strong((node.QName.localName))» (leaf)</li>\r
+ '''\r
+ }\r
+ \r
+ def CharSequence printShortInfo(LeafListSchemaNode node, int level, InstanceIdentifier path) {\r
+ return '''\r
+ <li>«strong((node.QName.localName))» (leaf-list)</li>\r
+ '''\r
+ }\r
+ \r
+ def CharSequence localLink(InstanceIdentifier identifier, CharSequence text) '''\r
+ <a href="#«FOR cmp : identifier.path SEPARATOR "/"»«cmp.nodeType.localName»«ENDFOR»">«text»</a>\r
+ '''\r
+ \r
+ \r
+ private def dispatch InstanceIdentifier append(InstanceIdentifier identifier, ContainerSchemaNode node) {\r
+ val pathArguments = new ArrayList(identifier.path)\r
+ pathArguments.add(new NodeIdentifier(node.QName));\r
+ return new InstanceIdentifier(pathArguments);\r
+ }\r
+ \r
+ private def dispatch InstanceIdentifier append(InstanceIdentifier identifier, ListSchemaNode node) {\r
+ val pathArguments = new ArrayList(identifier.path)\r
+ val keyValues = new LinkedHashMap<QName,Object>();\r
+ if(node.keyDefinition != null) {\r
+ for(definition : node.keyDefinition) {\r
+ keyValues.put(definition,new Object);\r
+ }\r
+ }\r
+ pathArguments.add(new NodeIdentifierWithPredicates(node.QName,keyValues));\r
+ return new InstanceIdentifier(pathArguments);\r
+ }\r
+ \r
+ \r
+ def asXmlPath(InstanceIdentifier identifier) {\r
+ return "";\r
+ }\r
+ \r
+ def asRestconfPath(InstanceIdentifier identifier) {\r
+ val it = new StringBuilder();\r
+ append(currentModule.name)\r
+ append(":")\r
+ var previous = false;\r
+ for(arg : identifier.path) {\r
+ if(previous) append("/")\r
+ append(arg.nodeType.localName);\r
+ previous = true;\r
+ if(arg instanceof NodeIdentifierWithPredicates) {\r
+ val nodeIdentifier = arg as NodeIdentifierWithPredicates;\r
+ for(qname : nodeIdentifier.keyValues.keySet) {\r
+ append("/{");\r
+ append(qname.localName)\r
+ append("}")\r
+ }\r
+ }\r
+ }\r
+ \r
+ return it.toString;\r
+ }\r
+ \r
+ \r
+ private def dispatch CharSequence printInfo(DataSchemaNode node, int level, InstanceIdentifier path) '''\r
+ «header(level+1,node.QName)»\r
+ '''\r
+ \r
+\r
+\r
+\r
+\r
+ def CharSequence childNodesInfoTree(Map<SchemaPath, DataSchemaNode> childNodes) '''\r
+ «IF childNodes !== null && !childNodes.empty»\r
+ «FOR child : childNodes.values»\r
+ «childInfo(child, childNodes)»\r
+ «ENDFOR»\r
+ «ENDIF»\r
+ '''\r
+\r
+ def CharSequence childInfo(DataSchemaNode node, Map<SchemaPath, DataSchemaNode> childNodes) '''\r
+ «val String path = nodeSchemaPathToPath(node, childNodes)»\r
+ «IF path != null»\r
+ «code(path)»\r
+ «IF node !== null»\r
+ <ul>\r
+ «node.descAndRef»\r
+ </ul>\r
+ «ENDIF»\r
+ «ENDIF»\r
+ '''\r
+\r
+ private def CharSequence treeSet(Collection<DataSchemaNode> childNodes, InstanceIdentifier path) '''\r
+ «IF childNodes !== null && !childNodes.empty»\r
+ <ul>\r
+ «FOR child : childNodes»\r
+ <li>\r
+ «child.tree(path)»\r
+ </li>\r
+ «ENDFOR»\r
+ </ul>\r
+ «ENDIF»\r
+ '''\r
+\r
+ def listKeys(ListSchemaNode node) '''\r
+ [«FOR key : node.keyDefinition SEPARATOR " "»«key.localName»«ENDFOR»]\r
+ '''\r
+\r
+ private def CharSequence augmentationInfo(AugmentationSchema augment, InstanceIdentifier path) '''\r
+ <ul>\r
+ «listItem(augment.description)»\r
+ «listItem("Reference", augment.reference)»\r
+ «IF augment.whenCondition !== null»\r
+ «listItem("When", augment.whenCondition.toString)»\r
+ «ENDIF»\r
+ <li>\r
+ Path «augment.targetPath.path.pathToTree»\r
+ </li>\r
+ <li>\r
+ Child nodes\r
+ «augment.childNodes.treeSet(path)»\r
+ </li>\r
+ </ul>\r
+ '''\r
+\r
+ private def CharSequence notificationInfo(NotificationDefinition notification,InstanceIdentifier path) '''\r
+ <ul>\r
+ «notification.descAndRef»\r
+ <li>\r
+ Child nodes\r
+ «notification.childNodes.treeSet(path)»\r
+ </li>\r
+ </ul>\r
+ '''\r
+\r
+ private def CharSequence rpcInfo(RpcDefinition rpc,InstanceIdentifier path) '''\r
+ <ul>\r
+ «rpc.descAndRef»\r
+ <li>\r
+ «rpc.input.tree(path)»\r
+ </li>\r
+ <li>\r
+ «rpc.output.tree(path)»\r
+ </li>\r
+ </ul>\r
+ '''\r
+\r
+ private def CharSequence extensionInfo(ExtensionDefinition ext, InstanceIdentifier path) '''\r
+ <ul>\r
+ «ext.descAndRef»\r
+ «listItem("Argument", ext.argument)»\r
+ </ul>\r
+ '''\r
+\r
+ private def dispatch CharSequence tree(Void obj, InstanceIdentifier path) '''\r
+ '''\r
+\r
+\r
+\r
+ /* #################### RESTRICTIONS #################### */\r
+ private def restrictions(TypeDefinition<?> type) '''\r
+ «type.toLength»\r
+ «type.toRange»\r
+ '''\r
+\r
+ private def dispatch toLength(TypeDefinition<?> type) {\r
+ }\r
+\r
+ private def dispatch toLength(BinaryTypeDefinition type) '''\r
+ «type.lengthConstraints.toLengthStmt»\r
+ '''\r
+\r
+ private def dispatch toLength(StringTypeDefinition type) '''\r
+ «type.lengthConstraints.toLengthStmt»\r
+ '''\r
+\r
+ private def dispatch toLength(ExtendedType type) '''\r
+ «type.lengthConstraints.toLengthStmt»\r
+ '''\r
+\r
+ private def dispatch toRange(TypeDefinition<?> type) {\r
+ }\r
+\r
+ private def dispatch toRange(DecimalTypeDefinition type) '''\r
+ «type.rangeConstraints.toRangeStmt»\r
+ '''\r
+\r
+ private def dispatch toRange(IntegerTypeDefinition type) '''\r
+ «type.rangeConstraints.toRangeStmt»\r
+ '''\r
+\r
+ private def dispatch toRange(UnsignedIntegerTypeDefinition type) '''\r
+ «type.rangeConstraints.toRangeStmt»\r
+ '''\r
+\r
+ private def dispatch toRange(ExtendedType type) '''\r
+ «type.rangeConstraints.toRangeStmt»\r
+ '''\r
+\r
+ def toLengthStmt(Collection<LengthConstraint> lengths) '''\r
+ «IF lengths != null && !lengths.empty»\r
+ «listItem("Length restrictions")»\r
+ <ul>\r
+ «FOR length : lengths»\r
+ <li>\r
+ «IF length.min == length.max»\r
+ «length.min»\r
+ «ELSE»\r
+ <«length.min», «length.max»>\r
+ «ENDIF»\r
+ </li>\r
+ «ENDFOR»\r
+ </ul>\r
+ «ENDIF»\r
+ '''\r
+\r
+ def toRangeStmt(Collection<RangeConstraint> ranges) '''\r
+ «IF ranges != null && !ranges.empty»\r
+ «listItem("Range restrictions")»\r
+ <ul>\r
+ «FOR range : ranges»\r
+ <li>\r
+ «IF range.min == range.max»\r
+ «range.min»\r
+ «ELSE»\r
+ <«range.min», «range.max»>\r
+ «ENDIF»\r
+ </li>\r
+ «ENDFOR»\r
+ </ul>\r
+ «ENDIF»\r
+ '''\r
+\r
+\r
+\r
+ /* #################### UTILITY #################### */\r
+ private def String strong(CharSequence str) '''<strong>«str»</strong>'''\r
+ private def italic(CharSequence str) '''<i>«str»</i>'''\r
+ private def pre(CharSequence str) '''<pre>«str»</pre>'''\r
+\r
+ def CharSequence descAndRef(SchemaNode node) '''\r
+ «listItem(node.description)»\r
+ «listItem("Reference", node.reference)»\r
+ '''\r
+\r
+ private def listItem(String value) '''\r
+ «IF value !== null && !value.empty»\r
+ <li>\r
+ «value»\r
+ </li>\r
+ «ENDIF»\r
+ '''\r
+\r
+ private def listItem(String name, String value) '''\r
+ «IF value !== null && !value.empty»\r
+ <li>\r
+ «name»\r
+ <ul>\r
+ <li>\r
+ «value»\r
+ </li>\r
+ </ul>\r
+ </li>\r
+ «ENDIF»\r
+ '''\r
+\r
+ private def String nodeSchemaPathToPath(DataSchemaNode node, Map<SchemaPath, DataSchemaNode> childNodes) {\r
+ if (node instanceof ChoiceNode || node instanceof ChoiceCaseNode) {\r
+ return null\r
+ }\r
+\r
+ val path = node.path.path\r
+ val absolute = node.path.absolute;\r
+ var StringBuilder result = new StringBuilder\r
+ if (absolute) {\r
+ result.append("/")\r
+ }\r
+ if (path !== null && !path.empty) {\r
+ val List<QName> actual = new ArrayList()\r
+ var i = 0;\r
+ for (pathElement : path) {\r
+ actual.add(pathElement)\r
+ val DataSchemaNode nodeByPath = childNodes.get(new SchemaPath(actual, absolute)) \r
+ if (!(nodeByPath instanceof ChoiceNode) && !(nodeByPath instanceof ChoiceCaseNode)) {\r
+ result.append(pathElement.localName)\r
+ if (i != path.size - 1) {\r
+ result.append("/")\r
+ }\r
+ }\r
+ i = i + 1\r
+ }\r
+ }\r
+ return result.toString\r
+ }\r
+\r
+ private def void collectChildNodes(Collection<DataSchemaNode> source, Map<SchemaPath, DataSchemaNode> destination) {\r
+ for (node : source) {\r
+ destination.put(node.path, node)\r
+ if (node instanceof DataNodeContainer) {\r
+ collectChildNodes((node as DataNodeContainer).childNodes, destination)\r
+ }\r
+ if (node instanceof ChoiceNode) {\r
+ val List<DataSchemaNode> choiceCases = new ArrayList()\r
+ for (caseNode : (node as ChoiceNode).cases) {\r
+ choiceCases.add(caseNode)\r
+ }\r
+ collectChildNodes(choiceCases, destination)\r
+ }\r
+ }\r
+ }\r
+\r
+ private def CharSequence pathToTree(List<QName> path) '''\r
+ «IF path !== null && !path.empty»\r
+ <ul>\r
+ «FOR pathElement : path»\r
+ <li>\r
+ «pathElement.namespace» «pathElement.localName»\r
+ </li>\r
+ «ENDFOR»\r
+ </ul>\r
+ «ENDIF»\r
+ '''\r
+\r
+ private def dispatch addedByInfo(SchemaNode node) '''\r
+ '''\r
+\r
+ private def dispatch addedByInfo(DataSchemaNode node) '''\r
+ «IF node.augmenting»(A)«ENDIF»«IF node.addedByUses»(U)«ENDIF»\r
+ '''\r
+\r
+ private def dispatch isAddedBy(SchemaNode node) {\r
+ return false;\r
+ }\r
+\r
+ private def dispatch isAddedBy(DataSchemaNode node) {\r
+ if (node.augmenting || node.addedByUses) {\r
+ return true\r
+ } else {\r
+ return false;\r
+ }\r
+ }\r
+\r
+ private def dispatch nodeName(SchemaNode node) '''\r
+ «IF node.isAddedBy»\r
+ «italic(node.QName.localName)»«node.addedByInfo»\r
+ «ELSE»\r
+ «node.QName.localName»«node.addedByInfo»\r
+ «ENDIF»\r
+ '''\r
+ \r
+ private def dispatch nodeName(ContainerSchemaNode node) '''\r
+ «IF node.isAddedBy»\r
+ «strong(italic(node.QName.localName))»«node.addedByInfo»\r
+ «ELSE»\r
+ «strong(node.QName.localName)»«node.addedByInfo»\r
+ «ENDIF»\r
+ '''\r
+\r
+ private def dispatch nodeName(ListSchemaNode node) '''\r
+ «IF node.isAddedBy»\r
+ «strong(italic(node.QName.localName))» «IF node.keyDefinition !== null && !node.keyDefinition.empty»«node.listKeys»«ENDIF»«node.addedByInfo»\r
+ «ELSE»\r
+ «strong(node.QName.localName)» «IF node.keyDefinition !== null && !node.keyDefinition.empty»«node.listKeys»«ENDIF»\r
+ «ENDIF»\r
+ '''\r
+\r
+}\r