Add generalized FileGenerator interface 34/52034/47
authorRobert Varga <rovarga@cisco.com>
Sat, 18 Feb 2017 11:44:17 +0000 (12:44 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Tue, 20 Oct 2020 11:08:03 +0000 (13:08 +0200)
This patch adds a maven-independent interface for code generators,
which captures enough semantics to make mapping usable. We will be
implementing this interface in place of the original SPI.

JIRA: YANGTOOLS-1146
Change-Id: I3daef73d3fa71e74a9678979fd00417579f60695
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
24 files changed:
artifacts/pom.xml
docs/pom.xml
plugin/plugin-generator-api/pom.xml [new file with mode: 0644]
plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/AbstractFileGeneratorFactory.java [new file with mode: 0644]
plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/AbstractGeneratedFile.java [new file with mode: 0644]
plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/AbstractGeneratedTextFile.java [new file with mode: 0644]
plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/ByteSourceGeneratedFile.java [new file with mode: 0644]
plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/CharSeqGeneratedTextFile.java [new file with mode: 0644]
plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/CharSourceGeneratedTextFile.java [new file with mode: 0644]
plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/FileGenerator.java [new file with mode: 0644]
plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/FileGeneratorException.java [new file with mode: 0644]
plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/FileGeneratorFactory.java [new file with mode: 0644]
plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/GeneratedFile.java [new file with mode: 0644]
plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/GeneratedFileLifecycle.java [new file with mode: 0644]
plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/GeneratedFilePath.java [new file with mode: 0644]
plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/GeneratedFileType.java [new file with mode: 0644]
plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/ModuleResourceResolver.java [new file with mode: 0644]
plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/package-info.java [new file with mode: 0644]
plugin/pom.xml [new file with mode: 0644]
pom.xml
yang/pom.xml
yang/yang-maven-plugin-spi/pom.xml
yang/yang-maven-plugin-spi/src/main/java/org/opendaylight/yangtools/yang2sources/spi/BasicCodeGenerator.java
yang/yang-maven-plugin-spi/src/main/java/org/opendaylight/yangtools/yang2sources/spi/ModuleResourceResolver.java

index 6fc96bfd8ee01b02aaa64f1fb2f8bf55b475349e..776a6f0e88dfb93db72b3721bf651c340ee387e1 100644 (file)
                 <version>6.0.1-SNAPSHOT</version>
                 <scope>test</scope>
             </dependency>
+
+            <dependency>
+                <groupId>org.opendaylight.yangtools</groupId>
+                <artifactId>plugin-generator-api</artifactId>
+                <version>6.0.1-SNAPSHOT</version>
+            </dependency>
             <dependency>
                 <groupId>org.opendaylight.yangtools</groupId>
                 <artifactId>yang-maven-plugin</artifactId>
index d670390035189d913830e884d48f2d05352f9b5a..e480dedb3cff60e8a62a79d70278166a27198813 100644 (file)
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>concepts</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>plugin-generator-api</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>yang-common</artifactId>
                         </group>
                         <group>
                             <title>yang-maven-plugin codegen interface</title>
-                            <packages>org.opendaylight.yangtools.yang2sources.spi*</packages>
+                            <packages>org.opendaylight.yangtools.plugin.generator.api*:org.opendaylight.yangtools.yang2sources.spi*</packages>
                         </group>
                         <group>
                             <title>Common YANG parser</title>
diff --git a/plugin/plugin-generator-api/pom.xml b/plugin/plugin-generator-api/pom.xml
new file mode 100644 (file)
index 0000000..8b8aa37
--- /dev/null
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ Copyright (c) 2020 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
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.opendaylight.yangtools</groupId>
+        <artifactId>bundle-parent</artifactId>
+        <version>6.0.1-SNAPSHOT</version>
+        <relativePath>../../bundle-parent</relativePath>
+    </parent>
+
+    <artifactId>plugin-generator-api</artifactId>
+    <packaging>bundle</packaging>
+    <name>${project.artifactId}</name>
+    <description>YANG Generator Plugin API</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>concepts</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-model-api</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Automatic-Module-Name>org.opendaylight.yangtools.plugin.generator.api</Automatic-Module-Name>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/AbstractFileGeneratorFactory.java b/plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/AbstractFileGeneratorFactory.java
new file mode 100644 (file)
index 0000000..e83ecf7
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2020 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.yangtools.plugin.generator.api;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import com.google.common.annotations.Beta;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.opendaylight.yangtools.concepts.AbstractIdentifiable;
+
+/**
+ * Abstract base class for {@link FileGeneratorFactory} implementations. Its constructor enforces no spaces in
+ * identifier.
+ */
+@Beta
+@NonNullByDefault
+public abstract class AbstractFileGeneratorFactory extends AbstractIdentifiable<String>
+        implements FileGeneratorFactory {
+    protected AbstractFileGeneratorFactory(final String identifier) {
+        super(identifier);
+        checkArgument(identifier.indexOf(' ') == -1, "Identifier may not contain any spaces");
+    }
+}
diff --git a/plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/AbstractGeneratedFile.java b/plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/AbstractGeneratedFile.java
new file mode 100644 (file)
index 0000000..840ad76
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2020 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.yangtools.plugin.generator.api;
+
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
+import com.google.common.base.MoreObjects.ToStringHelper;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * Abstract base class for {@link GeneratedFile}s. This class is suitable for binary files. For text files use
+ * {@link AbstractGeneratedTextFile}.
+ *
+ * @author Robert Varga
+ */
+@Beta
+@NonNullByDefault
+public abstract class AbstractGeneratedFile implements GeneratedFile {
+    private final GeneratedFileLifecycle lifecycle;
+
+    protected AbstractGeneratedFile(final GeneratedFileLifecycle lifecycle) {
+        this.lifecycle = requireNonNull(lifecycle);
+    }
+
+    /**
+     * Return the lifecycle governing this file.
+     *
+     * @return Governing lifecycle
+     */
+    @Override
+    public final GeneratedFileLifecycle getLifecycle() {
+        return lifecycle;
+    }
+
+    @Override
+    public final String toString() {
+        return addToStringAttributes(MoreObjects.toStringHelper(this).omitNullValues()).toString();
+    }
+
+    protected ToStringHelper addToStringAttributes(final ToStringHelper helper) {
+        return helper.add("lifecycle", lifecycle);
+    }
+}
diff --git a/plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/AbstractGeneratedTextFile.java b/plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/AbstractGeneratedTextFile.java
new file mode 100644 (file)
index 0000000..b4c38bf
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2020 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.yangtools.plugin.generator.api;
+
+import com.google.common.annotations.Beta;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.nio.charset.StandardCharsets;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The contents of a generated file and its {@link GeneratedFileLifecycle}. This class is suitable for text files,
+ * for binary files see {@link AbstractGeneratedFile}. Text files are encoded in {@link StandardCharsets#UTF_8}.
+ *
+ * @author Robert Varga
+ */
+@Beta
+@NonNullByDefault
+public abstract class AbstractGeneratedTextFile extends AbstractGeneratedFile {
+    protected AbstractGeneratedTextFile(final GeneratedFileLifecycle lifecycle) {
+        super(lifecycle);
+    }
+
+    @Override
+    public final void writeBody(final OutputStream output) throws IOException {
+        try (Writer writer = new OutputStreamWriter(output, StandardCharsets.UTF_8)) {
+            try (BufferedWriter buffered = new BufferedWriter(writer)) {
+                writeBody(buffered);
+            }
+        }
+    }
+
+    /**
+     * Write the body of this file into specified {@link Writer}.
+     *
+     * @param output writer where to write the output
+     * @throws IOException when the stream reports an IOException
+     */
+    protected abstract void writeBody(Writer output) throws IOException;
+}
diff --git a/plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/ByteSourceGeneratedFile.java b/plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/ByteSourceGeneratedFile.java
new file mode 100644 (file)
index 0000000..bb5352d
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2020 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.yangtools.plugin.generator.api;
+
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.base.MoreObjects.ToStringHelper;
+import com.google.common.io.ByteSource;
+import java.io.IOException;
+import java.io.OutputStream;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * A generated file with a body is available as a {@link ByteSource}.
+ */
+@NonNullByDefault
+final class ByteSourceGeneratedFile extends AbstractGeneratedFile {
+    private final ByteSource body;
+
+    ByteSourceGeneratedFile(final GeneratedFileLifecycle lifecycle, final ByteSource body) {
+        super(lifecycle);
+        this.body = requireNonNull(body);
+    }
+
+    @Override
+    public void writeBody(final @NonNull OutputStream output) throws IOException {
+        body.copyTo(output);
+    }
+
+    @Override
+    protected ToStringHelper addToStringAttributes(final ToStringHelper helper) {
+        return helper.add("body", body);
+    }
+}
diff --git a/plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/CharSeqGeneratedTextFile.java b/plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/CharSeqGeneratedTextFile.java
new file mode 100644 (file)
index 0000000..617e8a3
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2020 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.yangtools.plugin.generator.api;
+
+import static java.util.Objects.requireNonNull;
+
+import java.io.IOException;
+import java.io.Writer;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * A generated text file with a body is available as a {@link CharSequence}.
+ */
+@NonNullByDefault
+final class CharSeqGeneratedTextFile extends AbstractGeneratedTextFile {
+    private final CharSequence body;
+
+    CharSeqGeneratedTextFile(final GeneratedFileLifecycle lifecycle, final CharSequence body) {
+        super(lifecycle);
+        this.body = requireNonNull(body);
+    }
+
+    @Override
+    protected void writeBody(final Writer output) throws IOException {
+        output.append(body);
+    }
+}
diff --git a/plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/CharSourceGeneratedTextFile.java b/plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/CharSourceGeneratedTextFile.java
new file mode 100644 (file)
index 0000000..8f44502
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2020 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.yangtools.plugin.generator.api;
+
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.base.MoreObjects.ToStringHelper;
+import com.google.common.io.ByteSource;
+import com.google.common.io.CharSource;
+import java.io.IOException;
+import java.io.Writer;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * A generated file with a body is available as a {@link ByteSource}.
+ */
+@NonNullByDefault
+final class CharSourceGeneratedTextFile extends AbstractGeneratedTextFile {
+    private final CharSource body;
+
+    CharSourceGeneratedTextFile(final GeneratedFileLifecycle lifecycle, final CharSource body) {
+        super(lifecycle);
+        this.body = requireNonNull(body);
+    }
+
+    @Override
+    protected void writeBody(final Writer output) throws IOException {
+        body.copyTo(output);
+    }
+
+    @Override
+    protected ToStringHelper addToStringAttributes(final ToStringHelper helper) {
+        return helper.add("body", body);
+    }
+}
diff --git a/plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/FileGenerator.java b/plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/FileGenerator.java
new file mode 100644 (file)
index 0000000..200b7c2
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2020 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.yangtools.plugin.generator.api;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.Table;
+import java.util.Set;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * Interface implemented by plugins which can generate files from a {@link EffectiveModelContext}.
+ *
+ * @author Robert Varga
+ */
+@Beta
+@NonNullByDefault
+public interface FileGenerator {
+    /**
+     * Indicate import resolution mode this code generator requires. Default implementation indicates
+     * {@link ImportResolutionMode#REVISION_EXACT_OR_LATEST}.
+     *
+     * @return Required import resolution mode, null if the code generator does not care.
+     */
+    default ImportResolutionMode importResolutionMode() {
+        return ImportResolutionMode.REVISION_EXACT_OR_LATEST;
+    }
+
+    /**
+     * Generate files from a {@link SchemaContext}, being aware the that specific modules are local to the current
+     * project being processed.
+     *
+     * <p>
+     * Implementations of this interface must not interact with project directory directly, but rather supply the files
+     * generated as a set of {@link GeneratedFile}s. The caller of this method will use these to integrate with build
+     * management to ensure proper dependency tracking is performed.
+     *
+     * @param context SchemaContext to examine
+     * @param localModules Modules local to the project
+     * @param moduleResourcePathResolver Module-to-resource path resolver
+     * @return The set of generated files.
+     * @throws FileGeneratorException if anything bad happens
+     */
+    Table<GeneratedFileType, GeneratedFilePath, GeneratedFile> generateFiles(EffectiveModelContext context,
+            Set<Module> localModules, ModuleResourceResolver moduleResourcePathResolver) throws FileGeneratorException;
+
+    /**
+     * {@link EffectiveModelContext} can be assembled in multiple ways, we hold known modes here.
+     */
+    @Beta
+    enum ImportResolutionMode {
+        /**
+         * Standard, RFC6020 and RFC7950 compliant mode. Imports are satisfied by exact revision match (if specified),
+         * or by latest available revision.
+         */
+        REVISION_EXACT_OR_LATEST,
+        /**
+         * Semantic version based mode. Imports which specify a semantic version (via the OpenConfig extension) will
+         * be satisfied by module which exports the latest compatible revision. Imports which do not specify semantic
+         * version will be resolved just as they would be via {@link #REVISION_EXACT_OR_LATEST}.
+         */
+        SEMVER_LATEST,
+    }
+}
diff --git a/plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/FileGeneratorException.java b/plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/FileGeneratorException.java
new file mode 100644 (file)
index 0000000..18c32e9
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2020 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.yangtools.plugin.generator.api;
+
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * An exception reporting a problem with file generation. This exception should be reported when exception chaining
+ * occurs.
+ */
+@Beta
+public class FileGeneratorException extends Exception {
+    private static final long serialVersionUID = 1L;
+
+    public FileGeneratorException(final String message) {
+        super(requireNonNull(message));
+    }
+
+    public FileGeneratorException(final String message, final Throwable cause) {
+        super(requireNonNull(message), cause);
+    }
+}
diff --git a/plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/FileGeneratorFactory.java b/plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/FileGeneratorFactory.java
new file mode 100644 (file)
index 0000000..4b4deb6
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2020 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.yangtools.plugin.generator.api;
+
+import com.google.common.annotations.Beta;
+import java.util.Map;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.opendaylight.yangtools.concepts.Identifiable;
+
+/**
+ * A {@link java.util.ServiceLoader} factory for instantiating {@link FileGenerator} instances.
+ *
+ * @author Robert Varga
+ */
+@Beta
+@NonNullByDefault
+public interface FileGeneratorFactory extends Identifiable<String> {
+    /**
+     * {@inheritDoc}
+     *
+     * <p>
+     * This identifier must be a simple string without any whitespace, such as produced by
+     * {@link Class#getSimpleName()}.
+     */
+    @Override
+    String getIdentifier();
+
+    /**
+     * Create a new {@link FileGenerator}.
+     *
+     * @param configuration Configuration properties
+     * @return a new FileGenerator
+     * @throws FileGeneratorException if the configuration is not acceptable, or any other issue occurs.
+     */
+    FileGenerator newFileGenerator(Map<String, String> configuration) throws FileGeneratorException;
+}
diff --git a/plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/GeneratedFile.java b/plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/GeneratedFile.java
new file mode 100644 (file)
index 0000000..df2a8be
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2020 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.yangtools.plugin.generator.api;
+
+import com.google.common.annotations.Beta;
+import com.google.common.io.ByteSource;
+import com.google.common.io.CharSource;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.opendaylight.yangtools.concepts.Immutable;
+
+/**
+ * The contents of a generated file and its {@link GeneratedFileLifecycle}.
+ *
+ * @author Robert Varga
+ */
+@Beta
+@NonNullByDefault
+public interface GeneratedFile extends Immutable {
+    /**
+     * Return the lifecycle governing this file.
+     *
+     * @return Governing lifecycle
+     */
+    GeneratedFileLifecycle getLifecycle();
+
+    /**
+     * Write the body of this file into specified {@link OutputStream}.
+     *
+     * @param output stream where to write the output
+     * @throws IOException when the stream reports an IOException
+     */
+    void writeBody(OutputStream output) throws IOException;
+
+    /**
+     * Create a new {@link GeneratedFile} with the specified {@link CharSequence} body. The body will be encoded in
+     * {@link StandardCharsets#UTF_8}.
+     *
+     * @param lifecycle File lifecycle
+     * @param body File body
+     * @return A GeneratedFile.
+     * @throws NullPointerException if any argument is null
+     */
+    static GeneratedFile of(final GeneratedFileLifecycle lifecycle, final CharSequence body) {
+        return new CharSeqGeneratedTextFile(lifecycle, body);
+    }
+
+    /**
+     * Create a new {@link GeneratedFile} with the specified {@link CharSource} body. The body will be encoded in
+     * {@link StandardCharsets#UTF_8}.
+     *
+     * @param lifecycle File lifecycle
+     * @param body File body
+     * @return A GeneratedFile.
+     * @throws NullPointerException if any argument is null
+     */
+    static GeneratedFile of(final GeneratedFileLifecycle lifecycle, final CharSource body) {
+        return new CharSourceGeneratedTextFile(lifecycle, body);
+    }
+
+    /**
+     * Create a new {@link GeneratedFile} with the specified {@link ByteSource} body. The body will be written as is.
+     *
+     * @param lifecycle File lifecycle
+     * @param body File body
+     * @return A GeneratedFile.
+     * @throws NullPointerException if any argument is null
+     */
+    static GeneratedFile of(final GeneratedFileLifecycle lifecycle, final ByteSource body) {
+        return new ByteSourceGeneratedFile(lifecycle, body);
+    }
+}
diff --git a/plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/GeneratedFileLifecycle.java b/plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/GeneratedFileLifecycle.java
new file mode 100644 (file)
index 0000000..17664fc
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2020 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.yangtools.plugin.generator.api;
+
+import com.google.common.annotations.Beta;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * Lifecycle policy of a generated file. This governs how existing files interact with newly-generated bodies.
+ *
+ * @author Robert Varga
+ */
+@Beta
+@NonNullByDefault
+public enum GeneratedFileLifecycle {
+    /**
+     * Generated file should be transient and is not expected to be further modified.
+     */
+    TRANSIENT,
+    /**
+     * Generated file should be persistent and potentially customized. It should not be overwritten if it already
+     * exists.
+     */
+    PERSISTENT,
+}
diff --git a/plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/GeneratedFilePath.java b/plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/GeneratedFilePath.java
new file mode 100644 (file)
index 0000000..8c74906
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2020 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.yangtools.plugin.generator.api;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.CharMatcher;
+import com.google.common.base.MoreObjects;
+import java.io.File;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+
+/**
+ * A relative path to a generated file.
+ *
+ * @author Robert Varga
+ */
+@Beta
+@NonNullByDefault
+public final class GeneratedFilePath {
+    public static final char SEPARATOR = '/';
+    public static final String SEPARATOR_STR = "/";
+
+    private static final CharMatcher FS_MATCHER = CharMatcher.is(File.separatorChar);
+
+    private final String path;
+
+    private GeneratedFilePath(final String path) {
+        this.path = requireNonNull(path);
+        checkArgument(!path.isEmpty());
+    }
+
+    public static GeneratedFilePath ofPath(final String path) {
+        return new GeneratedFilePath(path);
+    }
+
+    public static GeneratedFilePath ofFile(final File file) {
+        return ofFilePath(file.getPath());
+    }
+
+    public static GeneratedFilePath ofFilePath(final String filePath) {
+        return ofPath(FS_MATCHER.replaceFrom(filePath, SEPARATOR));
+    }
+
+    public String getPath() {
+        return path;
+    }
+
+    @Override
+    public int hashCode() {
+        return path.hashCode();
+    }
+
+    @Override
+    public boolean equals(final @Nullable Object obj) {
+        return this == obj || obj instanceof GeneratedFilePath && path.equals(((GeneratedFilePath) obj).path);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this).add("path", path).toString();
+    }
+}
diff --git a/plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/GeneratedFileType.java b/plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/GeneratedFileType.java
new file mode 100644 (file)
index 0000000..0c53ac5
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2020 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.yangtools.plugin.generator.api;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableMap;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+
+/**
+ * Type of generated file. Four most common kinds are captured in {@link #RESOURCE}, {@link #SOURCE},
+ * {@link #TEST_RESOURCE} and {@link #TEST_SOURCE}, but others may be externally defined.
+ *
+ * <p>
+ * Users of {@link FileGenerator} are expected to provide sensible mapping of {@link GeneratedFileType} to their
+ * output structures. Notably they must handle pre-defined types, allow end users to specify mapping of custom types.
+ * They need to deal with runtime mismatches involving between FileGenerators and user's expectations, for example by
+ * issuing warnings when a mismatch is detected.
+ *
+ * @author Robert Varga
+ */
+@Beta
+@NonNullByDefault
+public final class GeneratedFileType {
+    /**
+     * A generated resource file. This file should be part of artifact's resources.
+     */
+    public static final GeneratedFileType RESOURCE = new GeneratedFileType("resource");
+
+    /**
+     * A generated source file. This file should be part of main compilation unit.
+     */
+    public static final GeneratedFileType SOURCE = new GeneratedFileType("source");
+
+    /**
+     * A generated test resource file. This file should be part of test resources.
+     */
+    public static final GeneratedFileType TEST_RESOURCE = new GeneratedFileType("test-resource");
+
+    /**
+     * A generated test source file. This file should be part of test sources.
+     */
+    public static final GeneratedFileType TEST_SOURCE = new GeneratedFileType("test-source");
+
+    private static final ImmutableMap<String, GeneratedFileType> WELL_KNOWN = ImmutableMap.of(
+        RESOURCE.name(), RESOURCE, TEST_RESOURCE.name(), TEST_RESOURCE,
+        SOURCE.name(), SOURCE, TEST_SOURCE.name(), TEST_SOURCE);
+
+    private final String name;
+
+    private GeneratedFileType(final String name) {
+        this.name = requireNonNull(name);
+    }
+
+    public static GeneratedFileType of(final String name) {
+        checkArgument(!name.isEmpty());
+        final @Nullable GeneratedFileType wellKnown = WELL_KNOWN.get(name);
+        return wellKnown != null ? wellKnown : new GeneratedFileType(name);
+    }
+
+    public String name() {
+        return name;
+    }
+
+    @Override
+    public int hashCode() {
+        return name.hashCode();
+    }
+
+    @Override
+    public boolean equals(final @Nullable Object obj) {
+        return this == obj || obj instanceof GeneratedFileType && name.equals(((GeneratedFileType) obj).name);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this).add("name", name).toString();
+    }
+}
diff --git a/plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/ModuleResourceResolver.java b/plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/ModuleResourceResolver.java
new file mode 100644 (file)
index 0000000..c97d03e
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2020 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.yangtools.plugin.generator.api;
+
+import com.google.common.annotations.Beta;
+import java.util.Optional;
+import org.opendaylight.yangtools.yang.model.api.ModuleLike;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation;
+import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
+
+/**
+ * An SPI-level interface to find the schema source for a particular YANG module, as packaged in the final artifact.
+ * The module must be part of the current resolution context.
+ */
+@Beta
+public interface ModuleResourceResolver {
+    /**
+     * Find the path of the packaged resource which corresponds to the specified module in the specified representation.
+     *
+     * @param module Requested module
+     * @param representation Requested representation
+     * @return Path to packaged resource
+     * @throws NullPointerException if any argument is null
+     * @throws IllegalArgumentException if the requested representation is not supported by this resolver
+     */
+    Optional<String> findModuleResourcePath(ModuleLike module,
+        Class<? extends SchemaSourceRepresentation> representation);
+
+    default Optional<String> findModuleYangTextResourcePath(final ModuleLike module) {
+        return findModuleResourcePath(module, YangTextSchemaSource.class);
+    }
+}
diff --git a/plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/package-info.java b/plugin/plugin-generator-api/src/main/java/org/opendaylight/yangtools/plugin/generator/api/package-info.java
new file mode 100644 (file)
index 0000000..1e0177d
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2020 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
+ */
+/**
+ * API exposed by generator plugins, i.e. pluggable pieces of code which want to create code (and other) files from an
+ * {@link org.opendaylight.yangtools.yang.model.api.EffectiveModelContext}.
+ *
+ * <p>
+ * The primary entry point is {@link org.opendaylight.yangtools.plugin.generator.api.FileGeneratorFactory}, which needs
+ * to be implemented for bootstrapping a particular generator. Such implementations are discovered using normal
+ * discovery methods, for example they <b>should</b> always be published as {@link java.util.ServiceLoader} services.
+ */
+package org.opendaylight.yangtools.plugin.generator.api;
\ No newline at end of file
diff --git a/plugin/pom.xml b/plugin/pom.xml
new file mode 100644 (file)
index 0000000..39a7040
--- /dev/null
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ Copyright (c) 2020 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
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <parent>
+        <groupId>org.opendaylight.odlparent</groupId>
+        <artifactId>odlparent-lite</artifactId>
+        <version>8.0.0</version>
+        <relativePath/>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.opendaylight.yangtools</groupId>
+    <artifactId>plugin-aggregator</artifactId>
+    <version>6.0.1-SNAPSHOT</version>
+    <packaging>pom</packaging>
+
+    <modules>
+        <module>plugin-generator-api</module>
+
+        <!-- FIXME:
+        <module>yang-maven-plugin</module>
+        <module>yang-maven-plugin-spi</module>
+        <module>yang-maven-plugin-it</module>
+         !-->
+    </modules>
+
+    <properties>
+        <maven.deploy.skip>true</maven.deploy.skip>
+        <maven.install.skip>true</maven.install.skip>
+    </properties>
+</project>
diff --git a/pom.xml b/pom.xml
index c5115eca86518364729ff87246bf52c414001bfc..15c385644b2233000e6d9e87accdb185d6a80660 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -41,6 +41,8 @@
         <module>common</module>
         <module>docs</module>
         <module>features</module>
