Merge remote-tracking branch 'origin/4.1.x' into sync_41x_50x

This commit is contained in:
wing328
2019-06-27 18:27:20 +08:00
1243 changed files with 38715 additions and 15082 deletions

View File

@@ -5,7 +5,9 @@
<parent>
<artifactId>openapi-generator-project</artifactId>
<groupId>org.openapitools</groupId>
<!-- RELEASE_VERSION -->
<version>5.0.0-SNAPSHOT</version>
<!-- /RELEASE_VERSION -->
<relativePath>../..</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -13,4 +15,27 @@
<artifactId>openapi-generator-core</artifactId>
<name>openapi-generator-core</name>
<url>https://github.com/openapitools/openapi-generator</url>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava-version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j-version}</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<slf4j-version>1.7.12</slf4j-version>
<guava-version>26.0-jre</guava-version>
</properties>
</project>

View File

@@ -0,0 +1,68 @@
/*
* Copyright 2019 OpenAPI-Generator Contributors (https://openapi-generator.tech)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openapitools.codegen.config;
/**
* The Context used for generation.
*
* @param <TSpecDocument> the type of the input spec document.
*/
public class Context<TSpecDocument> {
private TSpecDocument specDocument;
private GeneratorSettings generatorSettings;
private WorkflowSettings workflowSettings;
/**
* Instantiates a new Context.
*
* @param specDocument the spec document
* @param generatorSettings the generator settings
* @param workflowSettings the workflow settings
*/
public Context(TSpecDocument specDocument, GeneratorSettings generatorSettings, WorkflowSettings workflowSettings) {
this.specDocument = specDocument;
this.generatorSettings = generatorSettings;
this.workflowSettings = workflowSettings;
}
/**
* Gets the generator settings. These options are specific to "what" gets generated (language, framework).
*
* @return the generator settings
*/
public GeneratorSettings getGeneratorSettings() {
return generatorSettings;
}
/**
* Gets the spec document.
*
* @return the spec document
*/
public TSpecDocument getSpecDocument() {
return specDocument;
}
/**
* Gets the workflow settings. These options are specific to "how" code gets generated (input, output directory, ignore files, template engine, etc).
*
* @return the workflow settings
*/
public WorkflowSettings getWorkflowSettings() {
return workflowSettings;
}
}

View File

