import java.io.IOException\r
import java.util.HashSet\r
import java.io.BufferedWriter\r
-import java.io.OutputStream;\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.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.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
+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
path.mkdirs();\r
val it = new HashSet;\r
for (module : modulesToGen) {\r
- add(module.generateDocumentation());\r
+ add(generateDocumentation(module, context));\r
}\r
return it;\r
}\r
\r
- def generateDocumentation(Module module) {\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(module.generate);\r
+ bw.append(generate(module, ctx));\r
bw.close();\r
fw.close();\r
} catch (IOException e) {\r
return destination;\r
}\r
\r
- def generate(Module module) '''\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
- «module.body»\r
+ «body(module, ctx)»\r
</body>\r
</html>\r
'''\r
\r
- def body(Module module) '''\r
+ def body(Module module, SchemaContext ctx) '''\r
«header(module)»\r
\r
«typeDefinitions(module)»\r
\r
«notifications(module)»\r
\r
- «augmentations(module)»\r
+ «augmentations(module, ctx)»\r
\r
«rpcs(module)»\r
\r
<li>\r
«strong("typedef " + typedef.QName.localName)»\r
<ul>\r
- «typedef.descAndRef»\r
+ «typedef.descAndRefLi»\r
«typedef.restrictions»\r
</ul>\r
</li>\r
<li>\r
«strong("identity " + identity.QName.localName)»\r
<ul>\r
- «identity.descAndRef»\r
+ «identity.descAndRefLi»\r
«IF identity.baseIdentity != null»\r
«listItem("base", identity.baseIdentity.QName.localName)»\r
«ENDIF»\r
<li>\r
«strong("grouping " + grouping.QName.localName)»\r
<ul>\r
- «grouping.descAndRef»\r
+ «grouping.descAndRefLi»\r
</ul>\r
</li>\r
«ENDFOR»\r
'''\r
}\r
\r
- def augmentations(Module module) {\r
+ def augmentations(Module module, SchemaContext context) {\r
if (module.augmentations.empty) {\r
return '';\r
}\r
<ul>\r
«FOR augment : module.augmentations»\r
<li>\r
- augment\r
- «augment.augmentationInfo(InstanceIdentifier.builder().toInstance())»\r
- «augment.childNodes.printChildren(2,InstanceIdentifier.builder().toInstance())»\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
if (notificationdefs.empty) {\r
return '';\r
}\r
- \r
+\r
return '''\r
<h2>Notifications</h2>\r
«FOR notificationdef : notificationdefs»\r
- \r
+\r
<h3>«notificationdef.nodeName»</h3>\r
- «notificationdef.notificationInfo(InstanceIdentifier.builder().node(notificationdef.QName).toInstance())»\r
+ «notificationdef.descAndRef»\r
+ «notificationdef.childNodes.printChildren(3,InstanceIdentifier.builder().toInstance())»\r
«ENDFOR»\r
'''\r
}\r
if (module.rpcs.empty) {\r
return '';\r
}\r
- \r
+\r
return '''\r
<h2>RPC Definitions</h2>\r
«FOR rpc : module.rpcs»\r
<li>\r
<h3>«ext.nodeName»</h3>\r
</li>\r
+ «extensionInfo(ext)»\r
«ENDFOR»\r
'''\r
}\r
<li>\r
«strong("feature " + feature.QName.localName)»\r
<ul>\r
- «feature.descAndRef»\r
+ «feature.descAndRefLi»\r
</ul>\r
</li>\r
«ENDFOR»\r
\r
def header(Module module) '''\r
<h1>«module.name»</h1>\r
- \r
+\r
<h2>Base Information</h2>\r
<dl>\r
<dt>Prefix</dt>\r
<dd>«pre(module.namespace.toString)»</dd>\r
<dt>Revision</dt>\r
<dd>«pre(REVISION_FORMAT.format(module.revision))»</dd>\r
- \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
+\r
def code(String string) '''<code>«string»</code>'''\r
- \r
+\r
def process(Module module) {\r
throw new UnsupportedOperationException("TODO: auto-generated method stub")\r
}\r
«strong("module " + module.name)»\r
«module.childNodes.treeSet(InstanceIdentifier.builder.toInstance())»\r
'''\r
- \r
+\r
private def dispatch CharSequence tree(ChoiceNode node,InstanceIdentifier path) '''\r
«node.nodeName» (choice)\r
«casesTree(node.cases,path)»\r
'''\r
- \r
+\r
def casesTree(Set<ChoiceCaseNode> nodes,InstanceIdentifier path) '''\r
<ul>\r
«FOR node : nodes»\r
«localLink(newPath,node.nodeName)»\r
«node.childNodes.treeSet(newPath)»\r
'''\r
- \r
+\r
private def dispatch CharSequence tree(ContainerSchemaNode node,InstanceIdentifier path) '''\r
«val newPath = path.append(node)»\r
«localLink(newPath,node.nodeName)»\r
«IF childNodes !== null && !childNodes.empty»\r
<h2>Child nodes</h2>\r
\r
- «childNodes.printChildren(2,InstanceIdentifier.builder().toInstance())»\r
+ «childNodes.printChildren(3,InstanceIdentifier.builder().toInstance())»\r
«ENDIF»\r
'''\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 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
«childNode.printShortInfo(level,path)»\r
«ENDFOR»\r
</ul>\r
- \r
+ «ENDIF»\r
+\r
«IF !path.path.empty»\r
<h3>XML example</h3>\r
«nodes.xmlExample(path.path.last.nodeType,path)»\r
\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
+\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
- \r
+\r
private def dispatch CharSequence asXmlExampleTag(LeafSchemaNode node, InstanceIdentifier identifier) '''\r
«node.QName.xmlExampleTag("...")»\r
'''\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
+\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
+\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
+\r
+\r
private def dispatch CharSequence asXmlExampleTag(DataSchemaNode node, InstanceIdentifier identifier) '''\r
<!-- noop -->\r
'''\r
- \r
- \r
+\r
+\r
def xmlExampleTag(QName name, CharSequence data) {\r
return '''<«name.localName» xmlns="«name.namespace»">«data»</«name.localName»>'''\r
}\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
«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
+\r
private def dispatch CharSequence printInfo(ListSchemaNode node, int level, InstanceIdentifier path) '''\r
«val newPath = path.append(node)»\r
«header(level,newPath)»\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
+\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
+\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
+\r
def CharSequence printShortInfo(LeafListSchemaNode node, int level, InstanceIdentifier path) {\r
return '''\r
<li>«strong((node.QName.localName))» (leaf-list)</li>\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
+\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
+\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
pathArguments.add(new NodeIdentifierWithPredicates(node.QName,keyValues));\r
return new InstanceIdentifier(pathArguments);\r
}\r
- \r
- \r
+\r
+\r
def asXmlPath(InstanceIdentifier identifier) {\r
return "";\r
}\r
- \r
+\r
def asRestconfPath(InstanceIdentifier identifier) {\r
val it = new StringBuilder();\r
append(currentModule.name)\r
}\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
+ 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.localName.equals(name.localName)) {\r
+ node = notification\r
+ }\r
+ }\r
+ }\r
+\r
+ if (!(node instanceof ChoiceNode) && !(node instanceof ChoiceCaseNode)) {\r
+ var String prefix = node.QName.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(node.QName.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
«code(path)»\r
«IF node !== null»\r
<ul>\r
- «node.descAndRef»\r
+ «node.descAndRefLi»\r
</ul>\r
«ENDIF»\r
«ENDIF»\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
+ «rpc.descAndRefLi»\r
<li>\r
«rpc.input.tree(path)»\r
</li>\r
</ul>\r
'''\r
\r
- private def CharSequence extensionInfo(ExtensionDefinition ext, InstanceIdentifier path) '''\r
+ private def CharSequence extensionInfo(ExtensionDefinition ext) '''\r
<ul>\r
- «ext.descAndRef»\r
+ «ext.descAndRefLi»\r
«listItem("Argument", ext.argument)»\r
</ul>\r
'''\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
+ 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
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
+ «name»: «value»\r
</li>\r
«ENDIF»\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