* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-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.BufferedWriter\r
-import java.io.OutputStreamWriter;\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 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.sonatype.plexus.build.incremental.BuildContext;\r
-import org.sonatype.plexus.build.incremental.DefaultBuildContext;\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 org.opendaylight.yangtools.yang.model.api.LeafSchemaNode\r
+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.BufferedWriter
+import java.io.OutputStreamWriter;
+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 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 org.sonatype.plexus.build.incremental.BuildContext;
+import org.sonatype.plexus.build.incremental.DefaultBuildContext;
+
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates
+import java.util.LinkedHashMap
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode\rimport java.util.HashMap
import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode
-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
- static val BuildContext CTX = new DefaultBuildContext();\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(generateDocumentation(module, context));\r
- }\r
- return it;\r
- }\r
-\r
- def generateDocumentation(Module module, SchemaContext ctx) {\r
- val destination = new File(path, '''«module.name».html''')\r
- try {\r
- val fw = new OutputStreamWriter(CTX.newFileOutputStream(destination))\r
- val bw = new BufferedWriter(fw)\r
- currentModule = module;\r
- bw.append(generate(module, ctx));\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, SchemaContext ctx) '''\r
- <!DOCTYPE html>\r
- <html lang="en">\r
- <head>\r
- <title>«module.name»</title>\r
- </head>\r
- <body>\r
- «body(module, ctx)»\r
- </body>\r
- </html>\r
- '''\r
-\r
- def body(Module module, SchemaContext ctx) '''\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, ctx)»\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.descAndRefLi»\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.descAndRefLi»\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.descAndRefLi»\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, SchemaContext context) {\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
- <h3>Target [«schemaPathAsRestconfPath(module, augment.targetPath, context)»]</h3>\r
- «augment.description»\r
- «IF augment.reference !== null»\r
- Reference «augment.reference»\r
- «ENDIF»\r
- «IF augment.whenCondition !== null»\r
- When «augment.whenCondition.toString»\r
- «ENDIF»\r
- «augment.childNodes.printChildren(3,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.descAndRef»\r
- «notificationdef.childNodes.printChildren(3,InstanceIdentifier.builder().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
- «extensionInfo(ext)»\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.descAndRefLi»\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(3,InstanceIdentifier.builder().toInstance())»\r
- «ENDIF»\r
- '''\r
-\r
- def CharSequence printChildren(Set<DataSchemaNode> nodes, int level, InstanceIdentifier path) {\r
- val anyxmlNodes = nodes.filter(AnyXmlSchemaNode)\r
- val leafNodes = nodes.filter(LeafSchemaNode)\r
- val leafListNodes = nodes.filter(LeafListSchemaNode)\r
- val choices = nodes.filter(ChoiceNode)\r
- val cases = nodes.filter(ChoiceCaseNode)\r
- val containers = nodes.filter(ContainerSchemaNode)\r
- val lists = nodes.filter(ListSchemaNode)\r
- return '''\r
- «IF ((anyxmlNodes.size + leafNodes.size + leafListNodes.size + containers.size + lists.size) > 0)»\r
- <h3>Direct children</h3>\r
- <ul>\r
- «FOR childNode : anyxmlNodes»\r
- «childNode.printShortInfo(level,path)»\r
- «ENDFOR»\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
- «ENDIF»\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
- «FOR childNode : choices»\r
- «childNode.printInfo(level,path)»\r
- «ENDFOR»\r
- «FOR childNode : cases»\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
- def header(int level,QName name) '''<h«level»>«name.localName»</h«level»>'''\r
-\r
-\r
- def header(int level,InstanceIdentifier name) '''\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
-\r
-\r
- private def dispatch CharSequence printInfo(DataSchemaNode node, int level, InstanceIdentifier path) '''\r
- «header(level+1,node.QName)»\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
- 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
- private def dispatch CharSequence printInfo(ChoiceNode node, int level, InstanceIdentifier path) '''\r
- «val Set<DataSchemaNode> choiceCases = new HashSet(node.cases)»\r
- «choiceCases.printChildren(level,path)»\r
- '''\r
-\r
- private def dispatch CharSequence printInfo(ChoiceCaseNode node, int level, InstanceIdentifier path) '''\r
- «node.childNodes.printChildren(level,path)»\r
- '''\r
-\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(AnyXmlSchemaNode node, int level, InstanceIdentifier path) {\r
- return '''\r
- <li>«strong((node.QName.localName))» (anyxml)</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
- private def String schemaPathAsRestconfPath(Module module, SchemaPath schemaPath, SchemaContext ctx) {\r
- val Map<String, String> imports = new HashMap();\r
- for (mImport : module.imports) {\r
- imports.put(mImport.prefix, mImport.moduleName)\r
- }\r
-\r
- val List<QName> path = schemaPath.path\r
- val StringBuilder pathString = new StringBuilder()\r
- if (schemaPath.absolute) {\r
- pathString.append("/")\r
- }\r
-\r
- val QName qname = path.get(0)\r
- var Object parent = ctx.findModuleByNamespaceAndRevision(qname.namespace, qname.revision)\r
-\r
- for (name : path) {\r
- if (parent instanceof DataNodeContainer) {\r
- var SchemaNode node = (parent as DataNodeContainer).getDataChildByName(name)\r
- if (node == null && (parent instanceof Module)) {\r
- val notifications = (parent as Module).notifications;\r
- for (notification : notifications) {\r
- if (notification.QName.equals(name)) {\r
- node = notification\r
- }\r
- }\r
- }\r
+class GeneratorImpl {
+
+ File path
+ static val REVISION_FORMAT = new SimpleDateFormat("yyyy-MM-dd")
+ static val Logger LOG = LoggerFactory.getLogger(GeneratorImpl)
+ static val BuildContext CTX = new DefaultBuildContext();
+ var Module currentModule;
+
+
+ def generate(SchemaContext context, File targetPath, Set<Module> modulesToGen) throws IOException {
+ path = targetPath;
+ path.mkdirs();
+ val it = new HashSet;
+ for (module : modulesToGen) {
+ add(generateDocumentation(module, context));
+ }
+ return it;
+ }
+
+ def generateDocumentation(Module module, SchemaContext ctx) {
+ val destination = new File(path, '''«module.name».html''')
+ try {
+ val fw = new OutputStreamWriter(CTX.newFileOutputStream(destination))
+ val bw = new BufferedWriter(fw)
+ currentModule = module;
+ bw.append(generate(module, ctx));
+ bw.close();
+ fw.close();
+ } catch (IOException e) {
+ LOG.error(e.getMessage());
+ }
+ return destination;
+ }
+
+ def generate(Module module, SchemaContext ctx) '''
+ <!DOCTYPE html>
+ <html lang="en">
+ <head>
+ <title>«module.name»</title>
+ </head>
+ <body>
+ «body(module, ctx)»
+ </body>
+ </html>
+ '''
+
+ def body(Module module, SchemaContext ctx) '''
+ «header(module)»
+
+ «typeDefinitions(module)»
+
+ «identities(module)»
+
+ «groupings(module)»
+
+ «dataStore(module)»
+
+ «childNodes(module)»
+
+ «notifications(module)»
+
+ «augmentations(module, ctx)»
+
+ «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.descAndRefLi»
+ «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.descAndRefLi»
+ «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.descAndRefLi»
+ </ul>
+ </li>
+ «ENDFOR»
+ </ul>
+ '''
+ }
+
+ def dataStore(Module module) {
+ if (module.childNodes.empty) {
+ return '';
+ }
+ return '''
+ <h2>Datastore Structure</h2>
+ «tree(module)»
+ '''
+ }
+
+ def augmentations(Module module, SchemaContext context) {
+ if (module.augmentations.empty) {
+ return '';
+ }
+ return '''
+ <h2>Augmentations</h2>
+
+ <ul>
+ «FOR augment : module.augmentations»
+ <li>
+ <h3>Target [«schemaPathAsRestconfPath(module, augment.targetPath, context)»]</h3>
+ «augment.description»
+ «IF augment.reference !== null»
+ Reference «augment.reference»
+ «ENDIF»
+ «IF augment.whenCondition !== null»
+ When «augment.whenCondition.toString»
+ «ENDIF»
+ «augment.childNodes.printChildren(3,InstanceIdentifier.builder().toInstance())»
+ </li>
+ «ENDFOR»
+ </ul>
+ '''
+ }
+
+ def notifications(Module module) {
+ val Set<NotificationDefinition> notificationdefs = module.notifications
+ if (notificationdefs.empty) {
+ return '';
+ }
+
+ return '''
+ <h2>Notifications</h2>
+ «FOR notificationdef : notificationdefs»
+
+ <h3>«notificationdef.nodeName»</h3>
+ «notificationdef.descAndRef»
+ «notificationdef.childNodes.printChildren(3,InstanceIdentifier.builder().toInstance())»
+ «ENDFOR»
+ '''
+ }
+
+ def rpcs(Module module) {
+ if (module.rpcs.empty) {
+ return '';
+ }
+
+ return '''
+ <h2>RPC Definitions</h2>
+ «FOR rpc : module.rpcs»
+ <h3>«rpc.nodeName»</h3>
+ «rpc.rpcInfo(InstanceIdentifier.builder().node(rpc.QName).toInstance())»
+ «ENDFOR»
+ </ul>
+ '''
+ }
+
+ def extensions(Module module) {
+ if (module.extensionSchemaNodes.empty) {
+ return '';
+ }
+ return '''
+ <h2>Extensions</h2>
+ «FOR ext : module.extensionSchemaNodes»
+ <li>
+ <h3>«ext.nodeName»</h3>
+ </li>
+ «extensionInfo(ext)»
+ «ENDFOR»
+ '''
+ }
+
+ 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.descAndRefLi»
+ </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>«code(imp.prefix)» = «code(imp.moduleName)»</dd>
+ «ENDFOR»
+ </dl>
+ '''
+
+ def code(String string) '''<code>«string»</code>'''
+
+ def process(Module module) {
+ throw new UnsupportedOperationException("TODO: auto-generated method stub")
+ }
+
+ def CharSequence tree(Module module) '''
+ «strong("module " + module.name)»
+ «module.childNodes.treeSet(InstanceIdentifier.builder.toInstance())»
+ '''
+
+ private def dispatch CharSequence tree(ChoiceNode node,InstanceIdentifier path) '''
+ «node.nodeName» (choice)
+ «casesTree(node.cases,path)»
+ '''
+
+ def casesTree(Set<ChoiceCaseNode> nodes,InstanceIdentifier path) '''
+ <ul>
+ «FOR node : nodes»
+ <li>
+ «node.nodeName»
+ «node.childNodes.treeSet(path)»
+ </li>
+ «ENDFOR»
+ </ul>
+ '''
+
+ private def dispatch CharSequence tree(DataSchemaNode node,InstanceIdentifier path) '''
+ «node.nodeName»
+ '''
+
+ private def dispatch CharSequence tree(ListSchemaNode node,InstanceIdentifier path) '''
+ «val newPath = path.append(node)»
+ «localLink(newPath,node.nodeName)»
+ «node.childNodes.treeSet(newPath)»
+ '''
+
+ private def dispatch CharSequence tree(ContainerSchemaNode node,InstanceIdentifier path) '''
+ «val newPath = path.append(node)»
+ «localLink(newPath,node.nodeName)»
+ «node.childNodes.treeSet(newPath)»
+ '''
+
+ def CharSequence childNodes(Module module) '''
+ «val childNodes = module.childNodes»
+ «IF childNodes !== null && !childNodes.empty»
+ <h2>Child nodes</h2>
+
+ «childNodes.printChildren(3,InstanceIdentifier.builder().toInstance())»
+ «ENDIF»
+ '''
+
+ def CharSequence printChildren(Set<DataSchemaNode> nodes, int level, InstanceIdentifier path) {
+ val anyxmlNodes = nodes.filter(AnyXmlSchemaNode)
+ val leafNodes = nodes.filter(LeafSchemaNode)
+ val leafListNodes = nodes.filter(LeafListSchemaNode)
+ val choices = nodes.filter(ChoiceNode)
+ val cases = nodes.filter(ChoiceCaseNode)
+ val containers = nodes.filter(ContainerSchemaNode)
+ val lists = nodes.filter(ListSchemaNode)
+ return '''
+ «IF ((anyxmlNodes.size + leafNodes.size + leafListNodes.size + containers.size + lists.size) > 0)»
+ <h3>Direct children</h3>
+ <ul>
+ «FOR childNode : anyxmlNodes»
+ «childNode.printShortInfo(level,path)»
+ «ENDFOR»
+ «FOR childNode : leafNodes»
+ «childNode.printShortInfo(level,path)»
+ «ENDFOR»
+ «FOR childNode : leafListNodes»
+ «childNode.printShortInfo(level,path)»
+ «ENDFOR»
+ «FOR childNode : containers»
+ «childNode.printShortInfo(level,path)»
+ «ENDFOR»
+ «FOR childNode : lists»
+ «childNode.printShortInfo(level,path)»
+ «ENDFOR»
+ </ul>
+ «ENDIF»
+
+ «IF !path.path.empty»
+ <h3>XML example</h3>
+ «nodes.xmlExample(path.path.last.nodeType,path)»
+ </h3>
+ «ENDIF»
+ «FOR childNode : containers»
+ «childNode.printInfo(level,path)»
+ «ENDFOR»
+ «FOR childNode : lists»
+ «childNode.printInfo(level,path)»
+ «ENDFOR»
+ «FOR childNode : choices»
+ «childNode.printInfo(level,path)»
+ «ENDFOR»
+ «FOR childNode : cases»
+ «childNode.printInfo(level,path)»
+ «ENDFOR»
+
+ '''
+ }
+
+ def CharSequence xmlExample(Set<DataSchemaNode> nodes, QName name,InstanceIdentifier path) '''
+ <pre>
+ «xmlExampleTag(name,nodes.xmplExampleTags(path))»
+ </pre>
+ '''
+
+ def CharSequence xmplExampleTags(Set<DataSchemaNode> nodes, InstanceIdentifier identifier) '''
+ <!-- Child nodes -->
+ «FOR node : nodes»
+ <!-- «node.QName.localName» -->
+ «node.asXmlExampleTag(identifier)»
+ «ENDFOR»
+
+ '''
+
+ private def dispatch CharSequence asXmlExampleTag(LeafSchemaNode node, InstanceIdentifier identifier) '''
+ «node.QName.xmlExampleTag("...")»
+ '''
+
+ private def dispatch CharSequence asXmlExampleTag(LeafListSchemaNode node, InstanceIdentifier identifier) '''
+ <!-- This node could appear multiple times -->
+ «node.QName.xmlExampleTag("...")»
+ '''
+
+ private def dispatch CharSequence asXmlExampleTag(ContainerSchemaNode node, InstanceIdentifier identifier) '''
+ <!-- See «localLink(identifier.append(node),"definition")» for child nodes. -->
+ «node.QName.xmlExampleTag("...")»
+ '''
+
+
+ private def dispatch CharSequence asXmlExampleTag(ListSchemaNode node, InstanceIdentifier identifier) '''
+ <!-- See «localLink(identifier.append(node),"definition")» for child nodes. -->
+ <!-- This node could appear multiple times -->
+ «node.QName.xmlExampleTag("...")»
+ '''
+
+
+ private def dispatch CharSequence asXmlExampleTag(DataSchemaNode node, InstanceIdentifier identifier) '''
+ <!-- noop -->
+ '''
+
+
+ def xmlExampleTag(QName name, CharSequence data) {
+ return '''<«name.localName» xmlns="«name.namespace»">«data»</«name.localName»>'''
+ }
+
+ def header(int level,QName name) '''<h«level»>«name.localName»</h«level»>'''
+
+
+ def header(int level,InstanceIdentifier name) '''
+ <h«level» id="«FOR cmp : name.path SEPARATOR "/"»«cmp.nodeType.localName»«ENDFOR»">
+ «FOR cmp : name.path SEPARATOR "/"»«cmp.nodeType.localName»«ENDFOR»
+ </h«level»>
+ '''
+
+
+
+ private def dispatch CharSequence printInfo(DataSchemaNode node, int level, InstanceIdentifier path) '''
+ «header(level+1,node.QName)»
+ '''
+
+ private def dispatch CharSequence printInfo(ContainerSchemaNode node, int level, InstanceIdentifier path) '''
+ «val newPath = path.append(node)»
+ «header(level,newPath)»
+ <dl>
+ <dt>XML Path</dt>
+ <dd>«newPath.asXmlPath»</dd>
+ <dt>Restconf path</dt>
+ <dd>«code(newPath.asRestconfPath)»</dd>
+ </dl>
+ «node.childNodes.printChildren(level,newPath)»
+ '''
+
+ private def dispatch CharSequence printInfo(ListSchemaNode node, int level, InstanceIdentifier path) '''
+ «val newPath = path.append(node)»
+ «header(level,newPath)»
+ <dl>
+ <dt>XML Path</dt>
+ <dd>«newPath.asXmlPath»</dd>
+ <dt>Restconf path</dt>
+ <dd>«code(newPath.asRestconfPath)»</dd>
+ </dl>
+ «node.childNodes.printChildren(level,newPath)»
+ '''
+
+ private def dispatch CharSequence printInfo(ChoiceNode node, int level, InstanceIdentifier path) '''
+ «val Set<DataSchemaNode> choiceCases = new HashSet(node.cases)»
+ «choiceCases.printChildren(level,path)»
+ '''
+
+ private def dispatch CharSequence printInfo(ChoiceCaseNode node, int level, InstanceIdentifier path) '''
+ «node.childNodes.printChildren(level,path)»
+ '''
+
+
+
+ def CharSequence printShortInfo(ContainerSchemaNode node, int level, InstanceIdentifier path) {
+ val newPath = path.append(node);
+ return '''
+ <li>«strong(localLink(newPath,node.QName.localName))» (container)</li>
+ '''
+ }
+
+ def CharSequence printShortInfo(ListSchemaNode node, int level, InstanceIdentifier path) {
+ val newPath = path.append(node);
+ return '''
+ <li>«strong(localLink(newPath,node.QName.localName))» (list)</li>
+ '''
+ }
+
+ def CharSequence printShortInfo(AnyXmlSchemaNode node, int level, InstanceIdentifier path) {
+ return '''
+ <li>«strong((node.QName.localName))» (anyxml)</li>
+ '''
+ }
+
+ def CharSequence printShortInfo(LeafSchemaNode node, int level, InstanceIdentifier path) {
+ return '''
+ <li>«strong((node.QName.localName))» (leaf)</li>
+ '''
+ }
+
+ def CharSequence printShortInfo(LeafListSchemaNode node, int level, InstanceIdentifier path) {
+ return '''
+ <li>«strong((node.QName.localName))» (leaf-list)</li>
+ '''
+ }
+
+ def CharSequence localLink(InstanceIdentifier identifier, CharSequence text) '''
+ <a href="#«FOR cmp : identifier.path SEPARATOR "/"»«cmp.nodeType.localName»«ENDFOR»">«text»</a>
+ '''
+
+
+ private def dispatch InstanceIdentifier append(InstanceIdentifier identifier, ContainerSchemaNode node) {
+ val pathArguments = new ArrayList(identifier.path)
+ pathArguments.add(new NodeIdentifier(node.QName));
+ return new InstanceIdentifier(pathArguments);
+ }
+
+ private def dispatch InstanceIdentifier append(InstanceIdentifier identifier, ListSchemaNode node) {
+ val pathArguments = new ArrayList(identifier.path)
+ val keyValues = new LinkedHashMap<QName,Object>();
+ if(node.keyDefinition != null) {
+ for(definition : node.keyDefinition) {
+ keyValues.put(definition,new Object);
+ }
+ }
+ pathArguments.add(new NodeIdentifierWithPredicates(node.QName,keyValues));
+ return new InstanceIdentifier(pathArguments);
+ }
+
+
+ def asXmlPath(InstanceIdentifier identifier) {
+ return "";
+ }
+
+ def asRestconfPath(InstanceIdentifier identifier) {
+ val it = new StringBuilder();
+ append(currentModule.name)
+ append(":")
+ var previous = false;
+ for(arg : identifier.path) {
+ if(previous) append("/")
+ append(arg.nodeType.localName);
+ previous = true;
+ if(arg instanceof NodeIdentifierWithPredicates) {
+ val nodeIdentifier = arg as NodeIdentifierWithPredicates;
+ for(qname : nodeIdentifier.keyValues.keySet) {
+ append("/{");
+ append(qname.localName)
+ append("}")
+ }
+ }
+ }
+
+ return it.toString;
+ }
+
+ private def String schemaPathAsRestconfPath(Module module, SchemaPath schemaPath, SchemaContext ctx) {
+ val Map<String, String> imports = new HashMap();
+ for (mImport : module.imports) {
+ imports.put(mImport.prefix, mImport.moduleName)
+ }
+
+ val List<QName> path = schemaPath.path
+ val StringBuilder pathString = new StringBuilder()
+ if (schemaPath.absolute) {
+ pathString.append("/")
+ }
+
+ val QName qname = path.get(0)
+ var Object parent = ctx.findModuleByNamespaceAndRevision(qname.namespace, qname.revision)
+
+ for (name : path) {
+ if (parent instanceof DataNodeContainer) {
+ var SchemaNode node = (parent as DataNodeContainer).getDataChildByName(name)
+ if (node == null && (parent instanceof Module)) {
+ val notifications = (parent as Module).notifications;
+ for (notification : notifications) {
+ if (notification.QName.equals(name)) {
+ node = notification
+ }
+ }
+ }
if (node == null && (parent instanceof Module)) {
val rpcs = (parent as Module).rpcs;
for (rpc : rpcs) {
}
}
}
-\r
- if (!(node instanceof ChoiceNode) && !(node instanceof ChoiceCaseNode)) {\r
- var String prefix = name.prefix\r
- var String moduleName\r
- if (prefix == null || "".equals(prefix) || prefix.equals(module.prefix)) {\r
- moduleName = module.name\r
- } else {\r
- moduleName = imports.get(prefix)\r
- }\r
- pathString.append(moduleName)\r
- pathString.append(":")\r
- pathString.append(name.localName)\r
- pathString.append("/")\r
- }\r
- parent = node\r
- } else if (parent instanceof ChoiceNode) {\r
- parent = (parent as ChoiceNode).getCaseNodeByName(qname.localName)\r
- }\r
- }\r
- return pathString.toString;\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.descAndRefLi»\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 rpcInfo(RpcDefinition rpc,InstanceIdentifier path) '''\r
- <ul>\r
- «rpc.descAndRefLi»\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) '''\r
- <ul>\r
- «ext.descAndRefLi»\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 descAndRefLi(SchemaNode node) '''\r
- «listItem(node.description)»\r
- «listItem("Reference", node.reference)»\r
- '''\r
-\r
- def CharSequence descAndRef(SchemaNode node) '''\r
- «node.description»\r
- «IF node.reference !== null»\r
- Reference «node.reference»\r
- «ENDIF»\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»: «value»\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 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
+
+ if (!(node instanceof ChoiceNode) && !(node instanceof ChoiceCaseNode)) {
+ var String prefix = name.prefix
+ var String moduleName
+ if (prefix == null || "".equals(prefix) || prefix.equals(module.prefix)) {
+ moduleName = module.name
+ } else {
+ moduleName = imports.get(prefix)
+ }
+ pathString.append(moduleName)
+ pathString.append(":")
+ pathString.append(name.localName)
+ pathString.append("/")
+ }
+ parent = node
+ } else if (parent instanceof ChoiceNode) {
+ parent = (parent as ChoiceNode).getCaseNodeByName(qname.localName)
+ }
+ }
+ return pathString.toString;
+ }
+
+
+ def CharSequence childNodesInfoTree(Map<SchemaPath, DataSchemaNode> childNodes) '''
+ «IF childNodes !== null && !childNodes.empty»
+ «FOR child : childNodes.values»
+ «childInfo(child, childNodes)»
+ «ENDFOR»
+ «ENDIF»
+ '''
+
+ def CharSequence childInfo(DataSchemaNode node, Map<SchemaPath, DataSchemaNode> childNodes) '''
+ «val String path = nodeSchemaPathToPath(node, childNodes)»
+ «IF path != null»
+ «code(path)»
+ «IF node !== null»
+ <ul>
+ «node.descAndRefLi»
+ </ul>
+ «ENDIF»
+ «ENDIF»
+ '''
+
+ private def CharSequence treeSet(Collection<DataSchemaNode> childNodes, InstanceIdentifier path) '''
+ «IF childNodes !== null && !childNodes.empty»
+ <ul>
+ «FOR child : childNodes»
+ <li>
+ «child.tree(path)»
+ </li>
+ «ENDFOR»
+ </ul>
+ «ENDIF»
+ '''
+
+ def listKeys(ListSchemaNode node) '''
+ [«FOR key : node.keyDefinition SEPARATOR " "»«key.localName»«ENDFOR»]
+ '''
+
+ private def CharSequence rpcInfo(RpcDefinition rpc,InstanceIdentifier path) '''
+ <ul>
+ «rpc.descAndRefLi»
+ <li>
+ «rpc.input.tree(path)»
+ </li>
+ <li>
+ «rpc.output.tree(path)»
+ </li>
+ </ul>
+ '''
+
+ private def CharSequence extensionInfo(ExtensionDefinition ext) '''
+ <ul>
+ «ext.descAndRefLi»
+ «listItem("Argument", ext.argument)»
+ </ul>
+ '''
+
+ private def dispatch CharSequence tree(Void obj, InstanceIdentifier path) '''
+ '''
+
+
+
+ /* #################### RESTRICTIONS #################### */
+ private def restrictions(TypeDefinition<?> type) '''
+ «type.toLength»
+ «type.toRange»
+ '''
+
+ private def dispatch toLength(TypeDefinition<?> type) {
+ }
+
+ private def dispatch toLength(BinaryTypeDefinition type) '''
+ «type.lengthConstraints.toLengthStmt»
+ '''
+
+ private def dispatch toLength(StringTypeDefinition type) '''
+ «type.lengthConstraints.toLengthStmt»
+ '''
+
+ private def dispatch toLength(ExtendedType type) '''
+ «type.lengthConstraints.toLengthStmt»
+ '''
+
+ private def dispatch toRange(TypeDefinition<?> type) {
+ }
+
+ private def dispatch toRange(DecimalTypeDefinition type) '''
+ «type.rangeConstraints.toRangeStmt»
+ '''
+
+ private def dispatch toRange(IntegerTypeDefinition type) '''
+ «type.rangeConstraints.toRangeStmt»
+ '''
+
+ private def dispatch toRange(UnsignedIntegerTypeDefinition type) '''
+ «type.rangeConstraints.toRangeStmt»
+ '''
+
+ private 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(CharSequence str) '''<strong>«str»</strong>'''
+ private def italic(CharSequence str) '''<i>«str»</i>'''
+ private def pre(CharSequence str) '''<pre>«str»</pre>'''
+
+ def CharSequence descAndRefLi(SchemaNode node) '''
+ «listItem(node.description)»
+ «listItem("Reference", node.reference)»
+ '''
+
+ def CharSequence descAndRef(SchemaNode node) '''
+ «node.description»
+ «IF node.reference !== null»
+ Reference «node.reference»
+ «ENDIF»
+ '''
+
+ 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»: «value»
+ </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 dispatch addedByInfo(SchemaNode node) '''
+ '''
+
+ private def dispatch addedByInfo(DataSchemaNode node) '''
+ «IF node.augmenting»(A)«ENDIF»«IF node.addedByUses»(U)«ENDIF»
+ '''
+
+ private def dispatch isAddedBy(SchemaNode node) {
+ return false;
+ }
+
+ private def dispatch isAddedBy(DataSchemaNode node) {
+ if (node.augmenting || node.addedByUses) {
+ return true
+ } else {
+ return false;
+ }
+ }
+
+ private def dispatch nodeName(SchemaNode node) '''
+ «IF node.isAddedBy»
+ «italic(node.QName.localName)»«node.addedByInfo»
+ «ELSE»
+ «node.QName.localName»«node.addedByInfo»
+ «ENDIF»
+ '''
+
+ private def dispatch nodeName(ContainerSchemaNode node) '''
+ «IF node.isAddedBy»
+ «strong(italic(node.QName.localName))»«node.addedByInfo»
+ «ELSE»
+ «strong(node.QName.localName)»«node.addedByInfo»
+ «ENDIF»
+ '''
+
+ private def dispatch nodeName(ListSchemaNode node) '''
+ «IF node.isAddedBy»
+ «strong(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»
+ '''
+
+}