Skip to content

Commit

Permalink
Merge pull request #623 from Backbase/patternValidation
Browse files Browse the repository at this point in the history
Add validation on request params and map types
  • Loading branch information
miladbb authored Sep 5, 2023
2 parents 4aa4179 + 88f6963 commit 4dcfa62
Show file tree
Hide file tree
Showing 11 changed files with 323 additions and 44 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ It currently consists of
# Release Notes
BOAT is still under development and subject to change.

## 0.17.14
* boat-spring
* added validation constraints on primitive collection items types in request params (see `collectionDataTypeParam.mustache`)
* added validation constraints on primitive map value types (see `mapDataType.mustache`)
## 0.17.13
* boat-spring
* Fix: generate validation constraints on primitive collection items types (updates in pojo.mustache and new collectionDataType.mustache)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
package com.backbase.oss.codegen.java;

import static com.backbase.oss.codegen.java.BoatCodeGenUtils.getCollectionCodegenValue;
import static java.util.Arrays.stream;
import static java.util.stream.Collectors.joining;
import static org.apache.commons.lang3.StringUtils.contains;
import static org.apache.commons.lang3.StringUtils.isEmpty;
import static org.openapitools.codegen.utils.StringUtils.camelize;

import com.backbase.oss.codegen.java.BoatCodeGenUtils.CodegenValueType;
import com.samskivert.mustache.Mustache;
import com.samskivert.mustache.Template.Fragment;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.parameters.Parameter;
import io.swagger.v3.oas.models.servers.Server;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
import org.openapitools.codegen.*;
import org.openapitools.codegen.config.GlobalSettings;
import org.openapitools.codegen.languages.SpringCodegen;
import org.openapitools.codegen.templating.mustache.IndentedLambda;
import org.openapitools.codegen.utils.ModelUtils;

import java.io.IOException;
import java.io.Writer;
import java.util.List;
Expand All @@ -24,14 +22,21 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.IntStream;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.openapitools.codegen.CliOption;
import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.CodegenOperation;
import org.openapitools.codegen.CodegenParameter;
import org.openapitools.codegen.CodegenProperty;
import org.openapitools.codegen.config.GlobalSettings;
import org.openapitools.codegen.languages.SpringCodegen;
import org.openapitools.codegen.templating.mustache.IndentedLambda;
import org.openapitools.codegen.utils.ModelUtils;

import static com.backbase.oss.codegen.java.BoatCodeGenUtils.getCollectionCodegenValue;
import static java.util.Arrays.stream;
import static java.util.stream.Collectors.joining;
import static org.apache.commons.lang3.StringUtils.contains;
import static org.apache.commons.lang3.StringUtils.isEmpty;
import static org.openapitools.codegen.utils.StringUtils.camelize;