@@ -0,0 +1,872 @@
/*
* Copyright 2019 OpenAPI-Generator Contributors (https://openapi-generator.tech)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openapitools.codegen.config;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Serializable;
import java.util.*;
/**
* Represents those settings applied to a generator.
*/
public final class GeneratorSettings implements Serializable {
private static final Logger LOGGER = LoggerFactory.getLogger(GeneratorSettings.class);
private static String DEFAULT_GIT_USER_ID = "GIT_USER_ID";
private static String DEFAULT_GIT_REPO_ID = "GIT_REPO_ID";
private static String DEFAULT_RELEASE_NOTE = "Minor update";
private String generatorName;
private String apiPackage;
private String modelPackage;
private String invokerPackage;
private String packageName;
private String modelNamePrefix;
private String modelNameSuffix;
private String groupId;
private String artifactId;
private String artifactVersion;
private String library;
private ImmutableMap<String, String> instantiationTypes;
private ImmutableMap<String, String> typeMappings;
private ImmutableMap<String, Object> additionalProperties;
private ImmutableMap<String, String> importMappings;
private ImmutableSet<String> languageSpecificPrimitives;
private ImmutableMap<String, String> reservedWordMappings;
private String gitUserId;
private String gitRepoId;
private String releaseNote;
private String httpUserAgent;
/**
* Gets the name of the generator to use.
*
* @return the generator name
*/
public String getGeneratorName() {
return generatorName;
}
/**
* Gets the api package name for generated sources.
*
* @return the api package
*/
public String getApiPackage() {
return apiPackage;
}
/**
* Gets the model package name for generated sources
*
* @return the model package
*/
public String getModelPackage() {
return modelPackage;
}
/**
* Gets the invoker package name for generated sources.
*
* @return the invoker package
*/
public String getInvokerPackage() {
return invokerPackage;
}
/**
* Gets the overall package name for generated sources.
*
* @return the package name
*/
public String getPackageName() {
return packageName;
}
/**
* Gets a model name prefix for generated models. This name will be prefixed to a model name.
* <p>
* This option is often used to circumvent compilation issues where models match keywords.
* <p>
* Example:
* <p>
* Prefix <code>My</code> applied to <code>Object</code> results in a generated class named <code>MyObject</code>.
*
* @return the model name prefix
*/
public String getModelNamePrefix() {
return modelNamePrefix;
}
/**
* Gets a model name suffix for generated models. This name will be appended to a model name.
* <p>
* This option is often used to circumvent compilation issues where models match keywords.
* <p>
* Example:
* <p>
* Suffix <code>Gen</code> applied to <code>Object</code> results in a generated class named <code>ObjectGen</code>.
*
* @return the model name suffix
*/
public String getModelNameSuffix() {
return modelNameSuffix;
}
/**
* Gets the group id for generated sources which support this concept (e.g. Java and pom.xml, Scala and SBT/Gradle/pom).
*
* @return the group id
*/
public String getGroupId() {
return groupId;
}
/**
* Gets artifact id for generated sources which support this concept (e.g. Java and pom.xml, Scala and SBT/Gradle/pom).
*
* @return the artifact id
*/
public String getArtifactId() {
return artifactId;
}
/**
* Gets artifact version for generated sources which support this concept (e.g. Java and pom.xml, Scala and SBT/Gradle/pom).
*
* @return the artifact version
*/
public String getArtifactVersion() {
return artifactVersion;
}
/**
* Gets library (sub-template) for the target generated.
*
* @return the library
*/
public String getLibrary() {
return library;
}
/**
* Gets instantiation types mappings. These allow for customizing the defaults provided by a built-in generator.
* <p>
* For example, "array" to "ArrayList" applied to the Java generator will cause all array properties to be instantiated as ArrayList.
* <p>
* This option differs from {@link GeneratorSettings#getTypeMappings()} in that values provided here are generally used for type construction (what is applied to "new").
*
* @return the instantiation types
*/
public Map<String, String> getInstantiationTypes() {
return instantiationTypes;
}
/**
* Gets type mappings. These allow for customizing type definitions.
* <p>
* For example, "array" to "List" applied to the Java generator will cause all variable assignments for array properties to be of type <code>List</code>.
* <p>
* This option differs from {@link GeneratorSettings#getInstantiationTypes()} in that values provided here are variable reference types rather than concrete instantiation types.
*
* @return the type mappings
*/
public Map<String, String> getTypeMappings() {
return typeMappings;
}
/**
* Gets additional properties which will be passed to template as dynamic properties.
*
* @return the additional properties
*/
public Map<String, Object> getAdditionalProperties() {
return additionalProperties;
}
/**
* Gets import mappings between a given class and the import that should be used for that class.
* <p>
* Use import mappings, for example, when you want to "bring your own models" from another location.
*
* @return the import mappings
* @see <a href="https://openapi-generator.tech/docs/customization#bringing-your-own-models">Bringing your own models</a>
*/
public Map<String, String> getImportMappings() {
return importMappings;
}
/**
* Gets language specific primitives. These are in addition to the "base" primitives defined in a generator.
* <p>
* In general, a primitive defined here will indicate to the generator:
* <p>
* - models with these types don't require an import
* - model names not included here require imports and likely indicate a model reference
* <p>
* There may be generator-specific implementation details which differ slightly.
*
* @return the language specific primitives
*/
public Set<String> getLanguageSpecificPrimitives() {
return languageSpecificPrimitives;
}
/**
* Gets reserved word mappings. Values defined here define how a reserved word should be escaped.
* <p>
* If no mapping is present, the mapping is generally automatically applied to a default with prefixed underscore (<code>_name</code>). Note that
* some languages don't support identifiers beginning with a prefix, in which case the generator applies a more appropriate prefix.
*
* @return the reserved word mappings
*/
public Map<String, String> getReservedWordMappings() {
return reservedWordMappings;
}
/**
* Gets git user id. e.g. <strong>openapitools</strong>.
* <p>
* Generally used by git_push.sh in generated sources which support it.
* This value may also be used by templates in maven style references, READMEs, or other documentation.
*
* @return the git user id
*/
public String getGitUserId() {
return gitUserId;
}
/**
* Gets git repo id. e.g. <strong>openapi-generator</strong>.
* <p>
* Generally used by git_push.sh in generated sources which support it.
* This value may also be used by templates in maven style references, READMEs, or other documentation.
*
* @return the git repo id
*/
public String getGitRepoId() {
return gitRepoId;
}
/**
* Gets release note for the generated instance.
* <p>
* Generally used by git_push.sh in generated sources which support it.
* This value may also be used by templates in maven style references, READMEs, or other documentation.
*
* @return the release note
*/
public String getReleaseNote() {
return releaseNote;
}
/**
* Gets the http user agent to be used by client generators which support setting this value.
* <p>
* e.g. codegen_csharp_api_client, defaults to 'OpenAPI-Generator/{packageVersion}}/{language}'
*
* @return the http user agent
*/
public String getHttpUserAgent() {
return httpUserAgent;
}
private GeneratorSettings(Builder builder) {
setDefaults();
generatorName = builder.generatorName;
apiPackage = builder.apiPackage;
modelPackage = builder.modelPackage;
invokerPackage = builder.invokerPackage;
packageName = builder.packageName;
modelNamePrefix = builder.modelNamePrefix;
modelNameSuffix = builder.modelNameSuffix;
groupId = builder.groupId;
artifactId = builder.artifactId;
artifactVersion = builder.artifactVersion;
library = builder.library;
instantiationTypes = ImmutableMap.copyOf(builder.instantiationTypes);
typeMappings = ImmutableMap.copyOf(builder.typeMappings);
importMappings = ImmutableMap.copyOf(builder.importMappings);
languageSpecificPrimitives = ImmutableSet.copyOf(builder.languageSpecificPrimitives);
reservedWordMappings = ImmutableMap.copyOf(builder.reservedWordMappings);
gitUserId = builder.gitUserId;
gitRepoId = builder.gitRepoId;
releaseNote = builder.releaseNote;
httpUserAgent = builder.httpUserAgent;
Map<String, Object> additional = new HashMap<>(builder.additionalProperties);
if (isNotEmpty(apiPackage)) {
additional.put("apiPackage", apiPackage);
}
if (isNotEmpty(modelPackage)) {
additional.put("modelPackage", modelPackage);
}
if (isNotEmpty(invokerPackage)) {
additional.put("invokerPackage", invokerPackage);
}
if (isNotEmpty(packageName)) {
additional.put("packageName", packageName);
}
if (isNotEmpty(groupId)) {
additional.put("groupId", groupId);
}
if (isNotEmpty(artifactId)) {
additional.put("artifactId", artifactId);
}
if (isNotEmpty(artifactVersion)) {
additional.put("artifactVersion", artifactVersion);
}
if (isNotEmpty(modelNamePrefix)) {
additional.put("modelNamePrefix", modelNamePrefix);
}
if (isNotEmpty(modelNameSuffix)) {
additional.put("modelNameSuffix", modelNameSuffix);
}
if (isNotEmpty(gitUserId)) {
additional.put("gitUserId", gitUserId);
}
if (isNotEmpty(gitRepoId)) {
additional.put("gitRepoId", gitRepoId);
}
if (isNotEmpty(releaseNote)) {
additional.put("releaseNote", releaseNote);
}
if (isNotEmpty(httpUserAgent)) {
additional.put("httpUserAgent", httpUserAgent);
}
additionalProperties = ImmutableMap.copyOf(additional);
}
/**
* Instantiates a new Generator settings.
*/
@SuppressWarnings("unused")
public GeneratorSettings() {
setDefaults();
instantiationTypes = ImmutableMap.of();
typeMappings = ImmutableMap.of();
additionalProperties = ImmutableMap.of();
importMappings = ImmutableMap.of();
languageSpecificPrimitives = ImmutableSet.of();
reservedWordMappings = ImmutableMap.of();
}
private void setDefaults() {
gitUserId = DEFAULT_GIT_USER_ID;
gitRepoId = DEFAULT_GIT_REPO_ID;
releaseNote = DEFAULT_RELEASE_NOTE;
}
private boolean isNotEmpty(String value) {
return value != null && value.length() > 0;
}
/**
* New builder builder.
*
* @return the builder
*/
public static Builder newBuilder() {
return new Builder();
}
/**
* New builder builder.
*
* @param copy the copy
* @return the builder
*/
public static Builder newBuilder(GeneratorSettings copy) {
Builder builder = new Builder();
builder.generatorName = copy.getGeneratorName();
builder.apiPackage = copy.getApiPackage();
builder.modelPackage = copy.getModelPackage();
builder.invokerPackage = copy.getInvokerPackage();
builder.packageName = copy.getPackageName();
builder.modelNamePrefix = copy.getModelNamePrefix();
builder.modelNameSuffix = copy.getModelNameSuffix();
builder.groupId = copy.getGroupId();
builder.artifactId = copy.getArtifactId();
builder.artifactVersion = copy.getArtifactVersion();
builder.library = copy.getLibrary();
builder.instantiationTypes = new HashMap<>(copy.getInstantiationTypes());
builder.typeMappings = new HashMap<>(copy.getTypeMappings());
builder.additionalProperties = new HashMap<>(copy.getAdditionalProperties());
builder.importMappings = new HashMap<>(copy.getImportMappings());
builder.languageSpecificPrimitives = new HashSet<>(copy.getLanguageSpecificPrimitives());
builder.reservedWordMappings = new HashMap<>(copy.getReservedWordMappings());
builder.gitUserId = copy.getGitUserId();
builder.gitRepoId = copy.getGitRepoId();
builder.releaseNote = copy.getReleaseNote();
builder.httpUserAgent = copy.getHttpUserAgent();
return builder;
}
/**
* {@code GeneratorSettings} builder static inner class.
*/
@SuppressWarnings("UnusedReturnValue")
public static final class Builder {
private String generatorName;
private String apiPackage;
private String modelPackage;
private String invokerPackage;
private String packageName;
private String modelNamePrefix;
private String modelNameSuffix;
private String groupId;
private String artifactId;
private String artifactVersion;
private String library;
private Map<String, String> instantiationTypes;
private Map<String, String> typeMappings;
private Map<String, Object> additionalProperties;
private Map<String, String> importMappings;
private Set<String> languageSpecificPrimitives;
private Map<String, String> reservedWordMappings;
private String gitUserId;
private String gitRepoId;
private String releaseNote;
private String httpUserAgent;
/**
* Instantiates a new Builder.
*/
public Builder() {
instantiationTypes = new HashMap<>();
typeMappings = new HashMap<>();
additionalProperties = new HashMap<>();
importMappings = new HashMap<>();
languageSpecificPrimitives = new HashSet<>();
reservedWordMappings = new HashMap<>();
gitUserId = DEFAULT_GIT_USER_ID;
gitRepoId = DEFAULT_GIT_REPO_ID;
releaseNote = DEFAULT_RELEASE_NOTE;
}
/**
* Sets the {@code generatorName} and returns a reference to this Builder so that the methods can be chained together.
*
* @param generatorName the {@code generatorName} to set
* @return a reference to this Builder
*/
public Builder withGeneratorName(String generatorName) {
this.generatorName = generatorName;
return this;
}
/**
* Sets the {@code apiPackage} and returns a reference to this Builder so that the methods can be chained together.
*
* @param apiPackage the {@code apiPackage} to set
* @return a reference to this Builder
*/
public Builder withApiPackage(String apiPackage) {
this.apiPackage = apiPackage;
return this;
}
/**
* Sets the {@code modelPackage} and returns a reference to this Builder so that the methods can be chained together.
*
* @param modelPackage the {@code modelPackage} to set
* @return a reference to this Builder
*/
public Builder withModelPackage(String modelPackage) {
this.modelPackage = modelPackage;
return this;
}
/**
* Sets the {@code invokerPackage} and returns a reference to this Builder so that the methods can be chained together.
*
* @param invokerPackage the {@code invokerPackage} to set
* @return a reference to this Builder
*/
public Builder withInvokerPackage(String invokerPackage) {
this.invokerPackage = invokerPackage;
return this;
}
/**
* Sets the {@code packageName} and returns a reference to this Builder so that the methods can be chained together.
*
* @param packageName the {@code packageName} to set
* @return a reference to this Builder
*/
public Builder withPackageName(String packageName) {
this.packageName = packageName;
return this;
}
/**
* Sets the {@code modelNamePrefix} and returns a reference to this Builder so that the methods can be chained together.
*
* @param modelNamePrefix the {@code modelNamePrefix} to set
* @return a reference to this Builder
*/
public Builder withModelNamePrefix(String modelNamePrefix) {
this.modelNamePrefix = modelNamePrefix;
return this;
}
/**
* Sets the {@code modelNameSuffix} and returns a reference to this Builder so that the methods can be chained together.
*
* @param modelNameSuffix the {@code modelNameSuffix} to set
* @return a reference to this Builder
*/
public Builder withModelNameSuffix(String modelNameSuffix) {
this.modelNameSuffix = modelNameSuffix;
return this;
}
/**
* Sets the {@code groupId} and returns a reference to this Builder so that the methods can be chained together.
*
* @param groupId the {@code groupId} to set
* @return a reference to this Builder
*/
public Builder withGroupId(String groupId) {
this.groupId = groupId;
return this;
}
/**
* Sets the {@code artifactId} and returns a reference to this Builder so that the methods can be chained together.
*
* @param artifactId the {@code artifactId} to set
* @return a reference to this Builder
*/
public Builder withArtifactId(String artifactId) {
this.artifactId = artifactId;
return this;
}
/**
* Sets the {@code artifactVersion} and returns a reference to this Builder so that the methods can be chained together.
*
* @param artifactVersion the {@code artifactVersion} to set
* @return a reference to this Builder
*/
public Builder withArtifactVersion(String artifactVersion) {
this.artifactVersion = artifactVersion;
return this;
}
/**
* Sets the {@code library} and returns a reference to this Builder so that the methods can be chained together.
*
* @param library the {@code library} to set
* @return a reference to this Builder
*/
public Builder withLibrary(String library) {
this.library = library;
return this;
}
/**
* Sets the {@code instantiationTypes} and returns a reference to this Builder so that the methods can be chained together.
*
* @param instantiationTypes the {@code instantiationTypes} to set
* @return a reference to this Builder
*/
public Builder withInstantiationTypes(Map<String, String> instantiationTypes) {
this.instantiationTypes = instantiationTypes;
return this;
}
/**
* Sets a single {@code instantiationTypes} and returns a reference to this Builder so that the methods can be chained together.
*
* @param key A key for some instantiation type
* @param value The value of some instantiation type
* @return a reference to this Builder
*/
public Builder withInstantiationType(String key, String value) {
if (this.instantiationTypes == null) {
this.instantiationTypes = new HashMap<>();
}
this.instantiationTypes.put(key, value);
return this;
}
/**
* Sets the {@code typeMappings} and returns a reference to this Builder so that the methods can be chained together.
*
* @param typeMappings the {@code typeMappings} to set
* @return a reference to this Builder
*/
public Builder withTypeMappings(Map<String, String> typeMappings) {
this.typeMappings = typeMappings;
return this;
}
/**
* Sets the {@code additionalProperties} and returns a reference to this Builder so that the methods can be chained together.
*
* @param additionalProperties the {@code additionalProperties} to set
* @return a reference to this Builder
*/
public Builder withAdditionalProperties(Map<String, Object> additionalProperties) {
this.additionalProperties = additionalProperties;
return this;
}
/**
* Sets the {@code additionalProperties} and returns a reference to this Builder so that the methods can be chained together.
*
* @param key A key for some additional property
* @param value The value of some additional property
* @return a reference to this Builder
*/
public Builder withAdditionalProperty(String key, Object value) {
if (this.additionalProperties == null) {
this.additionalProperties = new HashMap<>();
}
this.additionalProperties.put(key, value);
return this;
}
/**
* Sets the {@code importMappings} and returns a reference to this Builder so that the methods can be chained together.
*
* @param importMappings the {@code importMappings} to set
* @return a reference to this Builder
*/
public Builder withImportMappings(Map<String, String> importMappings) {
this.importMappings = importMappings;
return this;
}
/**
* Sets a single {@code importMappings} and returns a reference to this Builder so that the methods can be chained together.
*
* @param key A key for some import mapping
* @param value The value of some import mapping
* @return a reference to this Builder
*/
public Builder withImportMapping(String key, String value) {
if (this.importMappings == null) {
this.importMappings = new HashMap<>();
}
this.importMappings.put(key, value);
return this;
}
/**
* Sets the {@code languageSpecificPrimitives} and returns a reference to this Builder so that the methods can be chained together.
*
* @param languageSpecificPrimitives the {@code languageSpecificPrimitives} to set
* @return a reference to this Builder
*/
public Builder withLanguageSpecificPrimitives(Set<String> languageSpecificPrimitives) {
this.languageSpecificPrimitives = languageSpecificPrimitives;
return this;
}
/**
* Sets a single {@code languageSpecificPrimitives} and returns a reference to this Builder so that the methods can be chained together.
*
* @param value The value of some primitive to set
* @return a reference to this Builder
*/
public Builder withLanguageSpecificPrimitive(String value) {
if (this.languageSpecificPrimitives == null) {
this.languageSpecificPrimitives = new HashSet<>();
}
this.languageSpecificPrimitives.add(value);
return this;
}
/**
* Sets the {@code reservedWordMappings} and returns a reference to this Builder so that the methods can be chained together.
*
* @param reservedWordMappings the {@code reservedWordMappings} to set
* @return a reference to this Builder
*/
public Builder withReservedWordMappings(Map<String, String> reservedWordMappings) {
this.reservedWordMappings = reservedWordMappings;
return this;
}
/**
* Sets a single {@code reservedWordMappings} and returns a reference to this Builder so that the methods can be chained together.
*
* @param key A key for some reserved word mapping
* @param value The value of some reserved word mapping
* @return a reference to this Builder
*/
public Builder withReservedWordMapping(String key, String value) {
if (this.reservedWordMappings == null) {
this.reservedWordMappings = new HashMap<>();
}
this.reservedWordMappings.put(key, value);
return this;
}
/**
* Sets the {@code gitUserId} and returns a reference to this Builder so that the methods can be chained together.
*
* @param gitUserId the {@code gitUserId} to set
* @return a reference to this Builder
*/
public Builder withGitUserId(String gitUserId) {
this.gitUserId = gitUserId;
return this;
}
/**
* Sets the {@code gitRepoId} and returns a reference to this Builder so that the methods can be chained together.
*
* @param gitRepoId the {@code gitRepoId} to set
* @return a reference to this Builder
*/
public Builder withGitRepoId(String gitRepoId) {
this.gitRepoId = gitRepoId;
return this;
}
/**
* Sets the {@code releaseNote} and returns a reference to this Builder so that the methods can be chained together.
*
* @param releaseNote the {@code releaseNote} to set
* @return a reference to this Builder
*/
public Builder withReleaseNote(String releaseNote) {
this.releaseNote = releaseNote;
return this;
}
/**
* Sets the {@code httpUserAgent} and returns a reference to this Builder so that the methods can be chained together.
*
* @param httpUserAgent the {@code httpUserAgent} to set
* @return a reference to this Builder
*/
public Builder withHttpUserAgent(String httpUserAgent) {
this.httpUserAgent = httpUserAgent;
return this;
}
/**
* Returns a {@code GeneratorSettings} built from the parameters previously set.
*
* @return a {@code GeneratorSettings} built with parameters of this {@code GeneratorSettings.Builder}
*/
public GeneratorSettings build() {
GeneratorSettings instance = new GeneratorSettings(this);
//noinspection PlaceholderCountMatchesArgumentCount
LOGGER.debug("GeneratorSettings#build: %s", instance.toString());
return instance;
}
}
@Override
public String toString() {
return "GeneratorSettings{" +
"generatorName='" + generatorName + '\'' +
", apiPackage='" + apiPackage + '\'' +
", modelPackage='" + modelPackage + '\'' +
", invokerPackage='" + invokerPackage + '\'' +
", packageName='" + packageName + '\'' +
", modelNamePrefix='" + modelNamePrefix + '\'' +
", modelNameSuffix='" + modelNameSuffix + '\'' +
", groupId='" + groupId + '\'' +
", artifactId='" + artifactId + '\'' +
", artifactVersion='" + artifactVersion + '\'' +
", library='" + library + '\'' +
", instantiationTypes=" + instantiationTypes +
", typeMappings=" + typeMappings +
", additionalProperties=" + additionalProperties +
", importMappings=" + importMappings +
", languageSpecificPrimitives=" + languageSpecificPrimitives +
", reservedWordMappings=" + reservedWordMappings +
", gitUserId='" + gitUserId + '\'' +
", gitRepoId='" + gitRepoId + '\'' +
", releaseNote='" + releaseNote + '\'' +
", httpUserAgent='" + httpUserAgent + '\'' +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof GeneratorSettings)) return false;
GeneratorSettings that = (GeneratorSettings) o;
return Objects.equals(getGeneratorName(), that.getGeneratorName()) &&
Objects.equals(getApiPackage(), that.getApiPackage()) &&
Objects.equals(getModelPackage(), that.getModelPackage()) &&
Objects.equals(getInvokerPackage(), that.getInvokerPackage()) &&
Objects.equals(getPackageName(), that.getPackageName()) &&
Objects.equals(getModelNamePrefix(), that.getModelNamePrefix()) &&
Objects.equals(getModelNameSuffix(), that.getModelNameSuffix()) &&
Objects.equals(getGroupId(), that.getGroupId()) &&
Objects.equals(getArtifactId(), that.getArtifactId()) &&
Objects.equals(getArtifactVersion(), that.getArtifactVersion()) &&
Objects.equals(getLibrary(), that.getLibrary()) &&
Objects.equals(getInstantiationTypes(), that.getInstantiationTypes()) &&
Objects.equals(getTypeMappings(), that.getTypeMappings()) &&
Objects.equals(getAdditionalProperties(), that.getAdditionalProperties()) &&
Objects.equals(getImportMappings(), that.getImportMappings()) &&
Objects.equals(getLanguageSpecificPrimitives(), that.getLanguageSpecificPrimitives()) &&
Objects.equals(getReservedWordMappings(), that.getReservedWordMappings()) &&
Objects.equals(getGitUserId(), that.getGitUserId()) &&
Objects.equals(getGitRepoId(), that.getGitRepoId()) &&
Objects.equals(getReleaseNote(), that.getReleaseNote()) &&
Objects.equals(getHttpUserAgent(), that.getHttpUserAgent());
}
@Override
public int hashCode() {
return Objects.hash(
getGeneratorName(),
getApiPackage(),
getModelPackage(),
getInvokerPackage(),
getPackageName(),
getModelNamePrefix(),
getModelNameSuffix(),
getGroupId(),
getArtifactId(),
getArtifactVersion(),
getLibrary(),
getInstantiationTypes(),
getTypeMappings(),
getAdditionalProperties(),
getImportMappings(),
getLanguageSpecificPrimitives(),
getReservedWordMappings(),
getGitUserId(),
getGitRepoId(),
getReleaseNote(),
getHttpUserAgent()
);
}
}

