var Module currentModule;
val Map<String, String> imports = new HashMap();
var SchemaContext ctx;
-
+
StringBuilder augmentChildNodesAsString
-
+
DataSchemaNode lastNodeInTargetPath = null
def generate(SchemaContext context, File targetPath, Set<Module> modulesToGen) throws IOException {
}
return '''
<h2>Augmentations</h2>
-
+
<ul>
«FOR augment : module.augmentations»
<li>
«FOR childNode : augment.childNodes»
«childNode.printSchemaNodeInfo»
«ENDFOR»
-
+
<h3>Example</h3>
«createAugmentChildNodesAsString(new ArrayList(augment.childNodes))»
«printNodeChildren(parseTargetPath(augment.targetPath))»
</ul>
'''
}
-
+
private def createAugmentChildNodesAsString(List<DataSchemaNode> childNodes) {
augmentChildNodesAsString = new StringBuilder();
augmentChildNodesAsString.append(printNodeChildren(childNodes))
return ''
}
-
+
private def parseTargetPath(SchemaPath path) {
val List<DataSchemaNode> nodes = new ArrayList<DataSchemaNode>();
for (QName pathElement : path.pathFromRoot) {
if(! nodes.empty) {
lastNodeInTargetPath = nodes.get(nodes.size() - 1)
}
-
+
val List<DataSchemaNode> targetPathNodes = new ArrayList<DataSchemaNode>();
targetPathNodes.add(lastNodeInTargetPath)
-
+
return targetPathNodes
}
-
+
private def DataSchemaNode findNodeInChildNodes(QName findingNode, Iterable<DataSchemaNode> childNodes) {
for(child : childNodes) {
if (child.QName.equals(findingNode))
}
}
}
-
+
private def printNodeChildren(List<DataSchemaNode> childNodes) {
if (childNodes.empty) {
return ''
}
-
- return
+
+ return
'''
<pre>
«printAugmentedNode(childNodes.get(0))»
</pre>
'''
}
-
+
private def CharSequence printAugmentedNode(DataSchemaNode child) {
-
+
if(child instanceof ChoiceCaseNode)
return ''
-
+
return
'''
«IF child instanceof ContainerSchemaNode»
«ENDIF»
'''
}
-
+
private def printChoiceNode(ChoiceSchemaNode child) {
val List<ChoiceCaseNode> cases = new ArrayList(child.cases);
if(!cases.empty) {
printAugmentedNode(caseChildNode)
}
}
-
+
private def printListNode(ListSchemaNode listNode) {
return
'''
</«listNode.QName.localName»>
'''
}
-
+
private def printContainerNode(ContainerSchemaNode containerNode) {
return
'''
</«containerNode.QName.localName»>
'''
}
-
+
private def printLeafListNode(LeafListSchemaNode leafListNode) {
return
'''
<«leafListNode.QName.localName»>. . .</«leafListNode.QName.localName»>
'''
}
-
+
private def printAnyXmlNode(AnyXmlSchemaNode anyXmlNode) {
- return
+ return
'''
<«anyXmlNode.QName.localName»>. . .</«anyXmlNode.QName.localName»>
'''
}
-
+
private def printLeafNode(LeafSchemaNode leafNode) {
- return
+ return
'''
<«leafNode.QName.localName»>. . .</«leafNode.QName.localName»>
'''
import org.sonatype.plexus.build.incremental.DefaultBuildContext
class WadlRestconfGenerator {
-
- File path
- static val BuildContext CTX = new DefaultBuildContext();
- static val PATH_DELIMETER = '/'
- var SchemaContext context;
- var List<DataSchemaNode> configData;
- var List<DataSchemaNode> operationalData;
- var Module module;
- var List<LeafSchemaNode> pathListParams;
-
- new(File targetPath) {
- if (!targetPath.exists) targetPath.mkdirs
- path = targetPath
- }
-
- def generate(SchemaContext context, Set<Module> modules) {
+
+ File path
+ static val BuildContext CTX = new DefaultBuildContext();
+ static val PATH_DELIMETER = '/'
+ var SchemaContext context;
+ var List<DataSchemaNode> configData;
+ var List<DataSchemaNode> operationalData;
+ var Module module;
+ var List<LeafSchemaNode> pathListParams;
+
+ new(File targetPath) {
+ if (!targetPath.exists) targetPath.mkdirs
+ path = targetPath
+ }
+
+ def generate(SchemaContext context, Set<Module> modules) {
val result = new HashSet;
- this.context = context
- for (module : modules) {
- val dataContainers = module.childNodes.filter[it|it.listOrContainer]
- if (!dataContainers.empty || !module.rpcs.nullOrEmpty) {
- configData = new ArrayList
- operationalData = new ArrayList
-
- for (data : dataContainers) {
- if (data.configuration) {
- configData.add(data)
- } else {
- operationalData.add(data)
- }
- }
-
- this.module = module
- val destination = new File(path, '''«module.name».wadl''')
- val fw = new OutputStreamWriter(CTX.newFileOutputStream(destination), StandardCharsets.UTF_8)
- val bw = new BufferedWriter(fw)
- bw.append(application);
- bw.close();
- fw.close();
- result.add(destination)
- }
- }
- return result
- }
-
- private def application() '''
- <?xml version="1.0"?>
- <application xmlns="http://wadl.dev.java.net/2009/02" «module.importsAsNamespaces» xmlns:«module.prefix»="«module.namespace»">
-
- «grammars»
-
- «resources»
- </application>
- '''
-
- private def importsAsNamespaces(Module module) '''
- «FOR imprt : module.imports»
- xmlns:«imprt.prefix»="«context.findModuleByName(imprt.moduleName, imprt.revision).namespace»"
- «ENDFOR»
- '''
-
- private def grammars() '''
- <grammars>
- <include href="«module.name».yang"/>
- «FOR imprt : module.imports»
- <include href="«imprt.moduleName».yang"/>
- «ENDFOR»
- </grammars>
- '''
-
- private def resources() '''
- <resources base="http://localhost:9998/restconf">
- «resourceOperational»
- «resourceConfig»
- «resourceOperations»
- </resources>
- '''
-
- private def resourceOperational() '''
- «IF !operationalData.nullOrEmpty»
- <resource path="operational">
- «FOR schemaNode : operationalData»
- «schemaNode.firstResource(false)»
- «ENDFOR»
- </resource>
- «ENDIF»
- '''
-
- private def resourceConfig() '''
- «IF !configData.nullOrEmpty»
- <resource path="config">
- «FOR schemaNode : configData»
- «schemaNode.mehodPost»
- «ENDFOR»
- «FOR schemaNode : configData»
- «schemaNode.firstResource(true)»
- «ENDFOR»
- </resource>
- «ENDIF»
- '''
-
- private def resourceOperations() '''
- «IF !module.rpcs.nullOrEmpty»
- <resource path="operations">
- «FOR rpc : module.rpcs»
- <resource path="«module.name»:«rpc.QName.localName»">
- «methodPostRpc(rpc.input !== null, rpc.output !== null)»
- </resource>
- «ENDFOR»
- </resource>
- «ENDIF»
- '''
-
- private def String firstResource(DataSchemaNode schemaNode, boolean config) '''
- <resource path="«module.name»:«schemaNode.createPath»">
- «resourceBody(schemaNode, config)»
- </resource>
- '''
-
- private def String resource(DataSchemaNode schemaNode, boolean config) '''
- <resource path="«schemaNode.createPath»">
- «resourceBody(schemaNode, config)»
- </resource>
- '''
-
- private def String createPath(DataSchemaNode schemaNode) {
- pathListParams = new ArrayList
- var StringBuilder path = new StringBuilder
- path.append(schemaNode.QName.localName)
- if (schemaNode instanceof ListSchemaNode) {
- for (listKey : schemaNode.keyDefinition) {
- pathListParams.add((schemaNode as DataNodeContainer).getDataChildByName(listKey) as LeafSchemaNode)
- path.append(PATH_DELIMETER)
- path.append('{')
- path.append(listKey.localName)
- path.append('}')
- }
- }
- return path.toString
- }
-
- private def String resourceBody(DataSchemaNode schemaNode, boolean config) '''
- «IF !pathListParams.nullOrEmpty»
- «resourceParams»
- «ENDIF»
- «schemaNode.methodGet»
- «val children = (schemaNode as DataNodeContainer).childNodes.filter[it|it.listOrContainer]»
- «IF config»
- «schemaNode.methodDelete»
- «schemaNode.mehodPut»
- «FOR child : children»
- «child.mehodPost»
- «ENDFOR»
- «ENDIF»
- «FOR child : children»
- «child.resource(config)»
- «ENDFOR»
- '''
-
- private def resourceParams() '''
- «FOR pathParam : pathListParams»
- «IF pathParam !== null»
- «val type = pathParam.type.QName.localName»
- <param required="true" style="template" name="«pathParam.QName.localName»" type="«type»"/>
- «ENDIF»
- «ENDFOR»
- '''
-
- private def methodGet(DataSchemaNode schemaNode) '''
- <method name="GET">
- <response>
- «representation(schemaNode.QName.namespace, schemaNode.QName.localName)»
- </response>
- </method>
- '''
-
- private def mehodPut(DataSchemaNode schemaNode) '''
- <method name="PUT">
- <request>
- «representation(schemaNode.QName.namespace, schemaNode.QName.localName)»
- </request>
- </method>
- '''
-
- private def mehodPost(DataSchemaNode schemaNode) '''
- <method name="POST">
- <request>
- «representation(schemaNode.QName.namespace, schemaNode.QName.localName)»
- </request>
- </method>
- '''
-
- private def methodPostRpc(boolean input, boolean output) '''
- <method name="POST">
- «IF input»
- <request>
- «representation(null, "input")»
- </request>
- «ENDIF»
- «IF output»
- <response>
- «representation(null, "output")»
- </response>
- «ENDIF»
- </method>
- '''
-
- private def methodDelete(DataSchemaNode schemaNode) '''
- <method name="DELETE" />
- '''
-
- private def representation(URI prefix, String name) '''
- «val elementData = name»
- <representation mediaType="application/xml" element="«elementData»"/>
- <representation mediaType="text/xml" element="«elementData»"/>
- <representation mediaType="application/json" element="«elementData»"/>
- <representation mediaType="application/yang.data+xml" element="«elementData»"/>
- <representation mediaType="application/yang.data+json" element="«elementData»"/>
- '''
-
- private def boolean isListOrContainer(DataSchemaNode schemaNode) {
- return (schemaNode instanceof ListSchemaNode || schemaNode instanceof ContainerSchemaNode)
- }
+ this.context = context
+ for (module : modules) {
+ val dataContainers = module.childNodes.filter[it|it.listOrContainer]
+ if (!dataContainers.empty || !module.rpcs.nullOrEmpty) {
+ configData = new ArrayList
+ operationalData = new ArrayList
+
+ for (data : dataContainers) {
+ if (data.configuration) {
+ configData.add(data)
+ } else {
+ operationalData.add(data)
+ }
+ }
+
+ this.module = module
+ val destination = new File(path, '''«module.name».wadl''')
+ val fw = new OutputStreamWriter(CTX.newFileOutputStream(destination), StandardCharsets.UTF_8)
+ val bw = new BufferedWriter(fw)
+ bw.append(application);
+ bw.close();
+ fw.close();
+ result.add(destination)
+ }
+ }
+ return result
+ }
+
+ private def application() '''
+ <?xml version="1.0"?>
+ <application xmlns="http://wadl.dev.java.net/2009/02" «module.importsAsNamespaces» xmlns:«module.prefix»="«module.namespace»">
+
+ «grammars»
+
+ «resources»
+ </application>
+ '''
+
+ private def importsAsNamespaces(Module module) '''
+ «FOR imprt : module.imports»
+ xmlns:«imprt.prefix»="«context.findModuleByName(imprt.moduleName, imprt.revision).namespace»"
+ «ENDFOR»
+ '''
+
+ private def grammars() '''
+ <grammars>
+ <include href="«module.name».yang"/>
+ «FOR imprt : module.imports»
+ <include href="«imprt.moduleName».yang"/>
+ «ENDFOR»
+ </grammars>
+ '''
+
+ private def resources() '''
+ <resources base="http://localhost:9998/restconf">
+ «resourceOperational»
+ «resourceConfig»
+ «resourceOperations»
+ </resources>
+ '''
+
+ private def resourceOperational() '''
+ «IF !operationalData.nullOrEmpty»
+ <resource path="operational">
+ «FOR schemaNode : operationalData»
+ «schemaNode.firstResource(false)»
+ «ENDFOR»
+ </resource>
+ «ENDIF»
+ '''
+
+ private def resourceConfig() '''
+ «IF !configData.nullOrEmpty»
+ <resource path="config">
+ «FOR schemaNode : configData»
+ «schemaNode.mehodPost»
+ «ENDFOR»
+ «FOR schemaNode : configData»
+ «schemaNode.firstResource(true)»
+ «ENDFOR»
+ </resource>
+ «ENDIF»
+ '''
+
+ private def resourceOperations() '''
+ «IF !module.rpcs.nullOrEmpty»
+ <resource path="operations">
+ «FOR rpc : module.rpcs»
+ <resource path="«module.name»:«rpc.QName.localName»">
+ «methodPostRpc(rpc.input !== null, rpc.output !== null)»
+ </resource>
+ «ENDFOR»
+ </resource>
+ «ENDIF»
+ '''
+
+ private def String firstResource(DataSchemaNode schemaNode, boolean config) '''
+ <resource path="«module.name»:«schemaNode.createPath»">
+ «resourceBody(schemaNode, config)»
+ </resource>
+ '''
+
+ private def String resource(DataSchemaNode schemaNode, boolean config) '''
+ <resource path="«schemaNode.createPath»">
+ «resourceBody(schemaNode, config)»
+ </resource>
+ '''
+
+ private def String createPath(DataSchemaNode schemaNode) {
+ pathListParams = new ArrayList
+ var StringBuilder path = new StringBuilder
+ path.append(schemaNode.QName.localName)
+ if (schemaNode instanceof ListSchemaNode) {
+ for (listKey : schemaNode.keyDefinition) {
+ pathListParams.add((schemaNode as DataNodeContainer).getDataChildByName(listKey) as LeafSchemaNode)
+ path.append(PATH_DELIMETER)
+ path.append('{')
+ path.append(listKey.localName)
+ path.append('}')
+ }
+ }
+ return path.toString
+ }
+
+ private def String resourceBody(DataSchemaNode schemaNode, boolean config) '''
+ «IF !pathListParams.nullOrEmpty»
+ «resourceParams»
+ «ENDIF»
+ «schemaNode.methodGet»
+ «val children = (schemaNode as DataNodeContainer).childNodes.filter[it|it.listOrContainer]»
+ «IF config»
+ «schemaNode.methodDelete»
+ «schemaNode.mehodPut»
+ «FOR child : children»
+ «child.mehodPost»
+ «ENDFOR»
+ «ENDIF»
+ «FOR child : children»
+ «child.resource(config)»
+ «ENDFOR»
+ '''
+
+ private def resourceParams() '''
+ «FOR pathParam : pathListParams»
+ «IF pathParam !== null»
+ «val type = pathParam.type.QName.localName»
+ <param required="true" style="template" name="«pathParam.QName.localName»" type="«type»"/>
+ «ENDIF»
+ «ENDFOR»
+ '''
+
+ private def methodGet(DataSchemaNode schemaNode) '''
+ <method name="GET">
+ <response>
+ «representation(schemaNode.QName.namespace, schemaNode.QName.localName)»
+ </response>
+ </method>
+ '''
+
+ private def mehodPut(DataSchemaNode schemaNode) '''
+ <method name="PUT">
+ <request>
+ «representation(schemaNode.QName.namespace, schemaNode.QName.localName)»
+ </request>
+ </method>
+ '''
+
+ private def mehodPost(DataSchemaNode schemaNode) '''
+ <method name="POST">
+ <request>
+ «representation(schemaNode.QName.namespace, schemaNode.QName.localName)»
+ </request>
+ </method>
+ '''
+
+ private def methodPostRpc(boolean input, boolean output) '''
+ <method name="POST">
+ «IF input»
+ <request>
+ «representation(null, "input")»
+ </request>
+ «ENDIF»
+ «IF output»
+ <response>
+ «representation(null, "output")»
+ </response>
+ «ENDIF»
+ </method>
+ '''
+
+ private def methodDelete(DataSchemaNode schemaNode) '''
+ <method name="DELETE" />
+ '''
+
+ private def representation(URI prefix, String name) '''
+ «val elementData = name»
+ <representation mediaType="application/xml" element="«elementData»"/>
+ <representation mediaType="text/xml" element="«elementData»"/>
+ <representation mediaType="application/json" element="«elementData»"/>
+ <representation mediaType="application/yang.data+xml" element="«elementData»"/>
+ <representation mediaType="application/yang.data+json" element="«elementData»"/>
+ '''
+
+ private def boolean isListOrContainer(DataSchemaNode schemaNode) {
+ return (schemaNode instanceof ListSchemaNode || schemaNode instanceof ContainerSchemaNode)
+ }
}