+        <module>plugin</module>
+
         <module>yang</module>
         <module>yang-validation-tool</module>
     </modules>
index 5dee24ea0193922ee1531d1b0bd7837d6cc7a6ec..e77b5e4eb87a52718cecf83eb35f777fb8879202 100644 (file)
         <module>yang-data-codec-binfmt</module>
         <module>yang-data-codec-gson</module>
         <module>yang-data-codec-xml</module>
-        <module>yang-maven-plugin</module>
-        <module>yang-maven-plugin-it</module>
-        <module>yang-maven-plugin-spi</module>
         <module>yang-model-api</module>
         <module>yang-model-export</module>
         <module>yang-model-util</module>
         <module>yang-model-util-ut</module>
 
+        <!-- Code Generation and build plugins -->
+        <module>yang-maven-plugin</module>
+        <module>yang-maven-plugin-spi</module>
+        <module>yang-maven-plugin-it</module>
+
         <!-- YANG XPath API and implementation -->
         <module>yang-xpath-api</module>
         <module>yang-xpath-antlr</module>
index 76e7a3d86dd2cfe9ebc0ed03d46ad877e3debb60..7bb01a62e1f1403bd4ec3ac2cc36c96637d48f1b 100644 (file)
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>yang-model-api</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>plugin-generator-api</artifactId>
+        </dependency>
 
         <dependency>
             <groupId>org.apache.maven</groupId>