View File

@@ -0,0 +1,534 @@
/*
* Copyright 2019 OpenAPI-Generator Contributors (https://openapi-generator.tech)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openapitools.codegen.config;
import com.google.common.collect.ImmutableMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
* Represents those settings applied to a generation workflow.
*/
@SuppressWarnings("WeakerAccess")
public class WorkflowSettings {
private static final Logger LOGGER = LoggerFactory.getLogger(WorkflowSettings.class);
private String inputSpec;
private String outputDir;
private boolean verbose;
private boolean skipOverwrite;
private boolean removeOperationIdPrefix;
private boolean logToStderr;
private boolean validateSpec;
private boolean enablePostProcessFile;
private boolean enableMinimalUpdate;
private boolean strictSpecBehavior;
private String templateDir;
private String templatingEngineName;
private String ignoreFileOverride;
private ImmutableMap<String, String> systemProperties;
private WorkflowSettings(Builder builder) {
setDefaults();
inputSpec = builder.inputSpec;
outputDir = builder.outputDir;
verbose = builder.verbose;
skipOverwrite = builder.skipOverwrite;
removeOperationIdPrefix = builder.removeOperationIdPrefix;
logToStderr = builder.logToStderr;
validateSpec = builder.validateSpec;
enablePostProcessFile = builder.enablePostProcessFile;
enableMinimalUpdate = builder.enableMinimalUpdate;
strictSpecBehavior = builder.strictSpecBehavior;
templateDir = builder.templateDir;
templatingEngineName = builder.templatingEngineName;
ignoreFileOverride = builder.ignoreFileOverride;
systemProperties = ImmutableMap.copyOf(builder.systemProperties);
}
/**
* Instantiates a new workflow settings.
*/
@SuppressWarnings("unused")
public WorkflowSettings() {
setDefaults();
systemProperties = ImmutableMap.of();
}
private void setDefaults(){
validateSpec = true;
strictSpecBehavior = true;
outputDir = ".";
}
public static Builder newBuilder() {
return new Builder();
}
public static Builder newBuilder(WorkflowSettings copy) {
Builder builder = new Builder();
builder.inputSpec = copy.getInputSpec();
builder.outputDir = copy.getOutputDir();
builder.verbose = copy.isVerbose();
builder.skipOverwrite = copy.isSkipOverwrite();
builder.removeOperationIdPrefix = copy.isRemoveOperationIdPrefix();
builder.logToStderr = copy.isLogToStderr();
builder.validateSpec = copy.isValidateSpec();
builder.enablePostProcessFile = copy.isEnablePostProcessFile();
builder.enableMinimalUpdate = copy.isEnableMinimalUpdate();
builder.strictSpecBehavior = copy.isStrictSpecBehavior();
builder.templatingEngineName = copy.getTemplatingEngineName();
builder.ignoreFileOverride = copy.getIgnoreFileOverride();
builder.systemProperties = ImmutableMap.copyOf(copy.getSystemProperties());
// force builder "with" methods to invoke side effects
builder.withTemplateDir(copy.getTemplateDir());
return builder;
}
/**
* Gets input spec's location, as URL or file
*
* @return the input spec
*/
public String getInputSpec() {
return inputSpec;
}
/**
* Gets the output dir (where we write generated files). Defaults to the current directory.
*
* @return the output dir
*/
public String getOutputDir() {
return outputDir;
}
/**
* Configures verbosity of generation. When <code>true</code>, more messages will be printed during generation.
*
* @return <code>true</code> if verbose mode, <code>false</code> otherwise.
*/
public boolean isVerbose() {
return verbose;
}
/**
* Indicates whether or not the existing files should be overwritten during the generation. This option is more rudimentary than
* defining patterns in .openapi-generator-ignore or {@link WorkflowSettings#isEnableMinimalUpdate()}.
*
* @return <code>true</code> if defaulting to overwriting files, false otherwise.
* @see <a href="https://openapi-generator.tech/docs/customization#ignore-file-format">Ignore File Format</a>
*/
public boolean isSkipOverwrite() {
return skipOverwrite;
}
/**
* Indicates whether or not to remove the prefix of operationId, e.g. <code>config_getId</code> to <code>getId</code>.
*
* @return <code>true</code> if the operation id prefix should be removed during generation, <code>false</code> otherwise.
*/
public boolean isRemoveOperationIdPrefix() {
return removeOperationIdPrefix;
}
/**
* Indicates whether or not the generator's executor will write all log messages (not just errors) to STDOUT. Useful for
* piping the JSON output of debug options (e.g. <code>-DdebugOperations</code>) to an external parser directly while testing a generator.
*
* @return <code>true</code> if the executor should attempt to write all messages to stderr,
* false otherwise (which defaults to logging configuration, not necessarily stdout).
*/
public boolean isLogToStderr() {
return logToStderr;
}
/**
* Indicates whether or not generation should also validate an input specification.
* <p>
* NOTE: Invalid specs may result in a generation error, disabling may cause unexpected results.
*
* @return <code>true</code> if spec document validation is enabled, otherwise <code>false</code>. Default: <code>true</code>.
*/
public boolean isValidateSpec() {
return validateSpec;
}
/**
* Indicates whether or not file post-processing is enabled for generators which support it. Refer to individual generator documentation for details.
* <p>
* In general, once enabled, a generator will evaluate a command stored in <code>LANG_POST_PROCESS_FILE</code>.
* <p>
* For example:
*
* <code>export SCALA_POST_PROCESS_FILE=/usr/local/bin/scalafmt</code>
* <p>
* Here, a Scala generator which supports file post-processing will run scalafmt for each generated file.
*
* @return <code>true</code> if file post-processing is enabled, otherwise <code>false</code>.
*/
public boolean isEnablePostProcessFile() {
return enablePostProcessFile;
}
/**
* Indicates whether or not the generation should update only those files which have changed.
*
* @return <code>true</code> if minimal updates are enabled, otherwise <code>false</code>.
*/
public boolean isEnableMinimalUpdate() {
return enableMinimalUpdate;
}
/**
* Indicates whether or not 'MUST' and 'SHALL' wording in the api specification is strictly adhered to.
* For example, when <code>false</code>, no automatic 'fixes' will be applied to documents which pass validation but don't follow the spec.
*
* @return <code>true</code> if the generator should attempt to strictly follow rules in the specification, otherwise <code>false</code>.
*/
public boolean isStrictSpecBehavior() {
return strictSpecBehavior;
}
/**
* Gets the directory holding templates used in generation. This option allows users to extend or modify built-in templates, or to write their own.
*
* @return the template dir
*/
public String getTemplateDir() {
return templateDir;
}
/**
* Gets the name of the templating engine to target. This option allows a user to target an engine which differs from the generator default, or to
* refer to their own fully qualified type name of a custom template engine adapter.
*
* @return the templating engine name
* @see <a href="https://openapi-generator.tech/docs/templating#custom-engines">Custom Engines</a>
*/
public String getTemplatingEngineName() {
return templatingEngineName;
}
/**
* Gets the override location for the .openapi-generator-ignore file. Most useful on initial generation.
*
* @return the ignore file override
*/
public String getIgnoreFileOverride() {
return ignoreFileOverride;
}
/**
* Gets system properties applied to the generator.
*
* @return the system properties
*/
public Map<String, String> getSystemProperties() {
return systemProperties;
}
/**
* {@code WorkflowSettings} builder static inner class.
*/
@SuppressWarnings("unused")
public static final class Builder {
private String inputSpec;
private String outputDir;
private boolean verbose;
private boolean skipOverwrite;
private boolean removeOperationIdPrefix;
private boolean logToStderr;
private boolean validateSpec;
private boolean enablePostProcessFile;
private boolean enableMinimalUpdate;
private boolean strictSpecBehavior;
private String templateDir;
private String templatingEngineName;
private String ignoreFileOverride;
private Map<String, String> systemProperties;
private Builder() {
systemProperties = new HashMap<>();
}
/**
* Sets the {@code inputSpec} and returns a reference to this Builder so that the methods can be chained together.
*
* @param inputSpec the {@code inputSpec} to set
* @return a reference to this Builder
*/
public Builder withInputSpec(String inputSpec) {
this.inputSpec = inputSpec;
return this;
}
/**
* Sets the {@code outputDir} and returns a reference to this Builder so that the methods can be chained together.
*
* @param outputDir the {@code outputDir} to set
* @return a reference to this Builder
*/
public Builder withOutputDir(String outputDir) {
this.outputDir = Paths.get(outputDir).toAbsolutePath().toString();;
return this;
}
/**
* Sets the {@code verbose} and returns a reference to this Builder so that the methods can be chained together.
*
* @param verbose the {@code verbose} to set
* @return a reference to this Builder
*/
public Builder withVerbose(boolean verbose) {
this.verbose = verbose;
return this;
}
/**
* Sets the {@code skipOverwrite} and returns a reference to this Builder so that the methods can be chained together.
*
* @param skipOverwrite the {@code skipOverwrite} to set
* @return a reference to this Builder
*/
public Builder withSkipOverwrite(boolean skipOverwrite) {
this.skipOverwrite = skipOverwrite;
return this;
}
/**
* Sets the {@code removeOperationIdPrefix} and returns a reference to this Builder so that the methods can be chained together.
*
* @param removeOperationIdPrefix the {@code removeOperationIdPrefix} to set
* @return a reference to this Builder
*/
public Builder withRemoveOperationIdPrefix(boolean removeOperationIdPrefix) {
this.removeOperationIdPrefix = removeOperationIdPrefix;
return this;
}
/**
* Sets the {@code logToStderr} and returns a reference to this Builder so that the methods can be chained together.
*
* @param logToStderr the {@code logToStderr} to set
* @return a reference to this Builder
*/
public Builder withLogToStderr(boolean logToStderr) {
this.logToStderr = logToStderr;
return this;
}
/**
* Sets the {@code validateSpec} and returns a reference to this Builder so that the methods can be chained together.
*
* @param validateSpec the {@code validateSpec} to set
* @return a reference to this Builder
*/
public Builder withValidateSpec(boolean validateSpec) {
this.validateSpec = validateSpec;
return this;
}
/**
* Sets the {@code enablePostProcessFile} and returns a reference to this Builder so that the methods can be chained together.
*
* @param enablePostProcessFile the {@code enablePostProcessFile} to set
* @return a reference to this Builder
*/
public Builder withEnablePostProcessFile(boolean enablePostProcessFile) {
this.enablePostProcessFile = enablePostProcessFile;
return this;
}
/**
* Sets the {@code enableMinimalUpdate} and returns a reference to this Builder so that the methods can be chained together.
*
* @param enableMinimalUpdate the {@code enableMinimalUpdate} to set
* @return a reference to this Builder
*/
public Builder withEnableMinimalUpdate(boolean enableMinimalUpdate) {
this.enableMinimalUpdate = enableMinimalUpdate;
return this;
}
/**
* Sets the {@code strictSpecBehavior} and returns a reference to this Builder so that the methods can be chained together.
*
* @param strictSpecBehavior the {@code strictSpecBehavior} to set
* @return a reference to this Builder
*/
public Builder withStrictSpecBehavior(boolean strictSpecBehavior) {
this.strictSpecBehavior = strictSpecBehavior;
return this;
}
/**
* Sets the {@code templateDir} and returns a reference to this Builder so that the methods can be chained together.
*
* @param templateDir the {@code templateDir} to set
* @return a reference to this Builder
*/
public Builder withTemplateDir(String templateDir) {
if (templateDir == null) {
this.templateDir = null;
} else {
File f = new File(templateDir);
// check to see if the folder exists
if (!(f.exists() && f.isDirectory())) {
throw new IllegalArgumentException(
"Template directory " + templateDir + " does not exist.");
}
this.templateDir = Paths.get(f.toURI()).toAbsolutePath().toString();
}
return this;
}
/**
* Sets the {@code templatingEngineName} and returns a reference to this Builder so that the methods can be chained together.
*
* @param templatingEngineName the {@code templatingEngineName} to set
* @return a reference to this Builder
*/
public Builder withTemplatingEngineName(String templatingEngineName) {
this.templatingEngineName = templatingEngineName;
return this;
}
/**
* Sets the {@code ignoreFileOverride} and returns a reference to this Builder so that the methods can be chained together.
*
* @param ignoreFileOverride the {@code ignoreFileOverride} to set
* @return a reference to this Builder
*/
public Builder withIgnoreFileOverride(String ignoreFileOverride) {
this.ignoreFileOverride = ignoreFileOverride;
return this;
}
/**
* Sets the {@code systemProperties} and returns a reference to this Builder so that the methods can be chained together.
*
* @param systemProperties the {@code systemProperties} to set
* @return a reference to this Builder
*/
public Builder withSystemProperties(Map<String, String> systemProperties) {
this.systemProperties = systemProperties;
return this;
}
/**
* Sets the {@code systemProperties} and returns a reference to this Builder so that the methods can be chained together.
*
* @param key The key of a system (global) property to set
* @param value The value of a system (global) property to set
* @return a reference to this Builder
*/
public Builder withSystemProperty(String key, String value) {
if (this.systemProperties == null) {
this.systemProperties = new HashMap<>();
}
this.systemProperties.put(key, value);
return this;
}
/**
* Returns a {@code WorkflowSettings} built from the parameters previously set.
*
* @return a {@code WorkflowSettings} built with parameters of this {@code WorkflowSettings.Builder}
*/
public WorkflowSettings build() {
WorkflowSettings instance = new WorkflowSettings(this);
//noinspection PlaceholderCountMatchesArgumentCount
LOGGER.debug("WorkflowSettings#build: %s", instance.toString());
return instance;
}
}
@Override
public String toString() {
return "WorkflowSettings{" +
"inputSpec='" + inputSpec + '\'' +
", outputDir='" + outputDir + '\'' +
", verbose=" + verbose +
", skipOverwrite=" + skipOverwrite +
", removeOperationIdPrefix=" + removeOperationIdPrefix +
", logToStderr=" + logToStderr +
", validateSpec=" + validateSpec +
", enablePostProcessFile=" + enablePostProcessFile +
", enableMinimalUpdate=" + enableMinimalUpdate +
", strictSpecBehavior=" + strictSpecBehavior +
", templateDir='" + templateDir + '\'' +
", templatingEngineName='" + templatingEngineName + '\'' +
", ignoreFileOverride='" + ignoreFileOverride + '\'' +
", systemProperties=" + systemProperties +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof WorkflowSettings)) return false;
WorkflowSettings that = (WorkflowSettings) o;
return isVerbose() == that.isVerbose() &&
isSkipOverwrite() == that.isSkipOverwrite() &&
isRemoveOperationIdPrefix() == that.isRemoveOperationIdPrefix() &&
isLogToStderr() == that.isLogToStderr() &&
isValidateSpec() == that.isValidateSpec() &&
isEnablePostProcessFile() == that.isEnablePostProcessFile() &&
isEnableMinimalUpdate() == that.isEnableMinimalUpdate() &&
isStrictSpecBehavior() == that.isStrictSpecBehavior() &&
Objects.equals(getInputSpec(), that.getInputSpec()) &&
Objects.equals(getOutputDir(), that.getOutputDir()) &&
Objects.equals(getTemplateDir(), that.getTemplateDir()) &&
Objects.equals(getTemplatingEngineName(), that.getTemplatingEngineName()) &&
Objects.equals(getIgnoreFileOverride(), that.getIgnoreFileOverride()) &&
Objects.equals(getSystemProperties(), that.getSystemProperties());
}
@Override
public int hashCode() {
return Objects.hash(
getInputSpec(),
getOutputDir(),
isVerbose(),
isSkipOverwrite(),
isRemoveOperationIdPrefix(),
isLogToStderr(),
isValidateSpec(),
isEnablePostProcessFile(),
isEnableMinimalUpdate(),
isStrictSpecBehavior(),
getTemplateDir(),
getTemplatingEngineName(),
getIgnoreFileOverride(),
getSystemProperties()
);
}
}

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2019 OpenAPI-Generator Contributors (https://openapi-generator.tech)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openapitools.codegen.meta;
/**

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2019 OpenAPI-Generator Contributors (https://openapi-generator.tech)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openapitools.codegen.meta;
/**

View File

@@ -0,0 +1,61 @@
/*
* Copyright 2019 OpenAPI-Generator Contributors (https://openapi-generator.tech)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openapitools.codegen.validation;
import java.util.List;
/**
* A generic implementation of a validator instance which simply applies rules to an input instance.
*
* @param <TInput> The type of object being evaluated.
*/
@SuppressWarnings({"WeakerAccess"})
public class GenericValidator<TInput> implements Validator<TInput> {
private List<ValidationRule> rules;
/**
* Constructs a new instance of {@link GenericValidator}.
*
* @param rules The rules to be evaluated during validation.
*/
public GenericValidator(List<ValidationRule> rules) {
this.rules = rules;
}
/**
* Validates input, resulting in a instance of {@link ValidationResult} which provides details on all validations performed (success, error, warning).
*
* @param input The object instance to be validated.
*
* @return A {@link ValidationResult} which details the success, error, and warning validation results.
*/
@Override
public ValidationResult validate(TInput input) {
ValidationResult result = new ValidationResult();
if (rules != null) {
rules.forEach(it -> {
boolean passes = it.evaluate(input);
if (passes) {
result.addResult(Validated.valid(it));
} else {
result.addResult(Validated.invalid(it, it.getFailureMessage()));
}
});
}
return result;
}
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright 2019 OpenAPI-Generator Contributors (https://openapi-generator.tech)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openapitools.codegen.validation;
/**
* Represents a {@link Validated} state which is "Invalid" to some degree of {@link Severity}.
*/
@SuppressWarnings({"WeakerAccess"})
public final class Invalid extends Validated {
private String message;
private ValidationRule rule;
/**
* Constructs a new {@link Invalid} instance.
*
* @param rule The rule which was evaluated and resulted in this state.
* @param message The message to be displayed for this invalid state.
*/
Invalid(ValidationRule rule, String message) {
this.rule = rule;
this.message = message;
}
@Override
String getMessage() {
return message;
}
@Override
ValidationRule getRule() {
return rule;
}
/**
* Get details about the severity of this invalid state.
* For instance, is this an {@link Severity#ERROR} or simply a {@link Severity#WARNING}.
*
* @return The {@link Severity} enum detailing this state's severity.
*/
public Severity getSeverity() {
return rule.getSeverity();
}
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright 2019 OpenAPI-Generator Contributors (https://openapi-generator.tech)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openapitools.codegen.validation;
/**
* Defines different levels of severity to be used during validation.
*/
public enum Severity {
/**
* Lower severity indicating that the target state may be unpredictable, no longer supported, or known to have issues.
* Marking a type with this value should not result in application exceptions under normal operating circumstances.
*/
WARNING,
/**
* Higher severity indicating that the target state is not supported, or is known to cause problems with the application.
* Marking a type with this value should result in an application exception or error exit code under normal operating circumstances.
*/
ERROR
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright 2019 OpenAPI-Generator Contributors (https://openapi-generator.tech)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openapitools.codegen.validation;
/**
* Represents a {@link Validated} state which is "valid" according to the defined rule.
*/
public final class Valid extends Validated {
private ValidationRule rule;
/**
* Defines whether or not the validation resulted in a "valid" condition.
*
* @return <code>true</code> if the instance passed validation of the rule returned by {@link Validated#getRule()}.
*/
@Override
boolean isValid() {
return true;
}
/**
* Constructs a new {@link Valid} instance.
*
* @param rule The rule which was evaluated and resulted in this state.
*/
Valid(ValidationRule rule) {
this.rule = rule;
}
@Override
public String getMessage() {
return null;
}
@Override
public ValidationRule getRule() {
return rule;
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright 2019 OpenAPI-Generator Contributors (https://openapi-generator.tech)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openapitools.codegen.validation;
/**
* Provides details about the state of a completed validation.
*/
public abstract class Validated {
/**
* Defines whether or not the validation resulted in a "valid" condition.
*
* @return <code>true</code> if the instance passed validation of the rule returned by {@link Validated#getRule()}.
*/
boolean isValid() {
return false;
}
/**
* Gets the rule which was evaluated and resulted in this state.
*
* @return The instance of {@link ValidationRule} which was evaluated.
*/
abstract ValidationRule getRule();
/**
* Gets the message with details about this validated state.
*
* @return A string intended to be displayed to a user.
*/
abstract String getMessage();
/**
* Creates an instance of an {@link Invalid} validation state.
*
* @param rule The rule which was evaluated.
* @param message The message to display to a user.
*
* @return A {@link Validated} instance representing an invalid state according to the rule.
*/
public static Validated invalid(ValidationRule rule, String message) {
return new Invalid(rule, message);
}
/**
* Creates an instance of an {@link Valid} validation state.
*
* @param rule The rule which was evaluated.
*
* @return A {@link Validated} instance representing a valid state according to the rule.
*/
public static Validated valid(ValidationRule rule) {
return new Valid(rule);
}
}

View File

@@ -0,0 +1,104 @@
/*
* Copyright 2019 OpenAPI-Generator Contributors (https://openapi-generator.tech)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openapitools.codegen.validation;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/**
* Encapsulates details about the result of a validation test.
*/
@SuppressWarnings("WeakerAccess")
public final class ValidationResult {
private final List<Validated> validations;
/**
* Constructs a new {@link ValidationResult} instance, backed by the provided validations (useful for testing).
*
* @param validations A pre-defined set of validations to begin with.
*/
private ValidationResult(List<Validated> validations) {
this.validations = Collections.synchronizedList(validations);
}
/**
* Constructs a new {@link ValidationResult} instance.
*/
public ValidationResult() {
this(new ArrayList<>());
}
/**
* Gets all the validated states resulting from the evaluation. This includes all {@link Valid} and {@link Invalid} instances.
*
* @return All validated results.
*/
public List<Validated> getAll() {
return validations;
}
/**
* Gets a filtered list of {@link Valid} states.
*
* @return A list containing only {@link Valid} states.
*/
public List<Valid> getValid(){
return validations.stream().filter(Validated::isValid).map(it -> (Valid)it).collect(Collectors.toList());
}
/**
* Gets a filters list of {@link Invalid} states with the level of {@link Severity#ERROR}
*
* @return A list of all validation errors.
*/
public List<Invalid> getErrors(){
return validations.stream()
.filter(it -> !it.isValid())
.map(it -> (Invalid)it)
.filter(it -> it.getSeverity().equals(Severity.ERROR))
.collect(Collectors.toList());
}
/**
* Gets a filtered list of {@link Invalid} states with the level of {@link Severity#WARNING}
*
* @return A list of all validation warnings.
*/
public List<Invalid> getWarnings(){
return validations.stream()
.filter(it -> !it.isValid())
.map(it -> (Invalid)it)
.filter(it -> it.getSeverity().equals(Severity.WARNING))
.collect(Collectors.toList());
}
/**
* Adds a validation state to the final results.
*
* @param validated The {@link Valid} or {@link Invalid} instance to add to validations.
*/
public void addResult(Validated validated) {
synchronized (validations) {
ValidationRule rule = validated.getRule();
if (rule != null && !rule.equals(ValidationRule.empty())) {
validations.add(validated);
}
}
}
}

View File

@@ -0,0 +1,152 @@
/*
* Copyright 2019 OpenAPI-Generator Contributors (https://openapi-generator.tech)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openapitools.codegen.validation;
import java.util.function.Function;
/**
* Defines a rule to be evaluated against some target object.
*/
@SuppressWarnings("WeakerAccess")
public class ValidationRule {
private Severity severity;
private String description;
private String failureMessage;
private Function<Object, Boolean> test;
/**
* Constructs a new instance of {@link ValidationRule}
*
* @param severity The declared severity if this validation rule fails.
* @param description A description to help differentiate this rule from others (not intended to be user-facing).
* @param failureMessage The message to be displayed in the event of a test failure (intended to be user-facing).
* @param test The test condition to be applied as a part of this rule, when this function returns <code>true</code>,
* the evaluated instance will be considered "valid" according to this rule.
*/
ValidationRule(Severity severity, String description, String failureMessage, Function<Object, Boolean> test) {
this.severity = severity;
this.description = description;
this.failureMessage = failureMessage;
this.test = test;
}
/**
* Gets the message to be displayed in the event of a test failure (intended to be user-facing).
*
* @return A string message
*/
public String getFailureMessage() {
return failureMessage;
}
/**
* Evalute an instance of an object against this rule.
*
* @param input The instance to be evaluated.
*
* @return <code>true</code> if the object state is valid according to this rule, otherwise <code>false</code>.
*/
public boolean evaluate(Object input) {
return test.apply(input);
}
/**
* Get the level of severity which this rule considers a failure in evaluation. For example, if this is {@link Severity#WARNING} and
* a call to {@link ValidationRule#evaluate(Object)} returns <code>false</code>, a user should not expect an error to be thrown under
* normal operation.
*
* @return An enum defining how severe a failure to evaluate this rule should be considered by the caller.
*/
public Severity getSeverity() {
return severity;
}
/**
* Gets a description to help differentiate this rule from others (not intended to be user-facing).
*
* @return A string description.
*/
public String getDescription() {
return description;
}
/**
* Constructs an empty rule (useful for testing).
*
* @return An "empty" rule.
*/
static ValidationRule empty() {
return new ValidationRule(Severity.ERROR, "empty", "failure message", (i) -> false);
}
/**
* Create an instance of a {@link ValidationRule}
*
* @param severity The declared severity if this validation rule fails.
* @param description A description to help differentiate this rule from others (not intended to be user-facing).
* @param failureMessage The message to be displayed in the event of a test failure (intended to be user-facing).
* @param fn The test condition to be applied as a part of this rule, when this function returns <code>true</code>,
* the evaluated instance will be considered "valid" according to this rule.
* @param <T> The type of the object being evaluated.
*
* @return A new instance of a {@link ValidationRule}
*/
@SuppressWarnings("unchecked")
public static <T> ValidationRule create(Severity severity, String description, String failureMessage, Function<T, Boolean> fn) {
return new ValidationRule(severity, description, failureMessage, (Function<Object, Boolean>) fn);
}
/**
* Create an instance of a {@link ValidationRule} which should result in an error should the evaluate of this rule fail.
*
* @param failureMessage The message to be displayed in the event of a test failure (intended to be user-facing).
* @param fn The test condition to be applied as a part of this rule, when this function returns <code>true</code>,
* the evaluated instance will be considered "valid" according to this rule.
* @param <T> The type of the object being evaluated.
*
* @return A new instance of a {@link ValidationRule}
*/
@SuppressWarnings("unchecked")
public static <T> ValidationRule error(String failureMessage, Function<T, Boolean> fn) {
return new ValidationRule(Severity.ERROR, null, failureMessage, (Function<Object, Boolean>) fn);
}
/**
* Create an instance of a {@link ValidationRule} which should result in a warning should the evaluate of this rule fail.
*
* @param description A description to help differentiate this rule from others (not intended to be user-facing).
* @param failureMessage The message to be displayed in the event of a test failure (intended to be user-facing).
* @param fn The test condition to be applied as a part of this rule, when this function returns <code>true</code>,
* the evaluated instance will be considered "valid" according to this rule.
* @param <T> The type of the object being evaluated.
*
* @return A new instance of a {@link ValidationRule}
*/
@SuppressWarnings("unchecked")
public static <T> ValidationRule warn(String description, String failureMessage, Function<T, Boolean> fn) {
return new ValidationRule(Severity.WARNING, description, failureMessage, (Function<Object, Boolean>) fn);
}
@Override
public String toString() {
return "ValidationRule{" +
"severity=" + severity +
", description='" + description + '\'' +
", failureMessage='" + failureMessage + '\'' +
'}';
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2019 OpenAPI-Generator Contributors (https://openapi-generator.tech)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openapitools.codegen.validation;
/**
* Defines a contract allowing some input to be validated.
*
* @param <TInput> The type of the input object.
*/
@FunctionalInterface
public interface Validator<TInput> {
/**
* Validates input, resulting in a instance of {@link ValidationResult} which provides details on all validations performed (success, error, warning).
*
* @param input The object instance to be validated.
*
* @return A {@link ValidationResult} which details the success, error, and warning validation results.
*/
ValidationResult validate(TInput input);
}

View File

@@ -0,0 +1,149 @@
/*
* Copyright 2019 OpenAPI-Generator Contributors (https://openapi-generator.tech)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openapitools.codegen.validation;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
public class GenericValidatorTest {
class Person {
private int age;
private String name;
Person(String name, int age) {
this.age = age;
this.name = name;
}
}
private static boolean isValidAge(Person person) {
return person.age > 0;
}
private static boolean isAdult(Person person) {
return person.age > 18;
}
private static boolean isNameSet(Person person) {
return person.name != null && person.name.length() > 0;
}
private static boolean isNameValid(Person person) {
String pattern = "^[A-Z][a-z]*$";
return person.name.matches(pattern);
}
private static boolean isNameNormalLength(Person person) {
return person.name.length() < 10;
}
private List<ValidationRule> validationRules = Arrays.asList(
ValidationRule.error("Age must be positive and more than zero", GenericValidatorTest::isValidAge),
ValidationRule.error("Only adults (18 years old and older)", GenericValidatorTest::isAdult),
ValidationRule.error("Name isn't set!", GenericValidatorTest::isNameSet),
ValidationRule.error("Name isn't formatted correct", GenericValidatorTest::isNameValid),
ValidationRule.warn("Name too long?", "Name may be too long.", GenericValidatorTest::isNameNormalLength)
);
@Test
public void testGenericValidatorSuccesses(){
Person person = new Person("Jim", 23);
GenericValidator<Person> validator = new GenericValidator<>(validationRules);
ValidationResult result = validator.validate(person);
List<Validated> validated = result.getAll();
List<Valid> valid = result.getValid();
List<Invalid> invalid = result.getErrors();
assertEquals(validated.size(), 5, "Expected 5 validations to run.");
assertEquals(valid.size(), 5, "Expected all validations to succeed");
assertEquals(invalid.size(), 0, "Expected zero validations to fail.");
}
@Test
public void testGenericValidatorSingleConditionFails(){
Person person = new Person("Jim", 3);
GenericValidator<Person> validator = new GenericValidator<>(validationRules);
ValidationResult result = validator.validate(person);
List<Validated> validated = result.getAll();
List<Valid> valid = result.getValid();
List<Invalid> errors = result.getErrors();
List<Invalid> warnings = result.getWarnings();
assertEquals(validated.size(), 5, "Expected 5 validations to run.");
assertEquals(valid.size(), 4, "Expected 4 validations to succeed");
assertEquals(errors.size(), 1, "Expected 1 validation to fail.");
assertEquals(warnings.size(), 0, "Expected no warnings to be triggered.");
Invalid failed = errors.get(0);
assertEquals(failed.getMessage(), "Only adults (18 years old and older)");
}
@Test
public void testGenericValidatorMultipleConditionsFail(){
Person person = new Person("asdf", 3);
GenericValidator<Person> validator = new GenericValidator<>(validationRules);
ValidationResult result = validator.validate(person);
List<Validated> validated = result.getAll();
List<Valid> valid = result.getValid();
List<Invalid> errors = result.getErrors();
List<Invalid> warnings = result.getWarnings();
assertEquals(validated.size(), 5, "Expected 5 validations to run.");
assertEquals(valid.size(), 3, "Expected 3 validations to succeed");
assertEquals(errors.size(), 2, "Expected 2 validations to fail.");
assertEquals(warnings.size(), 0, "Expected no warnings to be triggered.");
Optional<Invalid> nameValidation = errors.stream().filter(it -> it.getMessage().contains("formatted")).findFirst();
Optional<Invalid> ageValidation = errors.stream().filter(it -> it.getMessage().contains("adults")).findFirst();
assertTrue(nameValidation.isPresent(), "Expected validation on name formatting to fail.");
assertTrue(ageValidation.isPresent(), "Expected validation on age requirements to fail.");
assertEquals(nameValidation.get().getMessage(), "Name isn't formatted correct");
assertEquals(ageValidation.get().getMessage(), "Only adults (18 years old and older)");
}
@Test
public void testGenericValidatorErrorsAndWarnings(){
Person person = new Person("0123456789asdfghjkl", 3);
GenericValidator<Person> validator = new GenericValidator<>(validationRules);
ValidationResult result = validator.validate(person);
List<Validated> validated = result.getAll();
List<Valid> valid = result.getValid();
List<Invalid> errors = result.getErrors();
List<Invalid> warnings = result.getWarnings();
assertEquals(validated.size(), 5, "Expected 5 validations to run.");
assertEquals(valid.size(), 2, "Expected 2 validations to succeed");
assertEquals(errors.size(), 2, "Expected 2 validations to fail.");
assertEquals(warnings.size(), 1, "Expected 1 warning to be triggered.");
Optional<Invalid> nameValidation = errors.stream().filter(it -> it.getMessage().contains("formatted")).findFirst();
Optional<Invalid> ageValidation = errors.stream().filter(it -> it.getMessage().contains("adults")).findFirst();
Invalid nameLengthWarning = warnings.get(0);
assertTrue(nameValidation.isPresent(), "Expected validation on name formatting to fail.");
assertTrue(ageValidation.isPresent(), "Expected validation on age requirements to fail.");
assertEquals(nameValidation.get().getMessage(), "Name isn't formatted correct");
assertEquals(ageValidation.get().getMessage(), "Only adults (18 years old and older)");
assertEquals(nameLengthWarning.getMessage(), "Name may be too long.");
}
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright 2019 OpenAPI-Generator Contributors (https://openapi-generator.tech)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openapitools.codegen.validation;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
public class ValidatedTest {
@Test
public void isValidTrueForValidType(){
boolean isValid = Validated.valid(ValidationRule.empty()).isValid();
assertTrue(isValid);
}
@Test
public void isValidFalseForInvalidType(){
boolean isValid = Validated.invalid(ValidationRule.empty(), "test").isValid();
assertFalse(isValid);
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright 2019 OpenAPI-Generator Contributors (https://openapi-generator.tech)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openapitools.codegen.validation;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
public class ValidationRuleTest {
class Sample {
private String name;
public Sample(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
private static boolean checkName(Sample input) {
return input.getName() != null && input.getName().length() > 7;
}
private static boolean checkPattern(Sample input) {
String pattern = "^[A-Z][a-z]*$";
return input.getName() != null && input.getName().matches(pattern);
}
@Test
public void createMethodUsingMethodReference(){
Sample nil = new Sample(null);
Sample six = new Sample("123456");
Sample seven = new Sample("1234567");
Sample eight = new Sample("12345678");
ValidationRule result = ValidationRule.error("test", ValidationRuleTest::checkName);
assertFalse(result.evaluate(nil));
assertFalse(result.evaluate(six));
assertFalse(result.evaluate(seven));
assertTrue(result.evaluate(eight));
}
@Test
public void createMethodUsingLambda(){
Sample nil = new Sample(null);
Sample lowercase = new Sample("jim");
Sample titlecase = new Sample("Jim");
ValidationRule result = ValidationRule.error("test", i -> checkPattern((Sample)i));
assertFalse(result.evaluate(nil));
assertFalse(result.evaluate(lowercase));
assertTrue(result.evaluate(titlecase));
}
}