*/
package org.opendaylight.mdsal.binding.yang.wadl.generator
+import static com.google.common.base.Preconditions.checkState;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.BufferedWriter
import java.io.File
+import java.io.IOException
import java.io.OutputStreamWriter
-import java.net.URI
import java.nio.charset.StandardCharsets
import java.util.ArrayList
+import java.util.Collection
import java.util.HashSet
import java.util.List
-import java.util.Set
+import org.opendaylight.yangtools.yang.common.XMLNamespace
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
import org.opendaylight.yangtools.yang.model.api.Module
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
import org.sonatype.plexus.build.incremental.BuildContext
class WadlRestconfGenerator {
+ static val Logger LOG = LoggerFactory.getLogger(WadlRestconfGenerator)
+
static val PATH_DELIMETER = '/'
val BuildContext buildContext;
val File path
var List<LeafSchemaNode> pathListParams;
new(BuildContext buildContext, File targetPath) {
- if (!targetPath.exists) targetPath.mkdirs
+ if (!targetPath.exists) {
+ checkState(targetPath.mkdirs, "Unable to create directory: %s", targetPath);
+ }
path = targetPath
this.buildContext = buildContext
}
- def generate(EffectiveModelContext context, Set<Module> modules) {
+ def generate(EffectiveModelContext context, Collection<? extends Module> modules) {
val result = new HashSet;
this.context = context
for (module : modules) {
this.module = module
val destination = new File(path, '''«module.name».wadl''')
- val fw = new OutputStreamWriter(buildContext.newFileOutputStream(destination), StandardCharsets.UTF_8)
- val bw = new BufferedWriter(fw)
- bw.append(application);
- bw.close();
- fw.close();
+ var OutputStreamWriter fw
+ var BufferedWriter bw
+ try {
+ fw = new OutputStreamWriter(buildContext.newFileOutputStream(destination), StandardCharsets.UTF_8)
+ bw = new BufferedWriter(fw)
+ bw.append(application);
+ } catch (IOException e) {
+ LOG.error("Failed to emit file {}", destination, e);
+ } finally {
+ if (bw !== null) {
+ bw.close();
+ }
+ if (fw !== null) {
+ fw.close();
+ }
+ }
result.add(destination)
}
}
<?xml version="1.0"?>
<application xmlns="http://wadl.dev.java.net/2009/02" «module.importsAsNamespaces» xmlns:«module.prefix»="«module.namespace»">
- «grammars»
+ <grammars>
+ <include href="«module.name».yang"/>
+ «FOR imprt : module.imports»
+ <include href="«imprt.moduleName».yang"/>
+ «ENDFOR»
+ </grammars>
- «resources»
+ <resources base="http://localhost:9998/restconf">
+ «IF !operationalData.nullOrEmpty»
+ <resource path="operational">
+ «FOR schemaNode : operationalData»
+ «schemaNode.firstResource(false)»
+ «ENDFOR»
+ </resource>
+ «ENDIF»
+ «IF !configData.nullOrEmpty»
+ <resource path="config">
+ «FOR schemaNode : configData»
+ «schemaNode.mehodPost»
+ «ENDFOR»
+ «FOR schemaNode : configData»
+ «schemaNode.firstResource(true)»
+ «ENDFOR»
+ </resource>
+ «ENDIF»
+ «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»
+ </resources>
</application>
'''
«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)»
<method name="DELETE" />
'''
- private def representation(URI prefix, String name) '''
+ private def representation(XMLNamespace prefix, String name) '''
«val elementData = name»
<representation mediaType="application/xml" element="«elementData»"/>
<representation mediaType="text/xml" element="«elementData»"/>
<representation mediaType="application/yang.data+json" element="«elementData»"/>
'''
+ @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
+ justification = "https://github.com/spotbugs/spotbugs/issues/811")
private def boolean isListOrContainer(DataSchemaNode schemaNode) {
return (schemaNode instanceof ListSchemaNode || schemaNode instanceof ContainerSchemaNode)
}