Skip to content

Commit

Permalink
[feat] Intro GeneratorMetadata (stability index) (#2816)
Browse files Browse the repository at this point in the history
* [feat] Intro GeneratorMetadata (stability index)

GeneratorMetadata offers an immutable object created via Builder pattern
which allows generators to explicitly define their stability (stable,
beta, experimental, deprecated) as well as a message to be shown during
generation.

This is a step toward:

* Fleshing out the "Core" artifact (#845)
* Providing a place to encapsulate feature-oriented metadata (#840)
* Providing a means to communicate end of life scheduling (#116)

This new structure, specifically the Stability property, allows us to
offer future enhancements such as allowing users to filter down to only
"Stable" generators via CLI, and eventually any compat table (see #503).

* Mark deprecated generators as deprecated in-code

* Re-export docs/generators.md
  • Loading branch information
jimschubert authored May 5, 2019
1 parent 26d0487 commit 6e1c897
Show file tree
Hide file tree
Showing 11 changed files with 225 additions and 5 deletions.
8 changes: 4 additions & 4 deletions docs/generators.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ The following generators are available:
- [cpp-restsdk](generators/cpp-restsdk.md)
- [cpp-tizen](generators/cpp-tizen.md)
- [csharp](generators/csharp.md)
- [csharp-dotnet2](generators/csharp-dotnet2.md)
- [csharp-dotnet2](generators/csharp-dotnet2.md) (deprecated)
- [csharp-netcore](generators/csharp-netcore.md)
- [dart](generators/dart.md)
- [dart-jaguar](generators/dart-jaguar.md)
Expand Down Expand Up @@ -47,10 +47,10 @@ The following generators are available:
- [rust](generators/rust.md)
- [scala-akka](generators/scala-akka.md)
- [scala-gatling](generators/scala-gatling.md)
- [scala-httpclient-deprecated](generators/scala-httpclient-deprecated.md)
- [scala-httpclient-deprecated](generators/scala-httpclient-deprecated.md) (deprecated)
- [scalaz](generators/scalaz.md)
- [swift2-deprecated](generators/swift2-deprecated.md)
- [swift3-deprecated](generators/swift3-deprecated.md)
- [swift2-deprecated](generators/swift2-deprecated.md) (deprecated)
- [swift3-deprecated](generators/swift3-deprecated.md) (deprecated)
- [swift4](generators/swift4.md)
- [typescript-angular](generators/typescript-angular.md)
- [typescript-angularjs](generators/typescript-angularjs.md)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import org.openapitools.codegen.CodegenConfig;
import org.openapitools.codegen.CodegenConfigLoader;
import org.openapitools.codegen.CodegenType;
import org.openapitools.codegen.meta.GeneratorMetadata;
import org.openapitools.codegen.meta.Stability;

import java.util.Comparator;
import java.util.List;
Expand Down Expand Up @@ -70,16 +72,27 @@ private void appendForType(StringBuilder sb, CodegenType type, String typeName,
sb.append(System.lineSeparator());

list.forEach(generator -> {
GeneratorMetadata meta = generator.getGeneratorMetadata();
if (docusaurus) {
sb.append("* ");
String id = "generators/" + generator.getName();
sb.append("[").append(generator.getName()).append("](").append(id).append(")");
sb.append("[").append(generator.getName());

if (meta != null && meta.getStability() != null && meta.getStability() != Stability.STABLE) {
sb.append(" (").append(meta.getStability().value()).append(")");
}

sb.append("](").append(id).append(")");

// trailing space is important for markdown list formatting
sb.append(" ");
} else {
sb.append(" - ");
sb.append(generator.getName());

if (meta != null && meta.getStability() != null && meta.getStability() != Stability.STABLE) {
sb.append(" (").append(meta.getStability().value()).append(")");
}
}
sb.append(System.lineSeparator());
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package org.openapitools.codegen.meta;

/**
* Represents metadata about a generator.
*/
public class GeneratorMetadata {
private Stability stability;
private String generationMessage;

private GeneratorMetadata(Builder builder) {
stability = builder.stability;
generationMessage = builder.generationMessage;
}

/**
* Creates a new builder object for {@link GeneratorMetadata}.
*
* @return A new builder instance.
*/
public static Builder newBuilder() {
return new Builder();
}

/**
* Creates a new builder object for {@link GeneratorMetadata}, accepting another instance from which to copy properties.
*
* @param copy An existing instance to copy defaults from
*
* @return A new builder instance, with values preset to those of 'copy'.
*/
public static Builder newBuilder(GeneratorMetadata copy) {
Builder builder = new Builder();
if (copy != null) {
builder.stability = copy.getStability();
builder.generationMessage = copy.getGenerationMessage();
}
return builder;
}

/**
* Returns a message which can be displayed during generation.
*
* @return A message, if defined.
*/
public String getGenerationMessage() {
return generationMessage;
}

/**
* Returns an enum describing the stability index of the generator.
*
* @return The defined stability index.
*/
public Stability getStability() {
return stability;
}

/**
* {@code GeneratorMetadata} builder static inner class.
*/
public static final class Builder {
private Stability stability;
private String generationMessage;

private Builder() {
}

/**
* Sets the {@code stability} and returns a reference to this Builder so that the methods can be chained together.
*
* @param stability the {@code stability} to set
* @return a reference to this Builder
*/
public Builder stability(Stability stability) {
this.stability = stability;
return this;
}

/**
* Sets the {@code generationMessage} and returns a reference to this Builder so that the methods can be chained together.
*
* @param generationMessage the {@code generationMessage} to set
* @return a reference to this Builder
*/
public Builder generationMessage(String generationMessage) {
this.generationMessage = generationMessage;
return this;
}

/**
* Returns a {@code GeneratorMetadata} built from the parameters previously set.
*
* @return a {@code GeneratorMetadata} built with parameters of this {@code GeneratorMetadata.Builder}
*/
public GeneratorMetadata build() {
return new GeneratorMetadata(this);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package org.openapitools.codegen.meta;

/**
* Represents the "stability index" of a generator or feature, based on the stability indexes defined in the node.js ecosystem.
*/
public enum Stability {
/**
* The feature or features are considered complete and "production-ready".
*/
STABLE("stable"),
/**
* The feature may be partially incomplete, but breaking changes will be avoided between major releases.
*/
BETA("beta"),
/**
* The feature is still under active development and subject to non-backward compatible changes or removal in any
* future version. Use of the feature is not recommended in production environments.
*/
EXPERIMENTAL("experimental"),
/**
* The feature may emit warnings. Backward compatibility is not guaranteed. Removal is likely to occur in a subsequent major release.
*/
DEPRECATED("deprecated");

private String description;

Stability(String description) {
this.description = description;
}

/**
* Returns a value for this stability index.
*
* @return The descriptive value of this enum.
*/
public String value() { return description; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,16 @@
import io.swagger.v3.oas.models.servers.Server;
import io.swagger.v3.oas.models.servers.ServerVariable;
import org.openapitools.codegen.api.TemplatingEngineAdapter;
import org.openapitools.codegen.meta.GeneratorMetadata;

import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.Set;

public interface CodegenConfig {
GeneratorMetadata getGeneratorMetadata();

CodegenType getTag();

String getName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
import org.openapitools.codegen.api.TemplatingEngineAdapter;
import org.openapitools.codegen.config.GeneratorProperties;
import org.openapitools.codegen.examples.ExampleGenerator;
import org.openapitools.codegen.meta.GeneratorMetadata;
import org.openapitools.codegen.meta.Stability;
import org.openapitools.codegen.serializer.SerializerUtils;
import org.openapitools.codegen.templating.MustacheEngineAdapter;
import org.openapitools.codegen.utils.ModelUtils;
Expand All @@ -63,6 +65,7 @@
public class DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultCodegen.class);

protected GeneratorMetadata generatorMetadata;
protected String inputSpec;
protected String outputFolder = "";
protected Set<String> defaultIncludes = new HashSet<String>();
Expand Down Expand Up @@ -816,6 +819,16 @@ public String toModelDocFilename(String name) {
return camelize(name);
}

/**
* Returns metadata about the generator.
*
* @return A provided {@link GeneratorMetadata} instance
*/
@Override
public GeneratorMetadata getGeneratorMetadata() {
return generatorMetadata;
}

/**
* Return the operation ID (method name)
*
Expand Down Expand Up @@ -932,6 +945,15 @@ public String toApiImport(String name) {
* returns string presentation of the example path (it's a constructor)
*/
public DefaultCodegen() {
CodegenType codegenType = getTag();
if (codegenType == null) {
codegenType = CodegenType.OTHER;
}
generatorMetadata = GeneratorMetadata.newBuilder()
.stability(Stability.STABLE)
.generationMessage(String.format(Locale.ROOT, "OpenAPI Generator: %s (%s)", getName(), codegenType.toValue()))
.build();

defaultIncludes = new HashSet<String>(
Arrays.asList("double",
"int",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
import org.openapitools.codegen.config.GeneratorProperties;
import org.openapitools.codegen.api.TemplatingEngineAdapter;
import org.openapitools.codegen.ignore.CodegenIgnoreProcessor;
import org.openapitools.codegen.meta.GeneratorMetadata;
import org.openapitools.codegen.meta.Stability;
import org.openapitools.codegen.templating.MustacheEngineAdapter;
import org.openapitools.codegen.config.GeneratorProperties;
import org.openapitools.codegen.utils.ImplementationVersion;
Expand Down Expand Up @@ -883,6 +885,23 @@ public List<File> generate() {
throw new RuntimeException("missing config!");
}

if (config.getGeneratorMetadata() == null) {
LOGGER.warn(String.format(Locale.ROOT, "Generator '%s' is missing generator metadata!", config.getName()));
} else {
GeneratorMetadata generatorMetadata = config.getGeneratorMetadata();
if (StringUtils.isNotEmpty(generatorMetadata.getGenerationMessage())) {
LOGGER.info(generatorMetadata.getGenerationMessage());
}

Stability stability = generatorMetadata.getStability();
String stabilityMessage = String.format(Locale.ROOT, "Generator '%s' is considered %s.", config.getName(), stability.value());
if (stability == Stability.DEPRECATED) {
LOGGER.warn(stabilityMessage);
} else {
LOGGER.info(stabilityMessage);
}
}

// resolve inline models
InlineModelResolver inlineModelResolver = new InlineModelResolver();
inlineModelResolver.flatten(openAPI);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import org.openapitools.codegen.CodegenType;
import org.openapitools.codegen.SupportingFile;

import org.openapitools.codegen.meta.GeneratorMetadata;
import org.openapitools.codegen.meta.Stability;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -38,6 +40,10 @@ public class CSharpDotNet2ClientCodegen extends AbstractCSharpCodegen {
public CSharpDotNet2ClientCodegen() {
super();

generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata)
.stability(Stability.DEPRECATED)
.build();

// clear import mapping (from default generator) as C# (2.0) does not use it
// at the moment
importMapping.clear();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

import org.apache.commons.lang3.StringUtils;
import org.openapitools.codegen.*;
import org.openapitools.codegen.meta.GeneratorMetadata;
import org.openapitools.codegen.meta.Stability;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -46,6 +48,11 @@ public class ScalaHttpClientCodegen extends AbstractScalaCodegen implements Code

public ScalaHttpClientCodegen() {
super();

generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata)
.stability(Stability.DEPRECATED)
.build();

outputFolder = "generated-code/scala-http-client";
modelTemplateFiles.put("model.mustache", ".scala");
apiTemplateFiles.put("api.mustache", ".scala");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.text.WordUtils;
import org.openapitools.codegen.*;
import org.openapitools.codegen.meta.GeneratorMetadata;
import org.openapitools.codegen.meta.Stability;
import org.openapitools.codegen.utils.ModelUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -68,6 +70,11 @@ public class Swift3Codegen extends DefaultCodegen implements CodegenConfig {

public Swift3Codegen() {
super();

generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata)
.stability(Stability.DEPRECATED)
.build();

outputFolder = "generated-code" + File.separator + "swift";
modelTemplateFiles.put("model.mustache", ".swift");
apiTemplateFiles.put("api.mustache", ".swift");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.text.WordUtils;
import org.openapitools.codegen.*;
import org.openapitools.codegen.meta.GeneratorMetadata;
import org.openapitools.codegen.meta.Stability;
import org.openapitools.codegen.utils.ModelUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -87,6 +89,11 @@ public String getHelp() {

public SwiftClientCodegen() {
super();

generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata)
.stability(Stability.DEPRECATED)
.build();

outputFolder = "generated-code" + File.separator + "swift";
modelTemplateFiles.put("model.mustache", ".swift");
apiTemplateFiles.put("api.mustache", ".swift");
Expand Down

0 comments on commit 6e1c897

Please sign in to comment.