index cac397db4d2a08f92ff2161d302690549557ff15..8f621ddb11ddf70ee3fa27decce51d78aad5d3e4 100644 (file)
@@ -12,6 +12,8 @@ import java.io.IOException;
 import java.util.Collection;
 import java.util.Map;
 import java.util.Set;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.plugin.generator.api.FileGenerator;
 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
 import org.opendaylight.yangtools.yang.model.api.Module;
 
@@ -24,13 +26,28 @@ public interface BasicCodeGenerator {
          * Standard, RFC6020 and RFC7950 compliant mode. Imports are satisfied by exact revision match (if specified),
          * or by latest available revision.
          */
-        REVISION_EXACT_OR_LATEST,
+        REVISION_EXACT_OR_LATEST(FileGenerator.ImportResolutionMode.REVISION_EXACT_OR_LATEST),
         /**
          * Semantic version based mode. Imports which specify a semantic version (via the OpenConfig extension) will
          * be satisfied by module which exports the latest compatible revision. Imports which do not specify semantic
          * version will be resolved just as they would be via {@link #REVISION_EXACT_OR_LATEST}.
          */
-        SEMVER_LATEST,
+        SEMVER_LATEST(FileGenerator.ImportResolutionMode.SEMVER_LATEST);
+
+        private final FileGenerator.@NonNull ImportResolutionMode fileGeneratorMode;
+
+        ImportResolutionMode(final FileGenerator.@NonNull ImportResolutionMode fileGeneratorMode) {
+            this.fileGeneratorMode = fileGeneratorMode;
+        }
+
+        /**
+         * Return {@link FileGenerator.ImportResolutionMode} equivalent of this mode.
+         *
+         * @return {@link FileGenerator.ImportResolutionMode} equivalent of this mode
+         */
+        public final FileGenerator.@NonNull ImportResolutionMode toFileGeneratorMode() {
+            return fileGeneratorMode;
+        }
     }
 
     /**
index d1e0c5b82f5b2c8bad2f8dfa9a5c7a030fbc4e73..62af2042b52a65c1ebd7eb5a22b48c2dd1410747 100644 (file)
@@ -8,9 +8,7 @@
 package org.opendaylight.yangtools.yang2sources.spi;
 
 import com.google.common.annotations.Beta;
-import java.util.Optional;
-import org.opendaylight.yangtools.yang.model.api.ModuleLike;
-import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 
 /**
  * An SPI-level interface to find the schema source for a particular YANG module, as packaged in the final artifact.
@@ -18,16 +16,7 @@ import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation
  */
 @Beta
 @FunctionalInterface
-public interface ModuleResourceResolver {
-    /**
-     * Find the path of the packaged resource which corresponds to the specified module in the specified representation.
-     *
-     * @param module Requested module
-     * @param representation Requested representation
-     * @return Path to packaged resource
-     * @throws NullPointerException if any argument is null
-     * @throws IllegalArgumentException if the requested representation is not supported by this resolver
-     */
-    Optional<String> findModuleResourcePath(ModuleLike module,
-        Class<? extends SchemaSourceRepresentation> representation);
+@SuppressFBWarnings(value = "NM_SAME_SIMPLE_NAME_AS_INTERFACE", justification = "Migration to new place")
+public interface ModuleResourceResolver extends org.opendaylight.yangtools.plugin.generator.api.ModuleResourceResolver {
+
 }