@Slf4j
public class BoatSpringCodeGen extends SpringCodegen {

public static final String NAME = "boat-spring";
Expand Down Expand Up @@ -65,11 +70,16 @@ public void execute(Fragment frag, Writer out) throws IOException {

for (final String line : lines) {
out.write(this.prefix);
out.write(StringUtils.substring(line, indent));
String processedLine = StringUtils.substring(line, indent);
out.write(postProcessLine(processedLine));
out.write(System.lineSeparator());
}
}

protected String postProcessLine(String line) {
return line;
}

private String[] splitLines(final String text) {
return stream(text.split("\\r\\n|\\n"))
.map(s -> s.replaceFirst(REGEX, ""))
Expand All @@ -93,6 +103,48 @@ static int indentLevel(String text) {
}
}

/**
* This lambda reformats multiline generated code into single line.
*/
static class FormatToOneLine implements Mustache.Lambda {

private static final String SINGLE_SPACE = " ";

private static final String WHITESPACE_REGEX = "\\s+";

@Override
public void execute(Fragment frag, Writer out) throws IOException {
String text = frag.execute();
if (text == null || text.isEmpty()) {
return;
}
String formatted = text
.replaceAll("\\n", SINGLE_SPACE)
.replaceAll(WHITESPACE_REGEX, SINGLE_SPACE)
.replaceAll("\\< ", "<")
.replaceAll(" >", ">")
.trim();

if (log.isTraceEnabled()) {
log.trace("Fragment [{}] reformatted into [{}]", text, formatted);
}

out.write(formatted);
}
}

static class TrimAndIndent extends NewLineIndent {

TrimAndIndent(int level, String space) {
super(level, space);
}

@Override
protected String postProcessLine(String line) {
return line.trim();
}
}

/**
* Add @Validated to class-level Api interfaces. Defaults to false
*/
Expand Down Expand Up @@ -295,9 +347,10 @@ public void processOpts() {
this.additionalProperties.put("newLine4", new NewLineIndent(4, " "));
this.additionalProperties.put("indent8", new IndentedLambda(8, " "));
this.additionalProperties.put("newLine8", new NewLineIndent(8, " "));
this.additionalProperties.put("toOneLine", new FormatToOneLine());
this.additionalProperties.put("trimAndIndent4", new TrimAndIndent(4, " "));
}


@Override
public void postProcessParameter(CodegenParameter p) {
super.postProcessParameter(p);
Expand Down
2 changes: 1 addition & 1 deletion boat-scaffold/src/main/templates/boat-spring/api.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ public interface {{classname}} {
consumes = { {{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}} }{{/hasConsumes}}{{/singleContentTypes}}
)
{{#jdk8-default-interface}}default {{/jdk8-default-interface}}{{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {{#delegate-method}}_{{/delegate-method}}{{operationId}}(
{{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{>cookieParams}}{{>httpServletParam}}{{^-last}},
{{#allParams}}{{#toOneLine}}{{>queryParams}}{{/toOneLine}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{>cookieParams}}{{>httpServletParam}}{{^-last}},
{{/-last}}{{/allParams}}{{#reactive}}{{#hasParams}},
{{/hasParams}}{{#swagger2AnnotationLibrary}}@Parameter(hidden = true){{/swagger2AnnotationLibrary}}{{#springFoxDocumentationProvider}}@ApiIgnore{{/springFoxDocumentationProvider}} final ServerWebExchange exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}{{#hasParams}},
{{/hasParams}}{{#springFoxDocumentationProvider}}@ApiIgnore {{/springFoxDocumentationProvider}}{{#springDocDocumentationProvider}}@ParameterObject {{/springDocDocumentationProvider}}final Pageable pageable{{/vendorExtensions.x-spring-paginated}}
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,20 @@
{{#openApiNullable}}{{#isNullable}}JsonNullable<{{/isNullable}}{{/openApiNullable}}{{{baseType}}}<{{#items}}{{#isPrimitiveType}}{{>beanValidationCore}}{{/isPrimitiveType}}{{^isPrimitiveType}}{{#useBeanValidation}}@Valid {{/useBeanValidation}}{{/isPrimitiveType}}{{/items}}{{{items.datatypeWithEnum}}}>{{#openApiNullable}}{{#isNullable}}>{{/isNullable}}{{/openApiNullable}}
{{#openApiNullable}}
{{#isNullable}}JsonNullable<{{/isNullable}}
{{/openApiNullable}}
{{! apply collection type e.g. Set, List }}
{{{baseType}}}<
{{#useBeanValidation}}
{{#items}}
{{#isPrimitiveType}}
{{>beanValidationCore}}
{{/isPrimitiveType}}
{{^isPrimitiveType}}
@Valid
{{/isPrimitiveType}}
{{/items}}
{{/useBeanValidation}}
{{! apply collection item type }}
{{{items.datatypeWithEnum}}}>
{{#openApiNullable}}
{{#isNullable}}>{{/isNullable}}
{{/openApiNullable}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{{#isArray}}
{{#useBeanValidation}}
{{#uniqueItems}}java.util.Set{{/uniqueItems}}
{{^uniqueItems}}java.util.List{{/uniqueItems}}<
{{#items}}
{{#isPrimitiveType}}
{{>beanValidationCore}}
{{/isPrimitiveType}}
{{^isPrimitiveType}}
@Valid
{{/isPrimitiveType}}
{{/items}}
{{{items.datatypeWithEnum}}}>
{{/useBeanValidation}}
{{^useBeanValidation}}
{{#uniqueItems}}java.util.Set{{/uniqueItems}}
{{^uniqueItems}}java.util.List{{/uniqueItems}}
<{{{dataType}}}>
{{/useBeanValidation}}
{{/isArray}}
{{^isArray}}
{{{dataType}}}
{{/isArray}}
21 changes: 21 additions & 0 deletions boat-scaffold/src/main/templates/boat-spring/mapDataType.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{{#openApiNullable}}
{{#isNullable}}JsonNullable<{{/isNullable}}
{{/openApiNullable}}
{{! apply map type with String as key type }}
{{{baseType}}}<String,
{{! apply validation on map values }}
{{#useBeanValidation}}
{{#items}}
{{#isPrimitiveType}}
{{>beanValidationCore}}
{{/isPrimitiveType}}
{{^isPrimitiveType}}
@Valid
{{/isPrimitiveType}}
{{/items}}
{{/useBeanValidation}}
{{! apply map value type with closing bracket }}
{{{items.datatypeWithEnum}}}>
{{#openApiNullable}}
{{#isNullable}}>{{/isNullable}}
{{/openApiNullable}}
Original file line number Diff line number Diff line change
@@ -1 +1,13 @@
{{#useOptional}}{{#required}}{{{dataType}}}{{/required}}{{^required}}Optional<{{#useBeanValidation}}{{>beanValidationCore}}{{/useBeanValidation}}{{{dataType}}}>{{/required}}{{/useOptional}}{{^useOptional}}{{{dataType}}}{{/useOptional}}
{{#toOneLine}}
{{#useOptional}}
{{#required}}
{{>collectionDataTypeParam}}
{{/required}}
{{^required}}
Optional<{{>collectionDataTypeParam}}>
{{/required}}
{{/useOptional}}
{{^useOptional}}
{{>collectionDataTypeParam}}
{{/useOptional}}
{{/toOneLine}}
39 changes: 26 additions & 13 deletions boat-scaffold/src/main/templates/boat-spring/pojo.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -67,25 +67,37 @@ public class {{classname}}{{#parent}} extends {{{parent}}}{{/parent}}{{^parent}}
{{#vendorExtensions.x-field-extra-annotation}}
{{{vendorExtensions.x-field-extra-annotation}}}
{{/vendorExtensions.x-field-extra-annotation}}
{{#trimAndIndent4}}
{{#isContainer}}
{{#isArray}}
{{#isMap}}
{{#useBeanValidation}}@Valid{{/useBeanValidation}}
{{#openApiNullable}}
private {{>collectionDataType}} {{name}}{{#isNullable}} = JsonNullable.undefined(){{/isNullable}}{{^isNullable}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/isNullable}};
private {{#toOneLine}}{{>mapDataType}}{{/toOneLine}} {{name}}{{#isNullable}} = JsonNullable.undefined(){{/isNullable}}{{^isNullable}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/isNullable}};
{{/openApiNullable}}
{{^openApiNullable}}
private {{>collectionDataType}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}};
private {{#toOneLine}}{{>mapDataType}}{{/toOneLine}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}};
{{/openApiNullable}}
{{/isArray}}
{{^isArray}}
{{#useBeanValidation}}@Valid{{/useBeanValidation}}
{{#openApiNullable}}
private {{>nullableDataType}} {{name}}{{#isNullable}} = JsonNullable.undefined(){{/isNullable}}{{^isNullable}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/isNullable}};
{{/openApiNullable}}
{{^openApiNullable}}
private {{>nullableDataType}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}};
{{/openApiNullable}}
{{/isArray}}
{{/isMap}}
{{^isMap}}
{{#isArray}}
{{#useBeanValidation}}@Valid{{/useBeanValidation}}
{{#openApiNullable}}
private {{#toOneLine}}{{>collectionDataType}}{{/toOneLine}} {{name}}{{#isNullable}} = JsonNullable.undefined(){{/isNullable}}{{^isNullable}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/isNullable}};
{{/openApiNullable}}
{{^openApiNullable}}
private {{#toOneLine}}{{>collectionDataType}}{{/toOneLine}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}};
{{/openApiNullable}}
{{/isArray}}
{{^isArray}}
{{#useBeanValidation}}@Valid{{/useBeanValidation}}
{{#openApiNullable}}
private {{>nullableDataType}} {{name}}{{#isNullable}} = JsonNullable.undefined(){{/isNullable}}{{^isNullable}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/isNullable}};
{{/openApiNullable}}
{{^openApiNullable}}
private {{>nullableDataType}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}};
{{/openApiNullable}}
{{/isArray}}
{{/isMap}}
{{/isContainer}}
{{^isContainer}}
{{#isDate}}
Expand All @@ -101,6 +113,7 @@ public class {{classname}}{{#parent}} extends {{{parent}}}{{/parent}}{{^parent}}
private {{>nullableDataType}} {{name}}{{#isNullable}} = null{{/isNullable}}{{^isNullable}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/isNullable}};
{{/openApiNullable}}
{{/isContainer}}
{{/trimAndIndent4}}
{{/vars}}
{{#generatedConstructorWithRequiredArgs}}
{{#hasRequired}}
Expand Down
Loading

0 comments on commit 4dcfa62

Please sign in to comment.