From 123a8fe79fa859b5e64e3efbd004d0730e25164d Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Wed, 23 Jun 2021 12:27:44 +0200 Subject: [PATCH] Convert WADL generator to FileGenerator API FileGeneratorFactory acts as a proper bootstrap for generators, and it really pushes us towards a proper generator/template split, slightly reducing the use of Xtend for non-templating purposes. JIRA: MDSAL-232 Change-Id: I5414bd154b02a87eb0cfccf776de54f38ca5fab9 Signed-off-by: Robert Varga --- .../yang/wadl/generator/WadlGenerator.java | 62 ++++------ .../wadl/generator/WadlGeneratorFactory.java | 26 ++++ ...confGenerator.xtend => WadlTemplate.xtend} | 111 ++++++------------ .../yang/wadl/generator/WadlGenTest.java | 90 ++------------ 4 files changed, 88 insertions(+), 201 deletions(-) create mode 100644 binding/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/mdsal/binding/yang/wadl/generator/WadlGeneratorFactory.java rename binding/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/mdsal/binding/yang/wadl/generator/{WadlRestconfGenerator.xtend => WadlTemplate.xtend} (66%) diff --git a/binding/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/mdsal/binding/yang/wadl/generator/WadlGenerator.java b/binding/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/mdsal/binding/yang/wadl/generator/WadlGenerator.java index 93eaa1ff55..0e806959c0 100644 --- a/binding/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/mdsal/binding/yang/wadl/generator/WadlGenerator.java +++ b/binding/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/mdsal/binding/yang/wadl/generator/WadlGenerator.java @@ -7,53 +7,31 @@ */ package org.opendaylight.mdsal.binding.yang.wadl.generator; -import static com.google.common.base.Preconditions.checkState; -import static java.util.Objects.requireNonNull; - -import java.io.File; -import java.io.IOException; -import java.util.Collection; -import java.util.Map; +import com.google.common.collect.ImmutableTable; +import com.google.common.collect.Table; import java.util.Set; +import org.opendaylight.yangtools.plugin.generator.api.FileGenerator; +import org.opendaylight.yangtools.plugin.generator.api.GeneratedFile; +import org.opendaylight.yangtools.plugin.generator.api.GeneratedFileLifecycle; +import org.opendaylight.yangtools.plugin.generator.api.GeneratedFilePath; +import org.opendaylight.yangtools.plugin.generator.api.GeneratedFileType; +import org.opendaylight.yangtools.plugin.generator.api.ModuleResourceResolver; import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; import org.opendaylight.yangtools.yang.model.api.Module; -import org.opendaylight.yangtools.yang2sources.spi.BasicCodeGenerator; -import org.opendaylight.yangtools.yang2sources.spi.BuildContextAware; -import org.opendaylight.yangtools.yang2sources.spi.ModuleResourceResolver; -import org.sonatype.plexus.build.incremental.BuildContext; - -public class WadlGenerator implements BasicCodeGenerator, BuildContextAware { - private BuildContext buildContext; - - @Override - public void setAdditionalConfig(final Map additionalConfiguration) { - // No-op - } - - @Override - public void setBuildContext(final BuildContext buildContext) { - this.buildContext = requireNonNull(buildContext); - } - - @Override - public void setResourceBaseDir(final File resourceBaseDir) { - // No-op - } +final class WadlGenerator implements FileGenerator { @Override - public Collection generateSources(final EffectiveModelContext context, final File outputBaseDir, - final Set currentModules, final ModuleResourceResolver moduleResourcePathResolver) - throws IOException { - final File outputDir; - if (outputBaseDir == null) { - // FIXME: this hard-codes the destination - outputDir = new File("target" + File.separator + "generated-sources" + File.separator - + "maven-sal-api-gen" + File.separator + "wadl"); - } else { - outputDir = outputBaseDir; + public Table generateFiles(final EffectiveModelContext context, + final Set localModules, final ModuleResourceResolver moduleResourcePathResolver) { + final var result = ImmutableTable.builder(); + + for (Module module : localModules) { + final CharSequence body = new WadlTemplate(context, module).body(); + if (body != null) { + result.put(GeneratedFileType.RESOURCE, GeneratedFilePath.ofPath(module.getName() + ".wadl"), + GeneratedFile.of(GeneratedFileLifecycle.TRANSIENT, body)); + } } - - checkState(buildContext != null, "BuildContext should have been set"); - return new WadlRestconfGenerator(buildContext, outputDir).generate(context, currentModules); + return result.build(); } } diff --git a/binding/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/mdsal/binding/yang/wadl/generator/WadlGeneratorFactory.java b/binding/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/mdsal/binding/yang/wadl/generator/WadlGeneratorFactory.java new file mode 100644 index 0000000000..6637dd2294 --- /dev/null +++ b/binding/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/mdsal/binding/yang/wadl/generator/WadlGeneratorFactory.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * 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.mdsal.binding.yang.wadl.generator; + +import java.util.Map; +import org.kohsuke.MetaInfServices; +import org.opendaylight.yangtools.plugin.generator.api.AbstractFileGeneratorFactory; +import org.opendaylight.yangtools.plugin.generator.api.FileGenerator; +import org.opendaylight.yangtools.plugin.generator.api.FileGeneratorFactory; + +@MetaInfServices(value = FileGeneratorFactory.class) +public final class WadlGeneratorFactory extends AbstractFileGeneratorFactory { + public WadlGeneratorFactory() { + super(WadlGenerator.class.getName()); + } + + @Override + public FileGenerator newFileGenerator(final Map configuration) { + return new WadlGenerator(); + } +} diff --git a/binding/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/mdsal/binding/yang/wadl/generator/WadlRestconfGenerator.xtend b/binding/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/mdsal/binding/yang/wadl/generator/WadlTemplate.xtend similarity index 66% rename from binding/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/mdsal/binding/yang/wadl/generator/WadlRestconfGenerator.xtend rename to binding/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/mdsal/binding/yang/wadl/generator/WadlTemplate.xtend index bba5e89521..9231b70efc 100644 --- a/binding/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/mdsal/binding/yang/wadl/generator/WadlRestconfGenerator.xtend +++ b/binding/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/mdsal/binding/yang/wadl/generator/WadlTemplate.xtend @@ -1,5 +1,6 @@ /* * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * Copyright (c) 2021 PANTHEON.tech, s.r.o. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, @@ -7,17 +8,10 @@ */ package org.opendaylight.mdsal.binding.yang.wadl.generator -import static com.google.common.base.Preconditions.checkState; +import static java.util.Objects.requireNonNull 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.nio.charset.StandardCharsets import java.util.ArrayList -import java.util.Collection -import java.util.HashSet import java.util.List import org.opendaylight.yangtools.yang.common.XMLNamespace import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode @@ -27,70 +21,37 @@ import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext 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) +final class WadlTemplate { static val PATH_DELIMETER = '/' - val BuildContext buildContext; - val File path - var EffectiveModelContext context; - var List configData; - var List operationalData; - var Module module; - var List pathListParams; - new(BuildContext buildContext, File targetPath) { - if (!targetPath.exists) { - checkState(targetPath.mkdirs, "Unable to create directory: %s", targetPath); - } - path = targetPath - this.buildContext = buildContext - } + val EffectiveModelContext context + val Module module + val List configData = new ArrayList + val List operationalData = new ArrayList - def generate(EffectiveModelContext context, Collection 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 + var List pathListParams - for (data : dataContainers) { - if (data.configuration) { - configData.add(data) - } else { - operationalData.add(data) - } - } + new(EffectiveModelContext context, Module module) { + this.context = requireNonNull(context) + this.module = requireNonNull(module) - this.module = module - val destination = new File(path, '''«module.name».wadl''') - 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(); - } + for (child : module.childNodes) { + if (child instanceof ContainerSchemaNode || child instanceof ListSchemaNode) { + if (child.configuration) { + configData.add(child) + } else { + operationalData.add(child) } - result.add(destination) } } - return result + } + + def body() { + if (!module.rpcs.empty || !configData.empty || !operationalData.empty) { + return application() + } + return null } private def application() ''' @@ -160,10 +121,7 @@ class WadlRestconfGenerator { 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('}') + path.append(PATH_DELIMETER).append('{').append(listKey.localName).append('}') } } return path.toString @@ -177,7 +135,7 @@ class WadlRestconfGenerator { «val children = (schemaNode as DataNodeContainer).childNodes.filter[it|it.listOrContainer]» «IF config» «schemaNode.methodDelete» - «schemaNode.mehodPut» + «schemaNode.methodPut» «FOR child : children» «child.mehodPost» «ENDFOR» @@ -196,7 +154,7 @@ class WadlRestconfGenerator { «ENDFOR» ''' - private def methodGet(DataSchemaNode schemaNode) ''' + private static def methodGet(DataSchemaNode schemaNode) ''' «representation(schemaNode.QName.namespace, schemaNode.QName.localName)» @@ -204,7 +162,7 @@ class WadlRestconfGenerator { ''' - private def mehodPut(DataSchemaNode schemaNode) ''' + private static def methodPut(DataSchemaNode schemaNode) ''' «representation(schemaNode.QName.namespace, schemaNode.QName.localName)» @@ -212,7 +170,7 @@ class WadlRestconfGenerator { ''' - private def mehodPost(DataSchemaNode schemaNode) ''' + private static def mehodPost(DataSchemaNode schemaNode) ''' «representation(schemaNode.QName.namespace, schemaNode.QName.localName)» @@ -220,7 +178,7 @@ class WadlRestconfGenerator { ''' - private def methodPostRpc(boolean input, boolean output) ''' + private static def methodPostRpc(boolean input, boolean output) ''' «IF input» @@ -235,11 +193,11 @@ class WadlRestconfGenerator { ''' - private def methodDelete(DataSchemaNode schemaNode) ''' + private static def methodDelete(DataSchemaNode schemaNode) ''' ''' - private def representation(XMLNamespace prefix, String name) ''' + private static def representation(XMLNamespace prefix, String name) ''' «val elementData = name» @@ -250,8 +208,7 @@ class WadlRestconfGenerator { @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) + private static def boolean isListOrContainer(DataSchemaNode schemaNode) { + return schemaNode instanceof ListSchemaNode || schemaNode instanceof ContainerSchemaNode } - } diff --git a/binding/maven-sal-api-gen-plugin/src/test/java/org/opendaylight/mdsal/binding/yang/wadl/generator/WadlGenTest.java b/binding/maven-sal-api-gen-plugin/src/test/java/org/opendaylight/mdsal/binding/yang/wadl/generator/WadlGenTest.java index f3aa38301a..97758b1fb2 100644 --- a/binding/maven-sal-api-gen-plugin/src/test/java/org/opendaylight/mdsal/binding/yang/wadl/generator/WadlGenTest.java +++ b/binding/maven-sal-api-gen-plugin/src/test/java/org/opendaylight/mdsal/binding/yang/wadl/generator/WadlGenTest.java @@ -8,99 +8,25 @@ package org.opendaylight.mdsal.binding.yang.wadl.generator; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import java.io.File; -import java.io.FileNotFoundException; -import java.net.URI; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; +import com.google.common.collect.Table; import java.util.Optional; import java.util.Set; -import org.junit.After; -import org.junit.Before; import org.junit.Test; +import org.opendaylight.yangtools.plugin.generator.api.GeneratedFile; +import org.opendaylight.yangtools.plugin.generator.api.GeneratedFilePath; +import org.opendaylight.yangtools.plugin.generator.api.GeneratedFileType; import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils; -import org.sonatype.plexus.build.incremental.DefaultBuildContext; public class WadlGenTest { - - private static final String FS = File.separator; - private static final String TEST_PATH = "target" + FS + "test" + FS + "site"; - private static final File GENERATOR_OUTPUT_DIR = new File(TEST_PATH); - - @Before - public void init() { - if (GENERATOR_OUTPUT_DIR.exists()) { - deleteTestDir(GENERATOR_OUTPUT_DIR); - } - assertTrue(GENERATOR_OUTPUT_DIR.mkdirs()); - } - - @After - public void cleanUp() { - if (GENERATOR_OUTPUT_DIR.exists()) { - deleteTestDir(GENERATOR_OUTPUT_DIR); - } - } - @Test - public void testListGeneration() throws Exception { - final List sourceFiles = getSourceFiles("/wadl-gen"); - final EffectiveModelContext context = YangParserTestUtils.parseYangFiles(sourceFiles); + public void testListGeneration() { final WadlGenerator generator = new WadlGenerator(); - generator.setBuildContext(new DefaultBuildContext()); - Collection generatedWadlFiles = generator.generateSources(context, GENERATOR_OUTPUT_DIR, + final EffectiveModelContext context = YangParserTestUtils.parseYangResourceDirectory("/wadl-gen"); + Table generatedWadlFiles = generator.generateFiles(context, Set.copyOf(context.getModules()), (module, representation) -> Optional.empty()); assertEquals(3, generatedWadlFiles.size()); - generatedWadlFiles.forEach(file -> assertTrue(file.exists())); - } - - @Test - public void testListGenerationWithoutPath() throws Exception { - final List sourceFiles = getSourceFiles("/wadl-gen"); - final EffectiveModelContext context = YangParserTestUtils.parseYangFiles(sourceFiles); - final WadlGenerator generator = new WadlGenerator(); - generator.setBuildContext(new DefaultBuildContext()); - Collection generatedWadlFiles = generator.generateSources(context, null, Set.copyOf(context.getModules()), - (module, representation) -> Optional.empty()); - assertEquals(3, generatedWadlFiles.size()); - generatedWadlFiles.forEach(file -> { - deleteTestDir(file); - assertFalse(file.exists()); - }); - } - - private static List getSourceFiles(final String path) throws Exception { - final URI resPath = WadlGenTest.class.getResource(path).toURI(); - final File sourcesDir = new File(resPath); - if (!sourcesDir.exists()) { - throw new FileNotFoundException("Testing files were not found(" + sourcesDir.getName() + ")"); - } - final List sourceFiles = new ArrayList<>(); - final File[] fileArray = sourcesDir.listFiles(); - if (fileArray == null) { - throw new IllegalArgumentException("Unable to locate files in " + sourcesDir); - } - sourceFiles.addAll(Arrays.asList(fileArray)); - return sourceFiles; - } - - private static void deleteTestDir(final File file) { - if (file.isDirectory()) { - File[] filesToDelete = file.listFiles(); - if (filesToDelete != null) { - for (File f : filesToDelete) { - deleteTestDir(f); - } - } - } - if (!file.delete()) { - throw new RuntimeException("Failed to clean up after test"); - } + // TODO: more asserts } } -- 2.36.6