diff --git a/.github/workflows/boat.yml b/.github/workflows/boat.yml index b43cd9d1e..fe83b5442 100644 --- a/.github/workflows/boat.yml +++ b/.github/workflows/boat.yml @@ -16,7 +16,7 @@ jobs: uses: actions/setup-java@v3 with: distribution: 'microsoft' - java-version: '11' + java-version: '17' cache: 'maven' - name: Build & Test run: mvn -B test @@ -31,10 +31,42 @@ jobs: uses: actions/setup-java@v3 with: distribution: 'microsoft' - java-version: '11' + java-version: '17' cache: 'maven' - name: Build and Analyze env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} run: mvn -B verify sonar:sonar -Dgpg.skip + publish: + if: "!contains(github.event.head_commit.message, '[version bump]')" + runs-on: ubuntu-latest + needs: [ test, sonar ] + steps: + - name: Checkout project + uses: actions/checkout@v3 + + - name: Setup Java + uses: actions/setup-java@v3 + with: + distribution: 'microsoft' + java-version: '17' + cache: 'maven' + server-id: ossrh + server-username: MAVEN_USERNAME + server-password: MAVEN_PASSWORD + gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }} + gpg-passphrase: GPG_PASSPHRASE + + - name: Build and Publish SNAPSHOT + run: | + mvn \ + --no-transfer-progress \ + --batch-mode \ + -DskipTests=true \ + deploy + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + MAVEN_USERNAME: ${{ secrets.NEXUS_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.NEXUS_PASSWORD }} + GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 44567afd3..ea71a31cd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -16,7 +16,7 @@ jobs: uses: actions/setup-java@v3 with: distribution: 'microsoft' - java-version: '11' + java-version: '17' cache: 'maven' - name: Build & Test run: mvn -B test @@ -31,7 +31,7 @@ jobs: uses: actions/setup-java@v3 with: distribution: 'microsoft' - java-version: '11' + java-version: '17' cache: 'maven' - name: Build and Analyze env: @@ -51,7 +51,7 @@ jobs: uses: actions/setup-java@v3 with: distribution: 'microsoft' - java-version: '11' + java-version: '17' cache: 'maven' server-id: ossrh server-username: MAVEN_USERNAME @@ -114,7 +114,7 @@ jobs: uses: actions/setup-java@v3 with: distribution: 'microsoft' - java-version: '11' + java-version: '17' cache: 'maven' - name: Configure Git user run: | diff --git a/.gitignore b/.gitignore index 9daf188a2..b39f369c4 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,5 @@ hs_err_pid* .* # but not git dot files (e.g. .gitattribute) !.git?* + +!boat-scaffold/src/main/templates/boat-java/gradle-wrapper.jar \ No newline at end of file diff --git a/README.md b/README.md index a1ed55113..d60ca283a 100644 --- a/README.md +++ b/README.md @@ -7,18 +7,26 @@ The Backbase Open API Tools is a collection of tools created to work efficiently It currently consists of -* RAML 1.0 Converter to OpenAPI 3.0 * Create Diff Report between 2 OpenAPI versions of the same spec (Based on https://github.com/quen2404/openapi-diff) * Decompose Transformer to remove Composed Schemas from OpenAPI specs to aid in code generators * Case Transformer to see how your API looks like when going from camelCase to snake_case (transforms examples too) * [Code Generator](boat-maven-plugin/README.md) based on [openapi-generator.tech](https://openapi-generator.tech/) with optimized templates and fixes. -* Lint mojo based on Zalando Zally API Guidelines +* Lint mojo based on Zalando Zally and Backbase API The project is very much Work In Progress and will be published on maven central when considered ready enough. # Release Notes BOAT is still under development and subject to change. +## 0.17.0 +* General + * Removed RAML Support + * Update OpenAPI Tools to 6.2.1 +* Boat Java Generator + * Jakarta EE 9 compatibility + * `spring-mvc` library is removed because it is not supported by OpenAPI Tools anymore + * Use of `Set` for unique items is now enabled by default as OpenAPI Generator fixed their implementation + ## 0.16.11 * Boat Angular generator * Set `removeComments: false` in generated tsconfig.json files to retain `/*#__PURE__*/` annotation in compiled JS. @@ -391,172 +399,8 @@ BOAT is still under development and subject to change. mvn install ``` -## CLI Usage - -### Convert RAML to Open API 3.0 -```shell script -cd boat-terminal -java -jar target/boat-terminal-0.0.1-SNAPSHOT-jar-with-dependencies.jar \ - -f src/test/resources/api.raml -``` - - -### Convert RAML to Open API 3.0 && Pipe output to file -```shell script -cd boat-terminal -java -jar target/boat-terminal-0.0.1-SNAPSHOT-jar-with-dependencies.jar \ - -f src/test/resources/api.raml \ - > openapi.yaml -``` - - -### Convert RAML to Open API 3.0 file and verbose logging -```shell script -cd boat-terminal -java -jar target/boat-terminal-0.0.1-SNAPSHOT-jar-with-dependencies.jar \ - -f src/test/resources/api.raml \ - -o swagger.yaml \ - -v -``` - -### Convert RAML to Open API 3.0 with examples exploded into /examples/ -```shell script -cd boat-terminal -java -jar target/boat-terminal-0.0.1-SNAPSHOT-jar-with-dependencies.jar \ - -f src/test/resources/api.raml \ - -o swagger.yaml \ - -d my-open-api-spec/ \ - -v -``` - - ## Maven Plugin Usage -Configuration - -```xml - - - - 4.0.0 - - my.project - my-specs-definition - 1.0 - pom - - - 0.1.4 - - - - - - com.backbase.oss - boat-maven-plugin - ${boat-maven-plugin.version} - - - export-raml-spec - generate-sources - - export - - - ${basedir}/src/main/resources/client-api.raml - - - - - - - -``` - -The following command will convert the given `client-api.raml` file into Open API 3.0 format. - -```bash -mvn boat:export -``` - -**NOTE:** RAML file name should end with `-api.raml`, `service-api.raml` or `client-api.raml`. - -## Export All Specifications in Bill-Of-Materials pom file -If you want to export all specifications referenced in a pom file, you can use the following mojo - -```xml - - - - com.backbase.boat - boat-maven-plugin - ${boat-maven-plugin.version} - - - com.backbase.dbs--> - banking-services-bom - [2.16.0,) - pom - - - ${project.basedir}/raml-2-openapi-specs - http://www.backbase.com/wp-content/uploads/2017/04/backbase-logo-png.png - Backbase - # Disclaimer -This API is converted from RAML1.0 using the boat-maven-plugin and is not final or validated! - - true - - - - - -``` - -### Configuration Options - -* The `addChangeLog` option will automagically insert a change log between all referenced versions -* The `includeVersionsRegEx` can be used to filter out certain versions. By default it's set to `^(\d+\.)?(\d+\.)?(\d+)$` to only allow x.x.x versions. To also include patch versions, set it to `^(\d+\.)?(\d+\.)?(\d+\.)?(\*|\d+)$` - -```bash -mvn boat:export-bom -``` - -## Generate API docs - -Configuration - -```xml - - - - - - com.backbase.oss - boat-maven-plugin - ${boat-maven-plugin.version} - - - generate-docs - generate-sources - - generate - - - ${project.basedir}/src/main/resources/api.yaml - ${project.build.directory}/generated-sources - html2 - - - - - - - - -``` - The following command will generate `index.html` file in the specified output folder that contains API endpoints description. ```bash diff --git a/boat-engine/pom.xml b/boat-engine/pom.xml index 225fe44e3..760199f37 100644 --- a/boat-engine/pom.xml +++ b/boat-engine/pom.xml @@ -5,7 +5,7 @@ com.backbase.oss backbase-openapi-tools - 0.16.12-SNAPSHOT + 0.17.0-SNAPSHOT boat-engine jar @@ -36,17 +36,6 @@ 0.3.2 - - org.raml - raml-parser-2 - 1.0.51 - - - com.github.fge - * - - - io.swagger.parser.v3 diff --git a/boat-engine/src/main/java/com/backbase/oss/boat/DirectoryExploder.java b/boat-engine/src/main/java/com/backbase/oss/boat/DirectoryExploder.java index 9a0d65009..2c1e17d1d 100644 --- a/boat-engine/src/main/java/com/backbase/oss/boat/DirectoryExploder.java +++ b/boat-engine/src/main/java/com/backbase/oss/boat/DirectoryExploder.java @@ -5,11 +5,11 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectWriter; import com.google.common.base.CaseFormat; +import jakarta.validation.constraints.NotNull; import org.apache.commons.io.FileUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.validation.constraints.NotNull; import java.io.File; import java.io.IOException; import java.nio.file.Files; diff --git a/boat-engine/src/main/java/com/backbase/oss/boat/ExampleUtils.java b/boat-engine/src/main/java/com/backbase/oss/boat/ExampleUtils.java deleted file mode 100644 index 094fbb9d5..000000000 --- a/boat-engine/src/main/java/com/backbase/oss/boat/ExampleUtils.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.backbase.oss.boat; - -import com.fasterxml.jackson.databind.ObjectMapper; -import java.io.IOException; -import java.util.stream.Collectors; -import org.raml.v2.api.model.v10.datamodel.ExampleSpec; -import org.raml.v2.api.model.v10.datamodel.TypeInstance; -import org.raml.v2.api.model.v10.datamodel.TypeInstanceProperty; - -@SuppressWarnings("java:S5411") -class ExampleUtils { - - - private static final ObjectMapper mapper = new ObjectMapper(); - - private ExampleUtils() { - throw new AssertionError("Private constructor"); - } - - - public static Object getExampleObject(ExampleSpec ramlExample, boolean convertJsonExamplesToYaml) { - if (ramlExample == null) { - return null; - } - Object value; - TypeInstance structuredValue = ramlExample.structuredValue(); - for (TypeInstanceProperty property : structuredValue.properties()) { - if (property.isArray()) { - return property.values().stream().map(TypeInstance::value).collect(Collectors.toList()); - } else { - return property.value().value(); - } - } - if (ramlExample.structuredValue() != null) { - value = ramlExample.structuredValue().value() != null ? prettyPrint(ramlExample.structuredValue().value().toString(), convertJsonExamplesToYaml) : null; - } else { - value = ramlExample.value() != null ? prettyPrint(ramlExample.value(), convertJsonExamplesToYaml) : null; - } - return value; - } - - private static Object prettyPrint(String example, boolean convertJsonExamplesToYaml) { - try { - Object json = mapper.readValue(example, Object.class); - if (convertJsonExamplesToYaml) { - return json; - } else { - return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(json); - } - } catch (IOException e) { - return example; - } - } - -} diff --git a/boat-engine/src/main/java/com/backbase/oss/boat/Exporter.java b/boat-engine/src/main/java/com/backbase/oss/boat/Exporter.java deleted file mode 100644 index 75e1f6afc..000000000 --- a/boat-engine/src/main/java/com/backbase/oss/boat/Exporter.java +++ /dev/null @@ -1,960 +0,0 @@ -package com.backbase.oss.boat; - -import com.backbase.oss.boat.loader.CachingResourceLoader; -import com.backbase.oss.boat.loader.RamlResourceLoader; -import com.backbase.oss.boat.transformers.Transformer; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.fasterxml.jackson.databind.node.TextNode; -import com.google.common.base.CaseFormat; -import io.swagger.v3.oas.models.Components; -import io.swagger.v3.oas.models.OpenAPI; -import io.swagger.v3.oas.models.Operation; -import io.swagger.v3.oas.models.PathItem; -import io.swagger.v3.oas.models.Paths; -import io.swagger.v3.oas.models.examples.Example; -import io.swagger.v3.oas.models.info.Info; -import io.swagger.v3.oas.models.media.Content; -import io.swagger.v3.oas.models.media.MediaType; -import io.swagger.v3.oas.models.media.Schema; -import io.swagger.v3.oas.models.media.StringSchema; -import io.swagger.v3.oas.models.parameters.HeaderParameter; -import io.swagger.v3.oas.models.parameters.Parameter; -import io.swagger.v3.oas.models.parameters.PathParameter; -import io.swagger.v3.oas.models.parameters.QueryParameter; -import io.swagger.v3.oas.models.parameters.RequestBody; -import io.swagger.v3.oas.models.responses.ApiResponse; -import io.swagger.v3.oas.models.responses.ApiResponses; -import io.swagger.v3.oas.models.servers.Server; -import io.swagger.v3.oas.models.tags.Tag; -import java.io.File; -import java.io.IOException; -import java.net.URL; -import java.nio.charset.Charset; -import java.nio.file.Files; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.TreeMap; -import java.util.concurrent.atomic.AtomicReference; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import lombok.SneakyThrows; -import org.apache.commons.lang.ArrayUtils; -import org.apache.commons.lang.StringEscapeUtils; -import org.apache.commons.lang3.StringUtils; -import org.raml.v2.api.RamlModelBuilder; -import org.raml.v2.api.RamlModelResult; -import org.raml.v2.api.model.v10.api.Api; -import org.raml.v2.api.model.v10.api.Library; -import org.raml.v2.api.model.v10.bodies.Response; -import org.raml.v2.api.model.v10.datamodel.JSONTypeDeclaration; -import org.raml.v2.api.model.v10.datamodel.TypeDeclaration; -import org.raml.v2.api.model.v10.datamodel.TypeInstance; -import org.raml.v2.api.model.v10.datamodel.TypeInstanceProperty; -import org.raml.v2.api.model.v10.datamodel.XMLTypeDeclaration; -import org.raml.v2.api.model.v10.declarations.AnnotationRef; -import org.raml.v2.api.model.v10.methods.Method; -import org.raml.v2.api.model.v10.resources.Resource; -import org.raml.v2.api.model.v10.system.types.AnnotableStringType; -import org.raml.v2.api.model.v10.system.types.MarkdownString; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import static com.backbase.oss.boat.ExampleUtils.getExampleObject; - -@SuppressWarnings("rawtypes") -public class Exporter { - - private static final Logger log = LoggerFactory.getLogger(Exporter.class); - private static final Pattern placeholderPattern = Pattern.compile("(\\{[^}]*\\})"); - public static final String X_EXAMPLES = "x-examples"; - public static final String NO_DESCRIPTION_AVAILABLE = "No description available"; - public static final String NEW_LINE = "\n"; - public static final String EXAMPLE = "example"; - private static final ObjectMapper mapper = Utils.createObjectMapper(); - - private final ExporterOptions exporterOptions; - - private Exporter(ExporterOptions exporterOptions) { - super(); - this.exporterOptions = exporterOptions; - } - - /** - * Better to use {@link #export(File, ExporterOptions)} - * - * @param inputFile The input file. - * @param addJavaTypeExtensions whether to annotate with x-java-type when json schema contains javaType. - * @param transformers a list of transformers. - * @return OpenApi - * @throws ExportException things going south. - */ - public static OpenAPI export(File inputFile, boolean addJavaTypeExtensions, List transformers) - throws ExportException { - ExporterOptions exporterOptions = new ExporterOptions(); - exporterOptions.setAddJavaTypeExtensions(addJavaTypeExtensions); - exporterOptions.setTransformers(transformers); - return export(inputFile, exporterOptions); - } - - /** - * Guesses the service name from the file path and calls {@link #export(String, File)}. - * - * @param inputFile The input file. - * @param options options. - * @return OpenApi - * @throws ExportException things going south. - */ - public static OpenAPI export(File inputFile, ExporterOptions options) throws ExportException { - // Guess Service Name - AtomicReference serviceName = new AtomicReference<>("serviceName"); - - String[] split = inputFile.getPath().split("/"); - ArrayUtils.reverse(split); - Arrays.stream(split) - .filter(part -> part.endsWith("-spec")) - .findFirst() - .ifPresent(s -> serviceName.set(s.replace("-spec", "-service"))); - - log.debug("Export: {} with options: {}", inputFile, options); - return new Exporter(options).export(serviceName.get(), inputFile); - } - - @SuppressWarnings("java:S3776") - @SneakyThrows - private OpenAPI export(String serviceName, File inputFile) throws ExportException { - - File parentFile = inputFile.getParentFile(); - URL baseUrl = parentFile.toURI().toURL(); - - Map ramlTypeReferences = new TreeMap<>(); - // Parse raml document as yaml instead to reverse engineer json references from types - try { - - String ramlAsString = new String(Files.readAllBytes(inputFile.toPath()), Charset.defaultCharset()); - JsonNode jsonNode = mapper.readTree(ramlAsString); - parseRamlTypeReferences(baseUrl, ramlTypeReferences, jsonNode); - } catch (Exception e) { - throw new ExportException("Failed to export ramlTypes", e); - } - - CachingResourceLoader resourceLoader = new CachingResourceLoader( - new RamlResourceLoader(inputFile, inputFile.getParentFile())); - RamlModelBuilder ramlModelBuilder = new RamlModelBuilder(resourceLoader); - RamlModelResult ramlModelResult = ramlModelBuilder.buildApi(inputFile); - - validateRamlModelResult(inputFile, ramlModelResult); - - Api ramlApi = ramlModelResult.getApiV10(); - Components components = new Components(); - components.setSchemas(new TreeMap<>(String.CASE_INSENSITIVE_ORDER)); - - JsonSchemaToOpenApi jsonSchemaToOpenApi = new JsonSchemaToOpenApi( - baseUrl, - components, - ramlTypeReferences - ); - - assert ramlApi != null; - Map types = collectTypesFromRamlSpec(ramlApi); - List operations = new ArrayList<>(); - - log.debug("Converting RAML Types from Spec and Libraries"); - for (Map.Entry entry : types.entrySet()) { - String name = entry.getKey(); - TypeDeclaration typeDeclaration = entry.getValue(); - Schema typeSchema; - String schemaName = Utils.normalizeSchemaName(name); - if (typeDeclaration instanceof JSONTypeDeclaration) { - typeSchema = jsonSchemaToOpenApi.convert(schemaName, (JSONTypeDeclaration) typeDeclaration); - } else { - typeSchema = RamlSchemaToOpenApi.convert(schemaName, typeDeclaration, components); - } - if (typeDeclaration.examples() != null && !typeDeclaration.examples().isEmpty()) { - List examples = typeDeclaration.examples().stream() - .map(exampleSpec -> new Example() - .value(getExampleObject(exampleSpec, exporterOptions.isConvertExamplesToYaml())) - .summary(exampleSpec.name())) - .collect(Collectors.toList()); - typeSchema.addExtension(X_EXAMPLES, examples); - } - - log.debug("Added type: {}", typeSchema.getName()); - } - - // Start Dereference Process - List schemas = new ArrayList<>(components.getSchemas().values()); - for (Schema schema : schemas) { - try { - jsonSchemaToOpenApi.dereferenceSchema(schema, components); - } catch (Exception e) { - throw new ExportException("Failed to dereference schema", e); - } - } - components.getSchemas().values() - .forEach(schema1 -> Utils.cleanUp(schema1, !exporterOptions.isAddJavaTypeExtensions())); - - Info info = setupInfo(ramlApi); - List tags = setupTags(ramlApi); - - String url = "/" + serviceName + "/"; - - List servers = new LinkedList<>(); - servers.add( - new Server() - .url(url) - .description("The server") - .variables(null)); - - Paths paths = new Paths(); - - String ramlBaseUrl = buildBaseUri(ramlApi); - - try { - convertResources(ramlBaseUrl, ramlApi.resources(), paths, components, jsonSchemaToOpenApi, operations); - } catch (DerefenceException e) { - throw new ExportException("Faield to defererence resources", e); - } - - OpenAPI openAPI = new OpenAPI(); - openAPI.setOpenapi("3.0.3"); - openAPI.setInfo(info); - openAPI.setTags(tags); - openAPI.setServers(servers); - openAPI.setComponents(components); - openAPI.setPaths(paths); - - // Start dereference Process - schemas = new ArrayList<>(components.getSchemas().values()); - for (Schema schema : schemas) { - try { - jsonSchemaToOpenApi.dereferenceSchema(schema, components); - } catch (Exception e) { - throw new ExportException("Failed to dereference schema", e); - } - } - components.getSchemas().values() - .forEach(schema -> Utils.cleanUp(schema, !exporterOptions.isAddJavaTypeExtensions())); - - exporterOptions.getTransformers().forEach(transformer -> transformer.transform(openAPI, new HashMap())); - - return openAPI; - } - - private String buildBaseUri(Api ramlApi) { - if (ramlApi.baseUri() == null) { - return "/"; - } - String ramlBaseUrl = ramlApi.baseUri().value(); - if (!ramlBaseUrl.startsWith("/")) { - ramlBaseUrl = "/" + ramlBaseUrl; - } - if (ramlBaseUrl.contains("{version}")) { - ramlBaseUrl = StringUtils.replace(ramlBaseUrl, "{version}", ramlApi.version().value()); - } - return ramlBaseUrl; - } - - @SuppressWarnings("java:S3776") - private Info setupInfo(Api ramlApi) { - log.debug("Setup Description"); - - String version = ramlApi.version() != null ? ramlApi.version().value() : "1.0"; - Info info = new Info() - .title(ramlApi.title().value()) - .version(version); - - final StringBuilder markdown = new StringBuilder(); - if (isNotBlank(ramlApi.description())) { - markdown - .append(ramlApi.description().value()) - .append(NEW_LINE); - } - if (ramlApi.documentation() != null) { - ramlApi.documentation().forEach( - documentationItem -> { - String title = null; - String documentation = null; - - if (isNotBlank(documentationItem.title())) { - title = documentationItem.title().value(); - } - if (isNotBlank(documentationItem.content())) { - documentation = documentationItem.content().value(); - } - - if (documentation != null && documentation.startsWith("# ")) { - markdown.append(documentationItem.content().value()); - markdown.append(NEW_LINE); - } else if (title != null) { - if (!title.startsWith("# ")) { - markdown.append("# "); - } - markdown.append(title); - markdown.append(NEW_LINE); - if (documentation != null) { - markdown.append(cleanupMarkdownString(documentationItem.content().value())); - markdown.append(NEW_LINE); - } - } - } - ); - } - if (markdown.length() != 0) { - info.setDescription(markdown.toString()); - } else { - info.setDescription(NO_DESCRIPTION_AVAILABLE); - log.warn("No description available."); - } - return info; - } - - private boolean isNotBlank(AnnotableStringType annotableStringType) { - return annotableStringType != null && StringUtils.isNotBlank(annotableStringType.value()); - } - - private List setupTags(Api ramlApi) { - String title = ramlApi.title().value().toLowerCase(Locale.ROOT); - return Collections.singletonList(new Tag().name(title)); - } - - protected static String cleanupMarkdownString(String value) { - StringBuilder stringBuilder = new StringBuilder(); - String[] lines = value.split(NEW_LINE); - for (int i = 0; i < lines.length; i++) { - if (i == 0 && lines[i].startsWith("#")) { - String title = "# " + StringUtils.substringAfterLast(lines[i], "#").trim(); - stringBuilder.append(title).append(NEW_LINE); - } else { - stringBuilder.append(lines[i]).append(NEW_LINE); - } - } - return stringBuilder.toString().trim(); - } - - private void parseRamlTypeReferences(URL baseUrl, Map ramlTypeReferences, - JsonNode jsonNode) { - if (jsonNode.hasNonNull("types")) { - ObjectNode types = (ObjectNode) jsonNode.get("types"); - types.fields().forEachRemaining(nodeEntry -> parseRamlRefEntry(baseUrl, ramlTypeReferences, nodeEntry)); - } - if (jsonNode.hasNonNull("schemas")) { - ObjectNode schemas = (ObjectNode) jsonNode.get("schemas"); - schemas.fields().forEachRemaining(nodeEntry -> parseRamlRefEntry(baseUrl, ramlTypeReferences, nodeEntry)); - } - - if (jsonNode.hasNonNull("uses")) { - ObjectNode traits = (ObjectNode) jsonNode.get("uses"); - traits.fields().forEachRemaining(traitMap -> { - String traitRef = traitMap.getValue().textValue(); - log.debug("Parsing trait ref: {}", traitRef); - try { - URL absoluteReference = Utils.getAbsoluteReference(baseUrl, traitRef); - URL absoluteReferenceParent = Utils.getAbsoluteReferenceParent(absoluteReference); - JsonNode trait = mapper.readTree(absoluteReference); - parseRamlTypeReferences(absoluteReferenceParent, ramlTypeReferences, trait); - - } catch (IOException e) { - log.error("Failed ot read url: {}", traitRef, e); - } - }); - - } - - - } - - private void parseRamlRefEntry(URL baseUrl, Map ramlTypeReferences, - Map.Entry nodeEntry) { - String key = nodeEntry.getKey(); - JsonNode typeReference = nodeEntry.getValue(); - if (typeReference.has("type") && typeReference instanceof ObjectNode) { - JsonNode typeNode = typeReference.get("type"); - String url = typeNode.textValue(); - if (typeNode instanceof TextNode && Utils.isUrl(url)) { - URL absoluteReference = Utils.getAbsoluteReference(baseUrl, url); - ramlTypeReferences.put(key, absoluteReference.toString()); - log.debug("Add raml type reference: {} to: {}", key, absoluteReference); - } else { - log.debug("Cannot create raml ref for: {}", url); - } - } else if (typeReference instanceof TextNode && typeReference.textValue().endsWith(".json")) { - URL absoluteReference = Utils.getAbsoluteReference(baseUrl, typeReference.textValue()); - ramlTypeReferences.put(key, absoluteReference.toString()); - log.debug("Add raml type reference: {} to: {}", key, absoluteReference); - } - } - - private Map collectTypesFromRamlSpec(Api ramlApi) { - Map types = new TreeMap<>(); - - for (Library library : ramlApi.uses()) { - library.schemas().forEach(typeDeclaration -> types.put(typeDeclaration.name(), typeDeclaration)); - library.types().forEach(typeDeclaration -> types.put(typeDeclaration.name(), typeDeclaration)); - } - ramlApi.schemas().forEach(typeDeclaration -> types.put(typeDeclaration.name(), typeDeclaration)); - ramlApi.types().forEach(typeDeclaration -> types.put(typeDeclaration.name(), typeDeclaration)); - return types; - } - - private void validateRamlModelResult(File file, RamlModelResult ramlModelResult) throws ExportException { - if (ramlModelResult.hasErrors()) { - log.error("Error validating RAML document: {}", file); - ramlModelResult.getValidationResults() - .forEach(validationResult -> log.error(validationResult.getMessage())); - throw new ExportException("Error validation RAML"); - } - - if (ramlModelResult.getApiV10() == null) { - throw new ExportException("Not a valid RAML 1.0 document"); - } - } - - private void convertResources(String rootPath, List resources, Paths paths, Components components, - JsonSchemaToOpenApi jsonSchemaToOpenApi, List operations) - throws ExportException, DerefenceException { - for (Resource resource : resources) { - if (log.isDebugEnabled()) { - log.debug("Mapping RAML Resource displayName: {} relativeUrl: {} with description: {} resourcePath: {}", - resource.displayName().value(), - resource.relativeUri().value(), - resource.description() != null ? resource.description().value() : null, - resource.resourcePath()); - } - PathItem pathItem = convertResource(resource, components, jsonSchemaToOpenApi, - operations); - String path = rootPath + resource.resourcePath(); - if (!pathItem.readOperations().isEmpty()) { - paths.addPathItem(path, pathItem); - } - convertResources(rootPath, resource.resources(), paths, components, jsonSchemaToOpenApi, operations); - } - } - - private PathItem convertResource(Resource resource, Components components, - JsonSchemaToOpenApi jsonSchemaToOpenApi, List operations) - throws ExportException, DerefenceException { - - PathItem pathItem = new PathItem(); - pathItem.summary(getDisplayName(resource.displayName())); - pathItem.description(getDescription(resource)); - log.debug("Mapping RAML resource: {}", pathItem.getSummary()); - mapUriParameters(resource, pathItem, components); - mapMethods(resource, pathItem, components, jsonSchemaToOpenApi, operations); - return pathItem; - } - - private void mapUriParameters(Resource resource, PathItem pathItem, - Components components) { - Resource current = resource; - Resource parent = current.parentResource(); - - while (parent != null) { - current.uriParameters().forEach(type -> { - log.debug("Mapping URI parameter: {}", type.name()); - log(type); - Parameter parameter = new PathParameter(); - convertTypeToParameter(type, parameter, components); - if (pathItem.getParameters() != null && pathItem.getParameters().stream().anyMatch( - existingParam -> existingParam.getName().equals(parameter.getName()) && existingParam.getIn() - .equals(parameter.getIn()))) { - log.warn("{} has double Parameter {} in path: {} Detected. ignoring", resource.resourcePath(), - parameter.getName(), pathItem.getDescription()); - } else { - pathItem.addParametersItem(parameter); - } - }); - - parent = current.parentResource(); - current = parent; - } - resolveUnspecifiedPathParameters(resource, pathItem); - } - - /** - * Some raml specs have unspecified uri parameters. OpenAPI requires all parameters to be specified. - * - * @param resource RAML Resource Item - * @param pathItem Path Item mapped to RAML Resource with added path parameters - */ - private void resolveUnspecifiedPathParameters(Resource resource, PathItem pathItem) { - String resourcePath = resource.resourcePath(); - Matcher matcher = placeholderPattern.matcher(resourcePath); - while (matcher.find()) { - String placeHolder = matcher.group(); - String placeholderName = placeHolder.substring(1, placeHolder.length() - 1); - - if (pathItem.getParameters() == null) { - pathItem.setParameters(new ArrayList<>()); - } - Optional optionalParameter = pathItem.getParameters().stream() - .filter(parameter -> parameter.getName().equals(placeholderName)) - .findFirst(); - - if (!optionalParameter.isPresent()) { - log.debug("Unspecified URI parameter: {} in RAML. Generating URI Parameter in OpenAPI", - placeholderName); - Parameter parameter = new PathParameter(); - parameter.setName(placeholderName); - parameter.setRequired(true); - parameter.description("Generated parameter by BOAT. Please specify the URI parameter in RAML"); - parameter.setSchema(new StringSchema()); - pathItem.addParametersItem(parameter); - } - } - } - - private void log(TypeDeclaration typeDeclaration) { - String description = getDescription(typeDeclaration.description()); - if (log.isDebugEnabled()) { - log.debug("Type name: {} type: {} displayName: {} defaultValue: {} description: {}", - typeDeclaration.name(), typeDeclaration.type(), getDisplayName(typeDeclaration.displayName()), - typeDeclaration.defaultValue(), description); - - } - } - - - private String getDisplayName(AnnotableStringType parameter) { - return parameter != null ? parameter.value() : null; - } - - private String getDescription(MarkdownString description) { - if (description == null) { - return NO_DESCRIPTION_AVAILABLE; - } - String result = description.value(); - return StringEscapeUtils.unescapeJavaScript(result); - } - - private void mapMethods(Resource resource, PathItem pathItem, Components components, - JsonSchemaToOpenApi jsonSchemaToOpenApi, List operations) - throws ExportException, DerefenceException { - for (Method ramlMethod : resource.methods()) { - PathItem.HttpMethod httpMethod = getHttpMethod(ramlMethod); - ApiResponses apiResponses = mapResponses(resource, ramlMethod, components, jsonSchemaToOpenApi); - - log.debug("Mapping method: {}", httpMethod); - - ArrayList parameters = new ArrayList<>(); - addHeaders(ramlMethod, parameters, components); - addQueryParameters(ramlMethod, parameters, components); - - RequestBody requestBody = convertRequestBody(resource, ramlMethod, components, jsonSchemaToOpenApi); - String resourcePath = resource.resourcePath(); - - String tag = Arrays.stream(resourcePath.substring(1).split("/")).findFirst().orElse("tag"); - String operationId = getOperationId(resource, ramlMethod, operations, requestBody); - String description = getDescription(ramlMethod.description()); - String summary; - List unwantedSummaries = new ArrayList<>(Arrays.asList("put", "get", "post", "delete")); - if (ramlMethod.displayName() == null || unwantedSummaries.contains(ramlMethod.displayName().value())) { - summary = getSummary(ramlMethod.description()); - } else { - summary = ramlMethod.displayName().value(); - } - - Operation operation = new Operation(); - - operation.addTagsItem(tag); - operation.setDescription(description); - operation.setResponses(apiResponses); - operation.setSummary(summary); - operation.setParameters(parameters.isEmpty() ? null : parameters); - operation.setOperationId(operationId); - operations.add(operation); - - if (httpMethod.equals(PathItem.HttpMethod.DELETE) && requestBody != null) { - log.warn("{} is a DELETE operation and must NOT have an requestBody. Removing operation entirely", - resourcePath); - } else { - operation.setRequestBody(requestBody); - } - - processMethodAnnotations(resourcePath, components, ramlMethod, httpMethod, operation, jsonSchemaToOpenApi); - if (description != null && description.contains("deprecated")) { - operation.deprecated(true); - } - - pathItem.operation(httpMethod, operation); - - } - } - - private String getSummary(MarkdownString description) { - if (description == null) { - return null; - } - return Stream.of(description.value().split(NEW_LINE)) - .findFirst() - .map(firstLine -> firstLine.replace("#", "")) - .map(String::trim) - .map(firstLine -> firstLine.endsWith(".") ? firstLine : firstLine + ".") - .orElse(null); - } - - @SuppressWarnings("java:S3776") - private String getOperationId(Resource resource, Method ramlMethod, List operations, - RequestBody requestBody) { - - String httpMethod = ramlMethod.method(); - String resourceName = resource.displayName().value(); - - // Some RAML display names consist "/" - if (resourceName.contains("/")) { - resourceName = Arrays.stream(resourceName.split("/")).map(StringUtils::capitalize) - .collect(Collectors.joining()); - } - - String operationId = httpMethod + resourceName; - - // If operationId is equal the http method name, - // take the display name or resource path name of the raml resource - if (operationId.equalsIgnoreCase(ramlMethod.method())) { - operationId = Utils.normalizeDisplayName(StringUtils.substringAfterLast(resource.resourcePath(), "/")); - } - - // If that name contains spaces, concat the name with capitalizing each word - if (operationId.contains(" ")) { - operationId = Arrays.stream(operationId.split(" ")).map(StringUtils::capitalize) - .collect(Collectors.joining()); - } - - // prepend http name ot to the operationId and ensure the rest has a capital - operationId = Utils.normalizeDisplayName(operationId); - - // path has path parameter, add By if not already there and hope for the best. - // Ensure format is lower camel case. - operationId = CaseFormat.UPPER_CAMEL.converterTo(CaseFormat.LOWER_CAMEL).convert(operationId); - - String finalOperationId = operationId; - if (operationIdExists(operations, finalOperationId) && requestBody != null) { - - Set placeHolders = Utils.getPlaceholders(resource.resourcePath()); - if (!placeHolders.isEmpty()) { - String suffix = - "By" + placeHolders.stream().map(StringUtils::capitalize).collect(Collectors.joining("And")); - if (!operationId.toLowerCase().endsWith(suffix.toLowerCase())) { - operationId += suffix; - } - } - if(log.isWarnEnabled()) { - log.warn("Operation {} for path: {} already exists! using: {}", finalOperationId, resource.resourcePath(), operationId); - } - } - - if (operationIdExists(operations, finalOperationId)) { - // So many ways these things go wrong. Now trying last part of resource path before placeholder - operationId += httpMethod + StringUtils.capitalize(Utils.normalizeDisplayName(resourceName)); - - } - if (log.isDebugEnabled()) { - log.debug("Resolve operationId: {} from resource: {} with method: {} and path: {}", operationId, - resource.displayName().value(), httpMethod, resource.resourcePath()); - } - return operationId; - } - - private boolean operationIdExists(List operations, String finalOperationId) { - return operations.stream().anyMatch(operation -> operation.getOperationId().equalsIgnoreCase(finalOperationId)); - } - - private void processMethodAnnotations(String resourcePath, Components components, Method ramlMethod, - PathItem.HttpMethod httpMethod, Operation operation, JsonSchemaToOpenApi jsonSchemaToOpenApi) - throws ExportException { - for (AnnotationRef annotationRef : ramlMethod.annotations()) { - TypeDeclaration annotation = annotationRef.annotation(); - TypeInstance typeInstance = annotationRef.structuredValue(); - - Schema annotationSchema = getAnnotationSchema(resourcePath, components, annotation, jsonSchemaToOpenApi); - - if (annotation.name().toLowerCase().contains("deprecat")) { - log.debug("Operation {} in path: {} marked deprecated", httpMethod, resourcePath); - operation.deprecated(true); - } - - for (TypeInstanceProperty property : typeInstance.properties()) { - String extensionName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, annotationSchema.getName()); - String propertyName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, property.name()); - if (property.isArray().booleanValue()) { - operation.addExtension("-" + extensionName + "-" + propertyName, property.values()); - } else { - operation.addExtension("x-" + extensionName + "-" + propertyName, property.value().value()); - } - } - } - } - - private Schema getAnnotationSchema(String resourcePath, Components components, TypeDeclaration annotation, - JsonSchemaToOpenApi jsonSchemaToOpenApi) throws ExportException { - Schema annotationSchema; - if (annotation instanceof JSONTypeDeclaration) { - JSONTypeDeclaration jsonType = (JSONTypeDeclaration) annotation; - if (jsonType.type().equals(jsonType.schemaContent())) { - // Type is inline. parse it as a new one - try { - annotationSchema = jsonSchemaToOpenApi.convert(annotation.name(), jsonType); - jsonSchemaToOpenApi.dereferenceSchema(annotationSchema, components); - } catch (DerefenceException e) { - throw new ExportException( - "Cannot dereference inline schema: : " + jsonType.schemaContent() + " for response: " - + resourcePath); - } - Utils.cleanUp(annotationSchema, !exporterOptions.isAddJavaTypeExtensions()); - } else { - String modelName = Utils.getProposedSchemaName(jsonType.type()); - annotationSchema = components.getSchemas().get(modelName); - if (annotationSchema == null) { - throw new ExportException( - "Cannot find schema definition for: " + jsonType.type() + " for response: " + resourcePath); - } - } - } else { - annotationSchema = RamlSchemaToOpenApi.convert(annotation.name(), annotation, components); - } - return annotationSchema; - } - - private RequestBody convertRequestBody(Resource resource, Method ramlMethod, Components components, - JsonSchemaToOpenApi jsonSchemaToOpenApi) throws DerefenceException, ExportException { - if (ramlMethod.body() == null || ramlMethod.body().isEmpty()) { - return null; - } - - Content content = new Content(); - for (TypeDeclaration body : ramlMethod.body()) { - String name = getName(resource, ramlMethod) + "Request"; - MediaType mediaType = convertBody(body, name, components, jsonSchemaToOpenApi); - content.addMediaType(body.name(), mediaType); - } - RequestBody requestBody = new RequestBody(); - requestBody.setContent(content); - requestBody.setDescription(ramlMethod.description() != null ? getDescription(ramlMethod.description()) : null); - return requestBody; - } - - private void addQueryParameters(Method ramlMethod, ArrayList parameters, Components components) { - ramlMethod.queryParameters().forEach(typeDeclaration -> { - Parameter parameter = new QueryParameter(); - convertTypeToParameter(typeDeclaration, parameter, components); - parameters.add(parameter); - }); - } - - private void addHeaders(Method ramlMethod, ArrayList parameters, Components components) { - ramlMethod.headers().forEach(type -> { - Parameter parameter = new HeaderParameter(); - convertTypeToParameter(type, parameter, components); - parameters.add(parameter); - }); - } - - private void convertTypeToParameter(TypeDeclaration typeDeclaration, Parameter parameter, - Components components) { - if (log.isDebugEnabled()) { - log.debug("Converting Parameter from: {} with type: {} into: {}", typeDeclaration.name(), - typeDeclaration.type(), parameter.getClass().getName()); - } - Schema schema = RamlSchemaToOpenApi.convert(typeDeclaration.name(), typeDeclaration, components); - - parameter.setName(typeDeclaration.name()); - parameter.setRequired(typeDeclaration.required()); - parameter.setSchema(schema); - if (Boolean.TRUE.equals(schema.getDeprecated())) { - parameter.deprecated(true); - } - parameter.setDescription(getDescription(typeDeclaration.description())); - - if (typeDeclaration.examples() != null && !typeDeclaration.examples().isEmpty()) { - parameter.setExamples(new LinkedHashMap<>()); - typeDeclaration.examples().forEach(exampleSpec -> { - Example example = new Example(); - example.setValue(getExampleObject(exampleSpec, true)); - example.setSummary(exampleSpec.name()); - parameter.getExamples().put(exampleSpec.name(), example); - }); - } else { - parameter.setExamples(new LinkedHashMap<>()); - Example example = new Example(); - example.setValue(getExampleObject(typeDeclaration.example(), true)); - example.setSummary(EXAMPLE); - parameter.getExamples().put(EXAMPLE, example); - } - - } - - private ApiResponses mapResponses(Resource resource, Method ramlMethod, Components components, - JsonSchemaToOpenApi jsonSchemaToOpenApi) throws ExportException, DerefenceException { - ApiResponses apiResponses = new ApiResponses(); - for (Response ramlResponse : ramlMethod.responses()) { - Content apiResponseContent = new Content(); - String responseCode = ramlResponse.code().value(); - String description = getDescription(ramlResponse); - - ApiResponse apiResponse = new ApiResponse(); - apiResponse.setDescription(description); - - if (!responseCode.equals("204")) { - List bodies = ramlResponse.body(); - for (TypeDeclaration body : bodies) { - String contentType = body.name(); - MediaType mediaType; - if ("application/json".equals(contentType) || "body".equals(contentType)) { - // This matches the name generated from RAML, e.g. PaymentCardsGetResponseBody - // The response is defined using an inline schema - String name = getName(resource, ramlMethod) + StringUtils.capitalize(ramlMethod.method()) - + "ResponseBody"; - mediaType = convertBody(body, name, components, jsonSchemaToOpenApi); - apiResponseContent.addMediaType(contentType, mediaType); - } - } - apiResponse.setContent(apiResponseContent); - } - - apiResponses.addApiResponse(responseCode, apiResponse); - } - return apiResponses; - } - - @SuppressWarnings("java:S3776") - private MediaType convertBody(TypeDeclaration body, String name, Components components, - JsonSchemaToOpenApi jsonSchemaToOpenApi) throws ExportException, DerefenceException { - Schema bodySchema = null; - MediaType mediaType = null; - - if (body instanceof JSONTypeDeclaration) { - mediaType = new MediaType(); - JSONTypeDeclaration jsonType = (JSONTypeDeclaration) body; - String type = jsonType.type(); - if (type.equals(jsonType.schemaContent())) { - //Check the if the - bodySchema = components.getSchemas().get(name); - if (bodySchema == null) { - // Type is inline. parse it as a new one - bodySchema = jsonSchemaToOpenApi.convert(name, jsonType); - jsonSchemaToOpenApi.dereferenceSchema(bodySchema, components); - - mediaType.setSchema(bodySchema); - Utils.cleanUp(bodySchema, !exporterOptions.isAddJavaTypeExtensions()); - } - mediaType.setSchema(new Schema().$ref(name)); - } else { - String schemaName = Utils.getProposedSchemaName(type); - bodySchema = components.getSchemas().get(schemaName); - if (bodySchema == null) { - log.error("No Schema with the name: {} resolved from: {} is present: ", schemaName, - type); - throw new ExportException("Invalid Schema"); - } - mediaType.setSchema(new Schema().$ref(schemaName)); - } - - } else if (body instanceof XMLTypeDeclaration) { - log.debug("No OpenAPI schema for: {} ", name); - } else { - bodySchema = RamlSchemaToOpenApi.convert(name, body, components); - mediaType = new MediaType(); - mediaType.setSchema(bodySchema); - } - - if (mediaType != null) { - convertExamples(body, mediaType); - - if (bodySchema.getExtensions() != null && bodySchema.getExtensions().containsKey(X_EXAMPLES)) { - List examples = (List) bodySchema.getExtensions().get(X_EXAMPLES); - for (Example example : examples) { - mediaType.addExamples(example.getSummary(), example); - } - mediaType.setExample(null); - } - - } - - return mediaType; - } - - private void convertExamples(TypeDeclaration body, MediaType mediaType) { - if (body.examples() != null && !body.examples().isEmpty()) { - body.examples().forEach(exampleSpec -> { - Example example = new Example(); - example.setValue(getExampleObject(exampleSpec, exporterOptions.isConvertExamplesToYaml())); - example.setSummary(exampleSpec.name()); - mediaType.addExamples(exampleSpec.name(), example); - mediaType.setExample(null); - }); - } else { - - Object exampleObject = getExampleObject(body.example(), exporterOptions.isConvertExamplesToYaml()); - if (exampleObject != null) { - Example example = new Example(); - example.setValue(exampleObject); - mediaType.addExamples(EXAMPLE, example); - mediaType.setExample(null); - } - } - } - - - private String getName(Resource resource, Method ramlMethod) { - AnnotableStringType annotableStringType = resource.displayName(); - if (annotableStringType != null) { - String value = annotableStringType.value(); - if (!value.contains("{") && !value.startsWith("/")) { - return Utils.normalizeSchemaName(value); - } - } - - List parts = new ArrayList<>(Arrays.asList(resource.resourcePath().split("/"))); - parts.add(ramlMethod.method()); - - return parts.stream() - .filter(StringUtils::isNotEmpty) - .map(Exporter::replacePlaceHolder) - .map(StringUtils::capitalize).collect(Collectors.joining()); - } - - private static String replacePlaceHolder(String part) { - if (part.contains("{")) { - return "ById"; - } else { - return part; - } - } - - private String getDescription(Response ramlResponse) { - String description = getDescription(ramlResponse.description()); - if (description == null) { - description = "Automagically created by RAML to Open API Exporter. " - + "Update RAML to include proper description for each response!"; - } - return description; - } - - private String getDescription(Resource resource) { - String description = getDescription(resource.description()); - if (description == null) { - return "Generated description for " + resource.displayName().value() - + ". Please update RAML spec to provide description for this resource"; - } else { - return description; - } - } - - - private static PathItem.HttpMethod getHttpMethod(Method ramlMethod) { - return PathItem.HttpMethod.valueOf(ramlMethod.method().toUpperCase()); - } - -} diff --git a/boat-engine/src/main/java/com/backbase/oss/boat/ExporterOptions.java b/boat-engine/src/main/java/com/backbase/oss/boat/ExporterOptions.java deleted file mode 100644 index ee82c80df..000000000 --- a/boat-engine/src/main/java/com/backbase/oss/boat/ExporterOptions.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.backbase.oss.boat; - -import com.backbase.oss.boat.transformers.Transformer; -import java.util.LinkedList; -import java.util.List; -import lombok.Data; - -@Data -public class ExporterOptions { - - private boolean addJavaTypeExtensions = false; - private boolean convertExamplesToYaml = true; - private List transformers = new LinkedList<>(); - - public ExporterOptions convertExamplesToYaml(boolean convertExamplesToYaml) { - this.convertExamplesToYaml = convertExamplesToYaml; - return this; - } - - public ExporterOptions transformers(List transformers) { - this.transformers = transformers; - return this; - } - - public ExporterOptions addJavaTypeExtensions(boolean addJavaTypeExtensions) { - this.addJavaTypeExtensions = addJavaTypeExtensions; - return this; - } - -} diff --git a/boat-engine/src/main/java/com/backbase/oss/boat/JsonSchemaToOpenApi.java b/boat-engine/src/main/java/com/backbase/oss/boat/JsonSchemaToOpenApi.java deleted file mode 100644 index cdb692c4b..000000000 --- a/boat-engine/src/main/java/com/backbase/oss/boat/JsonSchemaToOpenApi.java +++ /dev/null @@ -1,646 +0,0 @@ -package com.backbase.oss.boat; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.fasterxml.jackson.databind.node.TextNode; -import com.google.common.collect.BiMap; -import com.google.common.collect.HashBiMap; -import io.swagger.v3.oas.models.Components; -import io.swagger.v3.oas.models.media.ArraySchema; -import io.swagger.v3.oas.models.media.BooleanSchema; -import io.swagger.v3.oas.models.media.ComposedSchema; -import io.swagger.v3.oas.models.media.DateSchema; -import io.swagger.v3.oas.models.media.DateTimeSchema; -import io.swagger.v3.oas.models.media.EmailSchema; -import io.swagger.v3.oas.models.media.IntegerSchema; -import io.swagger.v3.oas.models.media.NumberSchema; -import io.swagger.v3.oas.models.media.ObjectSchema; -import io.swagger.v3.oas.models.media.Schema; -import io.swagger.v3.oas.models.media.StringSchema; -import java.io.IOException; -import java.math.BigDecimal; -import java.net.URI; -import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.TreeMap; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; -import lombok.SneakyThrows; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.raml.v2.api.model.v10.datamodel.JSONTypeDeclaration; - -@SuppressWarnings({"unchecked", "WeakerAccess", "rawtypes", "java:S3776", "java:S3740"}) -@Slf4j -class JsonSchemaToOpenApi { - - private static final String EXTENDS = "extends"; - public static final String X_RAML_TYPE = "x-raml-type"; - public static final String X_RAML_BASE = "x-raml-base"; - public static final String X_RAML_PARENT = "x-raml-parent"; - public static final String X_RAML_EXTENDS = "x-raml-extends"; - - public static final String X_JAVA_TYPE = "x-java-type"; - public static final String JAVA_TYPE = "javaType"; - public static final String PROPERTIES = "properties"; - public static final String JAVA_ENUM_NAMES = "javaEnumNames"; - public static final String X_JAVA_ENUM_NAMES = "x-java-enum-names"; - public static final String STRING = "string"; - public static final String FORMAT = "format"; - public static final String TYPE = "type"; - public static final String NUMBER = "number"; - public static final String DATE_TIME = "date-time"; - public static final String REQUIRED = "required"; - public static final String DATETIME_ONLY = "datetime-only"; - public static final String DATETIME = "datetime"; - public static final String DATE = "date"; - public static final String DATE_ONLY = "date-only"; - public static final String DOLLAR_REF = "$ref"; - - private final URL baseUrl; - private final Components components; - private final Map ramlTypeReferences; - private final Map jsonSchemas; - private final BiMap referenceNames; - private final ObjectMapper objectMapper = new ObjectMapper(); - - public JsonSchemaToOpenApi(URL baseUrl, Components components, Map ramlTypeReferences) { - this.baseUrl = baseUrl; - this.components = components; - this.jsonSchemas = new TreeMap<>(); - this.referenceNames = HashBiMap.create(); - this.ramlTypeReferences = ramlTypeReferences; - } - - - public Schema convert(String name, JSONTypeDeclaration typeDeclaration) throws ExportException { - log.debug("Converting JSONTypeDeclaration: {}", name); - String ramlRef = ramlTypeReferences.get(name); - String type = typeDeclaration.type(); - Schema schema; - String schemaName = Utils.normalizeSchemaName(name); - try { - if (ramlRef != null) { - URL referenceParent = Utils.getAbsoluteReferenceParent(ramlRef); - - schema = components.getSchemas().get(schemaName); - if (schema == null) { - JsonNode jsonSchema = objectMapper.readTree(type); - schema = Utils.resolveSchemaByJavaType(jsonSchema, components); - if (schema == null) { - schema = createNewSchema(null, jsonSchema, schemaName, components, referenceParent); - components.addSchemas(schemaName, schema); - log.debug("Created new schema from: {} as: {} with ramlRef: {}", name, schemaName, ramlRef); - } else { - log.debug("Used existing schema: {} resolved by javaType: {}", schemaName, - schema.getExtensions().get(X_JAVA_TYPE)); - } - } else { - log.debug("Using existing schema: {}", schemaName); - } - } else { - JsonNode jsonSchema = objectMapper.readTree(type); - schema = Utils.resolveSchemaByJavaType(jsonSchema, components); - if (schema == null) { - String referenceName = baseUrl.toString() + "/" + name + ".raml"; - referenceNames.put(referenceName, name); - schema = createNewSchema(null, jsonSchema, name, components, baseUrl); - schema.setExample(ExampleUtils.getExampleObject(typeDeclaration.example(), true)); - components.addSchemas(name, schema); - } - log.debug("Created new schema from: {} as: {}", name, schemaName); - components.addSchemas(schemaName, schema); - } - } catch (IOException e) { - throw new ExportException("Cannot read json schema from type: " + typeDeclaration.name(), e); - } catch (DerefenceException e) { - throw new ExportException("Cannot dereference json schema from type: " + typeDeclaration.name(), e); - } catch (RuntimeException e) { - throw new ExportException("Runtime exception:", e); - } - - schema.setExample(ExampleUtils.getExampleObject(typeDeclaration.example(), true)); - - return schema; - - } - - - public Schema createNewSchema(Schema parent, JsonNode type, String name, Components components, URL baseUrl) - throws DerefenceException { - log.debug("Creating Schema for: {} with path: {}", name, baseUrl); - if (name.contains(" ")) { - throw new IllegalStateException("name cannot contain spaces"); - } - - Schema schema = Utils.resolveSchemaByJavaType(type, components); - if (schema != null) { - return schema; - } - - String jsonSchemaType = determineJsonSchemaType(type); - switch (jsonSchemaType) { - case DATE_TIME: - case DATETIME_ONLY: - case DATETIME: - schema = new DateTimeSchema(); - break; - case DATE: - case DATE_ONLY: - schema = new DateSchema(); - break; - case "object": - if (type.get(EXTENDS) != null) { - schema = new ComposedSchema(); - JsonNode extendsNode = type.get(EXTENDS); - String extendedSchemaName; - if (hasReference(extendsNode)) { - String extendsReference = extendsNode.get(DOLLAR_REF).asText(); - log.debug("Creating Composed Schema for {} with reference: {}", name, extendsReference); - - URL absoluteReference = resolveAbsoluteReference(parent, extendsReference, baseUrl); - URL absoluteReferenceParent = Utils.getAbsoluteReferenceParent(absoluteReference); - JsonNode dereferencedExtendedNode = getJsonNode(absoluteReference); - - JsonNode dereferenced = getJsonNode(absoluteReference); - extendedSchemaName = Utils.getSchemaNameFromJavaClass(dereferenced) - .orElse( - Utils.getSchemaNameFromReference(absoluteReference, schema.getName(), referenceNames)); - - if (extendedSchemaName.equals(name)) { - extendedSchemaName += "Parent"; - } - Schema extendedSchema = components.getSchemas().get(extendedSchemaName); - if (extendedSchema == null) { - log.debug("Creating new schema for extended reference: {} with: {}", absoluteReference, - absoluteReferenceParent); - extendedSchema = createNewSchema(parent, dereferencedExtendedNode, extendedSchemaName, - components, absoluteReferenceParent); - components.addSchemas(extendedSchemaName, extendedSchema); - schema.addExtension(X_RAML_EXTENDS, extendedSchema); - } else { - log.debug("Using existing schema: {}", extendedSchema.getName()); - } - } else { - extendedSchemaName = name + "Parent"; - Schema extendedSchema = components.getSchemas().get(extendedSchemaName); - if (extendedSchema == null) { - extendedSchema = createNewSchema(parent, extendsNode, extendedSchemaName, components, - baseUrl); - components.addSchemas(extendedSchemaName, extendedSchema); - } - } - ((ComposedSchema) schema) - .setAllOf(Collections.singletonList(new ObjectSchema().$ref(extendedSchemaName))); - } else { - schema = new ObjectSchema(); - } - break; - case STRING: - case "time-only": - schema = new StringSchema(); - break; - case "email": - schema = new EmailSchema(); - break; - case NUMBER: - schema = new NumberSchema(); - break; - case "integer": - schema = new IntegerSchema(); - break; - case "boolean": - schema = new BooleanSchema(); - break; - case "array": - schema = new ArraySchema(); - JsonNode itemJsonSchema = type.get("items"); - if (hasReference(itemJsonSchema)) { - String itemReference = itemJsonSchema.get(DOLLAR_REF).textValue(); - String absoluteReference; - if (StringUtils.isNotEmpty(itemReference) && !Utils.isUrl(itemReference) && !Utils - .isFragment(itemReference)) { - absoluteReference = Utils.getAbsoluteReference(baseUrl, itemReference).toString(); - } else if (Utils.isFragment(itemReference) && Utils.isDirectory(baseUrl, itemReference)) { - absoluteReference = getReferenceFromParent(itemReference, parent); - absoluteReference += itemReference; - } else { - absoluteReference = itemReference; - } - if (!absoluteReference.equals(itemReference)) { - itemJsonSchema = ((ObjectNode) itemJsonSchema).set(DOLLAR_REF, new TextNode(absoluteReference)); - } - Schema itemSchema = mapProperty(parent, components, name + "Item", (ObjectNode) itemJsonSchema, - baseUrl, false); - ((ArraySchema) schema).setItems(itemSchema); - } else { - Schema itemSchema = mapProperty(parent, components, name + "Item", (ObjectNode) itemJsonSchema, - baseUrl, false); - ((ArraySchema) schema).setItems(itemSchema); - } - break; - - case "anyOf": - schema = new ComposedSchema(); - ArrayNode anyOfJsonSchmema = (ArrayNode) type.get(TYPE); - Iterable iterable = anyOfJsonSchmema::elements; - Stream stream = StreamSupport.stream(iterable.spliterator(), false); - List anyOfSchemas = stream.map(jsonNode -> new Schema().type(jsonNode.textValue())) - .collect(Collectors.toList()); - ((ComposedSchema) schema).setAnyOf(anyOfSchemas); - break; - default: - schema = new StringSchema(); - } - - schema.addExtension(X_RAML_BASE, baseUrl); - schema.addExtension(X_RAML_TYPE, type); - schema.addExtension(X_RAML_PARENT, parent); - schema.setName(name); - schema.setTitle(getString(type, "title")); - schema.setMinLength(getInteger(type, "minLength")); - schema.setMaxLength(getInteger(type, "maxLength")); - schema.setPattern(getString(type, "pattern")); - schema.setMinimum(getBigDecimal(type, "minimum")); - schema.setMaximum(getBigDecimal(type, "maximum")); - String description = getString(type, "description"); - schema.setDescription(description); - if (description != null && (description.contains("deprecated") || (description.contains("@deprecated")))) { - schema.setDeprecated(true); - } - - Map properties = getProperties(schema, type, components, baseUrl); - if (schema.getProperties() == null) { - schema.setProperties(properties); - } else if (properties != null && properties.size() > 0) { - schema.getProperties().putAll(properties); - } - - getRequired(type).ifPresent(schema::setRequired); - - String ref = getString(type, DOLLAR_REF); - - if (StringUtils.isNotEmpty(ref) && !Utils.isUrl(ref) && !Utils.isFragment(ref)) { - ref = Utils.getAbsoluteReference(baseUrl, ref).toString(); - } else if (StringUtils.isNotEmpty(ref) && Utils.isFragment(ref) && Utils.isDirectory(baseUrl, ref)) { - ref = getReferenceFromParent(ref, parent); - } - schema.set$ref(ref); - if (type.hasNonNull(JAVA_TYPE)) { - schema.addExtension(X_JAVA_TYPE, type.get(JAVA_TYPE).textValue()); - } - if (type.hasNonNull(JAVA_ENUM_NAMES)) { - schema.addExtension(X_JAVA_ENUM_NAMES, getEnum(type, JAVA_ENUM_NAMES)); - } - getEnum(type).ifPresent(schema::setEnum); - return schema; - } - - @SneakyThrows - private URL resolveAbsoluteReference(Schema parent, String ref, URL baseUrl) { - if (StringUtils.isNotEmpty(ref) && !Utils.isUrl(ref) && !Utils.isFragment(ref)) { - return Utils.getAbsoluteReference(baseUrl, ref); - } else if (Utils.isFragment(ref) && Utils.isDirectory(baseUrl, ref)) { - String referenceFromParent = getReferenceFromParent(ref, parent); - if (referenceFromParent == null) { - throw new IllegalStateException("Whha??"); - } - return new URL(referenceFromParent); - } else if (Utils.isFragment(ref) && Utils.hasFragment(baseUrl.toString())) { - String base = StringUtils.substringBefore(baseUrl.toString(), "#"); - return new URL(base + ref); - } else { - return new URL(ref); - } - } - - private boolean hasReference(JsonNode itemJsonSchema) { - return itemJsonSchema.hasNonNull(DOLLAR_REF); - } - - private String determineJsonSchemaType(JsonNode type) { - assert type != null; - JsonNode jsonType = type.get(TYPE); - if (jsonType != null && jsonType.isTextual() && !type.has(FORMAT)) { - return determineTypeFromJavaType(type, jsonType.asText()); - } else if (jsonType != null && type.has(FORMAT)) { - return type.get(FORMAT).textValue(); - } else if (jsonType != null && jsonType.isArray()) { - return "anyOf"; - } else if (type.hasNonNull("enum")) { - return STRING; - } else if (type.hasNonNull(JAVA_TYPE) || type.hasNonNull(DOLLAR_REF)) { - return "object"; - } else if (type instanceof ObjectNode && ((ObjectNode) type).size() == 0) { - return STRING; - } else { - log.error("Cannot determine json type from: {}. Guessing string", type); - return STRING; - } - } - - private String determineTypeFromJavaType(JsonNode type, String fallback) { - if (type.hasNonNull(JAVA_TYPE)) { - String javaType = type.get(JAVA_TYPE).textValue(); - switch (javaType) { - case "java.util.Date": - Optional format = Optional - .ofNullable(type.hasNonNull(FORMAT) ? type.get(FORMAT).textValue() : null); - return format.orElseGet(() -> DATE_TIME); - case "java.lang.Long": - return NUMBER; - default: - return fallback; - } - } else { - return fallback; - } - } - - private Optional getEnum(JsonNode type) { - String propertyName = "enum"; - return getEnum(type, propertyName); - } - - private Optional getEnum(JsonNode type, String propertyName) { - if (type.hasNonNull(propertyName)) { - JsonNode enumList = type.get(propertyName); - ArrayList result = new ArrayList(); - ArrayNode arrayNode = (ArrayNode) enumList; - - arrayNode.forEach(jsonNode -> { - if (jsonNode.isTextual()) { - result.add(jsonNode.textValue()); - } else if (jsonNode.isInt()) { - result.add(jsonNode.intValue()); - } else if (jsonNode.isBigDecimal()) { - result.add(jsonNode.decimalValue()); - } else { - throw new UnsupportedOperationException("Haven't come across type enum type: " + type); - } - }); - return Optional.of(result); - } else { - return Optional.empty(); - } - } - - @SuppressWarnings({"Duplicates", "java:S112"}) - private Map getProperties(Schema parent, JsonNode type, Components components, URL - baseUrl) throws DerefenceException { - Map properties = new LinkedHashMap<>(); - - if (type.hasNonNull(PROPERTIES)) { - Iterator> fields = type.get(PROPERTIES).fields(); - List> fieldList = new ArrayList(); - fields.forEachRemaining(fieldList::add); - for (Map.Entry field : fieldList) { - JsonNode property = field.getValue(); - Schema schema = mapProperty(parent, components, field.getKey(), (ObjectNode) property, baseUrl, false); - properties.put(field.getKey(), schema); - - } - } - if (properties.isEmpty()) { - return null; - } else { - return properties; - } - } - - private Schema mapProperty(Schema parent, Components components, String propertyName, ObjectNode jsonSchema, - URL baseUrl, boolean derefence) throws DerefenceException { - Schema schema; - boolean hasJsonRef = jsonSchema.has(DOLLAR_REF) && StringUtils.isNotEmpty(jsonSchema.get(DOLLAR_REF).textValue()); - - if (hasJsonRef && !derefence) { - String reference = jsonSchema.get(DOLLAR_REF).textValue(); - URL absoluteReference = Utils.getAbsoluteReference(baseUrl, reference); - jsonSchema.set(DOLLAR_REF, new TextNode(absoluteReference.toString())); - schema = createNewSchema(parent, jsonSchema, propertyName, components, baseUrl); - } else if (hasJsonRef) { - String absoluteReference = jsonSchema.get(DOLLAR_REF).textValue(); - log.debug("Dereference jsonSchema: {}", absoluteReference); - JsonNode dereferencedJsonSchema = getJsonNode(absoluteReference); - String schemaName = Utils.getSchemaNameFromJavaClass(dereferencedJsonSchema) - .orElse(Utils.getSchemaNameFromReference(absoluteReference, parent.getName(), referenceNames)); - if (components.getSchemas().containsKey(schemaName)) { - schema = components.getSchemas().get(schemaName); - } else { - schema = Utils.resolveSchemaByJavaType(dereferencedJsonSchema, components); - if (schema == null) { - log.debug("Adding property {} schema to catalog as: {}", propertyName, schemaName); - schema = createNewSchema(parent, dereferencedJsonSchema, schemaName, components, - Utils.getAbsoluteReferenceParent(absoluteReference)); - components.addSchemas(schemaName, schema); - dereferenceSchema(schema, components); - } else { - log.debug("Reusing schema: {} for property: {}", schema.getName(), propertyName); - } - } - log.debug("Property referenced schema: {}", schema.getName()); - } else { - schema = createNewSchema(parent, jsonSchema, propertyName, components, baseUrl); - } - return schema; - } - - private Optional> getRequired(JsonNode type) { - if (!type.hasNonNull(PROPERTIES)) { - return Optional.empty(); - } - List required = new ArrayList<>(); - type.get(PROPERTIES).fields().forEachRemaining(field -> { - JsonNode property = field.getValue(); - if (property.hasNonNull(REQUIRED) && property.get(REQUIRED).asBoolean()) { - required.add(field.getKey()); - } - }); - - if (type.has(REQUIRED)) { - JsonNode requiredNode = type.get(REQUIRED); - if (requiredNode.isArray()) { - requiredNode.elements().forEachRemaining(jsonNode -> required.add(jsonNode.asText())); - } else { - log.warn("wut?"); - } - } - return required.isEmpty() ? Optional.empty() : Optional.of(required); - } - - private String getString(JsonNode result, String key) { - return result.hasNonNull(key) ? result.get(key).textValue() : null; - } - - private Integer getInteger(JsonNode result, String key) { - return result.hasNonNull(key) ? result.get(key).asInt() : null; - } - - private BigDecimal getBigDecimal(JsonNode result, String key) { - - if (result.hasNonNull(key) && result.get(key).isTextual()) { - String val = result.get(key).textValue(); - try { - return new BigDecimal(val); - } catch (Exception e) { - log.warn("Cannot convert: {} to Big Decimal", val); - } - } - return null; - } - - void dereferenceSchema(final Schema schema, Components components) throws DerefenceException { - String ref = schema.get$ref(); - - if (ref != null && Utils.isAbsolute(ref)) { - URL absoluteParentReference = Utils.getAbsoluteReferenceParent(ref); - log.debug("ref: {}", ref); - - JsonNode dereferenced = getJsonNode(ref); - String schemaName = Utils.getSchemaNameFromJavaClass(dereferenced) - .orElse(Utils.getSchemaNameFromReference(ref, schema.getName(), referenceNames)); - - log.debug("Dereference schema: {} with ref: {}", schemaName, ref); - - Schema referencedSchema = Utils.resolveSchemaByJavaType(dereferenced, components); - if (referencedSchema == null) { - if (components.getSchemas().containsKey(schemaName)) { - referencedSchema = components.getSchemas().get(schemaName); - } else { - referencedSchema = createNewSchema(schema, dereferenced, schemaName, components, - absoluteParentReference); - components.addSchemas(schemaName, referencedSchema); - if (hasReference(referencedSchema)) { - dereferenceSchema(referencedSchema, components); - } - } - } - schema.$ref(referencedSchema.getName()); - } - if (schema instanceof ArraySchema) { - dereferenceArraySchema((ArraySchema) schema, components); - } - if (schema.getProperties() != null) { - Map properties = new LinkedHashMap<>(schema.getProperties()); - for (Map.Entry entry : properties.entrySet()) { - Schema value = entry.getValue(); - value.addExtension(X_RAML_PARENT, schema); - log.debug("Deference item property: {} from: {}", value.getName(), schema.getName()); - dereferenceSchema(value, components); - } - } - } - - @SneakyThrows - private JsonNode getJsonNode(URL reference) { - log.debug("Getting json for: {}", reference); - return getJsonNode(reference.toURI()); - } - - @SneakyThrows - private JsonNode getJsonNode(String reference) { - URI ref = new URI(reference); - return getJsonNode(ref); - } - - @SneakyThrows - private JsonNode getJsonNode(URI ref) { - - if (jsonSchemas.containsKey(ref.toString())) { - log.debug("Returning cached ref: {}", ref); - return jsonSchemas.get(ref.toString()); - } - JsonNode dereferenced; - log.debug("getJsonNode for: {}", ref); - - dereferenced = objectMapper.readTree(ref.toURL()); - if (ref.getFragment() != null) { - List fragments = Arrays.stream(ref.getFragment().split("/")).filter(StringUtils::isNotEmpty) - .collect(Collectors.toList()); - for (String fragment : fragments) { - dereferenced = dereferenced.get(fragment); - } - } - jsonSchemas.put(ref.toString(), dereferenced); - return dereferenced; - } - - @SneakyThrows - private String getReferenceFromParent(String reference, Schema schema) { - Schema parentSchema = (Schema) schema.getExtensions().get(X_RAML_PARENT); - while (parentSchema != null && parentSchema.getExtensions() != null) { - String ref; - if (parentSchema instanceof ArraySchema) { - ref = ((ArraySchema) parentSchema).getItems().get$ref(); - } else { - ref = parentSchema.get$ref(); - } - if (ref != null && !ref.equals(reference)) { - return ref; - } - parentSchema = (Schema) parentSchema.getExtensions().get(X_RAML_PARENT); - } - return null; - } - - - private boolean hasReference(Schema schema) { - if (schema.get$ref() != null) { - return true; - } - if (schema instanceof ArraySchema && ((ArraySchema) schema).getItems().get$ref() != null) { - return true; - } - if (schema.getProperties() != null && schema.getProperties().values().stream() - .anyMatch(property -> hasReference((Schema) property))) { - return true; - } - return schema.getExtensions().containsKey(X_RAML_EXTENDS); - - } - - private void dereferenceArraySchema(ArraySchema schema, Components components) throws DerefenceException { - Schema parent = schema.getItems(); - String reference = parent.get$ref(); - - if (parent.getExtensions() != null && reference != null && Utils.isAbsolute(reference)) { - JsonNode dereferenced = getJsonNode(reference); - String schemaName = Utils.getSchemaNameFromJavaClass(dereferenced) - .orElse(Utils.getSchemaNameFromReference(reference, schema.getName(), referenceNames)); - - if (schemaName.equals(schema.getName())) { - schemaName = schemaName + "Item"; - } - - Schema referencedSchema; - if (components.getSchemas().containsKey(schemaName)) { - referencedSchema = components.getSchemas().get(schemaName); - } else { - - referencedSchema = Utils.resolveSchemaByJavaType(dereferenced, components); - if (referencedSchema == null) { - referencedSchema = createNewSchema(schema, dereferenced, schemaName, components, - Utils.getAbsoluteReferenceParent(reference)); - components.addSchemas(schemaName, referencedSchema); - if (hasReference(referencedSchema)) { - dereferenceSchema(referencedSchema, components); - } - } - } - schema.getItems().$ref(referencedSchema.getName()); - - } else { - dereferenceSchema(parent, components); - } - } -} diff --git a/boat-engine/src/main/java/com/backbase/oss/boat/RamlSchemaToOpenApi.java b/boat-engine/src/main/java/com/backbase/oss/boat/RamlSchemaToOpenApi.java deleted file mode 100644 index 0fa104e7c..000000000 --- a/boat-engine/src/main/java/com/backbase/oss/boat/RamlSchemaToOpenApi.java +++ /dev/null @@ -1,166 +0,0 @@ -package com.backbase.oss.boat; - -import io.swagger.v3.oas.models.Components; -import io.swagger.v3.oas.models.media.ArraySchema; -import io.swagger.v3.oas.models.media.BooleanSchema; -import io.swagger.v3.oas.models.media.ComposedSchema; -import io.swagger.v3.oas.models.media.DateSchema; -import io.swagger.v3.oas.models.media.DateTimeSchema; -import io.swagger.v3.oas.models.media.FileSchema; -import io.swagger.v3.oas.models.media.IntegerSchema; -import io.swagger.v3.oas.models.media.NumberSchema; -import io.swagger.v3.oas.models.media.ObjectSchema; -import io.swagger.v3.oas.models.media.Schema; -import io.swagger.v3.oas.models.media.StringSchema; -import java.math.BigDecimal; -import java.util.List; -import java.util.stream.Collectors; -import lombok.experimental.UtilityClass; -import org.raml.v2.api.model.v10.datamodel.AnyTypeDeclaration; -import org.raml.v2.api.model.v10.datamodel.ArrayTypeDeclaration; -import org.raml.v2.api.model.v10.datamodel.BooleanTypeDeclaration; -import org.raml.v2.api.model.v10.datamodel.DateTimeOnlyTypeDeclaration; -import org.raml.v2.api.model.v10.datamodel.DateTimeTypeDeclaration; -import org.raml.v2.api.model.v10.datamodel.DateTypeDeclaration; -import org.raml.v2.api.model.v10.datamodel.FileTypeDeclaration; -import org.raml.v2.api.model.v10.datamodel.IntegerTypeDeclaration; -import org.raml.v2.api.model.v10.datamodel.NullTypeDeclaration; -import org.raml.v2.api.model.v10.datamodel.NumberTypeDeclaration; -import org.raml.v2.api.model.v10.datamodel.ObjectTypeDeclaration; -import org.raml.v2.api.model.v10.datamodel.StringTypeDeclaration; -import org.raml.v2.api.model.v10.datamodel.TimeOnlyTypeDeclaration; -import org.raml.v2.api.model.v10.datamodel.TypeDeclaration; -import org.raml.v2.api.model.v10.datamodel.UnionTypeDeclaration; -import org.raml.v2.api.model.v10.datamodel.XMLTypeDeclaration; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@SuppressWarnings({"java:S3776","java:S3740", "rawtypes"}) -@UtilityClass -public class RamlSchemaToOpenApi { - - private static final Logger log = LoggerFactory.getLogger(RamlSchemaToOpenApi.class); - - public static Schema convert(String name, TypeDeclaration type, Components components) { - if (log.isDebugEnabled()){ - log.debug("Creating Schema: {} from RAML type: {}", name, type.type()); - } - - Schema schema; - if (type instanceof ArrayTypeDeclaration) { - schema = arrayDeclaration(name,type,components); - } else if (type instanceof StringTypeDeclaration) { - schema = stringDeclaration(type); - } else if (type instanceof BooleanTypeDeclaration) { - schema = new BooleanSchema(); - } else if ((type instanceof DateTimeOnlyTypeDeclaration) - || (type instanceof DateTimeTypeDeclaration) - || (type instanceof TimeOnlyTypeDeclaration)) { - schema = new DateTimeSchema(); - } else if (type instanceof DateTypeDeclaration) { - schema = new DateSchema(); - } else if (type instanceof IntegerTypeDeclaration) { - schema = new IntegerSchema(); - } else if (type instanceof NumberTypeDeclaration) { - schema = new NumberSchema(); - } else if (type instanceof ObjectTypeDeclaration) { - schema = objectDeclaration(name,type,components); - } else if (type instanceof AnyTypeDeclaration) { - schema = new Schema().type("string").nullable(true); - } else if (type instanceof NullTypeDeclaration) { - NullTypeDeclaration nullTypeDeclaration = (NullTypeDeclaration) type; - schema = new StringSchema(); - schema.setNullable(true); - schema.setName(nullTypeDeclaration.name()); - } else if (type instanceof FileTypeDeclaration) { - FileTypeDeclaration fileTypeDeclaration = (FileTypeDeclaration) type; - schema = new FileSchema(); - schema.setDescription(fileTypeDeclaration.description() != null ? fileTypeDeclaration.description().value() : null); - } else if (type instanceof XMLTypeDeclaration) { - XMLTypeDeclaration xmlTypeDeclaration = (XMLTypeDeclaration) type; - String schemaContent = xmlTypeDeclaration.schemaContent(); - schema = XmlSchemaToOpenApi.convert(name, schemaContent, components); - schema.setDescription(xmlTypeDeclaration.description() != null ? xmlTypeDeclaration.description().value() : null); - } else if (type instanceof UnionTypeDeclaration) { - - schema = unionDeclaration(type,components); - - } else { - throw new UnsupportedOperationException("Not yet implemented"); - } - - - return depreciate(schema,name,type); - } - - private static Schema arrayDeclaration(String name, TypeDeclaration type, Components components){ - Schema schema = new ArraySchema(); - ArrayTypeDeclaration arrayTypeDeclaration = (ArrayTypeDeclaration) type; - Schema itemSchema = convert(name, arrayTypeDeclaration.items(), components); - ((ArraySchema) schema).setItems(itemSchema); - if (arrayTypeDeclaration.maxItems() != null) { - ((ArraySchema) schema).setMaximum(new BigDecimal(arrayTypeDeclaration.maxItems())); - } - if (arrayTypeDeclaration.minItems() != null) { - ((ArraySchema) schema).setMinimum(new BigDecimal(arrayTypeDeclaration.minItems())); - } - return schema; - } - - private static Schema stringDeclaration( TypeDeclaration type){ - Schema schema = new StringSchema(); - StringTypeDeclaration stringTypeDeclaration = (StringTypeDeclaration) type; - schema.setPattern(stringTypeDeclaration.pattern()); - schema.setMaxLength(stringTypeDeclaration.maxLength()); - schema.setMinLength(stringTypeDeclaration.minLength()); - - if (!stringTypeDeclaration.enumValues().isEmpty()) { - schema.setEnum(stringTypeDeclaration.enumValues()); - } - return schema; - } - - private static Schema objectDeclaration(String name, TypeDeclaration type, Components components){ - Schema schema = new ObjectSchema(); - schema.setName(name); - ObjectSchema objectSchema = (ObjectSchema) schema; - ObjectTypeDeclaration objectTypeDeclaration = (ObjectTypeDeclaration) type; - objectTypeDeclaration.properties().forEach(typeDeclaration -> { - Schema propertySchmea = convert(typeDeclaration.name(), typeDeclaration, components); - objectSchema.addProperties(typeDeclaration.name(), propertySchmea); - }); - - return schema; - } - - private static Schema unionDeclaration(TypeDeclaration type, Components components){ - UnionTypeDeclaration unionTypeDeclaration = (UnionTypeDeclaration) type; - - List of = unionTypeDeclaration.of().stream().map(typeDeclaration -> - convert(typeDeclaration.name(), typeDeclaration, components)) - .collect(Collectors.toList()); - - Schema schema = new ComposedSchema(); - ((ComposedSchema) schema).setAnyOf(of); - schema.setName(unionTypeDeclaration.name()); - schema.setDescription(unionTypeDeclaration.description() != null ? unionTypeDeclaration.description().value() : null); - return schema; - } - - - - private static Schema depreciate(Schema schema, String name, TypeDeclaration type){ - schema.setName(name); - String description = type.description() != null ? type.description().value() : null; - if (description != null && (description.contains("deprecated") || (description.contains("@deprecated")))) { - schema.setDeprecated(true); - } - - if (type.defaultValue() != null) { - schema.setDefault(type.defaultValue()); - } - return schema; - } - - -} diff --git a/boat-engine/src/main/java/com/backbase/oss/boat/Utils.java b/boat-engine/src/main/java/com/backbase/oss/boat/Utils.java index 39695766c..3d4068ea0 100644 --- a/boat-engine/src/main/java/com/backbase/oss/boat/Utils.java +++ b/boat-engine/src/main/java/com/backbase/oss/boat/Utils.java @@ -1,18 +1,12 @@ package com.backbase.oss.boat; -import static com.backbase.oss.boat.JsonSchemaToOpenApi.X_JAVA_ENUM_NAMES; -import static com.backbase.oss.boat.JsonSchemaToOpenApi.X_JAVA_TYPE; - -import com.fasterxml.jackson.core.json.JsonReadFeature; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import com.google.common.base.CaseFormat; import com.google.common.collect.BiMap; -import io.swagger.v3.oas.models.Components; -import io.swagger.v3.oas.models.media.ArraySchema; -import io.swagger.v3.oas.models.media.ComposedSchema; -import io.swagger.v3.oas.models.media.Schema; +import lombok.SneakyThrows; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.io.File; import java.io.IOException; import java.net.URI; @@ -20,45 +14,19 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.PathMatcher; -import java.util.LinkedHashSet; -import java.util.Optional; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import java.util.stream.Stream; -import lombok.SneakyThrows; -import org.apache.commons.lang.StringUtils; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - @SuppressWarnings({"Duplicates", "java:S3776", "java:S3740"}) public class Utils { private static final Logger log = LoggerFactory.getLogger(Utils.class); - public static final String JAVA_TYPE = "javaType"; private Utils() { throw new UnsupportedOperationException("private constructor"); } - @SneakyThrows - static URL getAbsoluteReference(URL base, String ref) { - URI uri = base.toURI().resolve(ref); - log.trace("Resolved: {} from {} and {}", uri, base, ref); - File file = new File(uri.toURL().getFile()); - if (!file.exists()) { - throw new DerefenceException("File does not exist: " + file.getAbsolutePath()); - } - if (file.isDirectory()) { - throw new DerefenceException("File is a directory" + file.getAbsolutePath()); - } - return uri.normalize().toURL(); - } - @SneakyThrows static boolean isDirectory(URL base, String ref) { URI uri = base.toURI().resolve(ref); @@ -70,21 +38,7 @@ static boolean isDirectory(URL base, String ref) { return directory; } - @SneakyThrows - static boolean isFragment(String ref) { - return ref.startsWith("#"); - } - @SneakyThrows - static boolean isAbsolute(String ref) { - return new URI(ref).isAbsolute(); - } - - - @SneakyThrows - static boolean hasFragment(String ref) { - return ref.contains("#"); - } @SneakyThrows static URL getAbsoluteReferenceParent(String absoluteReference) { @@ -102,37 +56,6 @@ static URL getAbsoluteReferenceParent(URL absoluteReference) { return parent.toURL(); } - static Schema resolveSchemaByJavaType(JsonNode type, Components components) { - if (type.hasNonNull(JAVA_TYPE) && !type.get(JAVA_TYPE).textValue().startsWith("java")) { - if(log.isDebugEnabled()){ - log.debug("Resolving Schema Type from javaType: {}", type.get(JAVA_TYPE).textValue()); - } - final String javaType = type.get(JAVA_TYPE).textValue(); - Optional first = components.getSchemas().values().stream() - .filter(schema -> schema.getExtensions() != null && javaType - .equals(schema.getExtensions().get(X_JAVA_TYPE))) - .findFirst(); - if (first.isPresent()) { - log.debug("Found Schema: {} for javaType: {} ", first.get().getName(), javaType); - return first.get(); - } - } - return null; - } - - static Optional getSchemaNameFromJavaClass(JsonNode type) { - if (type.hasNonNull(JAVA_TYPE)) { - if(log.isDebugEnabled()){ - log.debug("javaType: {}", type.get(JAVA_TYPE).textValue()); - } - final String javaType = type.get(JAVA_TYPE).textValue(); - if (!javaType.startsWith("java.")) { - return Optional.of(StringUtils.substringAfterLast(javaType, ".")); - } - } - return Optional.empty(); - - } static String getSchemaNameFromReference(URL absoluteReference, String parentSchemaName, BiMap referenceNames) { @@ -203,20 +126,6 @@ public static String normalizeSchemaName(String name) { return name; } - public static String normalizeDisplayName(String name) { - name = name.replaceAll("[^A-Za-z0-9]", ""); - return name; - } - - protected static Set getPlaceholders(String url) { - Matcher m = Pattern.compile("\\{(.*?)\\}").matcher(url); - Set placeholders = new LinkedHashSet<>(); - while (m.find()) { - String match = m.group(0); - placeholders.add(match.substring(1, match.length() - 1)); - } - return placeholders; - } protected static boolean isUrl(String url) { try { @@ -227,49 +136,9 @@ protected static boolean isUrl(String url) { } } - public static void cleanUp(Schema schema, boolean removeJavaExtensions) { - if (schema == null) { - return; - } - if (schema.getExtensions() != null) { - schema.getExtensions().remove(JsonSchemaToOpenApi.X_RAML_TYPE); - schema.getExtensions().remove(JsonSchemaToOpenApi.X_RAML_BASE); - schema.getExtensions().remove(JsonSchemaToOpenApi.X_RAML_PARENT); - schema.getExtensions().remove(JsonSchemaToOpenApi.X_RAML_EXTENDS); - - if (removeJavaExtensions) { - schema.getExtensions().remove(X_JAVA_TYPE); - schema.getExtensions().remove(X_JAVA_ENUM_NAMES); - } - } - if (schema.getProperties() != null) { - schema.getProperties().forEach((s, prop) -> cleanUp((Schema) prop, removeJavaExtensions)); - } - if (schema instanceof ArraySchema) { - cleanUp(((ArraySchema) schema).getItems(), removeJavaExtensions); - } - if (schema instanceof ComposedSchema) { - ComposedSchema composedSchema = (ComposedSchema) schema; - if (composedSchema.getAllOf() != null) { - composedSchema.getAllOf().forEach(schema1 -> cleanUp(schema1, removeJavaExtensions)); - } - if (composedSchema.getAnyOf() != null) { - composedSchema.getAnyOf().forEach(schema1 -> cleanUp(schema1, removeJavaExtensions)); - } - if (composedSchema.getOneOf() != null) { - composedSchema.getOneOf().forEach(schema1 -> cleanUp(schema1, removeJavaExtensions)); - } - } - } - - public static ObjectMapper createObjectMapper() { - YAMLFactory yamlFactory = new YAMLFactory(); - yamlFactory.enable(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature()); - return new ObjectMapper(yamlFactory); - } public static String[] selectInputs(Path inputPath, String glob) throws IOException { final PathMatcher matcher = inputPath diff --git a/boat-engine/src/main/java/com/backbase/oss/boat/XmlSchemaToOpenApi.java b/boat-engine/src/main/java/com/backbase/oss/boat/XmlSchemaToOpenApi.java deleted file mode 100644 index e3aee360b..000000000 --- a/boat-engine/src/main/java/com/backbase/oss/boat/XmlSchemaToOpenApi.java +++ /dev/null @@ -1,106 +0,0 @@ -package com.backbase.oss.boat; - -import io.swagger.v3.oas.models.Components; -import io.swagger.v3.oas.models.media.ArraySchema; -import io.swagger.v3.oas.models.media.BooleanSchema; -import io.swagger.v3.oas.models.media.IntegerSchema; -import io.swagger.v3.oas.models.media.ObjectSchema; -import io.swagger.v3.oas.models.media.Schema; -import io.swagger.v3.oas.models.media.StringSchema; -import io.swagger.v3.oas.models.media.XML; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import lombok.SneakyThrows; -import lombok.extern.java.Log; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang3.StringUtils; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; - -import java.nio.charset.StandardCharsets; - -@Log -@SuppressWarnings({"java:S3740", "rawtypes", "java:S2755"}) -public class XmlSchemaToOpenApi { - public static final String NAME = "name"; - public static final String TYPE = "type"; - private static final DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); - - private XmlSchemaToOpenApi(){ - throw new AssertionError("Private constructor"); - } - @SneakyThrows - public static Schema convert(String name, String schemaContent, Components components) { - DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); - Document doc = docBuilder.parse(IOUtils.toInputStream(schemaContent, StandardCharsets.UTF_8)); - - XML xml = new XML(); - xml.addExtension("x-bb-schema-content", schemaContent); - Schema root = new Schema(); - root.name(name); - map(doc.getDocumentElement(), root, components); - components.addSchemas(name, root); - return root; - - } - - private static void map(Element node, Schema schema, Components components) { - - NodeList complexTypes = ( node).getElementsByTagName("xs:complexType"); - for (int i = 0; i < complexTypes.getLength(); i++) { - Element complexType = (Element) complexTypes.item(i); - String name = complexType.getAttribute(NAME); - - Schema complexTypeSchema = components.getSchemas().getOrDefault(name, new ObjectSchema()); - map(complexType, complexTypeSchema, components); - components.addSchemas(name, complexTypeSchema); - } - NodeList elements = ( node).getElementsByTagName("xs:element"); - for (int i = 0; i < elements.getLength(); i++) { - Element element = (Element) elements.item(i); - String name = element.getAttribute(NAME); - String type = element.getAttribute(TYPE); - if (StringUtils.isEmpty(type)) { - type = "string"; - } - Schema propertySchema = createSchemaFor( type, components); - propertySchema.setName(name); - schema.addProperties(name, propertySchema); - } - for (int i = 0; i < elements.getLength(); i++) { - Element element = (Element) elements.item(i); - - String name = node.getAttribute(NAME); - ArraySchema arraySchema = new ArraySchema(); - arraySchema.setName(name); - Schema itemSchema = new Schema(); - map(element, itemSchema, components); - arraySchema.setItems(itemSchema); - - schema.$ref(name); - } - } - - - private static Schema createSchemaFor( String type, Components components) { - switch (type) { - case "xs:string": - return new StringSchema(); - case "xs:boolean": - return new BooleanSchema(); - case "xs:int": - return new IntegerSchema(); - default: - - } - Schema complexType = components.getSchemas().get(type); - if (complexType == null) { - complexType = new ObjectSchema(); - components.addSchemas(type, complexType); - - } - return complexType; - - } -} diff --git a/boat-engine/src/main/java/com/backbase/oss/boat/example/NamedExample.java b/boat-engine/src/main/java/com/backbase/oss/boat/example/NamedExample.java index 7e5c1c1b4..c06f29598 100644 --- a/boat-engine/src/main/java/com/backbase/oss/boat/example/NamedExample.java +++ b/boat-engine/src/main/java/com/backbase/oss/boat/example/NamedExample.java @@ -1,8 +1,8 @@ package com.backbase.oss.boat.example; import io.swagger.v3.oas.models.examples.Example; +import jakarta.validation.constraints.NotNull; -import javax.validation.constraints.NotNull; /** * A data class that has an example and its name. diff --git a/boat-engine/src/main/java/com/backbase/oss/boat/loader/CachingResourceLoader.java b/boat-engine/src/main/java/com/backbase/oss/boat/loader/CachingResourceLoader.java deleted file mode 100644 index a399e3625..000000000 --- a/boat-engine/src/main/java/com/backbase/oss/boat/loader/CachingResourceLoader.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.backbase.oss.boat.loader; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; -import java.io.IOException; -import java.io.InputStream; -import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import javax.annotation.Nullable; -import org.apache.commons.io.IOUtils; -import org.raml.v2.api.loader.ResourceLoaderExtended; -import org.raml.v2.api.loader.ResourceUriCallback; - -/** - * There are 3 purposes to this, to cache the resource content, to normalise all $ref URIs in the - * JSON and to provide reverse lookup from content to resource location. - */ -public class CachingResourceLoader implements ResourceLoaderExtended { - - private Map nameToContent = new HashMap<>(); - private Map contentToName = new HashMap<>(); - private ResourceLoaderExtended resourceLoader; - private ObjectMapper jsonMapper = new ObjectMapper(); - - public CachingResourceLoader(ResourceLoaderExtended resourceLoader) { - this.resourceLoader = resourceLoader; - } - - private InputStream cacheContent(URI foundUri, String resourceName, InputStream inputStream) { - if (inputStream == null) { - return null; - } - try (InputStream in = inputStream) { - String content = IOUtils.toString(in, StandardCharsets.UTF_8.name()); - - content = normaliseJsonRefs(foundUri, resourceName, content); - - ContentItem contentItem = new ContentItem(foundUri, content, resourceName); - nameToContent.put(resourceName, contentItem); - contentToName.put(content, contentItem); - return IOUtils.toInputStream(content, StandardCharsets.UTF_8); - } catch (IOException e) { - throw new RamlLoaderException("Failed to cache content", e); - } - } - - @Nullable - @Override - public InputStream fetchResource(String resourceName) { - return fetchResource(resourceName, null); - } - - @Override - public InputStream fetchResource(String resourceName, final ResourceUriCallback callback) { - if (nameToContent.containsKey(resourceName)) { - ContentItem contentItem = nameToContent.get(resourceName); - - if (callback != null) { - callback.onResourceFound(contentItem.getFoundUri()); - } - - return IOUtils.toInputStream(contentItem.getContent(), StandardCharsets.UTF_8); - } - - CachingResourceUriCallback myCallback = new CachingResourceUriCallback(callback); - InputStream inputStream = resourceLoader.fetchResource(resourceName, myCallback); - - return cacheContent(myCallback.getResourceUri(), resourceName, inputStream); - } - - /** - * Make all $ref properties in the JSON absolute and normalised. - * - * @param foundUri the URI for the resource - * @param resourceName path the JSON - * @param content the unprocessed content - * @return processed content with normalised JSON refs - */ - public String normaliseJsonRefs(URI foundUri, String resourceName, String content) { - if (!resourceName.endsWith(".json")) { - return content; - } - try { - JsonNode schema = jsonMapper.readTree(content); - List refs = schema.findParents("$ref"); - for (JsonNode ref : refs) { - String uriString = ref.findValue("$ref").asText(); - URI refUri = URI.create(uriString); - if (!refUri.isAbsolute()) { - // Update the URI only if it needs updating - URI resolvedUri = foundUri.resolve(refUri).normalize(); - ((ObjectNode) ref).put("$ref", resolvedUri.toString()); - } - } - return schema.toString(); - } catch (IOException e) { - throw new RamlLoaderException("Failed to normalize json references", e); - } - } - - public URI getUriCallBackParam() { - return this.resourceLoader != null ? this.resourceLoader.getUriCallBackParam() : null; - } -} diff --git a/boat-engine/src/main/java/com/backbase/oss/boat/loader/CachingResourceUriCallback.java b/boat-engine/src/main/java/com/backbase/oss/boat/loader/CachingResourceUriCallback.java deleted file mode 100644 index 84551b8ae..000000000 --- a/boat-engine/src/main/java/com/backbase/oss/boat/loader/CachingResourceUriCallback.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.backbase.oss.boat.loader; - -import java.net.URI; -import org.raml.v2.api.loader.ResourceUriCallback; - -/** - * Callback which stores the found resourceURI and calls another callback in a chain. - */ -class CachingResourceUriCallback implements ResourceUriCallback { - - private URI resourceUri; - private ResourceUriCallback callback; - - /** - * Constructor with callback. - * - * @param callback may be null - */ - public CachingResourceUriCallback(ResourceUriCallback callback) { - this.callback = callback; - } - - @Override - public void onResourceFound(URI resourceUri) { - this.resourceUri = resourceUri; - if (callback != null) { - callback.onResourceFound(resourceUri); - } - } - - public URI getResourceUri() { - return resourceUri; - } -} diff --git a/boat-engine/src/main/java/com/backbase/oss/boat/loader/ContentItem.java b/boat-engine/src/main/java/com/backbase/oss/boat/loader/ContentItem.java deleted file mode 100644 index eda5e7a16..000000000 --- a/boat-engine/src/main/java/com/backbase/oss/boat/loader/ContentItem.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.backbase.oss.boat.loader; - -import java.net.URI; - -/** - * Record the URI location and content of loaded resources. - */ -class ContentItem { - private final URI foundUri; - private final String content; - private final String resourceName; - - /** - * Constructor with required field values. - */ - public ContentItem(URI foundUri, String content, String resourceName) { - this.foundUri = foundUri; - this.content = content; - this.resourceName = resourceName; - } - - public URI getFoundUri() { - return foundUri; - } - - public String getContent() { - return content; - } - - public String getResourceName() { - return resourceName; - } -} diff --git a/boat-engine/src/main/java/com/backbase/oss/boat/loader/RamlLoaderException.java b/boat-engine/src/main/java/com/backbase/oss/boat/loader/RamlLoaderException.java deleted file mode 100644 index 384cdaa70..000000000 --- a/boat-engine/src/main/java/com/backbase/oss/boat/loader/RamlLoaderException.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.backbase.oss.boat.loader; - -public class RamlLoaderException extends RuntimeException { - - public RamlLoaderException(String message) { - super(message); - } - - public RamlLoaderException(String message, Throwable cause) { - super(message, cause); - } - -} diff --git a/boat-engine/src/main/java/com/backbase/oss/boat/loader/RamlResourceLoader.java b/boat-engine/src/main/java/com/backbase/oss/boat/loader/RamlResourceLoader.java deleted file mode 100644 index 35df8f311..000000000 --- a/boat-engine/src/main/java/com/backbase/oss/boat/loader/RamlResourceLoader.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.backbase.oss.boat.loader; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.net.URI; -import javax.annotation.Nullable; -import org.raml.v2.api.loader.DefaultResourceLoader; -import org.raml.v2.api.loader.ResourceLoader; -import org.raml.v2.api.loader.ResourceLoaderExtended; -import org.raml.v2.api.loader.ResourceUriCallback; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Fetches a resource using the following order. - *
    - *
  • If the name starts with '/' it is interpreted as an absolute path
  • - *
  • Else, it is assumed it is path relative to the root
  • - *
  • Otherwise, a DefaultResourceLoader is used to fall back on the default resource loading - * behaviour.
  • - *
- */ -public class RamlResourceLoader implements ResourceLoaderExtended { - - private final Logger log = LoggerFactory.getLogger(RamlResourceLoader.class); - - private final ResourceLoader fallBackResourceLoader = new DefaultResourceLoader(); - private final File baseDir; - private final File root; - - /** - * Constructor specifying where to look for resources. - * @param baseDir Base Directory to search references from - * @param root The raml file to load - */ - public RamlResourceLoader(File baseDir, File root) { - this.root = root; - this.baseDir = baseDir; - } - - @Nullable - @Override - public InputStream fetchResource(String resourceName, ResourceUriCallback callback) { - log.debug("Fetching resource: {}", resourceName); - File file = new File(resourceName); - if (!file.isAbsolute()) { - file = new File(this.root, resourceName); - if (!file.exists()) { - file = new File(this.baseDir, resourceName); - } - } - if (!file.exists()) { - log.debug("File {} does not seem to exist, falling back to default resource loader.", - file.getAbsolutePath()); - if (fallBackResourceLoader instanceof ResourceLoaderExtended && callback != null) { - return ((ResourceLoaderExtended) fallBackResourceLoader).fetchResource(resourceName, callback); - } else { - return this.fallBackResourceLoader.fetchResource(resourceName); - } - - } - if (file.isDirectory()) { - throw new RamlLoaderException("Cannot read " + file + " (Is a directory)"); - } - try { - log.debug("Returning {}", file.getAbsolutePath()); - if (callback != null) { - callback.onResourceFound(file.toURI()); - } - return new FileInputStream(file); - } catch (FileNotFoundException e) { - throw new RamlLoaderException("File not found: " + file, e); - } - } - - @Override - public InputStream fetchResource(String resourceName) { - return fetchResource(resourceName, null); - } - - public URI getUriCallBackParam() { - return this.fallBackResourceLoader instanceof ResourceLoaderExtended ? ((ResourceLoaderExtended)this.fallBackResourceLoader).getUriCallBackParam() : null; - } -} diff --git a/boat-engine/src/main/java/com/backbase/oss/boat/transformers/ExampleExtractors.java b/boat-engine/src/main/java/com/backbase/oss/boat/transformers/ExampleExtractors.java index 182352d5d..9948fecc5 100644 --- a/boat-engine/src/main/java/com/backbase/oss/boat/transformers/ExampleExtractors.java +++ b/boat-engine/src/main/java/com/backbase/oss/boat/transformers/ExampleExtractors.java @@ -9,9 +9,10 @@ import io.swagger.v3.oas.models.parameters.Parameter; import javax.annotation.Nullable; -import javax.validation.constraints.NotNull; import java.util.*; import java.util.stream.Collectors; + +import jakarta.validation.constraints.NotNull; import lombok.experimental.UtilityClass; /** diff --git a/boat-engine/src/main/java/com/backbase/oss/boat/transformers/OpenAPIExtractor.java b/boat-engine/src/main/java/com/backbase/oss/boat/transformers/OpenAPIExtractor.java index 3007fbde0..51bb922ff 100644 --- a/boat-engine/src/main/java/com/backbase/oss/boat/transformers/OpenAPIExtractor.java +++ b/boat-engine/src/main/java/com/backbase/oss/boat/transformers/OpenAPIExtractor.java @@ -6,8 +6,8 @@ import io.swagger.v3.oas.models.headers.Header; import io.swagger.v3.oas.models.parameters.Parameter; import io.swagger.v3.oas.models.responses.ApiResponse; +import jakarta.validation.constraints.NotNull; -import javax.validation.constraints.NotNull; import java.util.*; import java.util.stream.Collectors; diff --git a/boat-engine/src/main/java/org/raml/v2/internal/utils/ResourcePathUtils.java b/boat-engine/src/main/java/org/raml/v2/internal/utils/ResourcePathUtils.java deleted file mode 100644 index 261807819..000000000 --- a/boat-engine/src/main/java/org/raml/v2/internal/utils/ResourcePathUtils.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2013 (c) MuleSoft, Inc. - * - * 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.raml.v2.internal.utils; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import lombok.experimental.UtilityClass; - -/** - * This utility has been modified by Backbase to enable this to work with windows file paths. - */ -@UtilityClass -public class ResourcePathUtils { - private static final Pattern TEMPLATE_PATTERN = Pattern.compile("\\{([^}]+)\\}"); - - /** - * Returns the absolute resource location using the basePath basePath and relativePath must have - * forward slashes(/) as path separators. - * - * @param basePathParam The base path of the relative path - * @param relativePathParam the relative path - * @return The Absolute path - */ - public static String toAbsoluteLocation(String basePathParam, String relativePathParam) { - // This has been added by Backbase to enable this to work with windows file paths - // It also enforces the condition mentioned in the original method Javadoc. - // This shouldn't change anything on a UNIX like system as File.separator is / already - // The same for URL based path - // The returned value can be used by 'UNIX' and Windows - String basePath = basePathParam.replace("\\", "/"); - String relativePath = relativePathParam.replace("\\", "/"); - - String result = relativePath; - if (!isAbsolute(relativePath)) { - // This is for file based path - int lastSlash = basePath.lastIndexOf('/'); - if (lastSlash != -1) { - result = basePath.substring(0, lastSlash + 1) + relativePath; - } - - } - if (result.contains("#")) { - return result.split("#")[0]; - } - return result; - } - - public static boolean isAbsolute(String includePath) { - return includePath.startsWith("http:") || includePath.startsWith("https:") || includePath.startsWith("file:") || includePath.startsWith("/") || (new File(includePath)).isAbsolute(); - } - - public static List getUriTemplates(String value) { - List result = new ArrayList<>(); - if (value != null) { - Matcher m = TEMPLATE_PATTERN.matcher(value); - - while(m.find()) { - result.add(m.group(1)); - } - } - - return result; - } -} diff --git a/boat-engine/src/test/java/com/backbase/oss/boat/ExporterTests.java b/boat-engine/src/test/java/com/backbase/oss/boat/ExporterTests.java deleted file mode 100644 index 40de31289..000000000 --- a/boat-engine/src/test/java/com/backbase/oss/boat/ExporterTests.java +++ /dev/null @@ -1,204 +0,0 @@ -package com.backbase.oss.boat; - -import com.backbase.oss.boat.serializer.SerializerUtils; -import com.backbase.oss.boat.transformers.Decomposer; -import io.swagger.v3.oas.models.OpenAPI; -import io.swagger.v3.parser.OpenAPIV3Parser; -import io.swagger.v3.parser.core.models.ParseOptions; -import io.swagger.v3.parser.core.models.SwaggerParseResult; -import java.io.File; -import java.io.IOException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Locale; -import java.util.TimeZone; - -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.CsvSource; -import org.junit.jupiter.params.provider.ValueSource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import static org.junit.jupiter.api.Assertions.*; - - -class ExporterTests extends AbstractBoatEngineTestBase { - - Logger log = LoggerFactory.getLogger(ExporterTests.class); - - @BeforeAll - static void setupLocale() { - Locale.setDefault(Locale.ENGLISH); - TimeZone.setDefault(TimeZone.getTimeZone("Europe/London")); - } - - @ParameterizedTest - @ValueSource(strings = {"/raml-examples/backbase-wallet/presentation-client-api.raml", - "/raml-examples/backbase-wallet/presentation-xml-client-api.raml", - "/raml-examples/backbase-wallet/presentation-client-api-duplicate-operation-id.raml"}) - void testExportOfDifferentSchema(String fileName) throws Exception { - File inputFile = getFile(fileName); - OpenAPI openAPI = Exporter.export(inputFile, true, new ArrayList<>()); - String export = SerializerUtils.toYamlString(openAPI); - validateExport(export); - } - - @Test - void normalizeNameTests() { - String s = Utils.normalizeSchemaName("BatchUpload-GET-Response"); - assertEquals("BatchuploadGetResponse", s); - s = Utils.normalizeSchemaName("batchUpload-GET-Response"); - assertEquals("BatchuploadGetResponse", s); - } - - @Test - void testWalletPresentation() throws Exception { - File inputFile = getFile("/raml-examples/backbase-wallet/presentation-client-api.raml"); - OpenAPI openAPI = Exporter.export(inputFile, new ExporterOptions() - .addJavaTypeExtensions(true) - .convertExamplesToYaml(true) - .transformers(Collections.singletonList(new Decomposer()))); - String export = SerializerUtils.toYamlString(openAPI); - SwaggerParseResult swaggerParseResult = validateExport(export); - assertNotNull(swaggerParseResult.getOpenAPI().getPaths().get("/client-api/v1/wallet/paymentcards")); - assertNotNull(swaggerParseResult.getOpenAPI().getPaths().get("/client-api/v1/wallet/paymentcards/{cardId}")); - assertNotNull(swaggerParseResult.getOpenAPI().getPaths().get("/client-api/v1/patch")); - } - - - - @Test - void testMarkupDocumentation() throws IOException, ExportException { - File inputFile = getFile("/raml-examples/backbase-wallet/presentation-markup-documentation-client.raml"); - OpenAPI openAPI = Exporter.export(inputFile, true, new ArrayList<>()); - String export = SerializerUtils.toYamlString(openAPI); - validateExport(export); - - String cleanmarkup = Exporter.cleanupMarkdownString(markup()); - assertFalse(cleanmarkup.startsWith("##")); - } - - private String markup(){ - return "## Innovation Layer / Bi-Modal\n" + - " Web API facade on to Alainn's SOA Architecture. Designed to be the central point of access to all business process level SOAP services.\n" + - "\n" + - " # Resource Hierarchy\n" + - "\n" + - " The resources are in part independent of the user browsing them\n" + - "\n" + - " * /items\n" + - " * /brands"; - } - - @ParameterizedTest - @CsvSource( { - "/raml-examples/invalid-ramls/empty.raml, Error validation RAML", - "/raml-examples/invalid-ramls/invalid-types.raml, Error validation RAML", - "/raml-examples/backbase-wallet/presentation-service-api-invalid-missing-ref.raml, Cannot dereference json schema from type: application/json", - "/raml-examples/backbase-wallet/presentation-service-api-invalid-ref.raml, Cannot dereference json schema from type: application/json" - }) - void testErrorCatching(String inputFileName, String expected) { - File inputFile = getFile(inputFileName); - - try { - Exporter.export(inputFile, new ExporterOptions() - .addJavaTypeExtensions(true) - .convertExamplesToYaml(true) - .transformers(Collections.singletonList(new Decomposer()))); - fail("expected ExportException to be thrown"); - } catch (ExportException e){ - assertEquals(expected,e.getMessage()); - } - } - - @Test - void testWalletIntegration() throws Exception { - File inputFile = getFile("/raml-examples/backbase-wallet/presentation-integration-api.raml"); - OpenAPI openAPI = Exporter.export(inputFile, new ExporterOptions() - .addJavaTypeExtensions(true) - .convertExamplesToYaml(true) - .transformers(Collections.singletonList(new Decomposer()))); - String export = SerializerUtils.toYamlString(openAPI); - SwaggerParseResult swaggerParseResult = validateExport(export); - assertNotNull(swaggerParseResult.getOpenAPI().getPaths().get("/integration-api/v1/items")); - } - - @Test - void testWalletService() throws Exception { - File inputFile = getFile("/raml-examples/backbase-wallet/presentation-service-api.raml"); - OpenAPI openAPI = Exporter.export(inputFile, new ExporterOptions() - .addJavaTypeExtensions(true) - .convertExamplesToYaml(true) - .transformers(Collections.singletonList(new Decomposer()))); - String export = SerializerUtils.toYamlString(openAPI); - SwaggerParseResult swaggerParseResult = validateExport(export); - assertNotNull( - swaggerParseResult.getOpenAPI().getPaths().get("/service-api/v1/wallet/admin/{userId}/paymentcards")); - } - - - @ParameterizedTest - @ValueSource(strings = {"/raml-examples/others/banking-api/api.raml", - "/raml-examples/backbase-wallet/presentation-client-api.raml", - "/raml-examples/backbase-wallet/presentation-client-api-extension.raml"}) - void testExportWithDifferentApis(String apiFile) throws Exception { - - File inputFile = getFile(apiFile); - OpenAPI openAPI = Exporter.export(inputFile, true, Collections.singletonList(new Decomposer())); - String export = SerializerUtils.toYamlString(openAPI); - validateExport(export); - } - - - @ParameterizedTest - @CsvSource({ - "/openapi/error-catching/bad-export-api/openapi.yaml, Error validation RAML", - "/raml-examples/invalid-ramls, Failed to export ramlTypes" - }) - void testExportErrorCatching(String fileName, String expected) throws IOException { - File inputFile = getFile(fileName); - try{ - Exporter.export(inputFile, true, Collections.singletonList(new Decomposer())); - fail("expected ExportExpectation to be thrown"); - }catch (ExportException e){ - assertEquals(expected,e.getMessage()); - } - - } - -// void testExporterBodyConversion(){ -// new Exporter().convertExamples(); -// } - - protected SwaggerParseResult validateExport(String export) throws IOException, ExportException { - if (export == null) { - throw new ExportException("Invalid Export"); - } - - String child = "openapi.yaml"; - - writeOutput(export, child); - - OpenAPIV3Parser openAPIParser = new OpenAPIV3Parser(); - ParseOptions parseOptions = new ParseOptions(); - SwaggerParseResult swaggerParseResult = openAPIParser.readContents(export, new ArrayList<>(), parseOptions); - for (String message : swaggerParseResult.getMessages()) { - log.error("Error parsing Open API: {}", message); - } - assertTrue(swaggerParseResult.getMessages().isEmpty()); - - return swaggerParseResult; - } - - - protected File getFile(String name) { - URL resource = getClass().getResource(name); - assert resource != null; - return new File(resource.getFile()); - } - - -} diff --git a/boat-engine/src/test/java/com/backbase/oss/boat/LoaderTests.java b/boat-engine/src/test/java/com/backbase/oss/boat/LoaderTests.java deleted file mode 100644 index 02aac20d9..000000000 --- a/boat-engine/src/test/java/com/backbase/oss/boat/LoaderTests.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.backbase.oss.boat; - -import com.backbase.oss.boat.loader.*; - -import java.io.File; -import org.junit.jupiter.api.Test; -import org.raml.v2.api.loader.ResourceUriCallback; - -import static org.junit.jupiter.api.Assertions.assertThrows; - -class LoaderTests extends AbstractBoatEngineTestBase { - - @Test - void testRamlResourceLoaderException() { - File root = new File("src/test/resources/openapi/error-catching"); - File base = new File("src/test/resources/openapi/error-catching"); - String resourceName = "empty-directory"; - RamlResourceLoader ramlResourceLoader = new RamlResourceLoader(base, root); - assertThrows(RamlLoaderException.class, () -> ramlResourceLoader.fetchResource(resourceName)); - - - } - - - @Test - void testOpenApiLoader() { - assertThrows(OpenAPILoaderException.class,()->OpenAPILoader.load("src/test/resources/openapi/error-catching/empty-directory")); - } - - - - @Test - void testCatchingResourceLoader() { - File root = new File("src/test/resources/openapi/error-catching"); - File base = new File("src/test/resources/openapi/error-catching"); - String resourceName = "empty-directory"; - CachingResourceLoader cachingResourceLoader = new CachingResourceLoader(new RamlResourceLoader(base, root)); - assertThrows(RamlLoaderException.class, () -> cachingResourceLoader.fetchResource(resourceName)); - - - } - - -} diff --git a/boat-engine/src/test/java/com/backbase/oss/boat/UtilTests.java b/boat-engine/src/test/java/com/backbase/oss/boat/UtilTests.java index 3cde7cc86..28861d953 100644 --- a/boat-engine/src/test/java/com/backbase/oss/boat/UtilTests.java +++ b/boat-engine/src/test/java/com/backbase/oss/boat/UtilTests.java @@ -2,14 +2,11 @@ import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; - -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URL; import lombok.SneakyThrows; import org.junit.jupiter.api.Test; -import javax.validation.constraints.AssertFalse; +import java.net.MalformedURLException; +import java.net.URL; import static org.junit.Assert.assertFalse; import static org.junit.jupiter.api.Assertions.assertEquals; diff --git a/boat-engine/src/test/resources/logback.xml b/boat-engine/src/test/resources/logback.xml index ccc8f9324..5f9af4edc 100644 --- a/boat-engine/src/test/resources/logback.xml +++ b/boat-engine/src/test/resources/logback.xml @@ -7,6 +7,4 @@ - - \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/.gitignore b/boat-engine/src/test/resources/raml-examples/.gitignore deleted file mode 100644 index 3191f4a82..000000000 --- a/boat-engine/src/test/resources/raml-examples/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -.DS_STORE -**/*.html diff --git a/boat-engine/src/test/resources/raml-examples/README.md b/boat-engine/src/test/resources/raml-examples/README.md deleted file mode 100644 index c6f7d36bd..000000000 --- a/boat-engine/src/test/resources/raml-examples/README.md +++ /dev/null @@ -1,5 +0,0 @@ -Current RAML Versions: RAML 1.0 - -# RAML Examples - -This repository contains valid RAML examples. These examples are not only part of the spec, but also represent RAML features in different scenarios. diff --git a/boat-engine/src/test/resources/raml-examples/annotations/advanced.raml b/boat-engine/src/test/resources/raml-examples/annotations/advanced.raml deleted file mode 100644 index d356fbb4c..000000000 --- a/boat-engine/src/test/resources/raml-examples/annotations/advanced.raml +++ /dev/null @@ -1,33 +0,0 @@ -#%RAML 1.0 -title: Illustrating annotations -mediaType: application/json -annotationTypes: - deprecated: nil - experimental: string | nil - feedbackRequested: string? - testHarness: - type: string # This line may be omitted as it's the default type - badge: # This annotation type, too, allows string values - clearanceLevel: - properties: - level: - enum: [ low, medium, high ] - required: true - signature: - pattern: "\\d{3}-\\w{12}" - required: true -/groups: - (experimental): - (feedbackRequested): -/users: - (testHarness): usersTest - (badge): tested.gif - (clearanceLevel): - level: high - signature: 230-ghtwvfrs1itr - get: - (deprecated): - (experimental): - (feedbackRequested): Feedback committed! - responses: - 200: diff --git a/boat-engine/src/test/resources/raml-examples/annotations/annotation-targets.raml b/boat-engine/src/test/resources/raml-examples/annotations/annotation-targets.raml deleted file mode 100644 index 71ca9e880..000000000 --- a/boat-engine/src/test/resources/raml-examples/annotations/annotation-targets.raml +++ /dev/null @@ -1,25 +0,0 @@ -#%RAML 1.0 -title: Illustrating allowed targets -mediaType: application/json -annotationTypes: - meta-resource-method: - allowedTargets: [ Resource, Method ] - meta-data: - allowedTargets: TypeDeclaration -types: - User: - type: object - (meta-data): on an object; on a data type declaration - properties: - name: - type: string - (meta-data): on a string property -/users: - (meta-resource-method): on a resource - get: - (meta-resource-method): on a method - responses: - 200: - body: - type: User[] - (meta-data): on a body diff --git a/boat-engine/src/test/resources/raml-examples/annotations/simple-annotations.raml b/boat-engine/src/test/resources/raml-examples/annotations/simple-annotations.raml deleted file mode 100644 index d51c6f7de..000000000 --- a/boat-engine/src/test/resources/raml-examples/annotations/simple-annotations.raml +++ /dev/null @@ -1,21 +0,0 @@ -#%RAML 1.0 -title: Illustrating annotations -mediaType: application/json -annotationTypes: - testHarness: - type: string # This line may be omitted as it's the default type - badge: # This annotation type, too, allows string values - clearanceLevel: - properties: - level: - enum: [ low, medium, high ] - required: true - signature: - pattern: "\\d{3}-\\w{12}" - required: true -/users: - (testHarness): usersTest - (badge): tested.gif - (clearanceLevel): - level: high - signature: 230-ghtwvfrs1itr diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/bbt-common-xml.raml b/boat-engine/src/test/resources/raml-examples/backbase-wallet/bbt-common-xml.raml deleted file mode 100644 index b4501d962..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/bbt-common-xml.raml +++ /dev/null @@ -1,6 +0,0 @@ -#%RAML 1.0 Library -schemas: - ObjectWrappingException: !include common-schemas/body/object-wrapping-exception.json -types: - XmlContent: !include common-schemas/body/funky-values.json - TestHeadersResponseBody: !include common-schemas/body/test-headers-response.json \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/bbt-common.raml b/boat-engine/src/test/resources/raml-examples/backbase-wallet/bbt-common.raml deleted file mode 100644 index 2800d790b..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/bbt-common.raml +++ /dev/null @@ -1,7 +0,0 @@ -#%RAML 1.0 Library - schemas: - ObjectWrappingException: !include common-schemas/body/object-wrapping-exception.json - types: - PaymentCard: !include common-schemas/body/paymentcard-item.json - PaymentCards: !include common-schemas/body/paymentcards-get.json - TestHeadersResponseBody: !include common-schemas/body/test-headers-response.json \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/content.xml b/boat-engine/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/content.xml deleted file mode 100644 index f8e38d38e..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/content.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/date-query-params.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/date-query-params.json deleted file mode 100644 index 377c9a7fc..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/date-query-params.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType":"com.backbase.buildingblocks.test.data.DateTimeTestResponse", - "properties": { - "dateTimeOnly": { - "type": "string" - }, - "dateTimeOnlyParsedValue": { - "type": "string" - }, - "dateTime": { - "type": "string" - }, - "dateTimeParsedValue": { - "type": "string" - }, - "dateTime2616": { - "type": "string" - }, - "dateTime2616ParsedValue": { - "type": "string" - }, - "date": { - "type": "string" - }, - "dateParsedValue": { - "type": "string" - }, - "time": { - "type": "string" - }, - "timeParsedValue": { - "type": "string" - }, - "formatDateTime": { - "description": "The dateTime parameter formatted as 'date-time', java.util.Date or java.time.ZoneDateTime", - "type": "string", - "format": "date-time" - }, - "formatDate": { - "description": "The date parameter formatted as 'date', String or java.time.LocalDate", - "type": "string", - "format": "date" - }, - "formatTime": { - "description": "The time parameter formatted as 'time', String or java.time.LocalTime", - "type": "string", - "format": "time" - }, - "formatUtcMillisec": { - "description": "The dateTime parameter formatted as 'date', long", - "type": "string", - "format": "utc-millisec" - } - } -} \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/funky-values.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/funky-values.json deleted file mode 100644 index eff530819..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/funky-values.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType":"com.backbase.buildingblocks.test.data.XmlContent", - "properties": { - "id": { - "type": "string" - }, - "content": { - "type": "xml", - "description": "contents of the request" - }, - "creationDate" : { - "type":"string", - "format":"date-time" - }, - "user" : { - "type" : "string", - "default" : "GUEST" - } - }, - "required": [ - "id", - "content", - "creationDate", - "user" - ] -} \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/object-wrapping-exception.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/object-wrapping-exception.json deleted file mode 100644 index 4a3a7e1dd..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/object-wrapping-exception.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.test.exceptions.ObjectWrappingException", - "properties": { - "message": { - "type": "string" - }, - "data": { - "type": "object" - } - } -} diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/paymentcard-item.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/paymentcard-item.json deleted file mode 100644 index d7efaad73..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/paymentcard-item.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType":"com.backbase.buildingblocks.test.data.PaymentCard", - "properties": { - "id": { - "type": "string" - }, - "pan": { - "type": "string", - "description": "Must be sixteen digits, optionally in blocks of 4 separated by a dash", - "maxLength": 19 - }, - "cvc": { - "type": "string", - "description": "Card Verification Code", - "minLength": 3, - "maxLength": 3 - }, - "startDate": { - "type": "string", - "description": "Must be in one of these four formats: MM/YY MMYY MMYYYY MM/YYYY", - "pattern": "^(0[1-9]|1[0-2])\/?([0-9]{4}|[0-9]{2})$" - }, - "expiryDate": { - "type": "string", - "description": "Must be in one of these four formats: MM/YY MMYY MMYYYY MM/YYYY", - "pattern": "^(0[1-9]|1[0-2])\/?([0-9]{4}|[0-9]{2})$" - }, - "nameOnCard": { - "type": "string" - }, - "creationDate" : { - "type":"string", - "format":"date-time" - }, - "balance" : { - "type": "object", - "$ref": "../../lib/types/schemas/currency.json" - }, - "apr": { - "type": "number", - "javaType": "java.math.BigDecimal" - }, - "cardtype" : { - "type" : "string", - "default" : "CREDIT", - "enum" : ["CREDIT", "DEBIT", "PREPAID"] - } - }, - "required": [ - "id", - "pan", - "cvc", - "startDate", - "expiryDate", - "nameOnCard" - ] -} diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/paymentcards-get.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/paymentcards-get.json deleted file mode 100644 index 16c29a9f7..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/paymentcards-get.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "array", - "items": { - "$ref": "paymentcard-item.json" - } -} \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/test-headers-response.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/test-headers-response.json deleted file mode 100644 index 4c0635545..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/test-headers-response.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType":"com.backbase.buildingblocks.test.data.TestHeadersResponse", - "additionalProperties": false, - "properties": { - "requests": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "url": { - "type": "string" - }, - "headers": { - "type": "object", - "javaType": "java.util.Map" - } - } - } - } - } - } \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/datatypes/Content.raml b/boat-engine/src/test/resources/raml-examples/backbase-wallet/datatypes/Content.raml deleted file mode 100644 index 2b356c685..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/datatypes/Content.raml +++ /dev/null @@ -1,15 +0,0 @@ -#%RAML 1.0 DataType -type: object -properties: - name: - type: string - xml: - attribute: true # serialize it as an XML attribute - name: fullname # attribute should be called fullname - addresses: - type: Address[] - xml: - wrapped: false -examples: - ex1: - !include ../examples/body/Content-Example.raml \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/docs/intro.doc.raml b/boat-engine/src/test/resources/raml-examples/backbase-wallet/docs/intro.doc.raml deleted file mode 100644 index 27953a957..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/docs/intro.doc.raml +++ /dev/null @@ -1,84 +0,0 @@ -#%RAML 1.0 DocumentationItem - title: Introduction - content: | - # Innovation Layer / Bi-Modal - Web API facade on to Alainn's SOA Architecture. Designed to be the central point of access to all business process level SOAP services. - - # Resource Hierarchy - - The resources are in part independent of the user browsing them - - * /items - * /brands - - Others are personal to the authenticated User: - - * /basket - * /wish-list - - All return application/json as Response media-type and all accept only application/json as request media-type. - - # Hypermedia - - The usual form of each response is to include a links array with a number of objects of the form: - - **href**: the url - - **rel**: the meaning of the url (Image, prev, next, self, etc.) - - **label**: UI label - - ```json - "links": [ - { - "href": "https://alainn-omni-channel-api.cloudhub.io/v1.0?pageIndex=28&pageSize=7", - "rel": "next" - }, - { - "href": "https://alainn-omni-channel-api.cloudhub.io/v1.0?pageIndex=14&pageSize=7", - "rel": "prev" - }, - { - "href": "https://alainn-omni-channel-api.cloudhub.io/v1.0/items", - "rel": "self" - } - ] - ``` - - If the response is a collection object, it will have a links array at the root and for each item in the items array. - - ```json - "collection": { - "size": 7, - "items": [ - { - "id": "B003Y60XCC", - "type": "Chemical Hair Dyes", - "name": "L'Oreal Oreor 30 Volume Creme Developer", - "summary": "Fully stabilized formula - Freshness assured", - "brand": "L'Oreal Paris", - "links": [ - { - "href": "https://alainn-omni-channel-api.cloudhub.io/v1.0/items/B003Y60XCC", - "rel": "self" - }, - { - "href": "http://ecx.images-amazon.com/images/I/41MWX6KNAuL._SL75_.jpg", - "rel": "SmallImage" - } - ] - }, - { ... - ``` - - # API Manager - - Registered both as a Service with the OAuth 2.0 Access Token Enforcement policy applied, and also as a Consumer of - - * Item Service - * Customer Service - * Basket Service - * WishList Service - * Order-fulfillment Service - * Registration Service - * Point-of-Sale Service \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/docs/security.doc.raml b/boat-engine/src/test/resources/raml-examples/backbase-wallet/docs/security.doc.raml deleted file mode 100644 index 4946015cd..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/docs/security.doc.raml +++ /dev/null @@ -1,6 +0,0 @@ -#%RAML 1.0 DocumentationItem - title: Security - content: | - # Policy - - Though the API does not implement any authentication / authorisation logic itself, it is dependent on the user details which the Ping Federate Token enforcement policy leaves in context so as to correlate the personal calls mentioned in the section on Resource Hierarchy above. \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/events/add-paymentcard-command.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/events/add-paymentcard-command.json deleted file mode 100644 index 1296ef118..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/events/add-paymentcard-command.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "required": true, - "properties": { - "paymentcard": { - "type": "object", - "$ref": "../common-schemas/body/paymentcard-item.json" - } - } -} \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/events/delete-paymentcard-command.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/events/delete-paymentcard-command.json deleted file mode 100644 index 81b24e284..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/events/delete-paymentcard-command.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "required": true, - "properties": { - "paymentcard": { - "type": "object", - "$ref": "../schemas/body/paymentcard-id.json" - } - } -} \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/events/get-paymentcards-command.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/events/get-paymentcards-command.json deleted file mode 100644 index 2d04dc7a3..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/events/get-paymentcards-command.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "required": true, - "properties": { - "queryParams": { - "type": "object", - "$ref": "../schemas/body/paymentcards-query.json" - } - } -} \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/events/paymentcard-added-event.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/events/paymentcard-added-event.json deleted file mode 100644 index d1efda594..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/events/paymentcard-added-event.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "required": true, - "properties": { - "paymentcard": { - "type": "object", - "$ref": "../common-schemas/body/paymentcard-item.json" - }, - "emitDateTime": { - "description": "The dateTime parameter formatted as 'date-time', java.util.Date or java.time.ZoneDateTime", - "type": "string", - "format": "date-time" - }, - "emitDate": { - "description": "The date parameter formatted as 'date', String or java.time.LocalDate", - "type": "string", - "format": "date" - }, - "emitTime": { - "description": "The time parameter formatted as 'time', String or java.time.LocalTime", - "type": "string", - "format": "time" - }, - "emitMillisec": { - "description": "The dateTime parameter formatted as 'date', long", - "type": "string", - "format": "utc-millisec" - } - } -} \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/events/paymentcard-deleted-event.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/events/paymentcard-deleted-event.json deleted file mode 100644 index d1efda594..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/events/paymentcard-deleted-event.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "required": true, - "properties": { - "paymentcard": { - "type": "object", - "$ref": "../common-schemas/body/paymentcard-item.json" - }, - "emitDateTime": { - "description": "The dateTime parameter formatted as 'date-time', java.util.Date or java.time.ZoneDateTime", - "type": "string", - "format": "date-time" - }, - "emitDate": { - "description": "The date parameter formatted as 'date', String or java.time.LocalDate", - "type": "string", - "format": "date" - }, - "emitTime": { - "description": "The time parameter formatted as 'time', String or java.time.LocalTime", - "type": "string", - "format": "time" - }, - "emitMillisec": { - "description": "The dateTime parameter formatted as 'date', long", - "type": "string", - "format": "utc-millisec" - } - } -} \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/events/paymentcards-retrieved-event.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/events/paymentcards-retrieved-event.json deleted file mode 100644 index 2cbadf471..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/events/paymentcards-retrieved-event.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "required": true, - "properties": { - "queryParams": { - "type": "object", - "$ref": "../schemas/body/paymentcards-query.json" - }, - "results": { - "type": "array", - "items": { - "$ref": "../common-schemas/body/paymentcard-item.json" - } - }, - "emitDateTime": { - "description": "The dateTime parameter formatted as 'date-time', java.util.Date or java.time.ZoneDateTime", - "type": "string", - "format": "date-time" - }, - "emitDate": { - "description": "The date parameter formatted as 'date', String or java.time.LocalDate", - "type": "string", - "format": "date" - }, - "emitTime": { - "description": "The time parameter formatted as 'time', String or java.time.LocalTime", - "type": "string", - "format": "time" - }, - "emitMillisec": { - "description": "The dateTime parameter formatted as 'date', long", - "type": "string", - "format": "utc-millisec" - } - } -} \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/examples/body/Content-Example.raml b/boat-engine/src/test/resources/raml-examples/backbase-wallet/examples/body/Content-Example.raml deleted file mode 100644 index c8756564a..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/examples/body/Content-Example.raml +++ /dev/null @@ -1,7 +0,0 @@ -#%RAML 1.0 NamedExample -value: - name: TestName - addresses: - - - street: TestStreet 1 - city: TestCity \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/examples/body/example-build-info.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/examples/body/example-build-info.json deleted file mode 100644 index 5cc40dd5d..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/examples/body/example-build-info.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "build-info": { - "build.version": "1.1.111-SNAPSHOT" - } -} diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/examples/body/funky-values.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/examples/body/funky-values.json deleted file mode 100644 index 48277702d..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/examples/body/funky-values.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "id": "a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1", - "content": " \n Test Input\n ", - "cvc": "123", - "creationDate": "2011-05-30T12:13:14+03:00", - "user": "GUEST" -} diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/examples/body/item.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/examples/body/item.json deleted file mode 100644 index 89a3fdb1f..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/examples/body/item.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "Example", - "description": "Example description" -} diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/examples/body/paymentcard-created.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/examples/body/paymentcard-created.json deleted file mode 100644 index 3706a5fbc..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/examples/body/paymentcard-created.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "id": "a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1" -} \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/examples/body/paymentcard-item.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/examples/body/paymentcard-item.json deleted file mode 100644 index 72777d92d..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/examples/body/paymentcard-item.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "id": "a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1", - "pan": "5434111122223333", - "cvc": "123", - "startDate": "0116", - "expiryDate": "1219", - "nameOnCard": "Mr Timmy Tester", - "creationDate": "2011-05-30T12:13:14+03:00", - "balance": { - "amount": "1000", - "currencyCode": "EUR" - }, - "apr": 12.75 -} \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/examples/body/paymentcards-get.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/examples/body/paymentcards-get.json deleted file mode 100644 index a7d5dc369..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/examples/body/paymentcards-get.json +++ /dev/null @@ -1,44 +0,0 @@ -[ - { - "id": "a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1", - "pan": "5434111122223333", - "cvc": "123", - "startDate": "0116", - "expiryDate": "1219", - "nameOnCard": "Mr Timmy Tester", - "creationDate": "2011-05-30T12:13:14+03:00", - "balance": { - "amount": "2001", - "currencyCode": "EUR" - }, - "apr": 12.75 - }, - { - "id": "d593c212-70ad-41a6-a547-d5d9232414cb", - "pan": "5434111122224444", - "cvc": "101", - "startDate": "0216", - "expiryDate": "0120", - "nameOnCard": "Mr Timmothy Tester", - "creationDate": "2011-05-30T12:13:14+03:00", - "balance": { - "amount": "4.4399999999999995", - "currencyCode": "GBP" - }, - "apr": 12.75 - }, - { - "id": "9635966b-28e9-4479-8121-bb7bc9beeb62", - "pan": "5434121212121212", - "cvc": "121", - "startDate": "0115", - "expiryDate": "1218", - "nameOnCard": "Mr Timmy Tester", - "creationDate": "2011-05-30T12:13:14+03:00", - "balance": { - "amount": "1981", - "currencyCode": "EUR" - }, - "apr": 12.75 - } -] \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/examples/body/test-headers-response.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/examples/body/test-headers-response.json deleted file mode 100644 index bcc24c481..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/examples/body/test-headers-response.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "requests" : [ - { - "name": "building-blocks-test-wallet-presentation-service", - "url": "/client-api/v1/test/headers", - "headers": { - "correlation-id": [ "2ed475b714a3945a" ], - "accept": [ "application/json" ], - "x-bbt-test": [ "X-BBT-contentVal2" ], - "connection": [ "keep-alive" ] - } - }, - { - "name": "building-blocks-test-wallet-pandp-service", - "url": "/service-api/v1/test/headers", - "headers": { - "authorization": [ "Bearer eyJh" ], - "accept": [ "application/xml, text/xml, application/json, application/*+xml, application/*+json" ], - "content-type": [ "application/json" ], - "x-cxt-user-token": [ "Bearer ey" ], - "x-cxt-remote-user": [ "admin" ], - "x-cxt-requestuuid": [ "72002652-131a-4f28-bd00-16b8080932f5" ], - "correlation-id": [ "2ed475b714a3945a" ], - "x-bbt-test": [ "X-BBT-contentVal2" ] - } - }, - { - "name": "building-blocks-test-wallet-pandp-service", - "url": "/service-api/v1/test/headers", - "headers": { - "authorization": [ "Bearer eyJh" ], - "accept": [ "application/xml, text/xml, application/json, application/*+xml, application/*+json" ], - "content-type": [ "application/json" ], - "x-cxt-user-token": [ "Bearer ey" ], - "x-cxt-remote-user": [ "admin" ], - "x-cxt-requestuuid": [ "72002652-131a-4f28-bd00-16b8080932f5" ], - "correlation-id": [ "2ed475b714a3945a" ], - "x-bbt-test": [ "X-BBT-contentVal2" ] - } - } - ] -} \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/examples/body/test-values-response.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/examples/body/test-values-response.json deleted file mode 100644 index eb5f7bd7b..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/examples/body/test-values-response.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "message": "a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1", - "number": "102.4" -} \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/examples/errors/error.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/examples/errors/error.json deleted file mode 100644 index 26d84f14d..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/examples/errors/error.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "message": "Description of error", - "errorCode" : "EXAMPLE-000001" -} \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/annotations/annotations.raml b/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/annotations/annotations.raml deleted file mode 100644 index a62e83d2b..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/annotations/annotations.raml +++ /dev/null @@ -1,43 +0,0 @@ -#%RAML 1.0 Library - -securitySchemes: -# Custom 'bbAccessControl' security schema -# RAML 1-0 does not allow settings in an x-other security scheme, so no opportunity to describe extra information here - bbAccessControl: - displayName: Backbase Access Control - description: | - This API is secured by DBS Access Control - type: x-bb-access-control - -# RAML annotation and associated types that can be included in API specification files -annotationTypes: - x-bb-api-type: - displayName: API Type - description: | - Signals whether this API endpoint is intended for use by users (HTTP APIs exposed by presentation services) or by - systems (HTTP APIs exposed by inbound integration services) - type: array - items: - type: string - enum: [user, system] - x-bb-access-control: - displayName: Backbase Access Control - description: | - Describes which Resource, Function and Privilege need to be granted to the user to allow access to this API - type: BB-Access-Control - examples: - example1: - "resource": "User" - "function": "Manage Users" - "privilege": "view" - x-bb-api-deprecation: - displayName: API Deprecation - description: | - Signals that the API endpoint is deprecated, providing details on when the API was deprecated, when it will be - removed, the reason for deprecation and a more general description in Markdown that can be used to provide more - information on the deprecation and migration strategy - type: BB-Api-Deprecation - -schemas: - BB-Access-Control: !include ../types/schemas/bb-access-control.json - BB-Api-Deprecation: !include ../types/schemas/bb-api-deprecation.json \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/traits/traits.raml b/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/traits/traits.raml deleted file mode 100644 index a5abeb5e5..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/traits/traits.raml +++ /dev/null @@ -1,131 +0,0 @@ -#%RAML 1.0 Library -schemas: - Bad-Request-Error: !include ../types/schemas/bad-request-error.json - Unauthorized-Error: !include ../types/schemas/unauthorized-error.json - Unauthorized-Alt-Error: !include ../types/schemas/unauthorized-alt-error.json - Not-Acceptable-Error: !include ../types/schemas/not-acceptable-error.json - Internal-Server-Error: !include ../types/schemas/internal-server-error.json - Forbidden-Error: !include ../types/schemas/forbidden-error.json - Not-Found-Error: !include ../types/schemas/not-found-error.json - Unsupported-Media-Type-Error: !include ../types/schemas/unsupported-media-type-error.json -traits: - idempotent: - headers: - X-Request-Id: - description: Correlates HTTP requests between a client and server. - required: false - example: f058ebd6-02f7-4d3f-942e-904344e8cde5 - pageable: - queryParameters: - from: - description: Page Number. Skip over pages of elements by specifying a start value for the query - type: integer - required: false - example: 20 - default: 0 - cursor: - description: | - Record UUID. As an alternative for specifying 'from' this allows to point to the record to start the selection from. - type: string - required: false - example: 76d5be8b-e80d-4842-8ce6-ea67519e8f74 - default: "" - size: - description: | - Limit the number of elements on the response. When used in combination with cursor, the value - is allowed to be a negative number to indicate requesting records upwards from the starting point indicated - by the cursor. - type: integer - required: false - example: 80 - default: 10 - orderable: - queryParameters: - orderBy: - description: | - Order by field: <> - type: string - required: false - direction: - description: Direction - enum: [ASC, DESC] - default: DESC - required: false - challengeable: - headers: - X-MFA: - description: Challenge payload response - required: false - example: sms challenge="123456789" - responses: - 401: - description: Unauthorized - headers: - WWW-Authenticate: - description: Comma separated challenges - required: false - example: sms challenge="", pki challenge="Z8nlwZe0daUNWCWIbfJe3iIgauh" - body: - application/json: - type: Unauthorized-Error - BadRequestError: - responses: - 400: - description: BadRequest - body: - application/json: - type: Bad-Request-Error - UnauthorizedError: - responses: - 401: - description: Unauthorized - headers: - WWW-Authenticate: - description: Indicates the authentication scheme(s) and parameters applicable to the target resource - required: false - example: | - WWW-Authenticate: Newauth realm="apps", type=1, title="Login to \"apps\"", Basic realm="simple" - body: - application/json: - type: Unauthorized-Alt-Error - example: !include ../types/examples/example-unauthorized-alt-error.json - ForbiddenError: - responses: - 403: - description: Forbidden - body: - application/json: - type: Forbidden-Error - example: !include ../types/examples/example-forbidden-error.json - NotFoundError: - responses: - 404: - description: NotFound - body: - application/json: - type: Not-Found-Error - example: !include ../types/examples/example-not-found-error.json - NotAcceptableError: - responses: - 406: - description: NotAcceptable - body: - application/json: - type: Not-Acceptable-Error - example: !include ../types/examples/example-not-acceptable-error.json - UnsupportedMediaTypeError: - responses: - 415: - description: UnsupportedMediaType - body: - application/json: - type: Unsupported-Media-Type-Error - example: !include ../types/examples/example-unsupported-media-type-error.json - InternalServerError: - responses: - 500: - description: InternalServerError - body: - application/json: - type: Internal-Server-Error - example: !include ../types/examples/example-internal-server-error.json diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-bad-request-error.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-bad-request-error.json deleted file mode 100644 index 77243186b..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-bad-request-error.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "message": "Bad Request", - "errors": [ - { - "message": "Value Exceeded. Must be between {min} and {max}.", - "key": "common.api.shoesize", - "context": { - "max": "50", - "min": "1" - } - } - ] -} diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-currency.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-currency.json deleted file mode 100644 index ff365438f..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-currency.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "amount": "1.12", - "currencyCode": "TST" -} \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-forbidden-error.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-forbidden-error.json deleted file mode 100644 index e26366a7c..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-forbidden-error.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "message": "Access to requested resource denied.", - "errors": [ - { - "message": "Resource access denied due to an insufficient user quota of {quota}.", - "key": "common.api.quota", - "context": { - "quota": "someQuota" - } - } - ] -} diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-internal-server-error.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-internal-server-error.json deleted file mode 100644 index c6701087a..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-internal-server-error.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "message": "Description of error" -} \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-not-acceptable-error.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-not-acceptable-error.json deleted file mode 100644 index 0b4ab5da9..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-not-acceptable-error.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "message": "Could not find acceptable representation", - "supportedMediaTypes": [ - "application/json" - ] -} diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-not-found-error.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-not-found-error.json deleted file mode 100644 index 2d6d616b8..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-not-found-error.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "message": "Resource not found.", - "errors": [ - { - "message": "Unable to find the resource requested resource: {resource}.", - "key": "common.api.resource", - "context": { - "resource": "aResource" - } - } - ] -} diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-unauthorized-alt-error.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-unauthorized-alt-error.json deleted file mode 100644 index 6b692d0b3..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-unauthorized-alt-error.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "message": "Access to requested resource denied.", - "errors": [ - { - "message": "Resource access denied due to invalid credentials.", - "key": "common.api.token", - "context": { - "accessToken": "expired" - } - } - ] -} diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-unauthorized-error.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-unauthorized-error.json deleted file mode 100644 index 44f8e8dc6..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-unauthorized-error.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "message": "You are not authorized to perform this action" -} diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-unsupported-media-type-error.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-unsupported-media-type-error.json deleted file mode 100644 index 9dba54d8f..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-unsupported-media-type-error.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "message": "Unsupported media type.", - "errors": [ - { - "message": "The request entity has a media type {mediaType} which the resource does not support.", - "key": "common.api.mediaType", - "context": { - "mediaType": "application/javascript" - } - } - ] -} diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/bad-request-error.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/bad-request-error.json deleted file mode 100644 index d6314386c..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/bad-request-error.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.presentation.errors.BadRequestException", - "properties": { - "message": { - "type": "string", - "description": "Any further information" - }, - "errors": { - "type": "array", - "description": "Detailed error information", - "items": { - "$ref": "error-item.json" - } - } - }, - "required": [ - "message" - ] -} diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/bb-access-control.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/bb-access-control.json deleted file mode 100644 index 629f43147..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/bb-access-control.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "resource": { - "type": "string", - "description": "Resource being protected, e.g. 'User'" - }, - "function": { - "type": "string", - "description": "Business function, e.g. 'Manage Users'" - }, - "privilege": { - "type": "string", - "description": "The privilege required, e.g. 'view'" - } - }, - "required": [ - "resource", - "function", - "privilege" - ] -} diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/bb-api-deprecation.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/bb-api-deprecation.json deleted file mode 100644 index 9d7339566..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/bb-api-deprecation.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "deprecatedFromVersion": { - "type": "string", - "description": "Version of the product from which the endpoint has been deprecated and should no longer be used" - }, - "removedFromVersion": { - "type": "string", - "description": "Version of the product from which the API endpoint will be removed" - }, - "reason": { - "type": "string", - "description": "The reason the API endpoint was deprecated" - }, - "description": { - "type": "string", - "description": "Any further information, e.g. migration information" - } - }, - "required": [ - "deprecatedFromVersion", - "removedFromVersion", - "reason", - "description" - ] -} diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/currency.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/currency.json deleted file mode 100644 index 457bd84ed..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/currency.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "title": "Monetary Amount", - "description": "Schema defining monetary amount in given currency.", - "javaType": "com.backbase.rest.spec.common.types.Currency", - "properties": { - "amount": { - "type": "string", - "javaType": "java.math.BigDecimal", - "description": "The amount in the specified currency" - }, - "currencyCode": { - "type": "string", - "description": "The alpha-3 code (complying with ISO 4217) of the currency that qualifies the amount", - "pattern": "^[A-Z]{3}$" - } - }, - "required": [ - "amount", - "currencyCode" - ] -} \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/error-item.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/error-item.json deleted file mode 100644 index 4868a1047..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/error-item.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "description": "A validation error", - "javaInterfaces": [ - "java.io.Serializable", - "Cloneable" - ], - "properties": { - "message": { - "type": "string", - "description": "Default Message. Any further information." - }, - "key": { - "type": "string", - "description": "{capability-name}.api.{api-key-name}. For generated validation errors this is the path in the document the error resolves to. e.g. object name + '.' + field" - }, - "context": { - "type": "object", - "description": "Context can be anything used to construct localised messages.", - "javaType": "java.util.Map" - } - } -} diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/forbidden-error.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/forbidden-error.json deleted file mode 100644 index 671b17956..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/forbidden-error.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.presentation.errors.ForbiddenException", - "properties": { - "message": { - "type": "string", - "description": "Any further information" - }, - "errors": { - "type": "array", - "description": "Detailed error information", - "items": { - "$ref": "error-item.json" - } - } - } -} diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/internal-server-error.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/internal-server-error.json deleted file mode 100644 index d7d6cafd8..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/internal-server-error.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.presentation.errors.InternalServerErrorException", - "description": "Represents HTTP 500 Internal Server Error", - "properties": { - "message": { - "type": "string", - "description": "Further Information" - } - }, - "required": [ - "message" - ] -} \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/not-acceptable-error.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/not-acceptable-error.json deleted file mode 100644 index f39202d2b..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/not-acceptable-error.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.presentation.errors.NotAcceptableException", - "properties": { - "message": { - "type": "string" - }, - "supportedMediaTypes": { - "type": "array", - "description": "List of supported media types for this endpoint", - "items": { - "type": "string" - } - } - } -} diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/not-found-error.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/not-found-error.json deleted file mode 100644 index 3ce00ba4f..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/not-found-error.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.presentation.errors.NotFoundException", - "properties": { - "message": { - "type": "string", - "description": "Any further information" - }, - "errors": { - "type": "array", - "description": "Detailed error information", - "items": { - "$ref": "error-item.json" - } - } - } -} diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/unauthorized-alt-error.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/unauthorized-alt-error.json deleted file mode 100644 index 388b7326b..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/unauthorized-alt-error.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.presentation.errors.UnauthorizedException", - "properties": { - "message": { - "type": "string", - "description": "Any further information" - }, - "errors": { - "type": "array", - "description": "Detailed error information", - "items": { - "$ref": "error-item.json" - } - } - } -} diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/unauthorized-error.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/unauthorized-error.json deleted file mode 100644 index e29e4b1b8..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/unauthorized-error.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "message": { - "type": "string" - } - }, - "examples": { - "example": { - "message": "unauthorized " - } - }, - "required": [ - "message" - ] -} diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/unsupported-media-type-error.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/unsupported-media-type-error.json deleted file mode 100644 index 87e2ebba6..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/unsupported-media-type-error.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.presentation.errors.UnsupportedMediaTypeException", - "properties": { - "message": { - "type": "string", - "description": "Any further information" - }, - "errors": { - "type": "array", - "description": "Detailed error information", - "items": { - "$ref": "error-item.json" - } - } - } -} diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/presentation-client-api-duplicate-operation-id.raml b/boat-engine/src/test/resources/raml-examples/backbase-wallet/presentation-client-api-duplicate-operation-id.raml deleted file mode 100644 index a877d3a0f..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/presentation-client-api-duplicate-operation-id.raml +++ /dev/null @@ -1,146 +0,0 @@ -#%RAML 1.0 ---- -#=============================================================== -# Messages - RAML example http://raml.org/ -# References: -# - RAML Specification - https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md -#=============================================================== -title: Jobs Test Client API -uses: - traits: lib/traits/traits.raml - bb: lib/annotations/annotations.raml - common: bbt-common-xml.raml -version: v1 -baseUri: "client-api/{version}" -mediaType: [application/json, application/xml] -protocols: [ HTTP, HTTPS ] -types: - Song: !include schemas/body/song-type.xsd - Person: - properties: - name: - xml: - attribute: true # serialize it as an XML attribute - name: "fullname" # attribute should be called fullname - addresses: - type: Address[] - xml: - wrapped: true # serialize it into its own ... XML element - age: number - birthday: date-only - other: any - Address: - properties: - street: string - city: string - examples: - example1: - strict: false - value: - street: "sweetums" - city: "Pawnee" - example2: - strict: false - value: - street: "copy paper" - city: "Staples" - customFile: - type: file - fileTypes: ['*/*'] # any file type allowed - maxLength: 1048576 - unionType: - type: integer|boolean - - CustomDate: - type: datetime-only - facets: - onlyFutureDates?: boolean # optional in `PossibleMeetingDate` - noHolidays: boolean # required in `PossibleMeetingDate` - User: - properties: - firstname: string - lastname: - type: string|nil - example: Doe - required: false - songId: - type: string - maxLength: 15 - examples: - example: "1890-8541-0423" -annotationTypes: - deprecated: - properties: - date: datetime - deprecatedBy: User - comment: nil | string - -#=============================================================== -# API resource definitions -#=============================================================== -securedBy: [ bb.bbAccessControl ] -(bb.x-bb-api-type): [user] -/jobs: - displayName: Jobs - post: - description: Create a Job - body: - application/xml: - schema: | - - - - - - - - - - examples: - example: | - - Test Input - - responses: - 200: - body: - application/xml: - schema: !include common-schemas/body/content.xml -/customer: - post: - body: - application/xml: - schema: !include schemas/body/request.xsd - responses: - 200: - body: - application/xml: - type: Person | nil -/songs: - displayName: Songs - description: Access to all songs inside the music world library. - /{songId}: - uriParameters: - songId: - type: string - examples: - example: "1890-8541-0423" - /{songId}: - get: - responses: - 200: - body: - application/xml: - schema: !include schemas/body/song.xsd - /customer: - post: - body: - application/xml: - schema: !include schemas/body/request.xsd - responses: - 200: - body: - application/xml: - type: Person | nil diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/presentation-client-api-extension.raml b/boat-engine/src/test/resources/raml-examples/backbase-wallet/presentation-client-api-extension.raml deleted file mode 100644 index 92e98889f..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/presentation-client-api-extension.raml +++ /dev/null @@ -1,78 +0,0 @@ -#%RAML 1.0 Extension -# File located at: -# /extensions/en_US/additionalResources.raml -extends: ./presentation-client-api.raml -usage: This extension defines additional resources for version 2 of the API. -version: v2 -types: - Address: - properties: - street: string - city: string - examples: - example1: - strict: false - value: - street: "sweetums" - city: "Pawnee" - example2: - strict: false - value: - street: "copy paper" - city: "Staples" -/wallet: - displayName: Wallet - /paymentcards: - displayName: Payment Cards - get: - (bb.x-bb-access-control): - resource: WALLET - function: MANAGE_PAYMENT_CARDS - privilege: READ_PAYMENT_CARD - is: [traits.BadRequestError, traits.NotAcceptableError, traits.orderable: {fieldsList: nameOnCard}, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: "Returns available payment card details for user, optionally filtered by nameOnCard" - queryParameters: - nameOnCard: - description: "Filter by the cardholder's name (case-insensitive), can be the first one or more characters of one of the words/names" - required: false - type: string - example: "Smi" - dateTimeOnly: - description: Creation date in datetime-only format - required: false - type: datetime-only - example: 2017-10-04T14:54:36 - dateTime: - description: Creation date in Zoned RFC3339 Date-time format - required: false - type: datetime - format: rfc3339 - example: 2017-10-04T14:54:36Z - dateTime2616: - description: Zoned RFC2616 Date-time param example - required: false - type: datetime - format: rfc2616 - example: Wed, 4 Jul 2001 12:08:56 PDT - date: - description: Date-only param example - required: false - type: date-only - example: 2017-10-04 - time: - description: time-only param example - required: false - type: time-only - cardHolderAddress: - description: return all payment card infomation - type: Address - required: false - responses: - 200: - body: - application/json: - type: common.PaymentCards - examples: - example: !include examples/body/paymentcards-get.json - text/csv: - application/xml: \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/presentation-client-api.raml b/boat-engine/src/test/resources/raml-examples/backbase-wallet/presentation-client-api.raml deleted file mode 100644 index 7f9a84d70..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/presentation-client-api.raml +++ /dev/null @@ -1,228 +0,0 @@ -#%RAML 1.0 ---- -#=============================================================== -# Messages - RAML example http://raml.org/ -# References: -# - RAML Specification - https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md -#=============================================================== -title: Wallet Test Client API -uses: - traits: lib/traits/traits.raml - bb: lib/annotations/annotations.raml - common: bbt-common.raml -version: v1 -baseUri: "client-api/{version}" -mediaType: application/json -protocols: [ HTTP, HTTPS ] -#=============================================================== -# API resource definitions -#=============================================================== -securedBy: [ bb.bbAccessControl ] -(bb.x-bb-api-type): [user] -/wallet: - displayName: Wallet - /paymentcards: - displayName: Payment Cards - get: - (bb.x-bb-access-control): - resource: WALLET - function: MANAGE_PAYMENT_CARDS - privilege: READ_PAYMENT_CARD - is: [traits.BadRequestError, traits.NotAcceptableError, traits.orderable: {fieldsList: nameOnCard}, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: "Returns available payment card details for user, optionally filtered by nameOnCard" - queryParameters: - nameOnCard: - description: "Filter by the cardholder's name (case-insensitive), can be the first one or more characters of one of the words/names" - required: false - type: string - example: "Smi" - dateTimeOnly: - description: Creation date in datetime-only format - required: false - type: datetime-only - example: 2017-10-04T14:54:36 - dateTime: - description: Creation date in Zoned RFC3339 Date-time format - required: false - type: datetime - format: rfc3339 - example: 2017-10-04T14:54:36Z - dateTime2616: - description: Zoned RFC2616 Date-time param example - required: false - type: datetime - format: rfc2616 - example: Wed, 4 Jul 2001 12:08:56 PDT - date: - description: Date-only param example - required: false - type: date-only - example: 2017-10-04 - time: - description: time-only param example - required: false - type: time-only - example: 14:54:36 - responses: - 200: - body: - application/json: - type: common.PaymentCards - examples: - example: !include examples/body/paymentcards-get.json - text/csv: - application/xml: - post: - (bb.x-bb-access-control): - resource: WALLET - function: MANAGE_PAYMENT_CARDS - privilege: WRITE_PAYMENT_CARD - is: [traits.BadRequestError, traits.InternalServerError, traits.idempotent, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Adds a payment card to the user's wallet - body: - application/json: - type: common.PaymentCard - example: !include examples/body/paymentcard-item.json - responses: - 201: - description: request to create payment card accepted - body: - application/json: - schema: !include schemas/body/paymentcard-id.json - example: !include examples/body/paymentcard-created.json - /{cardId}: - displayName: Payment Card - uriParameters: - cardId: - type: string - get: - (bb.x-bb-access-control): - resource: WALLET - function: MANAGE_PAYMENT_CARDS - privilege: READ_PAYMENT_CARD - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Returns details of a specific payment card - displayName: Get payment card - responses: - 200: - body: - application/json: - type: common.PaymentCard - example: !include examples/body/paymentcard-item.json - delete: - (bb.x-bb-access-control): - resource: WALLET - function: MANAGE_PAYMENT_CARDS - privilege: DELETE_PAYMENT_CARD - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Deletes a payment card with a given id - responses: - 204: - description: Payment card is succesfully deleted -/bbt: - description: API for test operations. - displayName: BBT - /build-info: - get: - description: "Build Information" - responses: - 200: - body: - application/json: - schema: !include schemas/body/build-info.json - example: !include examples/body/example-build-info.json -/patch: - description: PATCH endpoint for test operations - displayName: patch - patch: - is: [traits.BadRequestError, traits.InternalServerError, traits.idempotent, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: "Patch Test" - responses: - 200: - body: - text/plain: - schema: !include schemas/body/patch-response.json -/test: - /required-boolean-query-param: - description: arbitrary tests - displayName: required boolean query param - get: - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - queryParameters: - bool: - description: Required boolean parameter with no default value - required: true - type: boolean - example: false - responses: - 200: - body: - application/json: - schema: !include schemas/body/test-response-extension.json - /values: - description: Test Values - displayName: Test Values - get: - is: [traits.InternalServerError] - responses: - 200: - body: - application/json: - schema: !include schemas/body/test-values-response.json - example: !include examples/body/test-values-response.json - /headers: - description: Test header propagation - displayName: Test header propagation - get: - is: [traits.InternalServerError] - queryParameters: - addHops: - description: number of additional hops to perform - required: false - type: integer - responses: - 200: - body: - application/json: - schema: common.TestHeadersResponseBody - example: !include examples/body/test-headers-response.json - /date-query-params: - description: | - Tests for date/time query parameters in service-apis. Sends the same query parameters to the equivalent endpoint - in the pandp service which echoes the given values back in the response body. Values echoed by the pandp service - are then returned in the response to this request. - displayName: dateQueryParam - get: - queryParameters: - dateTimeOnly: - description: Creation date in datetime-only format - required: false - type: datetime-only - example: 2017-10-04T14:54:36 - dateTime: - description: Creation date in Zoned RFC3339 Date-time format - required: false - type: datetime - format: rfc3339 - example: 2017-10-04T14:54:36Z - dateTime2616: - description: Zoned RFC2616 Date-time param example - required: false - type: datetime - format: rfc2616 - example: Wed, 4 Jul 2001 12:08:56 PDT - date: - description: Date-only param example - required: false - type: date-only - example: 2017-10-04 - time: - description: time-only param example - required: false - type: time-only - example: 14:54:36 - responses: - 200: - body: - application/json: - schema: !include common-schemas/body/date-query-params.json diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/presentation-integration-api.raml b/boat-engine/src/test/resources/raml-examples/backbase-wallet/presentation-integration-api.raml deleted file mode 100644 index 2b2c5f204..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/presentation-integration-api.raml +++ /dev/null @@ -1,33 +0,0 @@ -#%RAML 1.0 ---- -#=============================================================== -# Integration API example -#=============================================================== -title: Example -version: v1 -baseUri: "integration-api/{version}" -mediaType: application/json -protocols: [ HTTP, HTTPS ] -#=============================================================== -# API documentation - Overall documentation. -#=============================================================== -documentation: - - title: Example - content: Test Schema to test an integration-api - -#=============================================================== -# API resource definitions -#=============================================================== -/items: - description: Retrieve all items. - displayName: items - uriParameters: null - get: - description: "Retrieve list of all items." - responses: - 200: - description: Test Schema - body: - application/json: - schema: !include schemas/body/item.json - example: !include examples/body/item.json \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/presentation-markup-documentation-client.raml b/boat-engine/src/test/resources/raml-examples/backbase-wallet/presentation-markup-documentation-client.raml deleted file mode 100644 index af9ce3ea7..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/presentation-markup-documentation-client.raml +++ /dev/null @@ -1,132 +0,0 @@ -#%RAML 1.0 ---- -#=============================================================== -# Messages - RAML example http://raml.org/ -# References: -# - RAML Specification - https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md -#=============================================================== -title: Wallet Test Service API -description: This is an api -documentation: - - !include docs/intro.doc.raml - - !include docs/security.doc.raml - -uses: - traits: lib/traits/traits.raml - bb: lib/annotations/annotations.raml - common: bbt-common.raml -version: v1 -baseUri: "service-api/{version}" -mediaType: application/json -protocols: [ HTTP, HTTPS ] -#=============================================================== -# API resource definitions -#=============================================================== -securedBy: [ bb.bbAccessControl ] -(bb.x-bb-api-type): [system] -/wallet: - displayName: WalletService - /admin/{userId}: - uriParameters: - userId: - type: string - /paymentcards: - displayName: Payment Cards - get: - is: [traits.BadRequestError, traits.NotAcceptableError, traits.orderable: {fieldsList: nameOnCard}, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: "Returns available payment card details for user, optionally filtered by nameOnCard" - queryParameters: - nameOnCard: - description: "Filter by the cardholder's name (case-insensitive), can be the first one or more characters of one of the words/names" - required: false - type: string - example: "Smi" - dateTimeOnly: - description: Creation date in datetime-only format - required: false - type: datetime-only - example: 2017-10-04T14:54:36 - dateTime: - description: Creation date in Zoned RFC3339 Date-time format - required: false - type: datetime - format: rfc3339 - example: 2017-10-04T14:54:36Z - dateTime2616: - description: Zoned RFC2616 Date-time param example - required: false - type: datetime - format: rfc2616 - example: Wed, 4 Jul 2001 12:08:56 PDT - date: - description: Date-only param example - required: false - type: date-only - example: 2017-10-04 - time: - description: time-only param example - required: false - type: time-only - example: 14:54:36 - responses: - 200: - body: - application/json: - type: common.PaymentCards - example: !include examples/body/paymentcards-get.json - post: - is: [traits.BadRequestError, traits.InternalServerError, traits.idempotent, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Adds a payment card to the user's wallet - body: - application/json: - type: common.PaymentCard - example: !include examples/body/paymentcard-item.json - responses: - 201: - description: request to create payment card accepted - body: - application/json: - schema: !include schemas/body/paymentcard-id.json - example: !include examples/body/paymentcard-created.json - /{cardId}: - displayName: Payment Card - uriParameters: - cardId: - type: string - get: - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Returns details of a specific payment card - responses: - 200: - body: - application/json: - type: common.PaymentCard - example: !include examples/body/paymentcard-item.json - delete: - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Deletes a payment card with a given id - (bb.x-bb-api-deprecation): - deprecatedFromVersion: v2 - removedFromVersion: v3 - reason: Endpoints is going to be covered to post. - description: Here we can put an elaborate description for deprecated items - responses: - 204: - description: Payment card is succesfully deleted -/testQuery: - /required-boolean-query-param: - description: arbitrary tests - displayName: required boolean query param - get: - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - queryParameters: - bool: - description: Required boolean parameter with no default value - required: true - type: boolean - example: false - responses: - 200: - body: - application/json: - schema: !include schemas/body/test-response.json \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/presentation-service-api-invalid-missing-ref.raml b/boat-engine/src/test/resources/raml-examples/backbase-wallet/presentation-service-api-invalid-missing-ref.raml deleted file mode 100644 index 68f42db6b..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/presentation-service-api-invalid-missing-ref.raml +++ /dev/null @@ -1,122 +0,0 @@ -#%RAML 1.0 ---- -#=============================================================== -# Messages - RAML example http://raml.org/ -# References: -# - RAML Specification - https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md -#=============================================================== -title: Wallet Test Service API -uses: - traits: lib/traits/traits.raml - bb: lib/annotations/annotations.raml - common: bbt-common.raml -version: v1 -baseUri: "service-api/{version}" -mediaType: application/json -protocols: [ HTTP, HTTPS ] -#=============================================================== -# API resource definitions -#=============================================================== -securedBy: [ bb.bbAccessControl ] -(bb.x-bb-api-type): [system] -/wallet: - displayName: WalletService - /admin/{userId}: - uriParameters: - userId: - type: string - /paymentcards: - displayName: Payment Cards - get: - is: [traits.BadRequestError, traits.NotAcceptableError, traits.orderable: {fieldsList: nameOnCard}, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: "Returns available payment card details for user, optionally filtered by nameOnCard" - queryParameters: - nameOnCard: - description: "Filter by the cardholder's name (case-insensitive), can be the first one or more characters of one of the words/names" - required: false - type: string - example: "Smi" - dateTimeOnly: - description: Creation date in datetime-only format - required: false - type: datetime-only - example: 2017-10-04T14:54:36 - dateTime: - description: Creation date in Zoned RFC3339 Date-time format - required: false - type: datetime - format: rfc3339 - example: 2017-10-04T14:54:36Z - dateTime2616: - description: Zoned RFC2616 Date-time param example - required: false - type: datetime - format: rfc2616 - example: Wed, 4 Jul 2001 12:08:56 PDT - date: - description: Date-only param example - required: false - type: date-only - example: 2017-10-04 - time: - description: time-only param example - required: false - type: time-only - example: 14:54:36 - responses: - 200: - body: - application/json: - type: common.PaymentCards - example: !include examples/body/paymentcards-get.json - post: - is: [traits.BadRequestError, traits.InternalServerError, traits.idempotent, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Adds a payment card to the user's wallet - body: - application/json: - type: common.PaymentCard - example: !include examples/body/paymentcard-item.json - responses: - 201: - description: request to create payment card accepted - body: - application/json: - schema: !include schemas/body/paymentcard-id.json - example: !include examples/body/paymentcard-created.json - /{cardId}: - displayName: Payment Card - uriParameters: - cardId: - type: string - get: - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Returns details of a specific payment card - responses: - 200: - body: - application/json: - type: common.PaymentCard - example: !include examples/body/paymentcard-item.json - delete: - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Deletes a payment card with a given id - responses: - 204: - description: Payment card is succesfully deleted -/testQuery: - /required-boolean-query-param: - description: arbitrary tests - displayName: required boolean query param - get: - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - queryParameters: - bool: - description: Required boolean parameter with no default value - required: true - type: boolean - example: false - responses: - 200: - body: - application/json: - schema: !include schemas/body/test-response-invalid-ref.json \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/presentation-service-api-invalid-ref.raml b/boat-engine/src/test/resources/raml-examples/backbase-wallet/presentation-service-api-invalid-ref.raml deleted file mode 100644 index 928e82506..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/presentation-service-api-invalid-ref.raml +++ /dev/null @@ -1,122 +0,0 @@ -#%RAML 1.0 ---- -#=============================================================== -# Messages - RAML example http://raml.org/ -# References: -# - RAML Specification - https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md -#=============================================================== -title: Wallet Test Service API -uses: - traits: lib/traits/traits.raml - bb: lib/annotations/annotations.raml - common: bbt-common.raml -version: v1 -baseUri: "service-api/{version}" -mediaType: application/json -protocols: [ HTTP, HTTPS ] -#=============================================================== -# API resource definitions -#=============================================================== -securedBy: [ bb.bbAccessControl ] -(bb.x-bb-api-type): [system] -/wallet: - displayName: WalletService - /admin/{userId}: - uriParameters: - userId: - type: string - /paymentcards: - displayName: Payment Cards - get: - is: [traits.BadRequestError, traits.NotAcceptableError, traits.orderable: {fieldsList: nameOnCard}, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: "Returns available payment card details for user, optionally filtered by nameOnCard" - queryParameters: - nameOnCard: - description: "Filter by the cardholder's name (case-insensitive), can be the first one or more characters of one of the words/names" - required: false - type: string - example: "Smi" - dateTimeOnly: - description: Creation date in datetime-only format - required: false - type: datetime-only - example: 2017-10-04T14:54:36 - dateTime: - description: Creation date in Zoned RFC3339 Date-time format - required: false - type: datetime - format: rfc3339 - example: 2017-10-04T14:54:36Z - dateTime2616: - description: Zoned RFC2616 Date-time param example - required: false - type: datetime - format: rfc2616 - example: Wed, 4 Jul 2001 12:08:56 PDT - date: - description: Date-only param example - required: false - type: date-only - example: 2017-10-04 - time: - description: time-only param example - required: false - type: time-only - example: 14:54:36 - responses: - 200: - body: - application/json: - type: common.PaymentCards - example: !include examples/body/paymentcards-get.json - post: - is: [traits.BadRequestError, traits.InternalServerError, traits.idempotent, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Adds a payment card to the user's wallet - body: - application/json: - type: common.PaymentCard - example: !include examples/body/paymentcard-item.json - responses: - 201: - description: request to create payment card accepted - body: - application/json: - schema: !include schemas/body/paymentcard-id.json - example: !include examples/body/paymentcard-created.json - /{cardId}: - displayName: Payment Card - uriParameters: - cardId: - type: string - get: - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Returns details of a specific payment card - responses: - 200: - body: - application/json: - type: common.PaymentCard - example: !include examples/body/paymentcard-item.json - delete: - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Deletes a payment card with a given id - responses: - 204: - description: Payment card is succesfully deleted -/testQuery: - /required-boolean-query-param: - description: arbitrary tests - displayName: required boolean query param - get: - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - queryParameters: - bool: - description: Required boolean parameter with no default value - required: true - type: boolean - example: false - responses: - 200: - body: - application/json: - schema: !include schemas/body/test-response-missing-ref.json \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/presentation-service-api.raml b/boat-engine/src/test/resources/raml-examples/backbase-wallet/presentation-service-api.raml deleted file mode 100644 index 244b9b91b..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/presentation-service-api.raml +++ /dev/null @@ -1,124 +0,0 @@ -#%RAML 1.0 ---- -#=============================================================== -# Messages - RAML example http://raml.org/ -# References: -# - RAML Specification - https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md -#=============================================================== -title: Wallet Test Service API -uses: - traits: lib/traits/traits.raml - bb: lib/annotations/annotations.raml - common: bbt-common.raml -version: v1 -baseUri: "service-api/{version}" -mediaType: application/json -protocols: [ HTTP, HTTPS ] -#=============================================================== -# API resource definitions -#=============================================================== -securedBy: [ bb.bbAccessControl ] -(bb.x-bb-api-type): [system] -/wallet: - displayName: WalletService - /admin/{userId}: - /paymentcards: - displayName: Payment Cards - get: - is: [traits.BadRequestError, traits.NotAcceptableError, traits.orderable: {fieldsList: nameOnCard}, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: "Returns available payment card details for user, optionally filtered by nameOnCard" - queryParameters: - nameOnCard: - description: "Filter by the cardholder's name (case-insensitive), can be the first one or more characters of one of the words/names" - required: false - type: string - example: "Smi" - dateTimeOnly: - description: Creation date in datetime-only format - required: false - type: datetime-only - example: 2017-10-04T14:54:36 - dateTime: - description: Creation date in Zoned RFC3339 Date-time format - required: false - type: datetime - format: rfc3339 - example: 2017-10-04T14:54:36Z - dateTime2616: - description: Zoned RFC2616 Date-time param example - required: false - type: datetime - format: rfc2616 - example: Wed, 4 Jul 2001 12:08:56 PDT - date: - description: Date-only param example - required: false - type: date-only - example: 2017-10-04 - time: - description: time-only param example - required: false - type: time-only - example: 14:54:36 - responses: - 200: - body: - application/json: - type: common.PaymentCards - example: !include examples/body/paymentcards-get.json - post: - is: [traits.BadRequestError, traits.InternalServerError, traits.idempotent, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Adds a payment card to the user's wallet - body: - application/json: - type: common.PaymentCard - example: !include examples/body/paymentcard-item.json - responses: - 201: - description: request to create payment card accepted - body: - application/json: - schema: !include schemas/body/paymentcard-id.json - example: !include examples/body/paymentcard-created.json - /{cardId}: - displayName: Payment Card - uriParameters: - cardId: - type: string - get: - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Returns details of a specific payment card - responses: - 200: - body: - application/json: - type: common.PaymentCard - example: !include examples/body/paymentcard-item.json - delete: - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Deletes a payment card with a given id - (bb.x-bb-api-deprecation): - deprecatedFromVersion: v2 - removedFromVersion: v3 - reason: Endpoints is going to be covered to post. - description: Here we can put an elaborate description for deprecated items - responses: - 204: - description: Payment card is succesfully deleted -/testQuery: - /required-boolean-query-param: - description: arbitrary tests - displayName: required boolean query param - get: - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - queryParameters: - bool: - description: Required boolean parameter with no default value - required: true - type: boolean - example: false - responses: - 200: - body: - application/json: - schema: !include schemas/body/test-response.json \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/presentation-xml-client-api.raml b/boat-engine/src/test/resources/raml-examples/backbase-wallet/presentation-xml-client-api.raml deleted file mode 100644 index a1be3f4b5..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/presentation-xml-client-api.raml +++ /dev/null @@ -1,135 +0,0 @@ -#%RAML 1.0 ---- -#=============================================================== -# Messages - RAML example http://raml.org/ -# References: -# - RAML Specification - https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md -#=============================================================== -title: Jobs Test Client API -uses: - traits: lib/traits/traits.raml - bb: lib/annotations/annotations.raml - common: bbt-common-xml.raml -version: v1 -baseUri: "client-api/{version}" -mediaType: [application/json, application/xml] -protocols: [ HTTP, HTTPS ] -types: - Song: !include schemas/body/song-type.xsd - Person: - properties: - name: - xml: - attribute: true # serialize it as an XML attribute - name: "fullname" # attribute should be called fullname - addresses: - type: Address[] - xml: - wrapped: true # serialize it into its own ... XML element - age: number - birthday: date-only - other: any - Address: - properties: - street: string - city: string - examples: - example1: - strict: false - value: - street: "sweetums" - city: "Pawnee" - example2: - strict: false - value: - street: "copy paper" - city: "Staples" - customFile: - type: file - fileTypes: ['*/*'] # any file type allowed - maxLength: 1048576 - unionType: - type: integer|boolean - - CustomDate: - type: datetime-only - facets: - onlyFutureDates?: boolean # optional in `PossibleMeetingDate` - noHolidays: boolean # required in `PossibleMeetingDate` - User: - properties: - firstname: string - lastname: - type: string|nil - example: Doe - required: false - songId: - type: string - maxLength: 15 - examples: - example: "1890-8541-0423" -annotationTypes: - deprecated: - properties: - date: datetime - deprecatedBy: User - comment: nil | string - -#=============================================================== -# API resource definitions -#=============================================================== -securedBy: [ bb.bbAccessControl ] -(bb.x-bb-api-type): [user] -/jobs: - displayName: Jobs - post: - description: Create a Job - body: - application/xml: - schema: | - - - - - - - - - - examples: - example: | - - Test Input - - responses: - 200: - body: - application/xml: - schema: !include common-schemas/body/content.xml -/customer: - post: - body: - application/xml: - schema: !include schemas/body/request.xsd - responses: - 200: - body: - application/xml: - type: Person | nil -/songs: - displayName: Songs - description: Access to all songs inside the music world library. - /{songId}: - uriParameters: - songId: - type: string - examples: - example: "1890-8541-0423" - get: - responses: - 200: - body: - application/xml: - schema: !include schemas/body/song.xsd diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/build-info.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/build-info.json deleted file mode 100644 index 8ed0b3e16..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/build-info.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "build-info": { - "javaType": "java.util.Map", - "type": "object" - } - } -} diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/item.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/item.json deleted file mode 100644 index 176cb4743..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/item.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "description": "this models a simple item.", - "properties": { - "name": { - "type": "string" - }, - "description": { - "type": "string" - } - }, - "required": [ - "name" - ] -} diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/patch-response.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/patch-response.json deleted file mode 100644 index a427bffd5..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/patch-response.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "message": { - "type": "string" - } - } -} \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/paymentcard-id.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/paymentcard-id.json deleted file mode 100644 index cc79400fb..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/paymentcard-id.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "id": { - "type": "string" - } - } -} \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/paymentcards-query.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/paymentcards-query.json deleted file mode 100644 index fd251f418..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/paymentcards-query.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "nameOnCard": { - "type": "string" - }, - "creationDate" : { - "type": "string", - "format": "date-time" - } - }, - "required": [] -} \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/request.xsd b/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/request.xsd deleted file mode 100644 index d9cbf6b9d..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/request.xsd +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/song-type.xsd b/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/song-type.xsd deleted file mode 100644 index 398949635..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/song-type.xsd +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/song.xsd b/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/song.xsd deleted file mode 100644 index 6a7988aa9..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/song.xsd +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/test-response-extension.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/test-response-extension.json deleted file mode 100644 index 9100112cc..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/test-response-extension.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "extends": { - "$ref": "test-response.json" - }, - "properties": { - "status": { - "type": "string", - "description": "Http status codes available for response", - "enum": [ - "200", - "400", - "404", - "500" - ], - "javaEnumNames": [ - "HTTP_STATUS_OK", - "HTTP_STATUS_BAD_REQUEST", - "HTTP_STATUS_NOT_FOUND", - "HTTP_STATUS_INTERNAL_SERVER_ERROR" - ] - }, - "polymorphic": { - "type": "object", - "properties": { - "street_address": { "type": "string" }, - "city": { "type": "string" }, - "state": { "type": "string" } - }, - "anyOf": [ - { "type": "string", "maxLength": 5 }, - { "type": "number", "minimum": 0 } - ] - } - } -} \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/test-response-invalid-ref.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/test-response-invalid-ref.json deleted file mode 100644 index cef106730..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/test-response-invalid-ref.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "message": { - "type": "string" - }, - "invalid-ref": { - "$ref": "idontexist.json" - } - } -} \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/test-response-missing-ref.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/test-response-missing-ref.json deleted file mode 100644 index f13021dcd..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/test-response-missing-ref.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "message": { - "type": "string" - }, - "missing-ref": { - "$ref": "" - } - } -} \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/test-response.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/test-response.json deleted file mode 100644 index a427bffd5..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/test-response.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "message": { - "type": "string" - } - } -} \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/test-values-response.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/test-values-response.json deleted file mode 100644 index 2b72f6913..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/body/test-values-response.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "message": { - "type": "string" - }, - "number": { - "type": "string", - "javaType": "java.math.BigDecimal" - } - } -} \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/errors/error.json b/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/errors/error.json deleted file mode 100644 index 362d7e72d..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/schemas/errors/error.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "message": { - "type": "string" - }, - "errorCode": { - "type": "string" - } - }, - "required": [ - "message", - "errorCode" - ] -} \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/backbase-wallet/xml-common.raml b/boat-engine/src/test/resources/raml-examples/backbase-wallet/xml-common.raml deleted file mode 100644 index 281655811..000000000 --- a/boat-engine/src/test/resources/raml-examples/backbase-wallet/xml-common.raml +++ /dev/null @@ -1,7 +0,0 @@ -#%RAML 1.0 Library -schemas: - ObjectWrappingException: !include common-schemas/body/object-wrapping-exception.json -types: - PaymentCard: !include common-schemas/body/paymentcard-item.json - PaymentCards: !include common-schemas/body/paymentcards-get.json - TestHeadersResponseBody: !include common-schemas/body/test-headers-response.json \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/defining-examples/organisation-api.raml b/boat-engine/src/test/resources/raml-examples/defining-examples/organisation-api.raml deleted file mode 100644 index 4a9bb9388..000000000 --- a/boat-engine/src/test/resources/raml-examples/defining-examples/organisation-api.raml +++ /dev/null @@ -1,47 +0,0 @@ -#%RAML 1.0 -title: API with Examples - -types: - User: - type: object - properties: - name: string - lastname: string - example: - name: Bob - lastname: Marley - Org: - type: object - properties: - name: string - address?: string - value? : string -/organisation: - post: - headers: - UserID: - description: the identifier for the user that posts a new organisation - type: string - example: SWED-123 # single scalar example - body: - application/json: - type: Org - example: # single request body example - value: # needs to be declared since type contains 'value' property - name: Doe Enterprise - value: Silver - get: - description: Returns an organisation entity. - responses: - 201: - body: - application/json: - type: Org - examples: - acme: - name: Acme - softwareCorp: - value: # validate against the available facets for the map value of an example - name: Software Corp - address: 35 Central Street - value: Gold # validate against instance of the `value` property diff --git a/boat-engine/src/test/resources/raml-examples/defining-examples/using-strict.raml b/boat-engine/src/test/resources/raml-examples/defining-examples/using-strict.raml deleted file mode 100644 index d6f6094cc..000000000 --- a/boat-engine/src/test/resources/raml-examples/defining-examples/using-strict.raml +++ /dev/null @@ -1,14 +0,0 @@ -#%RAML 1.0 -title: Using strict=false API - -/person: - get: - queryParameters: - sort?: - type: string[] - description: | - The sort order in the format `property,property[,asc|desc]`. The default sort direction is ascending. - Can be used multiple times for different properties. - example: - strict: false - value: ?sort=givenName&sort=surname,asc diff --git a/boat-engine/src/test/resources/raml-examples/fragments/datatype/arrays/book.dataType.raml b/boat-engine/src/test/resources/raml-examples/fragments/datatype/arrays/book.dataType.raml deleted file mode 100644 index be8fe96cc..000000000 --- a/boat-engine/src/test/resources/raml-examples/fragments/datatype/arrays/book.dataType.raml +++ /dev/null @@ -1,10 +0,0 @@ -#%RAML 1.0 DataType - -usage: provides a type to store a book that has multiple chapters - -type: object -properties: - name: string - chapters: - type: array - items: !include chapter.dataType.raml diff --git a/boat-engine/src/test/resources/raml-examples/fragments/datatype/arrays/chapter.dataType.raml b/boat-engine/src/test/resources/raml-examples/fragments/datatype/arrays/chapter.dataType.raml deleted file mode 100644 index c5c511f82..000000000 --- a/boat-engine/src/test/resources/raml-examples/fragments/datatype/arrays/chapter.dataType.raml +++ /dev/null @@ -1,8 +0,0 @@ -#%RAML 1.0 DataType - -usage: provides information about a single chapter - -type: object -properties: - name: string - content: string diff --git a/boat-engine/src/test/resources/raml-examples/fragments/datatype/general/Email.dataType.raml b/boat-engine/src/test/resources/raml-examples/fragments/datatype/general/Email.dataType.raml deleted file mode 100644 index f8b74e6ce..000000000 --- a/boat-engine/src/test/resources/raml-examples/fragments/datatype/general/Email.dataType.raml +++ /dev/null @@ -1,5 +0,0 @@ -#%RAML 1.0 DataType - -usage: provides a pattern to validate against an email string - -pattern: ^.+@.+\..+$ diff --git a/boat-engine/src/test/resources/raml-examples/fragments/datatype/general/Url.dataType.raml b/boat-engine/src/test/resources/raml-examples/fragments/datatype/general/Url.dataType.raml deleted file mode 100644 index d9847586a..000000000 --- a/boat-engine/src/test/resources/raml-examples/fragments/datatype/general/Url.dataType.raml +++ /dev/null @@ -1,5 +0,0 @@ -#%RAML 1.0 DataType - -usage: provides a pattern to validate against an an HTTP string - -pattern: ^http:// diff --git a/boat-engine/src/test/resources/raml-examples/fragments/datatype/general/User.dataType.raml b/boat-engine/src/test/resources/raml-examples/fragments/datatype/general/User.dataType.raml deleted file mode 100644 index 9af421dcb..000000000 --- a/boat-engine/src/test/resources/raml-examples/fragments/datatype/general/User.dataType.raml +++ /dev/null @@ -1,11 +0,0 @@ -#%RAML 1.0 DataType - -usage: provides a type that stores user information - -description: A simple User -properties: - name: string - email: !include Email.dataType.raml - homepage: - description: User's homepage - type: !include Url.dataType.raml diff --git a/boat-engine/src/test/resources/raml-examples/fragments/datatype/general/api.raml b/boat-engine/src/test/resources/raml-examples/fragments/datatype/general/api.raml deleted file mode 100644 index 38c633f73..000000000 --- a/boat-engine/src/test/resources/raml-examples/fragments/datatype/general/api.raml +++ /dev/null @@ -1,5 +0,0 @@ -#%RAML 1.0 -title: DataType Include Example - -types: - User: !include User.dataType.raml # include external type declaration diff --git a/boat-engine/src/test/resources/raml-examples/fragments/datatype/inheritance/Animal.dataType.raml b/boat-engine/src/test/resources/raml-examples/fragments/datatype/inheritance/Animal.dataType.raml deleted file mode 100644 index 32dea3e8b..000000000 --- a/boat-engine/src/test/resources/raml-examples/fragments/datatype/inheritance/Animal.dataType.raml +++ /dev/null @@ -1,6 +0,0 @@ -#%RAML 1.0 DataType - -properties: - name: string - kind: string -discriminator: kind diff --git a/boat-engine/src/test/resources/raml-examples/fragments/datatype/inheritance/Dog.dataType.raml b/boat-engine/src/test/resources/raml-examples/fragments/datatype/inheritance/Dog.dataType.raml deleted file mode 100644 index 7b94f06b5..000000000 --- a/boat-engine/src/test/resources/raml-examples/fragments/datatype/inheritance/Dog.dataType.raml +++ /dev/null @@ -1,9 +0,0 @@ -#%RAML 1.0 DataType - -uses: - animal-lib: animal.lib.raml - -type: animal-lib.Animal -properties: - canBark: boolean -discriminatorValue: dog diff --git a/boat-engine/src/test/resources/raml-examples/fragments/datatype/inheritance/animal.lib.raml b/boat-engine/src/test/resources/raml-examples/fragments/datatype/inheritance/animal.lib.raml deleted file mode 100644 index 0accc1acd..000000000 --- a/boat-engine/src/test/resources/raml-examples/fragments/datatype/inheritance/animal.lib.raml +++ /dev/null @@ -1,4 +0,0 @@ -#%RAML 1.0 Library - -types: - Animal: !include Animal.dataType.raml diff --git a/boat-engine/src/test/resources/raml-examples/fragments/extensions/api.raml b/boat-engine/src/test/resources/raml-examples/fragments/extensions/api.raml deleted file mode 100644 index 1523d82ea..000000000 --- a/boat-engine/src/test/resources/raml-examples/fragments/extensions/api.raml +++ /dev/null @@ -1,14 +0,0 @@ -#%RAML 1.0 -title: My API -mediaType: application/json -baseUri: https://production.com -protocols: [ HTTPS ] - -uses: - lib: types.lib.raml - -/users: - get: - responses: - 200: - body: lib.User[] diff --git a/boat-engine/src/test/resources/raml-examples/fragments/extensions/dev-api.raml b/boat-engine/src/test/resources/raml-examples/fragments/extensions/dev-api.raml deleted file mode 100644 index 032e4224f..000000000 --- a/boat-engine/src/test/resources/raml-examples/fragments/extensions/dev-api.raml +++ /dev/null @@ -1,26 +0,0 @@ -#%RAML 1.0 Extension -extends: api.raml # RAML API definition to extend - -title: My Dev API # DEVELOPMENT-only API definition -baseUri: http://localhost # "localhost" baseUri -protocols: [ HTTP, HTTPS ] # allow unsecured HTTP - -uses: - lib: types.lib.raml - -types: - User: # add a few development-only properties to the "User" type - type: lib.User - properties: - id: integer - role: string - -/users: - post: # add a POST method to be able to create "test users" - body: User - - /{id}: # /users/{id} resource to view all of a given user's data set - get: - responses: - 200: - body: User diff --git a/boat-engine/src/test/resources/raml-examples/fragments/extensions/types.lib.raml b/boat-engine/src/test/resources/raml-examples/fragments/extensions/types.lib.raml deleted file mode 100644 index 4f3291372..000000000 --- a/boat-engine/src/test/resources/raml-examples/fragments/extensions/types.lib.raml +++ /dev/null @@ -1,11 +0,0 @@ -#%RAML 1.0 Library - -types: - Person: - properties: - name: string - age: integer - User: - type: Person - properties: - email: string \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/fragments/overlays/librarybooks.raml b/boat-engine/src/test/resources/raml-examples/fragments/overlays/librarybooks.raml deleted file mode 100644 index 54f78283d..000000000 --- a/boat-engine/src/test/resources/raml-examples/fragments/overlays/librarybooks.raml +++ /dev/null @@ -1,50 +0,0 @@ -#%RAML 1.0 - -title: Book Library API -documentation: - - title: Introduction - content: Automated access to books - - title: Licensing - content: Please respect copyrights on our books. -/books: - description: sdngdfsljgksdhjgs - get: - description: The collection of library books - responses: - 200: - body: - application/json: - schema: | - { - "title": "Song", - "type": "object", - "properties": { - "description?": { - "type": "string" - }, - "title": { - "type": "string", - "example": "Yesterday" - }, - "artist": { - "type": "object", - "properties": { - "name": { - "type": "string", - "example": "The Beatles" - }, - "is_band": { - "type": "boolean", - "example": "true" - } - } - } - }, - "$schema": "http://json-schema.org/draft-04/schema#" - } - example: | - { - - } -/library: - get: diff --git a/boat-engine/src/test/resources/raml-examples/fragments/overlays/spanish.overlay.raml b/boat-engine/src/test/resources/raml-examples/fragments/overlays/spanish.overlay.raml deleted file mode 100644 index bc0a9973a..000000000 --- a/boat-engine/src/test/resources/raml-examples/fragments/overlays/spanish.overlay.raml +++ /dev/null @@ -1,12 +0,0 @@ -#%RAML 1.0 Overlay - -usage: Spanish localization -extends: librarybooks.raml -documentation: - - title: Introducción - content: El acceso automatizado a los libros - - title: Licencias - content: Por favor respeta los derechos de autor de los libros -/books: - get: - description: La colección de libros de la biblioteca diff --git a/boat-engine/src/test/resources/raml-examples/fragments/resourcetype/api.raml b/boat-engine/src/test/resources/raml-examples/fragments/resourcetype/api.raml deleted file mode 100644 index 5046c0c86..000000000 --- a/boat-engine/src/test/resources/raml-examples/fragments/resourcetype/api.raml +++ /dev/null @@ -1,8 +0,0 @@ -#%RAML 1.0 -title: Products API - -resourceTypes: - collection: !include collection.resourceType.raml # include ResourceType fragment - -/products: - type: collection # reference to global resource type declaration diff --git a/boat-engine/src/test/resources/raml-examples/fragments/resourcetype/collection.resourceType.raml b/boat-engine/src/test/resources/raml-examples/fragments/resourcetype/collection.resourceType.raml deleted file mode 100644 index e8713c045..000000000 --- a/boat-engine/src/test/resources/raml-examples/fragments/resourcetype/collection.resourceType.raml +++ /dev/null @@ -1,13 +0,0 @@ -#%RAML 1.0 ResourceType - -usage: Use this to describe resource that list items # explains the purpose of this fragment - -description: A collection of <> # resource-level description -get: - description: Retrieve all <> # method-level description -post: - description: Add an <> # method-level description - responses: - 201: - headers: - Location: diff --git a/boat-engine/src/test/resources/raml-examples/helloworld/helloworld.raml b/boat-engine/src/test/resources/raml-examples/helloworld/helloworld.raml deleted file mode 100644 index d81c6ce7e..000000000 --- a/boat-engine/src/test/resources/raml-examples/helloworld/helloworld.raml +++ /dev/null @@ -1,23 +0,0 @@ -#%RAML 1.0 -title: Hello world # required title - -/helloworld: # optional resource - get: # HTTP method declaration - responses: # declare a response - 200: # HTTP status code - body: # declare content of response - application/json: # media type - type: | # structural definition of a response (schema or type) - { - "title": "Hello world Response", - "type": "object", - "properties": { - "message": { - "type": "string" - } - } - } - example: | # example of how a response looks - { - "message": "Hello world" - } diff --git a/boat-engine/src/test/resources/raml-examples/invalid-ramls/empty.raml b/boat-engine/src/test/resources/raml-examples/invalid-ramls/empty.raml deleted file mode 100644 index e69de29bb..000000000 diff --git a/boat-engine/src/test/resources/raml-examples/invalid-ramls/invalid-types.raml b/boat-engine/src/test/resources/raml-examples/invalid-ramls/invalid-types.raml deleted file mode 100644 index b320d1606..000000000 --- a/boat-engine/src/test/resources/raml-examples/invalid-ramls/invalid-types.raml +++ /dev/null @@ -1,58 +0,0 @@ -#%RAML 1.0 -title: My API with Types -mediaType: application/json -types: - Org: - type: object - $ref: i do not exist - Person: - type: object - discriminator: kind # reference to the `kind` property of `Person` - properties: - firstname: string - lastname: string - title?: string - kind: string # may be used to differenciate between classes that extend from `Person` - Phone: - type: string - pattern: "^[0-9|-]+$" # defines pattern for the content of type `Phone` - Manager: - type: Person # inherits all properties from type `Person` - properties: - reports: Person[] # inherits all properties from type `Person`; array type where `[]` is a shortcut - phone: Phone - Admin: - type: Person # inherits all properties from type `Person` - properties: - clearanceLevel: - enum: [ low, high ] - AlertableAdmin: - type: Admin # inherits all properties from type `Admin` - properties: - phone: Phone # inherits all properties from type `Phone`; uses shortcut syntax - Alertable: Manager | AlertableAdmin # union type; either a `Manager` or `AlertableAdmin` -/orgs/{orgId}: - get: - responses: - 200: - body: - application/json: - type: Org # reference to global type definition - example: - onCall: - firstname: nico - lastname: ark - kind: AlertableAdmin - clearanceLevel: low - phone: "12321" - Head: - firstname: nico - lastname: ark - kind: Manager - reports: - - - firstname: nico - lastname: ark - kind: Admin - clearanceLevel: low - phone: "123-23" diff --git a/boat-engine/src/test/resources/raml-examples/libraries/api.raml b/boat-engine/src/test/resources/raml-examples/libraries/api.raml deleted file mode 100644 index a96b723fb..000000000 --- a/boat-engine/src/test/resources/raml-examples/libraries/api.raml +++ /dev/null @@ -1,13 +0,0 @@ -#%RAML 1.0 -title: Main API - -uses: - types-lib: types.lib.raml - -/person: - get: - responses: - 200: - body: - application/json: - type: types-lib.Person diff --git a/boat-engine/src/test/resources/raml-examples/libraries/types.lib.raml b/boat-engine/src/test/resources/raml-examples/libraries/types.lib.raml deleted file mode 100644 index 899f8d5e2..000000000 --- a/boat-engine/src/test/resources/raml-examples/libraries/types.lib.raml +++ /dev/null @@ -1,7 +0,0 @@ -#%RAML 1.0 Library - -types: - Person: - properties: - name: string - age: integer diff --git a/boat-engine/src/test/resources/raml-examples/media-types/defaults/api.raml b/boat-engine/src/test/resources/raml-examples/media-types/defaults/api.raml deleted file mode 100644 index df748bdb3..000000000 --- a/boat-engine/src/test/resources/raml-examples/media-types/defaults/api.raml +++ /dev/null @@ -1,16 +0,0 @@ -#%RAML 1.0 -title: New API -mediaType: [ application/json, application/xml ] -types: - Person: - Another: -/list: - get: - responses: - 200: - body: Person[] -/send: - post: - body: - application/json: - type: Another diff --git a/boat-engine/src/test/resources/raml-examples/media-types/multipart-data/api.raml b/boat-engine/src/test/resources/raml-examples/media-types/multipart-data/api.raml deleted file mode 100644 index b76da3655..000000000 --- a/boat-engine/src/test/resources/raml-examples/media-types/multipart-data/api.raml +++ /dev/null @@ -1,34 +0,0 @@ -#%RAML 1.0 -title: My API - -types: - Image: - type: file - fileTypes: ['image/jpeg', 'image/png'] - HTMLFile: - type: file - fileTypes: ['text/html'] - Text: - type: file - fileTypes: ['text/plain'] - File: Image | HTMLFile | Text - -/files: - post: - body: - multipart/form-data: - properties: - files: - description: The file(s) to be uploaded - required: true - type: File[] - -/images: - get: - body: - multipart/form-data: - properties: - files: - description: The file(s) to be uploaded - required: true - type: File[] diff --git a/boat-engine/src/test/resources/raml-examples/others/alainn-mobile-shopping/api.raml b/boat-engine/src/test/resources/raml-examples/others/alainn-mobile-shopping/api.raml deleted file mode 100644 index 3e2fc90b5..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/alainn-mobile-shopping/api.raml +++ /dev/null @@ -1,92 +0,0 @@ -#%RAML 1.0 -title: Álainn Cosmetics Mobile Orders API -#baseUri: https://alainn-customer-mobile-v1.cloudhub.io/api -baseUri: https://ec2-52-201-242-128.compute-1.amazonaws.com/mocks/1201bcdf-f1a0-4eb3-a002-4f6f817d44cc/api -version: 1 -mediaType: application/json -documentation: - - !include docs/intro.doc.raml - - !include docs/security.doc.raml -uses: - res: modules/resource-types.lib.raml - tra: modules/traits.lib.raml - sec: modules/security.lib.raml - -securedBy: [sec.oauth_2_0] -/items: - type: res.read-only-collection - description: List of all items on sale - get: - is: [tra.searchable, tra.imageable] - /{item}: - type: res.member - get: - is: [tra.imageable] -/my-wish-list: - type: res.collection - post: - description: Add an Item to my Wish List. - /{wish}: - delete: - description: Remove from wish list -/my-basket: - type: res.collection - description: All items ready for purchase - post: - description: Add an Item to my Basket. Of course I may add more than 1 of the same Item. - /checkout: - type: res.controller - description: Orders both pending and fulfilled - /{item}: - delete: - description: Remove item from basket -/mobile-tokens/{mobileType}: - uriParameters: - mobileType: - type: string - enum: [ios, android] - post: - body: - type: - properties: - token: string - example: - token: afdasfas23lkesf -/my-profile: - type: res.base -/brands: - type: res.read-only-collection - get: - queryParameters: - name: - type: string - required: false - example: Deep Steep Honey Bubble Bath -/categories: - type: res.read-only-collection - get: - queryParameters: - name: - type: string - required: false - example: Oils - -/my-orders: - type: res.read-only-collection - delete: - description: Cancel order - patch: - description: 'Modify part of Order: quantity of items, delivery address' -/trending-items: - type: res.read-only-collection - get: - is: [tra.searchable] - /{item}/reviews: - type: res.read-only-collection -/recommendations: - type: res.read-only-collection - description: Recommended Products based on previous purchases -/promotions: - type: res.read-only-collection - get: - is: [tra.searchable] diff --git a/boat-engine/src/test/resources/raml-examples/others/alainn-mobile-shopping/docs/intro.doc.raml b/boat-engine/src/test/resources/raml-examples/others/alainn-mobile-shopping/docs/intro.doc.raml deleted file mode 100644 index f7a81e681..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/alainn-mobile-shopping/docs/intro.doc.raml +++ /dev/null @@ -1,85 +0,0 @@ -#%RAML 1.0 DocumentationItem - title: Introduction - content: | - - # Innovation Layer / Bi-Modal - Web API facade on to Alainn's SOA Architecture. Designed to be the central point of access to all business process level SOAP services. - - # Resource Hierarchy - - The resources are in part independent of the user browsing them - - * /items - * /brands - - Others are personal to the authenticated User: - - * /basket - * /wish-list - - All return application/json as Response media-type and all accept only application/json as request media-type. - - # Hypermedia - - The usual form of each response is to include a links array with a number of objects of the form: - - **href**: the url - - **rel**: the meaning of the url (Image, prev, next, self, etc.) - - **label**: UI label - - ```json - "links": [ - { - "href": "https://alainn-omni-channel-api.cloudhub.io/v1.0?pageIndex=28&pageSize=7", - "rel": "next" - }, - { - "href": "https://alainn-omni-channel-api.cloudhub.io/v1.0?pageIndex=14&pageSize=7", - "rel": "prev" - }, - { - "href": "https://alainn-omni-channel-api.cloudhub.io/v1.0/items", - "rel": "self" - } - ] - ``` - - If the response is a collection object, it will have a links array at the root and for each item in the items array. - - ```json - "collection": { - "size": 7, - "items": [ - { - "id": "B003Y60XCC", - "type": "Chemical Hair Dyes", - "name": "L'Oreal Oreor 30 Volume Creme Developer", - "summary": "Fully stabilized formula - Freshness assured", - "brand": "L'Oreal Paris", - "links": [ - { - "href": "https://alainn-omni-channel-api.cloudhub.io/v1.0/items/B003Y60XCC", - "rel": "self" - }, - { - "href": "http://ecx.images-amazon.com/images/I/41MWX6KNAuL._SL75_.jpg", - "rel": "SmallImage" - } - ] - }, - { ... - ``` - - # API Manager - - Registered both as a Service with the OAuth 2.0 Access Token Enforcement policy applied, and also as a Consumer of - - * Item Service - * Customer Service - * Basket Service - * WishList Service - * Order-fulfillment Service - * Registration Service - * Point-of-Sale Service \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/others/alainn-mobile-shopping/docs/security.doc.raml b/boat-engine/src/test/resources/raml-examples/others/alainn-mobile-shopping/docs/security.doc.raml deleted file mode 100644 index f7b0d554c..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/alainn-mobile-shopping/docs/security.doc.raml +++ /dev/null @@ -1,6 +0,0 @@ -#%RAML 1.0 DocumentationItem - title: Security - content: | - # Policy - - Though the API does not implement any authentication / authorisation logic itself, it is dependent on the user details which the Ping Federate Token enforcement policy leaves in context so as to correlate the personal calls mentioned in the section on Resource Hierarchy above. \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/others/alainn-mobile-shopping/hypermedia.extension.raml b/boat-engine/src/test/resources/raml-examples/others/alainn-mobile-shopping/hypermedia.extension.raml deleted file mode 100644 index da59b1d36..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/alainn-mobile-shopping/hypermedia.extension.raml +++ /dev/null @@ -1,13 +0,0 @@ -#%RAML 1.0 Extension -extends: api.raml - -uses: - ano: modules/annotations.lib.raml - -(ano.hypermedia-plan): - controls: - property: links -/items: - get: - (ano.hypermedia-control): - follow: true diff --git a/boat-engine/src/test/resources/raml-examples/others/alainn-mobile-shopping/modules/annotations.lib.raml b/boat-engine/src/test/resources/raml-examples/others/alainn-mobile-shopping/modules/annotations.lib.raml deleted file mode 100644 index 6fa039a53..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/alainn-mobile-shopping/modules/annotations.lib.raml +++ /dev/null @@ -1,36 +0,0 @@ -#%RAML 1.0 Library - -annotationTypes: - hypermedia-plan: - allowedTargets: [ API, Resource ] - properties: - controls: - description: Inform the (client / client developer) where in the message hypermedia is to be found - properties: - url?: - default: href - semantic?: - default: rel - ui?: - default: label - property: string - permanentUri?: - type: boolean - default: true - hypermedia-control: - allowedTargets: [ TypeDeclaration, Method ] - properties: - method?: - description: Which method should be executed on resource? - default: get - visible?: - type: boolean - description: Should client should provide link to user? - default: true - targetResource?: - type: string - description: Resource as defined in this API - follow?: - type: boolean - description: Should client invoke the url upon reception? - default: false \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/others/alainn-mobile-shopping/modules/resource-types.lib.raml b/boat-engine/src/test/resources/raml-examples/others/alainn-mobile-shopping/modules/resource-types.lib.raml deleted file mode 100644 index 535719bda..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/alainn-mobile-shopping/modules/resource-types.lib.raml +++ /dev/null @@ -1,52 +0,0 @@ -#%RAML 1.0 Library - -uses: - tra: traits.lib.raml - typ: types.lib.raml - - -resourceTypes: - base: - get: - responses: - 200: - body: - application/json: - type: typ.Get<>Response - read-only-collection: - type: base - get: - is: [tra.pageable] - collection: - type: read-only-collection - post: - body: - type: typ.Post<>Request - responses: - 201: - description: Created! - headers: - Location: - description: uri of new resource - type: string - required: true - controller: - post: - responses: - 204: - description: Done! - member: - type: base - put?: - body: - type: typ.Put<>Request - responses: - 204: - description: Modified - patch?: - body: - type: typ.Patch<>Request - delete?: - responses: - 204: - description: Delete diff --git a/boat-engine/src/test/resources/raml-examples/others/alainn-mobile-shopping/modules/security.lib.raml b/boat-engine/src/test/resources/raml-examples/others/alainn-mobile-shopping/modules/security.lib.raml deleted file mode 100644 index a19b6f511..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/alainn-mobile-shopping/modules/security.lib.raml +++ /dev/null @@ -1,28 +0,0 @@ -#%RAML 1.0 Library - -securitySchemes: - oauth_2_0: - description: | - This API supports OAuth 2.0 for authenticating all requests. - type: OAuth 2.0 - describedBy: - headers: - access_token: - description: | - Used to send a valid OAuth 2 access token. Do not use - with the "access_token" query string parameter. - type: string - responses: - 401: - description: | - Bad or expired token. This can happen if the access token - has been revoked or expired. To fix, you should re- - authenticate the user. - 403: - description: | - Bad OAuth request (wrong consumer key, bad nonce, expired - timestamp...). Unfortunately, re-authenticating the user won't help here. - settings: - authorizationUri: http://test-alainn-cosmetics.cloudhub.io/authorize - accessTokenUri: http://test-alainn-cosmetics.cloudhub.io/access-token - authorizationGrants: [ authorization_code ] \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/others/alainn-mobile-shopping/modules/traits.lib.raml b/boat-engine/src/test/resources/raml-examples/others/alainn-mobile-shopping/modules/traits.lib.raml deleted file mode 100644 index 7de3dce4d..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/alainn-mobile-shopping/modules/traits.lib.raml +++ /dev/null @@ -1,37 +0,0 @@ -#%RAML 1.0 Library - -traits: - pageable: - queryParameters: - pageIndex: - type: integer - default: 0 - example: 1 - required: false - pageSize: - type: integer - default: 10 - example: 10 - required: false - searchable: - queryParameters: - name: - type: string - required: false - example: Deep Steep Honey Bubble Bath - type: - type: string - required: false - example: Oils - brand: - type: string - required: false - example: Naturtint - imageable: - queryParameters: - imageType: - description: Comma , separated list just like in example. One alone may be present - type: string - required: false - default: SmallImage - example: TinyImage,SwatchImage,SmallImage,MediumImage,LargeImage \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/others/alainn-mobile-shopping/modules/types.lib.raml b/boat-engine/src/test/resources/raml-examples/others/alainn-mobile-shopping/modules/types.lib.raml deleted file mode 100644 index a2abe05ef..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/alainn-mobile-shopping/modules/types.lib.raml +++ /dev/null @@ -1,267 +0,0 @@ -#%RAML 1.0 Library - -uses: - ano: annotations.lib.raml - -types: - ResourceLink: - properties: - href: string - rel: - enum: [self, next, prev] - method?: - default: get - ImageLink: - properties: - href: string - rel: - enum: [SmallImage, MediumImage, LargeImage] - Item: - properties: - id: string - type?: string - name: string - summary?: string - brand?: string - links: (ResourceLink | ImageLink)[] - Sku: - type: Item - properties: - price: number - sku: string - stockQuantity: integer - - GetItemsResponse: - properties: - links: ResourceLink[] - collection: - properties: - size: integer - items: Item[] - example: - links: - - href: https://alainn-customer-mobile-v1.cloudhub.io/api/items?pageIndex=30&pageSize=10 - rel: next - - href: https://alainn-customer-mobile-v1.cloudhub.io/api/items?pageIndex=10&pageSize=10 - rel: prev - - href: https://alainn-customer-mobile-v1.cloudhub.io/api/items?pageIndex=20&pageSize=10 - rel: self - collection: - size: 2 - items: - - id: B003Y60XCC - type: Chemical Hair Dyes - name: L'Oreal Oreor 30 Volume Creme Developer - brand: L'Oreal Paris - links: - - href: https://alainn-customer-mobile-v1.cloudhub.io/api/items/B003Y60XCC - rel: self - - href: http://ecx.images-amazon.com/images/I/41MWX6KNAuL._SL75_.jpg - rel: SmallImage - - id: B0042YK9F6 - type: Bath Pearls & Flakes - name: Pearlcium Pearl Powder - brand: TheraPure Health Essentials - links: - - href: https://alainn-customer-mobile-v1.cloudhub.io/api/items/B0042YK9F6 - rel: self - - href: http://ecx.images-amazon.com/images/I/316RsE4g09L._SL75_.jpg - rel: SmallImage - - - - - GetItemResponse: - type: Item - properties: - skus: - properties: - size: integer - items: Sku[] - example: - links: - - href: https://localhost:8082/omni-channel-api/v1.0/items/B0044D30Z6 - rel: self - id: B0044D30Z6 - type: Chemical Hair Dyes - name: Garnier HerbaShine Color Creme with Bamboo Extract - brand: Garnier - skus: - size: 2 - items: - - id: B003JTE8JS - name: Garnier Herbashine Haircolor, 630 Light Golden Brown - summary: Only 10 minutes - price: 15.98 - sku: B003JTE8JS - stockQuantity: 3 - links: - - href: https://localhost:8082/omni-channel-api/v1.0/items/B003JTE8JS - rel: self - - href: http://ecx.images-amazon.com/images/I/517QdA0lU9L._SL75_.jpg - rel: SmallImage - - id: B003JTGCRE - name: Garnier HerbaShine Color Creme, with Bamboo Extract, Dark Natural, Brown 400 - summary: Used For Hair Color - price: 12.98 - sku: B003JTGCRE - stockQuantity: 3 - links: - - href: https://localhost:8082/omni-channel-api/v1.0/items/B003JTGCRE - rel: self - - href: http://ecx.images-amazon.com/images/I/610m3duxPEL._SL75_.jpg - rel: SmallImage - - - - GetMyWishListResponse: - type: GetItemsResponse - PostMyWishListRequest: - properties: - sku: string - example: - sku: B004GW14E4 - - - GetMyBasketResponse: - properties: - links: ResourceLink[] - items: - type: array - items: - type: Sku - properties: - quantity: integer - example: - links: - - href: https://localhost:8082/omni-channel-api/v1.0/items/B0044D30Z6 - rel: self - items: - - id: B003JTE8JS - name: Garnier Herbashine Haircolor, 630 Light Golden Brown - summary: Only 10 minutes - price: 15.98 - sku: B003JTE8JS - stockQuantity: 3 - links: - - href: https://localhost:8082/omni-channel-api/v1.0/items/B003JTE8JS - rel: self - - href: http://ecx.images-amazon.com/images/I/517QdA0lU9L._SL75_.jpg - rel: SmallImage - quantity: 5 - - id: B003JTGCRE - name: Garnier HerbaShine Color Creme, with Bamboo Extract, Dark Natural, Brown 400 - summary: Used For Hair Color - price: 12.98 - sku: B003JTGCRE - stockQuantity: 3 - links: - - href: https://localhost:8082/omni-channel-api/v1.0/items/B003JTGCRE - rel: self - - href: http://ecx.images-amazon.com/images/I/610m3duxPEL._SL75_.jpg - rel: SmallImage - quantity: 1 - - PostMyBasketRequest: - properties: - sku: string - quantity: integer - price: number - example: - sku: B0000530ED - quantity: 2 - price: 10.99 - - PostCheckoutRequest: - properties: - pickupLocation: string - items: - type: array - items: - properties: - sku: string - price: number - quantity: integer - example: - pickupLocation: Dublin - items: - - sku: B003JTE8JS - price: 10.99 - quantity: 1 - - sku: B0000530ED - price: 5.99 - quantity: 3 - - GetMyProfileResponse: - properties: - firstName: string - lastName: string - notificationPreferences: - type: array - items: - type: string - enum: [email, mobilePush, sms] - example: - firstName: Nial - lastName: Darbey - notificationPreferences: - - sms - - mobilePush - - GetBrandsResponse: - properties: - links: ResourceLink[] - items: string[] - example: - links: - - href: https://alainn-customer-mobile-v1.cloudhub.io/api/brands/dsf23 - rel: self - items: - - Jerome Russell - - Now Foods - - GetCategoriesResponse: - properties: - links: ResourceLink[] - items: string[] - example: - links: - - href: https://alainn-customer-mobile-v1.cloudhub.io/api/categories/xx22 - rel: self - items: - - Soaps - - Perfumes - GetMyOrdersResponse: - properties: - links: ResourceLink[] - orders: - type: array - items: - properties: - date: datetime - items: - type: array - items: - type: Sku - properties: - quantity: integer - GetRecommendationsResponse: - type: GetItemsResponse - - GetTrendingItemsResponse: - type: GetItemsResponse - - GetPromotionsResponse: - type: GetItemsResponse - - GetReviewsResponse: - properties: - collection: - properties: - size: integer - items: - type: array - items: - properties: - user: string - review: string diff --git a/boat-engine/src/test/resources/raml-examples/others/banking-api/api.raml b/boat-engine/src/test/resources/raml-examples/others/banking-api/api.raml deleted file mode 100755 index 275ddced6..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/banking-api/api.raml +++ /dev/null @@ -1,185 +0,0 @@ -#%RAML 1.0 - -title: ACME Banking HTTP API -version: 1.0 -mediaType: application/json - -uses: - shapes: ./dataTypes/shapes.raml - -traits: - contentCacheable: !include traits/content-cacheable.raml - -resourceTypes: - collection: !include resourceTypes/collection.raml - member: !include resourceTypes/member.raml - -types: - CustomerMemberResponse: shapes.OrganizationData | shapes.PersonData - -securitySchemes: - oauth2_0: !include securitySchemes/oauth2_0.raml - -securedBy: oauth2_0 - -/customers: - displayName: Customer Resource - /corporate: - post: - description: Customer data created correctly for an Organization - body: shapes.NewOrganizationData - /commercial: - post: - description: Customer data created correctly for a Person - body: shapes.NewPersonData - - /{customer_id}: - type: - member: - get-response-type: CustomerMemberResponse - get-response-example: - type: Person - id: "!23456" - lei: 54930084UKLVMY22DS16 - tax_id: "999999999" - email: info@new.org - given_name: Dirk - family_name: Fabian - gender: male - birth_date: 1987-09-30 - address: - address_country: US - address_locality: CA - postal_code: "90003" - patch-response-type: shapes.CustomerPatchData - uriParameters: - customer_id: string - patch: - delete: - /accounts: - type: - collection: - response-type: shapes.BankAccountData - request-type: shapes.NewBankAccountRequestData - /{account_id}: - type: - member: - get-response-type: shapes.BankAccountData - get-response-example: - id: my_account - account_number: "12345667" - accountType: standard - amount: - value: 123.45 - currency: Euro - lei: 54930084UKLVMY22DS16 - fees_and_comissions: no fees - review_state: opened - interest_rate: 12 - annual_interest_rate: 15 - minimum_inflow: - value: 1000 - currency: Euro - overdraft_limit: - value: 500 - currency: Euro - uriParameters: - account_id: string - delete: - /loans: - type: - collection: - response-type: shapes.LoanData - request-type: shapes.NewLoanRequestData - get: - is: [ contentCacheable ] - /{loan_id}: - type: - member: - get-response-type: shapes.LoanData - get-response-example: - id: my_account - account_number: "12345667" - accountType: standard - amount: - value: 500 - currency: Euro - lei: 54930084UKLVMY22DS16 - fees_and_comissions: no fees - review_state: opened - interest_rate: 12 - annual_interest_rate: 15 - minimum_inflow: - value: 500 - currency: Euro - overdraft_limit: - value: 500 - currency: Euro - grace_period: - value: 12m - uriParameters: - loan_id: string - /schedule: - get: - description: Returns the repayments schedule for a Loan - responses: - 200: - body: shapes.RepaymentSpecificationData - /cards: - /debit: - type: - collection: - response-type: shapes.DebitCardData - request-type: shapes.NewDebitCardRequestData - /{card_id}: - type: - member: - get-response-type: shapes.DebitCardData - get-response-example: - id: my_account - lei: 54930084UKLVMY22DS16 - fees_and_comissions: no fees - review_state: opened - cash_back: true - contactless: false - floor_limit: - value: 500 - currency: Euro - uriParameters: - card_id: string - delete: - /credit: - type: - collection: - response-type: shapes.CreditCardData - request-type: shapes.NewCreditCardRequestData - /{card_id}: - type: - member: - get-response-type: shapes.CreditCardData - get-response-example: - id: my_account - amount: - value: 500 - currency: Euro - lei: 54930084UKLVMY22DS16 - cash_back: true - contactless: true - floor_limit: - value: 500 - currency: Euro - fees_and_comissions: no fees - review_state: opened - interest_rate: 12 - annual_interest_rate: 15 - minimum_inflow: - value: 500 - currency: Euro - overdraft_limit: - value: 500 - currency: Euro - grace_period: - value: 12m - uriParameters: - card_id: string - delete: \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/others/banking-api/dataTypes/CustomErrorMessage.raml b/boat-engine/src/test/resources/raml-examples/others/banking-api/dataTypes/CustomErrorMessage.raml deleted file mode 100755 index ef03593c3..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/banking-api/dataTypes/CustomErrorMessage.raml +++ /dev/null @@ -1,5 +0,0 @@ -#%RAML 1.0 DataType -type: object -properties: - statusCode: string - message: string diff --git a/boat-engine/src/test/resources/raml-examples/others/banking-api/dataTypes/shapes.raml b/boat-engine/src/test/resources/raml-examples/others/banking-api/dataTypes/shapes.raml deleted file mode 100755 index 7f27b8976..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/banking-api/dataTypes/shapes.raml +++ /dev/null @@ -1,251 +0,0 @@ -#%RAML 1.0 Library - -usage: Data shapes for the HTTP API - -types: - MonetaryAmountData: - properties: - value: number - currency: - - DurationData: - properties: - value: - - RepaymentSpecificationData: - properties: - down_payment: MonetaryAmountData - payment_frequency: number - number_payments: integer - payment_amount: MonetaryAmountData - early_payment_penalty: MonetaryAmountData - - AddressData: - properties: - address_country: - address_locality?: - address_region?: - postal_code: - street_address?: - - NewCustomerData: - type: AddressData - properties: - lei: - tax_id: - email: - telephone: - - NewOrganizationData: - type: NewCustomerData - properties: - name: - vat_id: - - NewPersonData: - type: NewCustomerData - properties: - title?: - type: string - enum: [mr, mrs, ms, dr] - given_name: - family_name: - gender: - type: string - enum: [female, male] - vat_id?: - birth_date: date-only - - - CustomerData: - discriminator: type - properties: - type: - lei: - tax_id: - email: - address: AddressData - - OrganizationData: - discriminatorValue: Organization - type: CustomerData - properties: - id: - name: - vat_id: - - - PersonData: - discriminatorValue: Person - type: CustomerData - properties: - id: - title?: - type: - enum: [mr, mrs, ms, dr] - given_name: - family_name: - gender: - type: string - enum: [female, male] - vat_id?: - birth_date: date-only - death_date?: date-only - - - CustomerPatchData: - properties: - lei?: - tax_id?: - email?: - title?: - type: string - enum: [mr, mrs, ms, dr] - name?: - family_name?: - gender?: - type: string - enum: [female, male] - vat_id?: - birth_date?: date-only - death_date?: date-only - address_country?: - address_locality?: - address_region?: - postal_code?: - street_address?: - - - NewBankAccountRequestData: - properties: - accountType: - type: string - enum: [ standard, saver ] - - BankAccountData: - properties: - id: - account_number: - accountType: - type: string - enum: [ standard, saver ] - amount: MonetaryAmountData - lei: - fees_and_comissions: - review_state: - type: - enum: [ requested, cancelled, opened, closed ] - interest_rate: number - annual_interest_rate: number - minimum_inflow: MonetaryAmountData - overdraft_limit: MonetaryAmountData - - NewLoanRequestData: - properties: - category: - amount: MonetaryAmountData - term: DurationData - interest_rate: number - down_payment: MonetaryAmountData - payment_amount: MonetaryAmountData - payment_frequency: number - review_state: - type: string - enum: - - requested - - underwriting - - rejected - - accepted - - repaying - - failed - - closed - - LoanData: - properties: - id: - account_number: - accountType: - type: string - enum: [ standard, saver ] - amount: MonetaryAmountData - lei: - fees_and_comissions: - review_state: - type: string - enum: - - requested - - cancelled - - underwriting - - accepted - - opened - - failed - - closed - interest_rate: number - annual_interest_rate: number - minimum_inflow: MonetaryAmountData - overdraft_limit: MonetaryAmountData - grace_period: DurationData - - NewDebitCardRequestData: - properties: - cash_back: boolean - contactless: boolean - - DebitCardData: - properties: - id: - lei: - fees_and_comissions: - review_state: - type: string - enum: - - requested - - cancelled - - opened - - closed - cash_back: boolean - contactless: boolean - floor_limit: MonetaryAmountData - - NewCreditCardRequestData: - properties: - cash_back: boolean - contactless: boolean - interest_rate: number - payment_amount: MonetaryAmountData - payment_frequency: number - review_state: - type: string - enum: - - requested - - cancelled - - underwriting - - accepted - - opened - - failed - - closed - - CreditCardData: - properties: - id: - amount: MonetaryAmountData - lei: - cash_back: boolean - contactless: boolean - floor_limit: MonetaryAmountData - fees_and_comissions: - review_state: - type: string - enum: - - requested - - cancelled - - underwriting - - accepted - - opened - - failed - - closed - interest_rate: number - annual_interest_rate: number - minimum_inflow: MonetaryAmountData - overdraft_limit: MonetaryAmountData - grace_period: DurationData diff --git a/boat-engine/src/test/resources/raml-examples/others/banking-api/resourceTypes/collection.raml b/boat-engine/src/test/resources/raml-examples/others/banking-api/resourceTypes/collection.raml deleted file mode 100755 index 3ce5f82d6..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/banking-api/resourceTypes/collection.raml +++ /dev/null @@ -1,20 +0,0 @@ -#%RAML 1.0 ResourceType - -usage: Apply this resource type to any resource that returns a collection of members. - -uses: - traits: ../traits/traits.raml - -get: - is: [ traits.pageable, traits.sortable ] - description: Returns a collection of <> - responses: - 200: - body: - application/json: - type: <>[] -post: - description: Requests the creation of a new <> - body: - application/json: - type: <> \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/others/banking-api/resourceTypes/member.raml b/boat-engine/src/test/resources/raml-examples/others/banking-api/resourceTypes/member.raml deleted file mode 100755 index 6a71e2803..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/banking-api/resourceTypes/member.raml +++ /dev/null @@ -1,25 +0,0 @@ -#%RAML 1.0 ResourceType - -usage: Apply this resource type to any resource that returns only a single item. - -uses: - traits: ../traits/traits.raml - -get: - is: [ traits.partial ] - description: Returns <> data - responses: - 200: - body: - application/json: - type: <> - example: <> -patch?: - description: Updates <> data - responses: - 200: - body: - application/json: - type: <> -delete?: - description: Removes a <> from the system \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/others/banking-api/securitySchemes/oauth2_0.raml b/boat-engine/src/test/resources/raml-examples/others/banking-api/securitySchemes/oauth2_0.raml deleted file mode 100755 index e27f54c5b..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/banking-api/securitySchemes/oauth2_0.raml +++ /dev/null @@ -1,25 +0,0 @@ -#%RAML 1.0 SecurityScheme -type: OAuth 2.0 -description: ACME Banking API supports OAuth 2.0 security policy for methods that involve updating existing data -describedBy: - headers: - Authorization: - description: | - Used to send a valid OAuth 2 access token. Do not use with the "access_token" query string parameter. - type: string - queryParameters: - access_token: - description: | - Used to send a valid OAuth 2 access token. Do not use together with the "Authorization" header - type: string - responses: - 401: - description: | - Bad or expired token. This can happen if the API consumer uses a revoked or expired access token. To fix, you should re-authenticate the user. - 403: - description: | - Bad OAuth request (wrong consumer key, bad nonce, expired timestamp...). Unfortunately, re-authenticating the user won't help here. -settings: - authorizationUri: https://placeholder.com/oauth2/authorize - accessTokenUri: https://placeholder.com/oauth2/access_token - authorizationGrants: implicit diff --git a/boat-engine/src/test/resources/raml-examples/others/banking-api/traits/content-cacheable.raml b/boat-engine/src/test/resources/raml-examples/others/banking-api/traits/content-cacheable.raml deleted file mode 100755 index a10c019da..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/banking-api/traits/content-cacheable.raml +++ /dev/null @@ -1,33 +0,0 @@ -#%RAML 1.0 Trait -usage: Apply this trait to a GET method that supports content-based caching using ETags -headers: - If-None-Match?: - type: string - description: | - Requests the resource only if its version (previously returned in the ETag header) - is different than the one provided in this header. If the resource has not been modified - (it still has the same version), then HTTP status code '304 Not Modified' (with empty body) - will be returned instead of the actual resource. - example: 8b8405f6-b3e6-41a0-9f72-d7a283001a09 -responses: - 200: - description: | - The resource has been modified. The body contains the new resource. - headers: - ETag: - type: string - example: adcab6f4-0086-4966-829a-d986a2c76aa2 - Cache-Control: - type: string - example: private, max-age=3600000 - 304: - description: | - The resource has not been modified, the body is empty and the version cached by the API - consumer client may be used. - headers: - ETag: - type: string - example: 8b8405f6-b3e6-41a0-9f72-d7a283001a09 - Cache-Control: - type: string - example: private, max-age=3600000 \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/others/banking-api/traits/pageable.raml b/boat-engine/src/test/resources/raml-examples/others/banking-api/traits/pageable.raml deleted file mode 100755 index f35324942..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/banking-api/traits/pageable.raml +++ /dev/null @@ -1,18 +0,0 @@ -#%RAML 1.0 Trait -usage: Apply this trait to a GET method that supports pagination. -queryParameters: - offset?: - type: integer - default: 10 - minimum: 0 - description: The `offset` parameter specifies the first entry to return from a collection. - limit?: - type: integer - default: 50 - minimum: 1 - description: The `limit` parameter restricts the number of entries returned. - page?: - type: integer - default: 1 - minimum: 1 - description: The `page` parameter specifies the page of results to return. \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/others/banking-api/traits/partial.raml b/boat-engine/src/test/resources/raml-examples/others/banking-api/traits/partial.raml deleted file mode 100755 index 68b8b9295..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/banking-api/traits/partial.raml +++ /dev/null @@ -1,8 +0,0 @@ -#%RAML 1.0 Trait -usage: Apply this trait to a metheod that supports returning only specific attributes of the response -queryParameters: - fields?: - type: string - description: | - Comma-separated expressions to be used to select attributes of the response. - example: $.store.name, $.store.book \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/others/banking-api/traits/sortable.raml b/boat-engine/src/test/resources/raml-examples/others/banking-api/traits/sortable.raml deleted file mode 100755 index abed069a0..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/banking-api/traits/sortable.raml +++ /dev/null @@ -1,6 +0,0 @@ -#%RAML 1.0 Trait -usage: Apply this to a method that support sorting. -queryParameters: - sort?: - type: string - example: name,-age \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/others/banking-api/traits/traits.raml b/boat-engine/src/test/resources/raml-examples/others/banking-api/traits/traits.raml deleted file mode 100755 index 20fbaae5c..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/banking-api/traits/traits.raml +++ /dev/null @@ -1,10 +0,0 @@ -#%RAML 1.0 Library - -usage: Common traits for the HTTP API - -traits: - pageable: !include pageable.raml - sortable: !include sortable.raml - contentCacheable: !include content-cacheable.raml - partial: !include partial.raml - \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/others/mobile-order-api/api.raml b/boat-engine/src/test/resources/raml-examples/others/mobile-order-api/api.raml deleted file mode 100644 index 12f44f5dc..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/mobile-order-api/api.raml +++ /dev/null @@ -1,57 +0,0 @@ -#%RAML 1.0 -title: Mobile Order API -version: 1.0 -baseUri: http://localhost:8081/api - -uses: - assets: assets.lib.raml - -/orders: - displayName: Orders - description: Orders collection resource used to create new orders. - get: - is: [ assets.paging ] - description: lists all orders of a specific user - queryParameters: - userId: - type: string - description: use to query all orders of a user - required: true - example: "1964401a-a8b3-40c1-b86e-d8b9f75b5842" - responses: - 200: - body: - application/json: - type: assets.Orders - examples: - single-order: - orders: - - - order_id: "ORDER-437563756" - creation_date: "2016-03-30" - items: - - - product_id: "PRODUCT-1" - quantity: 5 - - - product_id: "PRODUCT-2" - quantity: 2 - multiple-orders: - orders: - - - order_id: "ORDER-437563756" - creation_date: "2016-03-30" - items: - - - product_id: "PRODUCT-1" - quantity: 5 - - - product_id: "PRODUCT-2" - quantity: 2 - - - order_id: "ORDER-437542111" - creation_date: "2016-03-30" - items: - - - product_id: "PRODUCT-7" - quantity: 6 diff --git a/boat-engine/src/test/resources/raml-examples/others/mobile-order-api/assets.lib.raml b/boat-engine/src/test/resources/raml-examples/others/mobile-order-api/assets.lib.raml deleted file mode 100644 index b9c2e40d6..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/mobile-order-api/assets.lib.raml +++ /dev/null @@ -1,32 +0,0 @@ -#%RAML 1.0 Library - -types: - ProductItem: - type: object - properties: - product_id: string - quantity: integer - Order: - type: object - properties: - order_id: string - creation_date: string - items: ProductItem[] - Orders: - type: object - properties: - orders: Order[] - -traits: - paging: - queryParameters: - size: - description: the amount of elements of each result page - type: integer - required: false - example: 10 - page: - description: the page number - type: integer - required: false - example: 0 diff --git a/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/heybulldog.mp3 b/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/heybulldog.mp3 deleted file mode 100644 index 709f9d2a3..000000000 Binary files a/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/heybulldog.mp3 and /dev/null differ diff --git a/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-api.raml b/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-api.raml deleted file mode 100644 index 181bcde17..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-api.raml +++ /dev/null @@ -1,193 +0,0 @@ -#%RAML 1.0 ---- -title: Jukebox API -baseUri: http://jukebox.api.com -version: v1 - -types: - song: !include jukebox-include-song.schema - artist: !include jukebox-include-artist.schema - album: !include jukebox-include-album.schema - - -resourceTypes: - readOnlyCollection: - description: Collection of available <> in Jukebox. - get: - description: Get a list of <>. - responses: - 200: - body: - application/json: - example: | - <> - collection: - description: Collection of available <> in Jukebox. - get: - description: Get a list of <>. - responses: - 200: - body: - application/json: - example: | - <> - post: - description: | - Add a new <> to Jukebox. - queryParameters: - access_token: - description: "The access token provided by the authentication application" - example: AABBCCDD - required: true - type: string - body: - application/json: - type: <> - example: | - <> - responses: - 200: - body: - application/json: - example: | - { "message": "The <> has been properly entered" } - collection-item: - description: Entity representing a <> - get: - description: | - Get the <> - with <>Id = - {<>Id} - responses: - 200: - body: - application/json: - example: | - <> - 404: - body: - application/json: - example: | - {"message": "<> not found" } -traits: - searchable: - queryParameters: - query: - description: | - JSON array [{"field1","value1","operator1"},{"field2","value2","operator2"},...,{"fieldN","valueN","operatorN"}] <> - example: | - <> - orderable: - queryParameters: - orderBy: - description: | - Order by field: <> - type: string - required: false - order: - description: Order - enum: [desc, asc] - default: desc - required: false - pageable: - queryParameters: - offset: - description: Skip over a number of elements by specifying an offset value for the query - type: integer - required: false - example: 20 - default: 0 - limit: - description: Limit the number of elements on the response - type: integer - required: false - example: 80 - default: 10 - -/songs: - type: - collection: - exampleCollection: !include jukebox-include-songs.sample - exampleItem: !include jukebox-include-song-new.sample - get: - is: [ - searchable: {description: "with valid searchable fields: songTitle", example: "[\"songTitle\", \"Get L\", \"like\"]"}, - orderable: {fieldsList: "songTitle"}, - pageable - ] - /{songId}: - type: - collection-item: - exampleItem: !include jukebox-include-song-retrieve.sample - /file-content: - description: The file to be reproduced by the client - get: - description: Get the file content - responses: - 200: - body: - application/octet-stream: - example: - !include heybulldog.mp3 - post: - description: | - Enters the file content for an existing song entity. - - The song needs to be created for the `/songs/{songId}/file-content` to exist. - You can use this second resource to get and post the file to reproduce. - - Use the "binary/octet-stream" content type to specify the content from any consumer (excepting web-browsers). - Use the "multipart-form/data" content type to upload a file which content will become the file-content - body: - application/octet-stream: - multipart/form-data: - properties: - file: - description: The file to be uploaded - required: true - type: file -/artists: - type: - collection: - exampleCollection: !include jukebox-include-artists.sample - exampleItem: !include jukebox-include-artist-new.sample - get: - is: [ - searchable: {description: "with valid searchable fields: countryCode", example: "[\"countryCode\", \"FRA\", \"equals\"]"}, - orderable: {fieldsList: "artistName, nationality"}, - pageable - ] - /{artistId}: - type: - collection-item: - exampleItem: !include jukebox-include-artist-retrieve.sample - /albums: - type: - readOnlyCollection: - exampleCollection: !include jukebox-include-artist-albums.sample - description: Collection of albulms belonging to the artist - get: - description: Get a specific artist's albums list - is: [orderable: {fieldsList: "albumName"}, pageable] -/albums: - type: - collection: - exampleCollection: !include jukebox-include-albums.sample - exampleItem: !include jukebox-include-album-new.sample - get: - is: [ - searchable: {description: "with valid searchable fields: genreCode", example: "[\"genreCode\", \"ELE\", \"equals\"]"}, - orderable: {fieldsList: "albumName, genre"}, - pageable - ] - /{albumId}: - type: - collection-item: - exampleItem: !include jukebox-include-album-retrieve.sample - /songs: - type: - readOnlyCollection: - exampleCollection: !include jukebox-include-album-songs.sample - get: - is: [orderable: {fieldsList: "songTitle"}] - description: Get the list of songs for the album with `albumId = {albumId}` \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-album-new.sample b/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-album-new.sample deleted file mode 100644 index c7ee88d18..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-album-new.sample +++ /dev/null @@ -1,8 +0,0 @@ -{ - "albumId": "183100e3-0e2b-4404-a716-66104d440550", - "albumName": "Random Access Memories", - "year": "2013", - "imageURL": "http://upload.wikimedia.org/wikipedia/en/a/a7/Random_Access_Memories.jpg", - "genreCode": "ELE", - "artistId": "110e8300-e32b-41d4-a716-664400445500" -} diff --git a/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-album-retrieve.sample b/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-album-retrieve.sample deleted file mode 100644 index 22941d1c4..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-album-retrieve.sample +++ /dev/null @@ -1,30 +0,0 @@ -{ - "albumId": "183100e3-0e2b-4404-a716-66104d440550", - "albumName": "Random Access Memories", - "year": "2013", - "genre": "Electric Funk", - "imageURL": "http://upload.wikimedia.org/wikipedia/en/a/a7/Random_Access_Memories.jpg", - "genre": { - "countryCode": "ELE", - "countryName": "Electronict" - }, - "songs": [ - { - "songId": "550e8400-e29b-41d4-a716-446655440000", - "songTitle": "Get Lucky" - }, - { - "songId": "550e8400-e29b-41d4-a716-446655440111", - "songTitle": "Loose yourself to dance" - }, - { - "songId": "550e8400-e29b-41d4-a716-446655440222", - "songTitle": "Gio sorgio by Moroder" - } - ], - "artist": { - "artistId": "110e8300-e32b-41d4-a716-664400445500", - "artistName": "Daft Punk", - "imageURL": "http://travelhymns.com/wp-content/uploads/2013/06/random-access-memories1.jpg" - } -} diff --git a/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-album-songs.sample b/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-album-songs.sample deleted file mode 100644 index 044e9c823..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-album-songs.sample +++ /dev/null @@ -1,14 +0,0 @@ -[ - { - "songId": "550e8400-e29b-41d4-a716-446655440000", - "songTitle": "Get Lucky" - }, - { - "songId": "550e8400-e29b-41d4-a716-446655440111", - "songTitle": "Loose yourself to dance" - }, - { - "songId": "550e8400-e29b-41d4-a716-446655440222", - "songTitle": "Gio sorgio by Moroder" - } -] diff --git a/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-album.schema b/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-album.schema deleted file mode 100644 index 13125010e..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-album.schema +++ /dev/null @@ -1,35 +0,0 @@ -{ - "type": "object", - "$schema": "http://json-schema.org/draft-03/schema", - "required":false, - "properties": { - "albumId": { - "type": "string", - "required":true, - "minLength": 36, - "maxLength": 36 - }, - "albumName": { - "type": "string", - "required": true - }, - "year": { - "type": "string", - "required": false - }, - "iamgeURL": { - "type": "string", - "required": false - }, - "genreCode": { - "type": "string", - "required": true - }, - "artistId": { - "type": "string", - "required":true, - "minLength": 36, - "maxLength": 36 - } - } -} diff --git a/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-albums.sample b/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-albums.sample deleted file mode 100644 index a6b3f5bdf..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-albums.sample +++ /dev/null @@ -1,32 +0,0 @@ -[ - { - "albumId": "183100e3-0e2b-4404-a716-66104d440550", - "albumName": "Random Access Memories", - "imageURL": "http://upload.wikimedia.org/wikipedia/en/a/a7/Random_Access_Memories.jpg", - "artistId": "110e8300-e32b-41d4-a716-664400445500", - "genre": { - "countryCode": "ELE", - "countryName": "Electronic" - } - }, - { - "albumId": "183100e3-0e2b-4404-3123-66111d4de520", - "albumName": "OK Computer", - "imageURL": "http://www.greenplastic.com/dev/wp-content/uploads/2010/12/ok-computer.jpg", - "artistId": "11032be3-41d4-4455-a716-664400a71600", - "genre": { - "countryCode": "ALT", - "countryName": "Alternative Rock" - } - }, - { - "albumId": "183100e3-cccc-4404-1111-63204d64coda", - "albumName": "The Dark Side of the Moon", - "imageURL": "http://upload.wikimedia.org/wikipedia/en/3/3b/Dark_Side_of_the_Moon.png", - "artistId": "110e8300-e32b-41d4-a716-229932554400", - "genre": { - "countryCode": "PRO", - "countryName": "Progressive Rock" - } - } -] diff --git a/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-artist-albums.sample b/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-artist-albums.sample deleted file mode 100644 index e2afc8aae..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-artist-albums.sample +++ /dev/null @@ -1,42 +0,0 @@ -[ - { - "albumId": "183100e3-0e2b-4404-a716-66104d440550", - "albumName": "Random Access Memories", - "imageURL": "http://upload.wikimedia.org/wikipedia/en/a/a7/Random_Access_Memories.jpg" - }, - { - "albumId": "183100e3-0e2b-4404-a716-66104d440551", - "albumName": "TRON: Legacy R3CONF1GUR3D", - "imageURL": "http://ecx.images-amazon.com/images/I/51Tvo-iArBL.jpg" - }, - { - "albumId": "183100e3-0e2b-4404-a716-66104d440552", - "albumName": "TRON: Legacy", - "imageURL": "http://upload.wikimedia.org/wikipedia/en/3/39/Tron_Legacy_Soundtrack.jpg" - }, - { - "albumId": "183100e3-0e2b-4404-a716-66104d440553", - "albumName": "Alive", - "imageURL": "http://upload.wikimedia.org/wikipedia/en/4/49/Daft_Punk_Alive_2007.JPG" - }, - { - "albumId": "183100e3-0e2b-4404-a716-66104d440554", - "albumName": "Musique Vol. 1", - "imageURL": "http://upload.wikimedia.org/wikipedia/en/a/ab/Musique_Vol._1_1993%E2%80%932005.png" - }, - { - "albumId": "183100e3-0e2b-4404-a716-66104d440555", - "albumName": "Human After All", - "imageURL": "http://upload.wikimedia.org/wikipedia/en/0/0d/Humanafterall.jpg" - }, - { - "albumId": "183100e3-0e2b-4404-a716-66104d440556", - "albumName": "Daft Club", - "imageURL": "http://upload.wikimedia.org/wikipedia/en/f/fc/Daftclub.jpg" - }, - { - "albumId": "183100e3-0e2b-4404-a716-66104d440557", - "albumName": "Discovery", - "imageURL": "http://ecx.images-amazon.com/images/I/71bsHTr6idL._SL1500_.jpg" - } -] diff --git a/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-artist-new.sample b/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-artist-new.sample deleted file mode 100644 index 0346bd5e9..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-artist-new.sample +++ /dev/null @@ -1,5 +0,0 @@ -{ - "artistName": "Daft Punk", - "description": "French electronic music duo consisting of musicians Guy-Manuel de Homem-Christo and Thomas Bangalter", - "imageURL": "http://travelhymns.com/wp-content/uploads/2013/06/random-access-memories1.jpg" -} diff --git a/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-artist-retrieve.sample b/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-artist-retrieve.sample deleted file mode 100644 index 394f8396d..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-artist-retrieve.sample +++ /dev/null @@ -1,52 +0,0 @@ -{ - "artistId": "110e8300-e32b-41d4-a716-664400445500", - "artistName": "Daft Punk", - "description": "French electronic music duo consisting of musicians Guy-Manuel de Homem-Christo and Thomas Bangalter", - "imageURL": "http://travelhymns.com/wp-content/uploads/2013/06/random-access-memories1.jpg", - "nationality": { - "countryCode": "FRA", - "countryName": "France" - }, - "albums": [ - { - "albumId": "183100e3-0e2b-4404-a716-66104d440550", - "albumName": "Random Access Memories", - "imageURL": "http://upload.wikimedia.org/wikipedia/en/a/a7/Random_Access_Memories.jpg" - }, - { - "albumId": "183100e3-0e2b-4404-a716-66104d440551", - "albumName": "TRON: Legacy R3CONF1GUR3D", - "imageURL": "http://ecx.images-amazon.com/images/I/51Tvo-iArBL.jpg" - }, - { - "albumId": "183100e3-0e2b-4404-a716-66104d440552", - "albumName": "TRON: Legacy", - "imageURL": "http://upload.wikimedia.org/wikipedia/en/3/39/Tron_Legacy_Soundtrack.jpg" - }, - { - "albumId": "183100e3-0e2b-4404-a716-66104d440553", - "albumName": "Alive", - "imageURL": "http://upload.wikimedia.org/wikipedia/en/4/49/Daft_Punk_Alive_2007.JPG" - }, - { - "albumId": "183100e3-0e2b-4404-a716-66104d440554", - "albumName": "Musique Vol. 1", - "imageURL": "http://upload.wikimedia.org/wikipedia/en/a/ab/Musique_Vol._1_1993%E2%80%932005.png" - }, - { - "albumId": "183100e3-0e2b-4404-a716-66104d440555", - "albumName": "Human After All", - "imageURL": "http://upload.wikimedia.org/wikipedia/en/0/0d/Humanafterall.jpg" - }, - { - "albumId": "183100e3-0e2b-4404-a716-66104d440556", - "albumName": "Daft Club", - "imageURL": "http://upload.wikimedia.org/wikipedia/en/f/fc/Daftclub.jpg" - }, - { - "albumId": "183100e3-0e2b-4404-a716-66104d440557", - "albumName": "Discovery", - "imageURL": "http://ecx.images-amazon.com/images/I/71bsHTr6idL._SL1500_.jpg" - } - ] -} diff --git a/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-artist.schema b/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-artist.schema deleted file mode 100644 index bbb96c0b8..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-artist.schema +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "object", - "$schema": "http://json-schema.org/draft-03/schema", - "required":false, - "properties": { - "artistName": { - "type": "string", - "required":true - }, - "description": { - "type": "string", - "required": false - }, - "imageURL": { - "type": "string", - "required": false - } - } -} diff --git a/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-artists.sample b/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-artists.sample deleted file mode 100644 index 28475ddfa..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-artists.sample +++ /dev/null @@ -1,32 +0,0 @@ -[ - { - "artistId": "110e8300-e32b-41d4-a716-664400445500", - "artistName": "Daft Punk", - "description": "French electronic music duo consisting of musicians Guy-Manuel de Homem-Christo and Thomas Bangalter", - "imageURL": "http://travelhymns.com/wp-content/uploads/2013/06/random-access-memories1.jpg", - "nationality": { - "countryCode": "FRA", - "countryName": "France" - } - }, - { - "artistId": "110e8300-e32b-41d4-a716-229932554400", - "artistName": "Pink Floyd", - "description": "English rock band that achieved international acclaim with their progressive and psychedelic music.", - "imageURL": "http://www.billboard.com/files/styles/promo_650/public/stylus/1251869-pink-floyd-reunions-617-409.jpg", - "nationality": { - "countryCode": "ENG", - "countryName": "England" - } - }, - { - "artistId": "11032be3-41d4-4455-a716-664400a71600", - "artistName": "Radiohead", - "description": " English rock band from Abingdon, Oxfordshire, formed in 1985", - "imageURL": "http://www.wired.com/images_blogs/photos/uncategorized/2007/10/01/radiohead.jpg", - "nationality": { - "countryCode": "ENG", - "countryName": "England" - } - } -] diff --git a/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-song-new.sample b/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-song-new.sample deleted file mode 100644 index d2d761fbe..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-song-new.sample +++ /dev/null @@ -1,5 +0,0 @@ -{ - "songId": "550e8400-e29b-41d4-a716-446655440000", - "songTitle": "Get Lucky", - "albumId": "183100e3-0e2b-4404-a716-66104d440550" -} diff --git a/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-song-retrieve.sample b/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-song-retrieve.sample deleted file mode 100644 index 0006294be..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-song-retrieve.sample +++ /dev/null @@ -1,15 +0,0 @@ -{ - "songId": "550e8400-e29b-41d4-a716-446655440000", - "songTitle": "Get Lucky", - "duration": "6:07", - "artist": { - "artistId": "110e8300-e32b-41d4-a716-664400445500", - "artistName": "Daft Punk", - "imageURL": "http://travelhymns.com/wp-content/uploads/2013/06/random-access-memories1.jpg" - }, - "album": { - "albumId": "183100e3-0e2b-4404-a716-66104d440550", - "albumName": "Random Access Memories", - "imageURL": "http://upload.wikimedia.org/wikipedia/en/a/a7/Random_Access_Memories.jpg" - } -} diff --git a/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-song.schema b/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-song.schema deleted file mode 100644 index 8c3dc500b..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-song.schema +++ /dev/null @@ -1,23 +0,0 @@ -{ - "type": "object", - "$schema": "http://json-schema.org/draft-03/schema", - "required": true, - "properties": { - "songId": { - "type": "string", - "required": true, - "minLength": 36, - "maxLength": 36 - }, - "songTitle": { - "type": "string", - "required": true - }, - "albumId": { - "type": "string", - "required": true, - "minLength": 36, - "maxLength": 36 - } - } -} diff --git a/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-songs.sample b/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-songs.sample deleted file mode 100644 index ca37d5160..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/tutorial-jukebox-api/jukebox-include-songs.sample +++ /dev/null @@ -1,14 +0,0 @@ -[ - { - "songId": "550e8400-e29b-41d4-a716-446655440000", - "songTitle": "Get Lucky" - }, - { - "songId": "550e8400-e29b-41d4-a716-446655440111", - "songTitle": "Loose yourself to dance" - }, - { - "songId": "550e8400-e29b-41d4-a716-446655440222", - "songTitle": "Gio sorgio by Morodera" - } -] diff --git a/boat-engine/src/test/resources/raml-examples/others/world-music-api/api.raml b/boat-engine/src/test/resources/raml-examples/others/world-music-api/api.raml deleted file mode 100644 index 55abcce4c..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/world-music-api/api.raml +++ /dev/null @@ -1,201 +0,0 @@ -#%RAML 1.0 -title: World Music API -description: This is an example of a music API. -version: v1 -baseUri: - value: http://{environment}.musicapi.com/{version} - (rediractable): true -baseUriParameters: - environment: - type: string - enum: [ "stg", "dev", "test", "prod" ] -protocols: [ HTTP, HTTPS ] -mediaType: [ application/json ] -documentation: - - title: Getting Started - content: | - This is a getting started guide for the World Music API. - - title: Legal - content: See http://legal.musicapi.com - -types: - Entry: | - { - "type": "array", - "items": { - "$ref": "#/definitions/song" - }, - "definitions": { - "song": { - "type": "object", - "properties": { - "title": { - "type": "string" - }, - "artist": { - "type": "string" - } - } - } - } - } - AnotherEntry: - type: Entry - description: | - This is just another entry to simulate that you can add facets also on JSON - schema defined types. Although you can only add documentation-based facets. - User: - properties: - firstname: string - lastname: - type: string - example: Doe - required: false - example: - firstname: John - -traits: - secured: !include secured/accessToken.trait.raml - -resourceTypes: - collection: - get: - description: returns a list of <> - responses: - 200: - body: - application/json: - schema: <> - - -annotationTypes: - deprecated: - properties: - date: datetime - deprecatedBy: User - comment: nil | string - monitoringInterval: - type: integer - description: interval in seconds - example: 2 - ready: - type: nil - description: markes a resource as ready - allowedTargets: Resource - info: - properties: - license: - type: string - enum: [ "MIT", "Apache 2.0" ] - allowedTargets: API - rediractable: boolean - -(info): - license: MIT - -securitySchemes: - oauth_1_0: - description: | - OAuth 1.0 continues to be supported for all API requests, but OAuth 2.0 is now preferred. - type: OAuth 1.0 - settings: - requestTokenUri: https://musicapi.com/1/oauth/request_token - authorizationUri: https://musicapi.com/1/oauth/authorize - tokenCredentialsUri: https://musicapi.com/1/oauth/access_token - signatures: [ 'HMAC-SHA1', 'PLAINTEXT' ] - oauth_2_0: - description: | - This API supports OAuth 2.0 for authenticating all API requests. - type: OAuth 2.0 - describedBy: - headers: - Authorization: - description: | - Used to send a valid OAuth 2 access token. Do not use - with the "access_token" query string parameter. - type: string - queryParameters: - access_token: - description: | - Used to send a valid OAuth 2 access token. Do not use with - the "Authorization" header. - type: string - responses: - 401: - description: | - Bad or expired token. This can happen if the access token - has been revoked or expired. To fix, re-authenticate - the user. - 403: - description: | - Bad OAuth request (wrong consumer key, bad nonce, expired - timestamp...). Unfortunately, re-authenticating the user won't help here. - settings: - authorizationUri: https://musicapi.com/1/oauth2/authorize - accessTokenUri: https://musicapi.com/1/oauth2/token - authorizationGrants: [ authorization_code, implicit, 'urn:ietf:params:oauth:grant-type:saml2-bearer' ] - custom_scheme: - description: | - A custom security scheme for authenticating requests. - type: x-custom - describedBy: - headers: - SpecialToken: - description: | - Used to send a custom token. - type: string - responses: - 401: - description: | - Bad token. - 403: - -securedBy: custom_scheme - -uses: - SongsLib: libraries/songs.lib.raml - ApiLib: libraries/api.lib.raml - -/api: - get: - queryString: - properties: - start?: number - page-size?: number - post: - body: - application/json: - type: ApiLib.RamlDataType -/entry: - type: collection - post: - responses: - 200: - body: AnotherEntry -/songs: - displayName: Songs - description: Access to all songs inside the music world library. - (ready): - is: [ secured ] - get: - securedBy: [ oauth_2_0, null ] - (monitoringInterval): 30 - queryParameters: - genre: - description: filter the songs by genre - post: - /{songId}: - get: - (deprecated): - date: 2016-02-28T16:41:41.090Z - deprecatedBy: - firstname: Christian - comment: no comment - responses: - 200: - body: - application/json: - type: SongsLib.Song - application/xml: - schema: !include schemas/songs.xsd - example: !include examples/songs.xml diff --git a/boat-engine/src/test/resources/raml-examples/others/world-music-api/examples/songs.xml b/boat-engine/src/test/resources/raml-examples/others/world-music-api/examples/songs.xml deleted file mode 100644 index 3c1b42100..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/world-music-api/examples/songs.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - str1234 - str1234 - diff --git a/boat-engine/src/test/resources/raml-examples/others/world-music-api/libraries/api.lib.raml b/boat-engine/src/test/resources/raml-examples/others/world-music-api/libraries/api.lib.raml deleted file mode 100644 index 15c5a73f8..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/world-music-api/libraries/api.lib.raml +++ /dev/null @@ -1,67 +0,0 @@ -#%RAML 1.0 Library - -types: - RamlDataType: - type: object - properties: - propString: string - propStringArray1: string[] - ideas: - type: array - items: !include ../schemas/idea.dataType.raml - extIdeas: - type: !include ../schemas/idea.dataType.raml - properties: - createdBy: string - feedback: - type: string - default: "very nice" - example: "very well made" - minLength: 1 - maxLength: 255 - pattern: "[a-zA-Z\\s]*" - propNumber: - type: number - minimum: 0 - maximum: 32 - format: int32 - multipleOf: 2 - propInteger: - type: integer - minimum: 3 - maximum: 5 - format: int8 - multipleOf: 1 - propBoolean: boolean - propDate: - type: date-only - example: 2015-05-23 - userPicture: - type: file - fileTypes: ['image/jpeg', 'image/png'] - maxLength: 307200 - NilValue: - type: object - properties: - name: - comment: string? - CatOrDog: Cat | Dog - CatAndDog: [ Cat, Dog ] - PossibleMeetingDate: - type: CustomDate - noHolidays: true - Cat: - type: object - properties: - name: string - color: string - Dog: - type: object - properties: - name: string - fangs: string - CustomDate: - type: date-only - facets: - onlyFutureDates?: boolean # optional in `PossibleMeetingDate` - noHolidays: boolean # required in `PossibleMeetingDate` diff --git a/boat-engine/src/test/resources/raml-examples/others/world-music-api/libraries/songs.lib.raml b/boat-engine/src/test/resources/raml-examples/others/world-music-api/libraries/songs.lib.raml deleted file mode 100644 index cdab596f2..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/world-music-api/libraries/songs.lib.raml +++ /dev/null @@ -1,24 +0,0 @@ -#%RAML 1.0 Library - -types: - Song: - properties: - title: string - length: number - examples: - song1: - strict: false - value: - title: "My Song" - length: 12 - song2: - title: "Last" - length: 3 - Album: - properties: - title: string - songs: Song[] - Musician: - properties: - name: string - discography: (Song | Album)[] diff --git a/boat-engine/src/test/resources/raml-examples/others/world-music-api/schemas/idea.dataType.raml b/boat-engine/src/test/resources/raml-examples/others/world-music-api/schemas/idea.dataType.raml deleted file mode 100644 index d81e54f2b..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/world-music-api/schemas/idea.dataType.raml +++ /dev/null @@ -1,4 +0,0 @@ -#%RAML 1.0 DataType - -properties: - comment: string diff --git a/boat-engine/src/test/resources/raml-examples/others/world-music-api/schemas/songs.xsd b/boat-engine/src/test/resources/raml-examples/others/world-music-api/schemas/songs.xsd deleted file mode 100644 index 8ed2846be..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/world-music-api/schemas/songs.xsd +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - diff --git a/boat-engine/src/test/resources/raml-examples/others/world-music-api/secured/accessToken.trait.raml b/boat-engine/src/test/resources/raml-examples/others/world-music-api/secured/accessToken.trait.raml deleted file mode 100644 index 9844ea319..000000000 --- a/boat-engine/src/test/resources/raml-examples/others/world-music-api/secured/accessToken.trait.raml +++ /dev/null @@ -1,7 +0,0 @@ -#%RAML 1.0 Trait - -usage: | - This trait can be used to apply an access token query parameter - to any resources or HTTP methods. -queryParameters: - access_token: string diff --git a/boat-engine/src/test/resources/raml-examples/query-parameters/api.raml b/boat-engine/src/test/resources/raml-examples/query-parameters/api.raml deleted file mode 100644 index f58e086ea..000000000 --- a/boat-engine/src/test/resources/raml-examples/query-parameters/api.raml +++ /dev/null @@ -1,30 +0,0 @@ -#%RAML 1.0 -title: My Querying API -mediaType: application/json - -/search: - get: - queryString: # at least one parameter required - minProperties: 1 - properties: - id?: integer - name?: string - q?: string - responses: - 200: - body: array - -/books: - get: - queryParameters: # filter results by nested fields, e.g. /books?author[name]= - /^author\[[a-zA-Z]\]+$/: string - responses: - 200: - body: - properties: - title: string - author: - properties: - name: string - origin: string - awarded: boolean diff --git a/boat-engine/src/test/resources/raml-examples/resourcetypes/optional-properties.raml b/boat-engine/src/test/resources/raml-examples/resourcetypes/optional-properties.raml deleted file mode 100644 index 9257f7990..000000000 --- a/boat-engine/src/test/resources/raml-examples/resourcetypes/optional-properties.raml +++ /dev/null @@ -1,20 +0,0 @@ -#%RAML 1.0 -title: Example of Optional Properties -resourceTypes: - corpResource: - post?: # optional property - description: Some info about <>. # contains custom parameter - headers: - X-Chargeback: - required: true -/servers: - type: - corpResource: - TextAboutPost: post method # post defined which will force to define the TextAboutPost parameter - get: - post: # will require the X-Chargeback header -/queues: - type: corpResource - get: - # will not have a post method defined which means one MUST not have to define - # the TextAboutPost parameter diff --git a/boat-engine/src/test/resources/raml-examples/resourcetypes/simple-resourcetype.raml b/boat-engine/src/test/resources/raml-examples/resourcetypes/simple-resourcetype.raml deleted file mode 100644 index 29d824615..000000000 --- a/boat-engine/src/test/resources/raml-examples/resourcetypes/simple-resourcetype.raml +++ /dev/null @@ -1,14 +0,0 @@ -#%RAML 1.0 -title: Example API - -resourceTypes: - collection: - usage: This resourceType should be used for any collection of items - description: The collection of <> - get: - description: Get all <>, optionally filtered - post: - description: Create a new <> - -/products: - type: collection diff --git a/boat-engine/src/test/resources/raml-examples/schemas/api.raml b/boat-engine/src/test/resources/raml-examples/schemas/api.raml deleted file mode 100644 index 9740f31b2..000000000 --- a/boat-engine/src/test/resources/raml-examples/schemas/api.raml +++ /dev/null @@ -1,48 +0,0 @@ -#%RAML 1.0 -title: Using XML and JSON Schema - -schemas: # can also be used with 'types' - PersonInline: | - { - "title": "Person Schema", - "type": "object", - "properties": { - "firstName": { - "type": "string" - }, - "lastName": { - "type": "string" - }, - "age": { - "description": "Age in years", - "type": "integer", - "minimum": 0 - } - }, - "required": ["firstName", "lastName"] - } - PersonInclude: !include person.json - -/person: - get: - responses: - 200: - body: - application/json: - schema: PersonInline # can also be used with 'type' - post: - body: - application/json: - schema: | # can also be used with 'type' - { - "title": "Body Declaration Schema", - "type": "object", - "properties": { - "firstName": { - "type": "string" - }, - "lastName": { - "type": "string" - } - } - } diff --git a/boat-engine/src/test/resources/raml-examples/schemas/person.json b/boat-engine/src/test/resources/raml-examples/schemas/person.json deleted file mode 100644 index f4bc137c2..000000000 --- a/boat-engine/src/test/resources/raml-examples/schemas/person.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "title": "Person Schema", - "type": "object", - "properties": { - "firstName": { - "type": "string" - }, - "lastName": { - "type": "string" - }, - "age": { - "description": "Age in years", - "type": "integer", - "minimum": 0 - } - }, - "required": [ - "firstName", - "lastName" - ] -} diff --git a/boat-engine/src/test/resources/raml-examples/traits/api.raml b/boat-engine/src/test/resources/raml-examples/traits/api.raml deleted file mode 100644 index 12bebaeaf..000000000 --- a/boat-engine/src/test/resources/raml-examples/traits/api.raml +++ /dev/null @@ -1,16 +0,0 @@ -#%RAML 1.0 -title: Example API -version: v1 -traits: - secured: !include secured.raml - orderable: !include orderable.raml - pageable: !include pageable.raml - -/users: - is: [ secured ] - get: - is: [ orderable, pageable ] - post: - patch: - put: - delete: diff --git a/boat-engine/src/test/resources/raml-examples/traits/orderable.raml b/boat-engine/src/test/resources/raml-examples/traits/orderable.raml deleted file mode 100644 index c35226239..000000000 --- a/boat-engine/src/test/resources/raml-examples/traits/orderable.raml +++ /dev/null @@ -1,12 +0,0 @@ -#%RAML 1.0 Trait - -queryParameters: - orderBy: - description: Order by field - type: string - required: false - order: - description: Order - enum: [desc, asc] - default: desc - required: false diff --git a/boat-engine/src/test/resources/raml-examples/traits/pageable.raml b/boat-engine/src/test/resources/raml-examples/traits/pageable.raml deleted file mode 100644 index 638c99e46..000000000 --- a/boat-engine/src/test/resources/raml-examples/traits/pageable.raml +++ /dev/null @@ -1,15 +0,0 @@ -#%RAML 1.0 Trait - -queryParameters: - offset: - description: Skip over a number of elements by specifying an offset value for the query - type: integer - required: false - example: 20 - default: 0 - limit: - description: Limit the number of elements on the response - type: integer - required: false - example: 80 - default: 10 diff --git a/boat-engine/src/test/resources/raml-examples/traits/secured.raml b/boat-engine/src/test/resources/raml-examples/traits/secured.raml deleted file mode 100644 index a2f560621..000000000 --- a/boat-engine/src/test/resources/raml-examples/traits/secured.raml +++ /dev/null @@ -1,8 +0,0 @@ -#%RAML 1.0 Trait - -usage: Apply this to any method that needs to be secured -headers: - access_token: - description: Access Token - example: 5757gh76 - required: true diff --git a/boat-engine/src/test/resources/raml-examples/typesystem/additional-properties/recipient-with-pattern.dataType.raml b/boat-engine/src/test/resources/raml-examples/typesystem/additional-properties/recipient-with-pattern.dataType.raml deleted file mode 100644 index 998c61b9f..000000000 --- a/boat-engine/src/test/resources/raml-examples/typesystem/additional-properties/recipient-with-pattern.dataType.raml +++ /dev/null @@ -1,11 +0,0 @@ -#%RAML 1.0 DataType - -description: | - defines an object that restricts certain additional properties in any - instance to be a `string` -type: object -properties: - name: string - address: string - /^note\d+$/: string # every additional property whose keys start with 'note' - # followed by one or more digits to be a string diff --git a/boat-engine/src/test/resources/raml-examples/typesystem/additional-properties/recipient.dataType.raml b/boat-engine/src/test/resources/raml-examples/typesystem/additional-properties/recipient.dataType.raml deleted file mode 100644 index 43fe6198a..000000000 --- a/boat-engine/src/test/resources/raml-examples/typesystem/additional-properties/recipient.dataType.raml +++ /dev/null @@ -1,10 +0,0 @@ -#%RAML 1.0 DataType - -description: | - defines an object that restricts all additional properties in any - instance to be a `string` -type: object -properties: - name: string - address: string - //: string # every additional property has to be a string diff --git a/boat-engine/src/test/resources/raml-examples/typesystem/array-type.lib.raml b/boat-engine/src/test/resources/raml-examples/typesystem/array-type.lib.raml deleted file mode 100644 index 5a853cf01..000000000 --- a/boat-engine/src/test/resources/raml-examples/typesystem/array-type.lib.raml +++ /dev/null @@ -1,24 +0,0 @@ -#%RAML 1.0 Library - -types: - Email: # normal object type declaration - type: object - properties: - subject: string - body: string - EmailsLong: # array type declaration - type: array - items: Email - minItems: 1 - uniqueItems: true - EmailsShort: # array type declaration using type expression shortcut - type: Email[] # '[]' expresses an array - minItems: 1 - uniqueItems: true - example: # example that contains array - - # start item 1 - subject: My Email 1 - body: This is the text for email 1. - - # start item 2 - subject: My Email 2 - body: This is the text for email 2. diff --git a/boat-engine/src/test/resources/raml-examples/typesystem/complex.raml b/boat-engine/src/test/resources/raml-examples/typesystem/complex.raml deleted file mode 100644 index 5a5d0e0d1..000000000 --- a/boat-engine/src/test/resources/raml-examples/typesystem/complex.raml +++ /dev/null @@ -1,60 +0,0 @@ -#%RAML 1.0 -title: My API with Types -mediaType: application/json -types: - Org: - type: object - properties: - onCall: Alertable # inherits all properties from type `Alertable` - Head: Manager # inherits all properties from type `Manager` - Person: - type: object - discriminator: kind # reference to the `kind` property of `Person` - properties: - firstname: string - lastname: string - title?: string - kind: string # may be used to differenciate between classes that extend from `Person` - Phone: - type: string - pattern: "^[0-9|-]+$" # defines pattern for the content of type `Phone` - Manager: - type: Person # inherits all properties from type `Person` - properties: - reports: Person[] # inherits all properties from type `Person`; array type where `[]` is a shortcut - phone: Phone - Admin: - type: Person # inherits all properties from type `Person` - properties: - clearanceLevel: - enum: [ low, high ] - AlertableAdmin: - type: Admin # inherits all properties from type `Admin` - properties: - phone: Phone # inherits all properties from type `Phone`; uses shortcut syntax - Alertable: Manager | AlertableAdmin # union type; either a `Manager` or `AlertableAdmin` -/orgs/{orgId}: - get: - responses: - 200: - body: - application/json: - type: Org # reference to global type definition - example: - onCall: - firstname: nico - lastname: ark - kind: AlertableAdmin - clearanceLevel: low - phone: "12321" - Head: - firstname: nico - lastname: ark - kind: Manager - reports: - - - firstname: nico - lastname: ark - kind: Admin - clearanceLevel: low - phone: "123-23" diff --git a/boat-engine/src/test/resources/raml-examples/typesystem/defining-dates.lib.raml b/boat-engine/src/test/resources/raml-examples/typesystem/defining-dates.lib.raml deleted file mode 100644 index bce603077..000000000 --- a/boat-engine/src/test/resources/raml-examples/typesystem/defining-dates.lib.raml +++ /dev/null @@ -1,20 +0,0 @@ -#%RAML 1.0 Library - -types: - birthday: - type: date-only # no implications about time or offset - example: 2015-05-23 - lunchtime: - type: time-only # no implications about date or offset - example: 12:30:00 - fireworks: - type: datetime-only # no implications about offset - example: 2015-07-04T21:00:00 - created: - type: datetime - example: 2016-02-28T16:41:41.090Z - format: rfc3339 # the default, so needn't be specified - If-Modified-Since: - type: datetime - example: Sun, 28 Feb 2016 16:41:41 GMT - format: rfc2616 # this time it's required as otherwise the example is in an invalid format diff --git a/boat-engine/src/test/resources/raml-examples/typesystem/discriminators/discriminator.raml b/boat-engine/src/test/resources/raml-examples/typesystem/discriminators/discriminator.raml deleted file mode 100644 index f923caf1a..000000000 --- a/boat-engine/src/test/resources/raml-examples/typesystem/discriminators/discriminator.raml +++ /dev/null @@ -1,17 +0,0 @@ -#%RAML 1.0 -title: My API With Types -types: - Person: - type: object - discriminator: kind # refers to the `kind` property of object `Person` - properties: - kind: string # contains name of the kind of a `Person` instance - name: string - Employee: # kind may equal to `Employee; default value for `discriminatorValue` - type: Person - properties: - employeeId: string - User: # kind may equal to `User`; default value for `discriminatorValue` - type: Person - properties: - userId: string diff --git a/boat-engine/src/test/resources/raml-examples/typesystem/discriminators/discriminatorValue.raml b/boat-engine/src/test/resources/raml-examples/typesystem/discriminators/discriminatorValue.raml deleted file mode 100644 index 58d408fed..000000000 --- a/boat-engine/src/test/resources/raml-examples/typesystem/discriminators/discriminatorValue.raml +++ /dev/null @@ -1,19 +0,0 @@ -#%RAML 1.0 -title: My API With Types -types: - Person: - type: object - discriminator: kind - properties: - name: string - kind: string - Employee: - type: Person - discriminatorValue: employee # override default - properties: - employeeId: string - User: - type: Person - discriminatorValue: user # override default - properties: - userId: string diff --git a/boat-engine/src/test/resources/raml-examples/typesystem/file-type.raml b/boat-engine/src/test/resources/raml-examples/typesystem/file-type.raml deleted file mode 100644 index 2ba928557..000000000 --- a/boat-engine/src/test/resources/raml-examples/typesystem/file-type.raml +++ /dev/null @@ -1,12 +0,0 @@ -#%RAML 1.0 -title: My Sample API - -types: - userPicture: - type: file - fileTypes: ['image/jpeg', 'image/png'] # only JPEG and PNG allowed - maxLength: 307200 - customFile: - type: file - fileTypes: ['*/*'] # any file type allowed - maxLength: 1048576 diff --git a/boat-engine/src/test/resources/raml-examples/typesystem/monetary.lib.raml b/boat-engine/src/test/resources/raml-examples/typesystem/monetary.lib.raml deleted file mode 100644 index 2302bfc33..000000000 --- a/boat-engine/src/test/resources/raml-examples/typesystem/monetary.lib.raml +++ /dev/null @@ -1,25 +0,0 @@ -#%RAML 1.0 Library -usage: Types to be used for monetary values - -types: - ZeroValue: - description: zero-value numbers, accepting either the 0 or 0.00 (hundreths) forms - type: number - enum: - - 0 - - 0.00 - HundredthsValue: - description: non-zero two-decimal place values (positive and negative) - type: number - multipleOf: 0.01 - MonetaryValue: - description: this type describes any monetary value comprised between -9,999,999,999,999.99 and 9,999,999,999,999.99 - type: ZeroValue | HundredthsValue - default: 0.00 - minimum: -9999999999999.99 - maximum: 9999999999999.99 - examples: - zero: 0 - zerozero: 0.00 - tenten: 10.10 - negative: -0.10 diff --git a/boat-engine/src/test/resources/raml-examples/typesystem/referencing-using-libs/api.raml b/boat-engine/src/test/resources/raml-examples/typesystem/referencing-using-libs/api.raml deleted file mode 100755 index 28a76d772..000000000 --- a/boat-engine/src/test/resources/raml-examples/typesystem/referencing-using-libs/api.raml +++ /dev/null @@ -1,16 +0,0 @@ -#%RAML 1.0 - -title: ACME Banking HTTP API -version: 1.0 -mediaType: application/json - -uses: - shapes: dataTypes/shapes.raml - -/resource: - get: - responses: - 200: - body: - application/json: - type: shapes.PersonData \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/typesystem/referencing-using-libs/dataTypes/address.raml b/boat-engine/src/test/resources/raml-examples/typesystem/referencing-using-libs/dataTypes/address.raml deleted file mode 100755 index 4f8011d68..000000000 --- a/boat-engine/src/test/resources/raml-examples/typesystem/referencing-using-libs/dataTypes/address.raml +++ /dev/null @@ -1,8 +0,0 @@ -#%RAML 1.0 DataType - -properties: - address_country: - address_locality: - address_region: - postal_code: - street_address: \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/typesystem/referencing-using-libs/dataTypes/customer.raml b/boat-engine/src/test/resources/raml-examples/typesystem/referencing-using-libs/dataTypes/customer.raml deleted file mode 100755 index 3bb61b053..000000000 --- a/boat-engine/src/test/resources/raml-examples/typesystem/referencing-using-libs/dataTypes/customer.raml +++ /dev/null @@ -1,11 +0,0 @@ -#%RAML 1.0 DataType - -uses: - shapes: shapes.raml - -properties: - type: - lei: - tax_id: - email: - address: shapes.AddressData \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/typesystem/referencing-using-libs/dataTypes/person.raml b/boat-engine/src/test/resources/raml-examples/typesystem/referencing-using-libs/dataTypes/person.raml deleted file mode 100755 index e2a38f941..000000000 --- a/boat-engine/src/test/resources/raml-examples/typesystem/referencing-using-libs/dataTypes/person.raml +++ /dev/null @@ -1,19 +0,0 @@ -#%RAML 1.0 DataType - -uses: - shapes: shapes.raml - -type: shapes.CustomerData -properties: - id: string - title?: - type: string - enum: [mr, mrs, ms, dr] - given_name: string - family_name: string - gender: - type: string - enum: [female, male] - vat_id?: string - birth_date: date-only - death_date?: date-only \ No newline at end of file diff --git a/boat-engine/src/test/resources/raml-examples/typesystem/referencing-using-libs/dataTypes/shapes.raml b/boat-engine/src/test/resources/raml-examples/typesystem/referencing-using-libs/dataTypes/shapes.raml deleted file mode 100755 index 841473785..000000000 --- a/boat-engine/src/test/resources/raml-examples/typesystem/referencing-using-libs/dataTypes/shapes.raml +++ /dev/null @@ -1,8 +0,0 @@ -#%RAML 1.0 Library - -usage: Data shapes for the HTTP API - -types: - AddressData: !include address.raml - CustomerData: !include customer.raml - PersonData: !include person.raml diff --git a/boat-engine/src/test/resources/raml-examples/typesystem/simple.raml b/boat-engine/src/test/resources/raml-examples/typesystem/simple.raml deleted file mode 100644 index a2b3aa335..000000000 --- a/boat-engine/src/test/resources/raml-examples/typesystem/simple.raml +++ /dev/null @@ -1,19 +0,0 @@ -#%RAML 1.0 -title: API with Types -types: # global type definitions that can be reused throughout this API - User: # define type named `User` - type: object - properties: - firstName: string - lastName: string - age: - type: integer - minimum: 0 - maximum: 125 -/users/{id}: - get: - responses: - 200: - body: - application/json: - type: User # reference to global type definition diff --git a/boat-maven-plugin/README.md b/boat-maven-plugin/README.md index 980e0b6e9..5d1469a52 100644 --- a/boat-maven-plugin/README.md +++ b/boat-maven-plugin/README.md @@ -2,20 +2,6 @@ The `boat` plugin has multiple goals: - -## boat:export - -Generates client/server code from a OpenAPI json/yaml definition. Finds files name `api.raml`, `client-api.raml` or `service-api.raml`. -Processes these files (and the json schemes they refer to) to produce `open-api.yaml` files in the output directory. - -## boat:export-bom - -Converts all RAML spec dependencies to OpenAPI Specs. See integration tests for examples - -## boat:export-dep - -Exports project dependencies where the ArtifactId ends with. See integration tests for examples '-spec'. - ## boat:generate Open API Generator based on https://github.com/OpenAPITools/openapi-generator/tree/master/modules/openapi-generator-maven-plugin. All configuration options as diff --git a/boat-maven-plugin/pom.xml b/boat-maven-plugin/pom.xml index 10abd165c..58ec41c9d 100644 --- a/boat-maven-plugin/pom.xml +++ b/boat-maven-plugin/pom.xml @@ -5,7 +5,7 @@ com.backbase.oss backbase-openapi-tools - 0.16.12-SNAPSHOT + 0.17.0-SNAPSHOT boat-maven-plugin @@ -32,7 +32,7 @@ - + @@ -43,10 +43,16 @@ ${project.version}
+ + commons-lang + commons-lang + 2.6 + + org.openapitools.openapidiff openapi-diff-core - 2.0.0-beta.6 + 2.1.0-beta.4 @@ -74,6 +80,13 @@ provided + + org.apache.maven + maven-artifact + ${maven.api.version} + provided + + org.apache.maven.shared maven-artifact-transfer @@ -111,13 +124,6 @@ provided - - org.apache.maven - maven-artifact - ${maven.api.version} - provided - - ch.qos.logback logback-classic @@ -332,7 +338,8 @@ ${project.build.directory}/local-repo src/it/settings.xml - org.jacoco:org.jacoco.agent:${jacoco-maven-plugin.version}:jar:runtime + org.jacoco:org.jacoco.agent:${jacoco-maven-plugin.version}:jar:runtime + @@ -366,7 +373,7 @@ com.backbase.oss.boat.bay.client.api feign java8 - @lombok.AllArgsConstructor @lombok.Builder @lombok.NoArgsConstructor + @lombok.AllArgsConstructor @lombok.Builder diff --git a/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/src/main/resources/presentation-client-api/index.html b/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/src/main/resources/presentation-client-api/index.html index 80aa61995..33e9fa22b 100644 --- a/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/src/main/resources/presentation-client-api/index.html +++ b/boat-maven-plugin/src/it/example/boat-artifact-input/openapi-specs/openapi-zips/src/main/resources/presentation-client-api/index.html @@ -6,19 +6,3 @@ - - - - - - - - - \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-artifact-input/pom.xml b/boat-maven-plugin/src/it/example/boat-artifact-input/pom.xml index 073f0b85d..4e7f588bb 100644 --- a/boat-maven-plugin/src/it/example/boat-artifact-input/pom.xml +++ b/boat-maven-plugin/src/it/example/boat-artifact-input/pom.xml @@ -16,7 +16,7 @@ BOAT :: DOCandLint - Example projects showing exporting RAML to OpenAPI from source files. + Example projects showing how to use BOAT Specs can be in source files, or retrieved from dependencies diff --git a/boat-maven-plugin/src/it/example/boat-export/export-bom/pom.xml b/boat-maven-plugin/src/it/example/boat-export/export-bom/pom.xml deleted file mode 100644 index cbf5439f0..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/export-bom/pom.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - 4.0.0 - - - com.backbase.oss.boat.example - boat-export - 1.0.0-SNAPSHOT - - - export-bom - pom - - - - - com.backbase.oss - boat-maven-plugin - - - export - generate-sources - - export-bom - - - - com.backbase.oss.boat.example - raml-spec-bom - [1.0.0,) - pom - - .* - http://www.backbase.com/wp-content/uploads/2017/04/backbase-logo-png.png - Backbase - # Disclaimer - This API is converted from RAML1.0 using the boat-maven-plugin. - - true - - - - - - - - - diff --git a/boat-maven-plugin/src/it/example/boat-export/export-dep/pom.xml b/boat-maven-plugin/src/it/example/boat-export/export-dep/pom.xml deleted file mode 100644 index a50fe463c..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/export-dep/pom.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - 4.0.0 - - - com.backbase.oss.boat.example - boat-export - 1.0.0-SNAPSHOT - - - export-dep - pom - - - - com.backbase.oss.boat.example - raml-spec - 1.0.0-SNAPSHOT - - - - - - - com.backbase.oss - boat-maven-plugin - - - export - generate-sources - - export-dep - - - **/*.raml - - - - - - - - - diff --git a/boat-maven-plugin/src/it/example/boat-export/pom.xml b/boat-maven-plugin/src/it/example/boat-export/pom.xml deleted file mode 100644 index 8475f5d03..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/pom.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - 4.0.0 - - - com.backbase.oss.boat.example - example - 1.0.0-SNAPSHOT - - - boat-export - - BOAT :: Export RAML 2 Open API - - - Example projects showing exporting RAML to OpenAPI from source files. - Specs can be in source files, or retrieved from dependencies - - - pom - - - raml-specs - export-bom - export-dep - - - diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/pom.xml b/boat-maven-plugin/src/it/example/boat-export/raml-specs/pom.xml deleted file mode 100644 index c26370636..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/pom.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - 4.0.0 - - - com.backbase.oss.boat.example - boat-export - 1.0.0-SNAPSHOT - - - raml-specs - pom - - - raml-spec - raml-spec-version-2 - raml-spec-bom - raml-spec-bom-version-2 - raml-spec-bom-version-3-profiles - - - - diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-bom-version-2/pom.xml b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-bom-version-2/pom.xml deleted file mode 100644 index c1b3cfb21..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-bom-version-2/pom.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - 4.0.0 - - com.backbase.oss.boat.example - raml-spec-bom - 1.1.0-SNAPSHOT - - - 1.1.0-SNAPSHOT - - - pom - - - BOAT :: RAML Bill-Of-Materials - - - - - com.backbase.oss.boat.example - raml-spec - ${raml-spec.version} - - - - - - - - diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-bom-version-3-profiles/pom.xml b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-bom-version-3-profiles/pom.xml deleted file mode 100644 index 7b57ed204..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-bom-version-3-profiles/pom.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - 4.0.0 - - com.backbase.oss.boat.example - raml-spec-bom - 1.2.0-SNAPSHOT - - - 1.1.0-SNAPSHOT - - - pom - - BOAT :: RAML Bill-Of-Materials - - - - - com.backbase.oss.boat.example - raml-spec - ${raml-spec.version} - - - - - - - profileWithSpecs - - - com.backbase.oss.boat.example - raml-spec - - - - - - - diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-bom/pom.xml b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-bom/pom.xml deleted file mode 100644 index 51b78d2fd..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-bom/pom.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - 4.0.0 - - com.backbase.oss.boat.example - raml-spec-bom - 1.0.0-SNAPSHOT - - - 1.0.0-SNAPSHOT - - - pom - - BOAT :: RAML Bill-Of-Materials - - - - - com.backbase.oss.boat.example - raml-spec - ${raml-spec.version} - - - - - - - - diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/pom.xml b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/pom.xml deleted file mode 100644 index 084b62ac1..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/pom.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - 4.0.0 - - com.backbase.oss.boat.example - raml-spec - 1.1.0-SNAPSHOT - - jar - - BOAT :: RAML Example - - diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/bbt-common.raml b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/bbt-common.raml deleted file mode 100644 index 281655811..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/bbt-common.raml +++ /dev/null @@ -1,7 +0,0 @@ -#%RAML 1.0 Library -schemas: - ObjectWrappingException: !include common-schemas/body/object-wrapping-exception.json -types: - PaymentCard: !include common-schemas/body/paymentcard-item.json - PaymentCards: !include common-schemas/body/paymentcards-get.json - TestHeadersResponseBody: !include common-schemas/body/test-headers-response.json \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/common-schemas/body/date-query-params.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/common-schemas/body/date-query-params.json deleted file mode 100644 index 377c9a7fc..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/common-schemas/body/date-query-params.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType":"com.backbase.buildingblocks.test.data.DateTimeTestResponse", - "properties": { - "dateTimeOnly": { - "type": "string" - }, - "dateTimeOnlyParsedValue": { - "type": "string" - }, - "dateTime": { - "type": "string" - }, - "dateTimeParsedValue": { - "type": "string" - }, - "dateTime2616": { - "type": "string" - }, - "dateTime2616ParsedValue": { - "type": "string" - }, - "date": { - "type": "string" - }, - "dateParsedValue": { - "type": "string" - }, - "time": { - "type": "string" - }, - "timeParsedValue": { - "type": "string" - }, - "formatDateTime": { - "description": "The dateTime parameter formatted as 'date-time', java.util.Date or java.time.ZoneDateTime", - "type": "string", - "format": "date-time" - }, - "formatDate": { - "description": "The date parameter formatted as 'date', String or java.time.LocalDate", - "type": "string", - "format": "date" - }, - "formatTime": { - "description": "The time parameter formatted as 'time', String or java.time.LocalTime", - "type": "string", - "format": "time" - }, - "formatUtcMillisec": { - "description": "The dateTime parameter formatted as 'date', long", - "type": "string", - "format": "utc-millisec" - } - } -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/common-schemas/body/object-wrapping-exception.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/common-schemas/body/object-wrapping-exception.json deleted file mode 100644 index 4a3a7e1dd..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/common-schemas/body/object-wrapping-exception.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.test.exceptions.ObjectWrappingException", - "properties": { - "message": { - "type": "string" - }, - "data": { - "type": "object" - } - } -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/common-schemas/body/paymentcard-item.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/common-schemas/body/paymentcard-item.json deleted file mode 100644 index 8542e05cb..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/common-schemas/body/paymentcard-item.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType":"com.backbase.buildingblocks.test.data.PaymentCard", - "properties": { - "id": { - "type": "string" - }, - "pan": { - "type": "string", - "description": "Must be sixteen digits, optionally in blocks of 4 separated by a dash", - "maxLength": 19 - }, - "cvc": { - "type": "string", - "description": "Card Verification Code", - "minLength": 3, - "maxLength": 3 - }, - "startDate": { - "type": "string", - "description": "Must be in one of these four formats: MM/YY MMYY MMYYYY MM/YYYY", - "pattern": "^(0[1-9]|1[0-2])\/?([0-9]{4}|[0-9]{2})$" - }, - "expiryDate": { - "type": "string", - "description": "Must be in one of these four formats: MM/YY MMYY MMYYYY MM/YYYY", - "pattern": "^(0[1-9]|1[0-2])\/?([0-9]{4}|[0-9]{2})$" - }, - "nameOnCard": { - "type": "string" - }, - "creationDate" : { - "type":"string", - "format":"date-time" - }, - "balance" : { - "type": "object", - "$ref": "../../lib/types/schemas/currency.json" - }, - "apr": { - "type": "number", - "javaType": "java.math.BigDecimal" - }, - "cardtype" : { - "type" : "string", - "default" : "CREDIT", - "enum" : ["CREDIT", "DEBIT", "PREPAID"] - } - }, - "required": [ - "id", - "pan", - "cvc", - "startDate", - "expiryDate", - "nameOnCard" - ] -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/common-schemas/body/paymentcards-get.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/common-schemas/body/paymentcards-get.json deleted file mode 100644 index 16c29a9f7..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/common-schemas/body/paymentcards-get.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "array", - "items": { - "$ref": "paymentcard-item.json" - } -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/common-schemas/body/test-headers-response.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/common-schemas/body/test-headers-response.json deleted file mode 100644 index 4c0635545..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/common-schemas/body/test-headers-response.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType":"com.backbase.buildingblocks.test.data.TestHeadersResponse", - "additionalProperties": false, - "properties": { - "requests": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "url": { - "type": "string" - }, - "headers": { - "type": "object", - "javaType": "java.util.Map" - } - } - } - } - } - } \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/events/add-paymentcard-command.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/events/add-paymentcard-command.json deleted file mode 100644 index 1296ef118..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/events/add-paymentcard-command.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "required": true, - "properties": { - "paymentcard": { - "type": "object", - "$ref": "../common-schemas/body/paymentcard-item.json" - } - } -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/events/delete-paymentcard-command.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/events/delete-paymentcard-command.json deleted file mode 100644 index 81b24e284..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/events/delete-paymentcard-command.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "required": true, - "properties": { - "paymentcard": { - "type": "object", - "$ref": "../schemas/body/paymentcard-id.json" - } - } -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/events/get-paymentcards-command.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/events/get-paymentcards-command.json deleted file mode 100644 index 2d04dc7a3..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/events/get-paymentcards-command.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "required": true, - "properties": { - "queryParams": { - "type": "object", - "$ref": "../schemas/body/paymentcards-query.json" - } - } -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/events/paymentcard-added-event.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/events/paymentcard-added-event.json deleted file mode 100644 index d1efda594..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/events/paymentcard-added-event.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "required": true, - "properties": { - "paymentcard": { - "type": "object", - "$ref": "../common-schemas/body/paymentcard-item.json" - }, - "emitDateTime": { - "description": "The dateTime parameter formatted as 'date-time', java.util.Date or java.time.ZoneDateTime", - "type": "string", - "format": "date-time" - }, - "emitDate": { - "description": "The date parameter formatted as 'date', String or java.time.LocalDate", - "type": "string", - "format": "date" - }, - "emitTime": { - "description": "The time parameter formatted as 'time', String or java.time.LocalTime", - "type": "string", - "format": "time" - }, - "emitMillisec": { - "description": "The dateTime parameter formatted as 'date', long", - "type": "string", - "format": "utc-millisec" - } - } -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/events/paymentcard-deleted-event.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/events/paymentcard-deleted-event.json deleted file mode 100644 index d1efda594..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/events/paymentcard-deleted-event.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "required": true, - "properties": { - "paymentcard": { - "type": "object", - "$ref": "../common-schemas/body/paymentcard-item.json" - }, - "emitDateTime": { - "description": "The dateTime parameter formatted as 'date-time', java.util.Date or java.time.ZoneDateTime", - "type": "string", - "format": "date-time" - }, - "emitDate": { - "description": "The date parameter formatted as 'date', String or java.time.LocalDate", - "type": "string", - "format": "date" - }, - "emitTime": { - "description": "The time parameter formatted as 'time', String or java.time.LocalTime", - "type": "string", - "format": "time" - }, - "emitMillisec": { - "description": "The dateTime parameter formatted as 'date', long", - "type": "string", - "format": "utc-millisec" - } - } -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/events/paymentcards-retrieved-event.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/events/paymentcards-retrieved-event.json deleted file mode 100644 index 2cbadf471..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/events/paymentcards-retrieved-event.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "required": true, - "properties": { - "queryParams": { - "type": "object", - "$ref": "../schemas/body/paymentcards-query.json" - }, - "results": { - "type": "array", - "items": { - "$ref": "../common-schemas/body/paymentcard-item.json" - } - }, - "emitDateTime": { - "description": "The dateTime parameter formatted as 'date-time', java.util.Date or java.time.ZoneDateTime", - "type": "string", - "format": "date-time" - }, - "emitDate": { - "description": "The date parameter formatted as 'date', String or java.time.LocalDate", - "type": "string", - "format": "date" - }, - "emitTime": { - "description": "The time parameter formatted as 'time', String or java.time.LocalTime", - "type": "string", - "format": "time" - }, - "emitMillisec": { - "description": "The dateTime parameter formatted as 'date', long", - "type": "string", - "format": "utc-millisec" - } - } -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/examples/body/example-build-info.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/examples/body/example-build-info.json deleted file mode 100644 index 5cc40dd5d..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/examples/body/example-build-info.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "build-info": { - "build.version": "1.1.111-SNAPSHOT" - } -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/examples/body/item.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/examples/body/item.json deleted file mode 100644 index 89a3fdb1f..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/examples/body/item.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "Example", - "description": "Example description" -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/examples/body/paymentcard-created.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/examples/body/paymentcard-created.json deleted file mode 100644 index 3706a5fbc..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/examples/body/paymentcard-created.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "id": "a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1" -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/examples/body/paymentcard-item.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/examples/body/paymentcard-item.json deleted file mode 100644 index 72777d92d..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/examples/body/paymentcard-item.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "id": "a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1", - "pan": "5434111122223333", - "cvc": "123", - "startDate": "0116", - "expiryDate": "1219", - "nameOnCard": "Mr Timmy Tester", - "creationDate": "2011-05-30T12:13:14+03:00", - "balance": { - "amount": "1000", - "currencyCode": "EUR" - }, - "apr": 12.75 -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/examples/body/paymentcards-get.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/examples/body/paymentcards-get.json deleted file mode 100644 index a7d5dc369..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/examples/body/paymentcards-get.json +++ /dev/null @@ -1,44 +0,0 @@ -[ - { - "id": "a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1", - "pan": "5434111122223333", - "cvc": "123", - "startDate": "0116", - "expiryDate": "1219", - "nameOnCard": "Mr Timmy Tester", - "creationDate": "2011-05-30T12:13:14+03:00", - "balance": { - "amount": "2001", - "currencyCode": "EUR" - }, - "apr": 12.75 - }, - { - "id": "d593c212-70ad-41a6-a547-d5d9232414cb", - "pan": "5434111122224444", - "cvc": "101", - "startDate": "0216", - "expiryDate": "0120", - "nameOnCard": "Mr Timmothy Tester", - "creationDate": "2011-05-30T12:13:14+03:00", - "balance": { - "amount": "4.4399999999999995", - "currencyCode": "GBP" - }, - "apr": 12.75 - }, - { - "id": "9635966b-28e9-4479-8121-bb7bc9beeb62", - "pan": "5434121212121212", - "cvc": "121", - "startDate": "0115", - "expiryDate": "1218", - "nameOnCard": "Mr Timmy Tester", - "creationDate": "2011-05-30T12:13:14+03:00", - "balance": { - "amount": "1981", - "currencyCode": "EUR" - }, - "apr": 12.75 - } -] \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/examples/body/test-headers-response.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/examples/body/test-headers-response.json deleted file mode 100644 index bcc24c481..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/examples/body/test-headers-response.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "requests" : [ - { - "name": "building-blocks-test-wallet-presentation-service", - "url": "/client-api/v1/test/headers", - "headers": { - "correlation-id": [ "2ed475b714a3945a" ], - "accept": [ "application/json" ], - "x-bbt-test": [ "X-BBT-contentVal2" ], - "connection": [ "keep-alive" ] - } - }, - { - "name": "building-blocks-test-wallet-pandp-service", - "url": "/service-api/v1/test/headers", - "headers": { - "authorization": [ "Bearer eyJh" ], - "accept": [ "application/xml, text/xml, application/json, application/*+xml, application/*+json" ], - "content-type": [ "application/json" ], - "x-cxt-user-token": [ "Bearer ey" ], - "x-cxt-remote-user": [ "admin" ], - "x-cxt-requestuuid": [ "72002652-131a-4f28-bd00-16b8080932f5" ], - "correlation-id": [ "2ed475b714a3945a" ], - "x-bbt-test": [ "X-BBT-contentVal2" ] - } - }, - { - "name": "building-blocks-test-wallet-pandp-service", - "url": "/service-api/v1/test/headers", - "headers": { - "authorization": [ "Bearer eyJh" ], - "accept": [ "application/xml, text/xml, application/json, application/*+xml, application/*+json" ], - "content-type": [ "application/json" ], - "x-cxt-user-token": [ "Bearer ey" ], - "x-cxt-remote-user": [ "admin" ], - "x-cxt-requestuuid": [ "72002652-131a-4f28-bd00-16b8080932f5" ], - "correlation-id": [ "2ed475b714a3945a" ], - "x-bbt-test": [ "X-BBT-contentVal2" ] - } - } - ] -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/examples/body/test-values-response.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/examples/body/test-values-response.json deleted file mode 100644 index eb5f7bd7b..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/examples/body/test-values-response.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "message": "a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1", - "number": "102.4" -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/examples/errors/error.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/examples/errors/error.json deleted file mode 100644 index 26d84f14d..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/examples/errors/error.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "message": "Description of error", - "errorCode" : "EXAMPLE-000001" -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/annotations/annotations.raml b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/annotations/annotations.raml deleted file mode 100644 index ea6032759..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/annotations/annotations.raml +++ /dev/null @@ -1,38 +0,0 @@ -#%RAML 1.0 Library - -securitySchemes: -# Custom 'bbAccessControl' security schema -# RAML 1-0 does not allow settings in an x-other security scheme, so no opportunity to describe extra information here - bbAccessControl: - displayName: Backbase Access Control - description: | - This API is secured by DBS Access Control - type: x-bb-access-control - -# RAML annotation and associated types that can be included in API specification files -annotationTypes: - x-bb-api-type: - displayName: API Type - description: | - Signals whether this API endpoint is intended for use by users (HTTP APIs exposed by presentation services) or by - systems (HTTP APIs exposed by inbound integration services) - type: array - items: - type: string - enum: [user, system] - x-bb-access-control: - displayName: Backbase Access Control - description: | - Describes which Resource, Function and Privilege need to be granted to the user to allow access to this API - type: BB-Access-Control - x-bb-api-deprecation: - displayName: API Deprecation - description: | - Signals that the API endpoint is deprecated, providing details on when the API was deprecated, when it will be - removed, the reason for deprecation and a more general description in Markdown that can be used to provide more - information on the deprecation and migration strategy - type: BB-Api-Deprecation - -schemas: - BB-Access-Control: !include ../types/schemas/bb-access-control.json - BB-Api-Deprecation: !include ../types/schemas/bb-api-deprecation.json \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/traits/traits.raml b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/traits/traits.raml deleted file mode 100644 index 1cfe6eb99..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/traits/traits.raml +++ /dev/null @@ -1,132 +0,0 @@ -#%RAML 1.0 Library -schemas: - Bad-Request-Error: !include ../types/schemas/bad-request-error.json - Unauthorized-Error: !include ../types/schemas/unauthorized-error.json - Unauthorized-Alt-Error: !include ../types/schemas/unauthorized-alt-error.json - Not-Acceptable-Error: !include ../types/schemas/not-acceptable-error.json - Internal-Server-Error: !include ../types/schemas/internal-server-error.json - Forbidden-Error: !include ../types/schemas/forbidden-error.json - Not-Found-Error: !include ../types/schemas/not-found-error.json - Unsupported-Media-Type-Error: !include ../types/schemas/unsupported-media-type-error.json -traits: - idempotent: - headers: - X-Request-Id: - description: Correlates HTTP requests between a client and server. - required: false - example: f058ebd6-02f7-4d3f-942e-904344e8cde5 - pageable: - queryParameters: - from: - description: Page Number. Skip over pages of elements by specifying a start value for the query - type: integer - required: false - example: 20 - default: 0 - cursor: - description: | - Record UUID. As an alternative for specifying 'from' this allows to point to the record to start the selection from. - type: string - required: false - example: 76d5be8b-e80d-4842-8ce6-ea67519e8f74 - default: "" - size: - description: | - Limit the number of elements on the response. When used in combination with cursor, the value - is allowed to be a negative number to indicate requesting records upwards from the starting point indicated - by the cursor. - type: integer - required: false - example: 80 - default: 10 - orderable: - queryParameters: - orderBy: - description: | - Order by field: <> - type: string - required: false - direction: - description: Direction - enum: [ASC, DESC] - default: DESC - required: false - challengeable: - headers: - X-MFA: - description: Challenge payload response - required: false - example: sms challenge="123456789" - responses: - 401: - description: Unauthorized - headers: - WWW-Authenticate: - description: Comma separated challenges - required: false - example: sms challenge="", pki challenge="Z8nlwZe0daUNWCWIbfJe3iIgauh" - body: - application/json: - type: Unauthorized-Error - BadRequestError: - responses: - 400: - description: BadRequest - body: - application/json: - type: Bad-Request-Error - example: !include ../types/examples/example-bad-request-error.json - UnauthorizedError: - responses: - 401: - description: Unauthorized - headers: - WWW-Authenticate: - description: Indicates the authentication scheme(s) and parameters applicable to the target resource - required: false - example: | - WWW-Authenticate: Newauth realm="apps", type=1, title="Login to \"apps\"", Basic realm="simple" - body: - application/json: - type: Unauthorized-Alt-Error - example: !include ../types/examples/example-unauthorized-alt-error.json - ForbiddenError: - responses: - 403: - description: Forbidden - body: - application/json: - type: Forbidden-Error - example: !include ../types/examples/example-forbidden-error.json - NotFoundError: - responses: - 404: - description: NotFound - body: - application/json: - type: Not-Found-Error - example: !include ../types/examples/example-not-found-error.json - NotAcceptableError: - responses: - 406: - description: NotAcceptable - body: - application/json: - type: Not-Acceptable-Error - example: !include ../types/examples/example-not-acceptable-error.json - UnsupportedMediaTypeError: - responses: - 415: - description: UnsupportedMediaType - body: - application/json: - type: Unsupported-Media-Type-Error - example: !include ../types/examples/example-unsupported-media-type-error.json - InternalServerError: - responses: - 500: - description: InternalServerError - body: - application/json: - type: Internal-Server-Error - example: !include ../types/examples/example-internal-server-error.json diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/examples/example-bad-request-error.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/examples/example-bad-request-error.json deleted file mode 100644 index 77243186b..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/examples/example-bad-request-error.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "message": "Bad Request", - "errors": [ - { - "message": "Value Exceeded. Must be between {min} and {max}.", - "key": "common.api.shoesize", - "context": { - "max": "50", - "min": "1" - } - } - ] -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/examples/example-currency.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/examples/example-currency.json deleted file mode 100644 index ff365438f..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/examples/example-currency.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "amount": "1.12", - "currencyCode": "TST" -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/examples/example-forbidden-error.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/examples/example-forbidden-error.json deleted file mode 100644 index e26366a7c..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/examples/example-forbidden-error.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "message": "Access to requested resource denied.", - "errors": [ - { - "message": "Resource access denied due to an insufficient user quota of {quota}.", - "key": "common.api.quota", - "context": { - "quota": "someQuota" - } - } - ] -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/examples/example-internal-server-error.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/examples/example-internal-server-error.json deleted file mode 100644 index c6701087a..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/examples/example-internal-server-error.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "message": "Description of error" -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/examples/example-not-acceptable-error.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/examples/example-not-acceptable-error.json deleted file mode 100644 index 0b4ab5da9..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/examples/example-not-acceptable-error.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "message": "Could not find acceptable representation", - "supportedMediaTypes": [ - "application/json" - ] -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/examples/example-not-found-error.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/examples/example-not-found-error.json deleted file mode 100644 index 2d6d616b8..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/examples/example-not-found-error.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "message": "Resource not found.", - "errors": [ - { - "message": "Unable to find the resource requested resource: {resource}.", - "key": "common.api.resource", - "context": { - "resource": "aResource" - } - } - ] -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/examples/example-unauthorized-alt-error.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/examples/example-unauthorized-alt-error.json deleted file mode 100644 index 6b692d0b3..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/examples/example-unauthorized-alt-error.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "message": "Access to requested resource denied.", - "errors": [ - { - "message": "Resource access denied due to invalid credentials.", - "key": "common.api.token", - "context": { - "accessToken": "expired" - } - } - ] -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/examples/example-unauthorized-error.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/examples/example-unauthorized-error.json deleted file mode 100644 index 44f8e8dc6..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/examples/example-unauthorized-error.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "message": "You are not authorized to perform this action" -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/examples/example-unsupported-media-type-error.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/examples/example-unsupported-media-type-error.json deleted file mode 100644 index 9dba54d8f..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/examples/example-unsupported-media-type-error.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "message": "Unsupported media type.", - "errors": [ - { - "message": "The request entity has a media type {mediaType} which the resource does not support.", - "key": "common.api.mediaType", - "context": { - "mediaType": "application/javascript" - } - } - ] -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/schemas/bad-request-error.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/schemas/bad-request-error.json deleted file mode 100644 index d6314386c..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/schemas/bad-request-error.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.presentation.errors.BadRequestException", - "properties": { - "message": { - "type": "string", - "description": "Any further information" - }, - "errors": { - "type": "array", - "description": "Detailed error information", - "items": { - "$ref": "error-item.json" - } - } - }, - "required": [ - "message" - ] -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/schemas/bb-access-control.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/schemas/bb-access-control.json deleted file mode 100644 index 629f43147..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/schemas/bb-access-control.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "resource": { - "type": "string", - "description": "Resource being protected, e.g. 'User'" - }, - "function": { - "type": "string", - "description": "Business function, e.g. 'Manage Users'" - }, - "privilege": { - "type": "string", - "description": "The privilege required, e.g. 'view'" - } - }, - "required": [ - "resource", - "function", - "privilege" - ] -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/schemas/bb-api-deprecation.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/schemas/bb-api-deprecation.json deleted file mode 100644 index 9d7339566..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/schemas/bb-api-deprecation.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "deprecatedFromVersion": { - "type": "string", - "description": "Version of the product from which the endpoint has been deprecated and should no longer be used" - }, - "removedFromVersion": { - "type": "string", - "description": "Version of the product from which the API endpoint will be removed" - }, - "reason": { - "type": "string", - "description": "The reason the API endpoint was deprecated" - }, - "description": { - "type": "string", - "description": "Any further information, e.g. migration information" - } - }, - "required": [ - "deprecatedFromVersion", - "removedFromVersion", - "reason", - "description" - ] -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/schemas/currency.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/schemas/currency.json deleted file mode 100644 index 457bd84ed..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/schemas/currency.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "title": "Monetary Amount", - "description": "Schema defining monetary amount in given currency.", - "javaType": "com.backbase.rest.spec.common.types.Currency", - "properties": { - "amount": { - "type": "string", - "javaType": "java.math.BigDecimal", - "description": "The amount in the specified currency" - }, - "currencyCode": { - "type": "string", - "description": "The alpha-3 code (complying with ISO 4217) of the currency that qualifies the amount", - "pattern": "^[A-Z]{3}$" - } - }, - "required": [ - "amount", - "currencyCode" - ] -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/schemas/error-item.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/schemas/error-item.json deleted file mode 100644 index 4868a1047..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/schemas/error-item.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "description": "A validation error", - "javaInterfaces": [ - "java.io.Serializable", - "Cloneable" - ], - "properties": { - "message": { - "type": "string", - "description": "Default Message. Any further information." - }, - "key": { - "type": "string", - "description": "{capability-name}.api.{api-key-name}. For generated validation errors this is the path in the document the error resolves to. e.g. object name + '.' + field" - }, - "context": { - "type": "object", - "description": "Context can be anything used to construct localised messages.", - "javaType": "java.util.Map" - } - } -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/schemas/forbidden-error.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/schemas/forbidden-error.json deleted file mode 100644 index 671b17956..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/schemas/forbidden-error.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.presentation.errors.ForbiddenException", - "properties": { - "message": { - "type": "string", - "description": "Any further information" - }, - "errors": { - "type": "array", - "description": "Detailed error information", - "items": { - "$ref": "error-item.json" - } - } - } -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/schemas/internal-server-error.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/schemas/internal-server-error.json deleted file mode 100644 index d7d6cafd8..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/schemas/internal-server-error.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.presentation.errors.InternalServerErrorException", - "description": "Represents HTTP 500 Internal Server Error", - "properties": { - "message": { - "type": "string", - "description": "Further Information" - } - }, - "required": [ - "message" - ] -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/schemas/not-acceptable-error.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/schemas/not-acceptable-error.json deleted file mode 100644 index f39202d2b..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/schemas/not-acceptable-error.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.presentation.errors.NotAcceptableException", - "properties": { - "message": { - "type": "string" - }, - "supportedMediaTypes": { - "type": "array", - "description": "List of supported media types for this endpoint", - "items": { - "type": "string" - } - } - } -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/schemas/not-found-error.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/schemas/not-found-error.json deleted file mode 100644 index 3ce00ba4f..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/schemas/not-found-error.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.presentation.errors.NotFoundException", - "properties": { - "message": { - "type": "string", - "description": "Any further information" - }, - "errors": { - "type": "array", - "description": "Detailed error information", - "items": { - "$ref": "error-item.json" - } - } - } -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/schemas/unauthorized-alt-error.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/schemas/unauthorized-alt-error.json deleted file mode 100644 index 388b7326b..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/schemas/unauthorized-alt-error.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.presentation.errors.UnauthorizedException", - "properties": { - "message": { - "type": "string", - "description": "Any further information" - }, - "errors": { - "type": "array", - "description": "Detailed error information", - "items": { - "$ref": "error-item.json" - } - } - } -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/schemas/unauthorized-error.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/schemas/unauthorized-error.json deleted file mode 100644 index 5c30948ac..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/schemas/unauthorized-error.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "message": { - "type": "string" - } - }, - "required": [ - "message" - ] -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/schemas/unsupported-media-type-error.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/schemas/unsupported-media-type-error.json deleted file mode 100644 index 87e2ebba6..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/lib/types/schemas/unsupported-media-type-error.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.presentation.errors.UnsupportedMediaTypeException", - "properties": { - "message": { - "type": "string", - "description": "Any further information" - }, - "errors": { - "type": "array", - "description": "Detailed error information", - "items": { - "$ref": "error-item.json" - } - } - } -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/presentation-client-api.raml b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/presentation-client-api.raml deleted file mode 100644 index d3523898a..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/presentation-client-api.raml +++ /dev/null @@ -1,226 +0,0 @@ -#%RAML 1.0 ---- -#=============================================================== -# Messages - RAML example http://raml.org/ -# References: -# - RAML Specification - https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md -#=============================================================== -title: Wallet Test Client API -uses: - traits: lib/traits/traits.raml - bb: lib/annotations/annotations.raml - common: bbt-common.raml -version: v1 -baseUri: "client-api/{version}" -mediaType: application/json -protocols: [ HTTP, HTTPS ] -#=============================================================== -# API resource definitions -#=============================================================== -securedBy: [ bb.bbAccessControl ] -(bb.x-bb-api-type): [user] -/wallet: - displayName: Wallet - /paymentcards: - displayName: Payment Cards - get: - (bb.x-bb-access-control): - resource: WALLET - function: MANAGE_PAYMENT_CARDS - privilege: READ_PAYMENT_CARD - is: [traits.BadRequestError, traits.NotAcceptableError, traits.orderable: {fieldsList: nameOnCard}, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: "Returns available payment card details for user, optionally filtered by nameOnCard" - queryParameters: - nameOnCard: - description: "Filter by the cardholder's name (case-insensitive), can be the first one or more characters of one of the words/names" - required: false - type: string - example: "Smi" - dateTimeOnly: - description: Creation date in datetime-only format - required: false - type: datetime-only - example: 2017-10-04T14:54:36 - dateTime: - description: Creation date in Zoned RFC3339 Date-time format - required: false - type: datetime - format: rfc3339 - example: 2017-10-04T14:54:36Z - dateTime2616: - description: Zoned RFC2616 Date-time param example - required: false - type: datetime - format: rfc2616 - example: Wed, 4 Jul 2001 12:08:56 PDT - date: - description: Date-only param example - required: false - type: date-only - example: 2017-10-04 - time: - description: time-only param example - required: false - type: time-only - example: 14:54:36 - responses: - 200: - body: - application/json: - type: common.PaymentCards - example: !include examples/body/paymentcards-get.json - text/csv: - application/xml: - post: - (bb.x-bb-access-control): - resource: WALLET - function: MANAGE_PAYMENT_CARDS - privilege: WRITE_PAYMENT_CARD - is: [traits.BadRequestError, traits.InternalServerError, traits.idempotent, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Adds a payment card to the user's wallet - body: - application/json: - type: common.PaymentCard - example: !include examples/body/paymentcard-item.json - responses: - 201: - description: request to create payment card accepted - body: - application/json: - schema: !include schemas/body/paymentcard-id.json - example: !include examples/body/paymentcard-created.json - /{cardId}: - displayName: Payment Card - uriParameters: - cardId: - type: string - get: - (bb.x-bb-access-control): - resource: WALLET - function: MANAGE_PAYMENT_CARDS - privilege: READ_PAYMENT_CARD - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Returns details of a specific payment card - responses: - 200: - body: - application/json: - type: common.PaymentCard - example: !include examples/body/paymentcard-item.json - delete: - (bb.x-bb-access-control): - resource: WALLET - function: MANAGE_PAYMENT_CARDS - privilege: DELETE_PAYMENT_CARD - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Deletes a payment card with a given id - responses: - 204: - description: Payment card is succesfully deleted -/bbt: - description: API for test operations. - displayName: BBT - /build-info: - get: - description: "Build Information" - responses: - 200: - body: - application/json: - schema: !include schemas/body/build-info.json - example: !include examples/body/example-build-info.json -/patch: - description: PATCH endpoint for test operations - displayName: patch - patch: - is: [traits.BadRequestError, traits.InternalServerError, traits.idempotent, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: "Patch Test" - responses: - 200: - body: - text/plain: - schema: !include schemas/body/patch-response.json -/test: - /required-boolean-query-param: - description: arbitrary tests - displayName: required boolean query param - get: - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - queryParameters: - bool: - description: Required boolean parameter with no default value - required: true - type: boolean - example: false - responses: - 200: - body: - application/json: - schema: !include schemas/body/test-response.json - /values: - description: Test Values - displayName: Test Values - get: - is: [traits.InternalServerError] - responses: - 200: - body: - application/json: - schema: !include schemas/body/test-values-response.json - example: !include examples/body/test-values-response.json - /headers: - description: Test header propagation - displayName: Test header propagation - get: - is: [traits.InternalServerError] - queryParameters: - addHops: - description: number of additional hops to perform - required: false - type: integer - responses: - 200: - body: - application/json: - schema: common.TestHeadersResponseBody - example: !include examples/body/test-headers-response.json - /date-query-params: - description: | - Tests for date/time query parameters in service-apis. Sends the same query parameters to the equivalent endpoint - in the pandp service which echoes the given values back in the response body. Values echoed by the pandp service - are then returned in the response to this request. - displayName: dateQueryParam - get: - queryParameters: - dateTimeOnly: - description: Creation date in datetime-only format - required: false - type: datetime-only - example: 2017-10-04T14:54:36 - dateTime: - description: Creation date in Zoned RFC3339 Date-time format - required: false - type: datetime - format: rfc3339 - example: 2017-10-04T14:54:36Z - dateTime2616: - description: Zoned RFC2616 Date-time param example - required: false - type: datetime - format: rfc2616 - example: Wed, 4 Jul 2001 12:08:56 PDT - date: - description: Date-only param example - required: false - type: date-only - example: 2017-10-04 - time: - description: time-only param example - required: false - type: time-only - example: 14:54:36 - responses: - 200: - body: - application/json: - schema: !include common-schemas/body/date-query-params.json diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/presentation-integration-api.raml b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/presentation-integration-api.raml deleted file mode 100644 index a477df038..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/presentation-integration-api.raml +++ /dev/null @@ -1,32 +0,0 @@ -#%RAML 1.0 ---- -#=============================================================== -# Integration API example -#=============================================================== -title: Example -version: v1 -baseUri: "integration-api/{version}" -mediaType: application/json -protocols: [ HTTP, HTTPS ] -#=============================================================== -# API documentation - Overall documentation. -#=============================================================== -documentation: - - title: Example - content: Test Schema to test an integration-api -#=============================================================== -# API resource definitions -#=============================================================== -/items: - description: Retrieve all items. - displayName: items - uriParameters: null - get: - description: "Retrieve list of all items." - responses: - 200: - description: Test Schema - body: - application/json: - schema: !include schemas/body/item.json - example: !include examples/body/item.json \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/presentation-service-api.raml b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/presentation-service-api.raml deleted file mode 100644 index db9214ea5..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/presentation-service-api.raml +++ /dev/null @@ -1,122 +0,0 @@ -#%RAML 1.0 ---- -#=============================================================== -# Messages - RAML example http://raml.org/ -# References: -# - RAML Specification - https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md -#=============================================================== -title: Wallet Test Service API -uses: - traits: lib/traits/traits.raml - bb: lib/annotations/annotations.raml - common: bbt-common.raml -version: v1 -baseUri: "service-api/{version}" -mediaType: application/json -protocols: [ HTTP, HTTPS ] -#=============================================================== -# API resource definitions -#=============================================================== -securedBy: [ bb.bbAccessControl ] -(bb.x-bb-api-type): [system] -/wallet: - displayName: WalletService - /admin/{userId}: - uriParameters: - userId: - type: string - /paymentcards: - displayName: Payment Cards - get: - is: [traits.BadRequestError, traits.NotAcceptableError, traits.orderable: {fieldsList: nameOnCard}, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: "Returns available payment card details for user, optionally filtered by nameOnCard" - queryParameters: - nameOnCard: - description: "Filter by the cardholder's name (case-insensitive), can be the first one or more characters of one of the words/names" - required: false - type: string - example: "Smi" - dateTimeOnly: - description: Creation date in datetime-only format - required: false - type: datetime-only - example: 2017-10-04T14:54:36 - dateTime: - description: Creation date in Zoned RFC3339 Date-time format - required: false - type: datetime - format: rfc3339 - example: 2017-10-04T14:54:36Z - dateTime2616: - description: Zoned RFC2616 Date-time param example - required: false - type: datetime - format: rfc2616 - example: Wed, 4 Jul 2001 12:08:56 PDT - date: - description: Date-only param example - required: false - type: date-only - example: 2017-10-04 - time: - description: time-only param example - required: false - type: time-only - example: 14:54:36 - responses: - 200: - body: - application/json: - type: common.PaymentCards - example: !include examples/body/paymentcards-get.json - post: - is: [traits.BadRequestError, traits.InternalServerError, traits.idempotent, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Adds a payment card to the user's wallet - body: - application/json: - type: common.PaymentCard - example: !include examples/body/paymentcard-item.json - responses: - 201: - description: request to create payment card accepted - body: - application/json: - schema: !include schemas/body/paymentcard-id.json - example: !include examples/body/paymentcard-created.json - /{cardId}: - displayName: Payment Card - uriParameters: - cardId: - type: string - get: - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Returns details of a specific payment card - responses: - 200: - body: - application/json: - type: common.PaymentCard - example: !include examples/body/paymentcard-item.json - delete: - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Deletes a payment card with a given id - responses: - 204: - description: Payment card is succesfully deleted -/testQuery: - /required-boolean-query-param: - description: arbitrary tests - displayName: required boolean query param - get: - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - queryParameters: - bool: - description: Required boolean parameter with no default value - required: true - type: boolean - example: false - responses: - 200: - body: - application/json: - schema: !include schemas/body/test-response.json \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/schemas/body/build-info.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/schemas/body/build-info.json deleted file mode 100644 index 8ed0b3e16..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/schemas/body/build-info.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "build-info": { - "javaType": "java.util.Map", - "type": "object" - } - } -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/schemas/body/item.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/schemas/body/item.json deleted file mode 100644 index 176cb4743..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/schemas/body/item.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "description": "this models a simple item.", - "properties": { - "name": { - "type": "string" - }, - "description": { - "type": "string" - } - }, - "required": [ - "name" - ] -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/schemas/body/patch-response.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/schemas/body/patch-response.json deleted file mode 100644 index a427bffd5..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/schemas/body/patch-response.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "message": { - "type": "string" - } - } -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/schemas/body/paymentcard-id.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/schemas/body/paymentcard-id.json deleted file mode 100644 index cc79400fb..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/schemas/body/paymentcard-id.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "id": { - "type": "string" - } - } -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/schemas/body/paymentcards-query.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/schemas/body/paymentcards-query.json deleted file mode 100644 index fd251f418..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/schemas/body/paymentcards-query.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "nameOnCard": { - "type": "string" - }, - "creationDate" : { - "type": "string", - "format": "date-time" - } - }, - "required": [] -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/schemas/body/test-response.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/schemas/body/test-response.json deleted file mode 100644 index a427bffd5..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/schemas/body/test-response.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "message": { - "type": "string" - } - } -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/schemas/body/test-values-response.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/schemas/body/test-values-response.json deleted file mode 100644 index 2b72f6913..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/schemas/body/test-values-response.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "message": { - "type": "string" - }, - "number": { - "type": "string", - "javaType": "java.math.BigDecimal" - } - } -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/schemas/errors/error.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/schemas/errors/error.json deleted file mode 100644 index 362d7e72d..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec-version-2/src/main/resources/schemas/errors/error.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "message": { - "type": "string" - }, - "errorCode": { - "type": "string" - } - }, - "required": [ - "message", - "errorCode" - ] -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/pom.xml b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/pom.xml deleted file mode 100644 index d27da4cde..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/pom.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - 4.0.0 - - com.backbase.oss.boat.example - raml-spec - 1.0.0-SNAPSHOT - - jar - - BOAT :: RAML Example - - - - diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/bbt-common.raml b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/bbt-common.raml deleted file mode 100644 index 281655811..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/bbt-common.raml +++ /dev/null @@ -1,7 +0,0 @@ -#%RAML 1.0 Library -schemas: - ObjectWrappingException: !include common-schemas/body/object-wrapping-exception.json -types: - PaymentCard: !include common-schemas/body/paymentcard-item.json - PaymentCards: !include common-schemas/body/paymentcards-get.json - TestHeadersResponseBody: !include common-schemas/body/test-headers-response.json \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/common-schemas/body/date-query-params.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/common-schemas/body/date-query-params.json deleted file mode 100644 index 377c9a7fc..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/common-schemas/body/date-query-params.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType":"com.backbase.buildingblocks.test.data.DateTimeTestResponse", - "properties": { - "dateTimeOnly": { - "type": "string" - }, - "dateTimeOnlyParsedValue": { - "type": "string" - }, - "dateTime": { - "type": "string" - }, - "dateTimeParsedValue": { - "type": "string" - }, - "dateTime2616": { - "type": "string" - }, - "dateTime2616ParsedValue": { - "type": "string" - }, - "date": { - "type": "string" - }, - "dateParsedValue": { - "type": "string" - }, - "time": { - "type": "string" - }, - "timeParsedValue": { - "type": "string" - }, - "formatDateTime": { - "description": "The dateTime parameter formatted as 'date-time', java.util.Date or java.time.ZoneDateTime", - "type": "string", - "format": "date-time" - }, - "formatDate": { - "description": "The date parameter formatted as 'date', String or java.time.LocalDate", - "type": "string", - "format": "date" - }, - "formatTime": { - "description": "The time parameter formatted as 'time', String or java.time.LocalTime", - "type": "string", - "format": "time" - }, - "formatUtcMillisec": { - "description": "The dateTime parameter formatted as 'date', long", - "type": "string", - "format": "utc-millisec" - } - } -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/common-schemas/body/object-wrapping-exception.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/common-schemas/body/object-wrapping-exception.json deleted file mode 100644 index 4a3a7e1dd..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/common-schemas/body/object-wrapping-exception.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.test.exceptions.ObjectWrappingException", - "properties": { - "message": { - "type": "string" - }, - "data": { - "type": "object" - } - } -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/common-schemas/body/paymentcard-item.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/common-schemas/body/paymentcard-item.json deleted file mode 100644 index 8542e05cb..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/common-schemas/body/paymentcard-item.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType":"com.backbase.buildingblocks.test.data.PaymentCard", - "properties": { - "id": { - "type": "string" - }, - "pan": { - "type": "string", - "description": "Must be sixteen digits, optionally in blocks of 4 separated by a dash", - "maxLength": 19 - }, - "cvc": { - "type": "string", - "description": "Card Verification Code", - "minLength": 3, - "maxLength": 3 - }, - "startDate": { - "type": "string", - "description": "Must be in one of these four formats: MM/YY MMYY MMYYYY MM/YYYY", - "pattern": "^(0[1-9]|1[0-2])\/?([0-9]{4}|[0-9]{2})$" - }, - "expiryDate": { - "type": "string", - "description": "Must be in one of these four formats: MM/YY MMYY MMYYYY MM/YYYY", - "pattern": "^(0[1-9]|1[0-2])\/?([0-9]{4}|[0-9]{2})$" - }, - "nameOnCard": { - "type": "string" - }, - "creationDate" : { - "type":"string", - "format":"date-time" - }, - "balance" : { - "type": "object", - "$ref": "../../lib/types/schemas/currency.json" - }, - "apr": { - "type": "number", - "javaType": "java.math.BigDecimal" - }, - "cardtype" : { - "type" : "string", - "default" : "CREDIT", - "enum" : ["CREDIT", "DEBIT", "PREPAID"] - } - }, - "required": [ - "id", - "pan", - "cvc", - "startDate", - "expiryDate", - "nameOnCard" - ] -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/common-schemas/body/paymentcards-get.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/common-schemas/body/paymentcards-get.json deleted file mode 100644 index 16c29a9f7..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/common-schemas/body/paymentcards-get.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "array", - "items": { - "$ref": "paymentcard-item.json" - } -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/common-schemas/body/test-headers-response.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/common-schemas/body/test-headers-response.json deleted file mode 100644 index 4c0635545..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/common-schemas/body/test-headers-response.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType":"com.backbase.buildingblocks.test.data.TestHeadersResponse", - "additionalProperties": false, - "properties": { - "requests": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "url": { - "type": "string" - }, - "headers": { - "type": "object", - "javaType": "java.util.Map" - } - } - } - } - } - } \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/events/add-paymentcard-command.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/events/add-paymentcard-command.json deleted file mode 100644 index 1296ef118..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/events/add-paymentcard-command.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "required": true, - "properties": { - "paymentcard": { - "type": "object", - "$ref": "../common-schemas/body/paymentcard-item.json" - } - } -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/events/delete-paymentcard-command.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/events/delete-paymentcard-command.json deleted file mode 100644 index 81b24e284..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/events/delete-paymentcard-command.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "required": true, - "properties": { - "paymentcard": { - "type": "object", - "$ref": "../schemas/body/paymentcard-id.json" - } - } -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/events/get-paymentcards-command.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/events/get-paymentcards-command.json deleted file mode 100644 index 2d04dc7a3..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/events/get-paymentcards-command.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "required": true, - "properties": { - "queryParams": { - "type": "object", - "$ref": "../schemas/body/paymentcards-query.json" - } - } -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/events/paymentcard-added-event.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/events/paymentcard-added-event.json deleted file mode 100644 index d1efda594..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/events/paymentcard-added-event.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "required": true, - "properties": { - "paymentcard": { - "type": "object", - "$ref": "../common-schemas/body/paymentcard-item.json" - }, - "emitDateTime": { - "description": "The dateTime parameter formatted as 'date-time', java.util.Date or java.time.ZoneDateTime", - "type": "string", - "format": "date-time" - }, - "emitDate": { - "description": "The date parameter formatted as 'date', String or java.time.LocalDate", - "type": "string", - "format": "date" - }, - "emitTime": { - "description": "The time parameter formatted as 'time', String or java.time.LocalTime", - "type": "string", - "format": "time" - }, - "emitMillisec": { - "description": "The dateTime parameter formatted as 'date', long", - "type": "string", - "format": "utc-millisec" - } - } -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/events/paymentcard-deleted-event.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/events/paymentcard-deleted-event.json deleted file mode 100644 index d1efda594..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/events/paymentcard-deleted-event.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "required": true, - "properties": { - "paymentcard": { - "type": "object", - "$ref": "../common-schemas/body/paymentcard-item.json" - }, - "emitDateTime": { - "description": "The dateTime parameter formatted as 'date-time', java.util.Date or java.time.ZoneDateTime", - "type": "string", - "format": "date-time" - }, - "emitDate": { - "description": "The date parameter formatted as 'date', String or java.time.LocalDate", - "type": "string", - "format": "date" - }, - "emitTime": { - "description": "The time parameter formatted as 'time', String or java.time.LocalTime", - "type": "string", - "format": "time" - }, - "emitMillisec": { - "description": "The dateTime parameter formatted as 'date', long", - "type": "string", - "format": "utc-millisec" - } - } -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/events/paymentcards-retrieved-event.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/events/paymentcards-retrieved-event.json deleted file mode 100644 index 2cbadf471..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/events/paymentcards-retrieved-event.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "required": true, - "properties": { - "queryParams": { - "type": "object", - "$ref": "../schemas/body/paymentcards-query.json" - }, - "results": { - "type": "array", - "items": { - "$ref": "../common-schemas/body/paymentcard-item.json" - } - }, - "emitDateTime": { - "description": "The dateTime parameter formatted as 'date-time', java.util.Date or java.time.ZoneDateTime", - "type": "string", - "format": "date-time" - }, - "emitDate": { - "description": "The date parameter formatted as 'date', String or java.time.LocalDate", - "type": "string", - "format": "date" - }, - "emitTime": { - "description": "The time parameter formatted as 'time', String or java.time.LocalTime", - "type": "string", - "format": "time" - }, - "emitMillisec": { - "description": "The dateTime parameter formatted as 'date', long", - "type": "string", - "format": "utc-millisec" - } - } -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/examples/body/example-build-info.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/examples/body/example-build-info.json deleted file mode 100644 index 5cc40dd5d..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/examples/body/example-build-info.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "build-info": { - "build.version": "1.1.111-SNAPSHOT" - } -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/examples/body/item.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/examples/body/item.json deleted file mode 100644 index 89a3fdb1f..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/examples/body/item.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "Example", - "description": "Example description" -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/examples/body/paymentcard-created.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/examples/body/paymentcard-created.json deleted file mode 100644 index 3706a5fbc..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/examples/body/paymentcard-created.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "id": "a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1" -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/examples/body/paymentcard-item.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/examples/body/paymentcard-item.json deleted file mode 100644 index 72777d92d..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/examples/body/paymentcard-item.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "id": "a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1", - "pan": "5434111122223333", - "cvc": "123", - "startDate": "0116", - "expiryDate": "1219", - "nameOnCard": "Mr Timmy Tester", - "creationDate": "2011-05-30T12:13:14+03:00", - "balance": { - "amount": "1000", - "currencyCode": "EUR" - }, - "apr": 12.75 -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/examples/body/paymentcards-get.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/examples/body/paymentcards-get.json deleted file mode 100644 index a7d5dc369..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/examples/body/paymentcards-get.json +++ /dev/null @@ -1,44 +0,0 @@ -[ - { - "id": "a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1", - "pan": "5434111122223333", - "cvc": "123", - "startDate": "0116", - "expiryDate": "1219", - "nameOnCard": "Mr Timmy Tester", - "creationDate": "2011-05-30T12:13:14+03:00", - "balance": { - "amount": "2001", - "currencyCode": "EUR" - }, - "apr": 12.75 - }, - { - "id": "d593c212-70ad-41a6-a547-d5d9232414cb", - "pan": "5434111122224444", - "cvc": "101", - "startDate": "0216", - "expiryDate": "0120", - "nameOnCard": "Mr Timmothy Tester", - "creationDate": "2011-05-30T12:13:14+03:00", - "balance": { - "amount": "4.4399999999999995", - "currencyCode": "GBP" - }, - "apr": 12.75 - }, - { - "id": "9635966b-28e9-4479-8121-bb7bc9beeb62", - "pan": "5434121212121212", - "cvc": "121", - "startDate": "0115", - "expiryDate": "1218", - "nameOnCard": "Mr Timmy Tester", - "creationDate": "2011-05-30T12:13:14+03:00", - "balance": { - "amount": "1981", - "currencyCode": "EUR" - }, - "apr": 12.75 - } -] \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/examples/body/test-headers-response.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/examples/body/test-headers-response.json deleted file mode 100644 index bcc24c481..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/examples/body/test-headers-response.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "requests" : [ - { - "name": "building-blocks-test-wallet-presentation-service", - "url": "/client-api/v1/test/headers", - "headers": { - "correlation-id": [ "2ed475b714a3945a" ], - "accept": [ "application/json" ], - "x-bbt-test": [ "X-BBT-contentVal2" ], - "connection": [ "keep-alive" ] - } - }, - { - "name": "building-blocks-test-wallet-pandp-service", - "url": "/service-api/v1/test/headers", - "headers": { - "authorization": [ "Bearer eyJh" ], - "accept": [ "application/xml, text/xml, application/json, application/*+xml, application/*+json" ], - "content-type": [ "application/json" ], - "x-cxt-user-token": [ "Bearer ey" ], - "x-cxt-remote-user": [ "admin" ], - "x-cxt-requestuuid": [ "72002652-131a-4f28-bd00-16b8080932f5" ], - "correlation-id": [ "2ed475b714a3945a" ], - "x-bbt-test": [ "X-BBT-contentVal2" ] - } - }, - { - "name": "building-blocks-test-wallet-pandp-service", - "url": "/service-api/v1/test/headers", - "headers": { - "authorization": [ "Bearer eyJh" ], - "accept": [ "application/xml, text/xml, application/json, application/*+xml, application/*+json" ], - "content-type": [ "application/json" ], - "x-cxt-user-token": [ "Bearer ey" ], - "x-cxt-remote-user": [ "admin" ], - "x-cxt-requestuuid": [ "72002652-131a-4f28-bd00-16b8080932f5" ], - "correlation-id": [ "2ed475b714a3945a" ], - "x-bbt-test": [ "X-BBT-contentVal2" ] - } - } - ] -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/examples/body/test-values-response.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/examples/body/test-values-response.json deleted file mode 100644 index eb5f7bd7b..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/examples/body/test-values-response.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "message": "a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1", - "number": "102.4" -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/examples/errors/error.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/examples/errors/error.json deleted file mode 100644 index 26d84f14d..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/examples/errors/error.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "message": "Description of error", - "errorCode" : "EXAMPLE-000001" -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/annotations/annotations.raml b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/annotations/annotations.raml deleted file mode 100644 index ea6032759..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/annotations/annotations.raml +++ /dev/null @@ -1,38 +0,0 @@ -#%RAML 1.0 Library - -securitySchemes: -# Custom 'bbAccessControl' security schema -# RAML 1-0 does not allow settings in an x-other security scheme, so no opportunity to describe extra information here - bbAccessControl: - displayName: Backbase Access Control - description: | - This API is secured by DBS Access Control - type: x-bb-access-control - -# RAML annotation and associated types that can be included in API specification files -annotationTypes: - x-bb-api-type: - displayName: API Type - description: | - Signals whether this API endpoint is intended for use by users (HTTP APIs exposed by presentation services) or by - systems (HTTP APIs exposed by inbound integration services) - type: array - items: - type: string - enum: [user, system] - x-bb-access-control: - displayName: Backbase Access Control - description: | - Describes which Resource, Function and Privilege need to be granted to the user to allow access to this API - type: BB-Access-Control - x-bb-api-deprecation: - displayName: API Deprecation - description: | - Signals that the API endpoint is deprecated, providing details on when the API was deprecated, when it will be - removed, the reason for deprecation and a more general description in Markdown that can be used to provide more - information on the deprecation and migration strategy - type: BB-Api-Deprecation - -schemas: - BB-Access-Control: !include ../types/schemas/bb-access-control.json - BB-Api-Deprecation: !include ../types/schemas/bb-api-deprecation.json \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/traits/traits.raml b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/traits/traits.raml deleted file mode 100644 index 1cfe6eb99..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/traits/traits.raml +++ /dev/null @@ -1,132 +0,0 @@ -#%RAML 1.0 Library -schemas: - Bad-Request-Error: !include ../types/schemas/bad-request-error.json - Unauthorized-Error: !include ../types/schemas/unauthorized-error.json - Unauthorized-Alt-Error: !include ../types/schemas/unauthorized-alt-error.json - Not-Acceptable-Error: !include ../types/schemas/not-acceptable-error.json - Internal-Server-Error: !include ../types/schemas/internal-server-error.json - Forbidden-Error: !include ../types/schemas/forbidden-error.json - Not-Found-Error: !include ../types/schemas/not-found-error.json - Unsupported-Media-Type-Error: !include ../types/schemas/unsupported-media-type-error.json -traits: - idempotent: - headers: - X-Request-Id: - description: Correlates HTTP requests between a client and server. - required: false - example: f058ebd6-02f7-4d3f-942e-904344e8cde5 - pageable: - queryParameters: - from: - description: Page Number. Skip over pages of elements by specifying a start value for the query - type: integer - required: false - example: 20 - default: 0 - cursor: - description: | - Record UUID. As an alternative for specifying 'from' this allows to point to the record to start the selection from. - type: string - required: false - example: 76d5be8b-e80d-4842-8ce6-ea67519e8f74 - default: "" - size: - description: | - Limit the number of elements on the response. When used in combination with cursor, the value - is allowed to be a negative number to indicate requesting records upwards from the starting point indicated - by the cursor. - type: integer - required: false - example: 80 - default: 10 - orderable: - queryParameters: - orderBy: - description: | - Order by field: <> - type: string - required: false - direction: - description: Direction - enum: [ASC, DESC] - default: DESC - required: false - challengeable: - headers: - X-MFA: - description: Challenge payload response - required: false - example: sms challenge="123456789" - responses: - 401: - description: Unauthorized - headers: - WWW-Authenticate: - description: Comma separated challenges - required: false - example: sms challenge="", pki challenge="Z8nlwZe0daUNWCWIbfJe3iIgauh" - body: - application/json: - type: Unauthorized-Error - BadRequestError: - responses: - 400: - description: BadRequest - body: - application/json: - type: Bad-Request-Error - example: !include ../types/examples/example-bad-request-error.json - UnauthorizedError: - responses: - 401: - description: Unauthorized - headers: - WWW-Authenticate: - description: Indicates the authentication scheme(s) and parameters applicable to the target resource - required: false - example: | - WWW-Authenticate: Newauth realm="apps", type=1, title="Login to \"apps\"", Basic realm="simple" - body: - application/json: - type: Unauthorized-Alt-Error - example: !include ../types/examples/example-unauthorized-alt-error.json - ForbiddenError: - responses: - 403: - description: Forbidden - body: - application/json: - type: Forbidden-Error - example: !include ../types/examples/example-forbidden-error.json - NotFoundError: - responses: - 404: - description: NotFound - body: - application/json: - type: Not-Found-Error - example: !include ../types/examples/example-not-found-error.json - NotAcceptableError: - responses: - 406: - description: NotAcceptable - body: - application/json: - type: Not-Acceptable-Error - example: !include ../types/examples/example-not-acceptable-error.json - UnsupportedMediaTypeError: - responses: - 415: - description: UnsupportedMediaType - body: - application/json: - type: Unsupported-Media-Type-Error - example: !include ../types/examples/example-unsupported-media-type-error.json - InternalServerError: - responses: - 500: - description: InternalServerError - body: - application/json: - type: Internal-Server-Error - example: !include ../types/examples/example-internal-server-error.json diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/examples/example-bad-request-error.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/examples/example-bad-request-error.json deleted file mode 100644 index 77243186b..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/examples/example-bad-request-error.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "message": "Bad Request", - "errors": [ - { - "message": "Value Exceeded. Must be between {min} and {max}.", - "key": "common.api.shoesize", - "context": { - "max": "50", - "min": "1" - } - } - ] -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/examples/example-currency.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/examples/example-currency.json deleted file mode 100644 index ff365438f..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/examples/example-currency.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "amount": "1.12", - "currencyCode": "TST" -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/examples/example-forbidden-error.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/examples/example-forbidden-error.json deleted file mode 100644 index e26366a7c..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/examples/example-forbidden-error.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "message": "Access to requested resource denied.", - "errors": [ - { - "message": "Resource access denied due to an insufficient user quota of {quota}.", - "key": "common.api.quota", - "context": { - "quota": "someQuota" - } - } - ] -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/examples/example-internal-server-error.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/examples/example-internal-server-error.json deleted file mode 100644 index c6701087a..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/examples/example-internal-server-error.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "message": "Description of error" -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/examples/example-not-acceptable-error.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/examples/example-not-acceptable-error.json deleted file mode 100644 index 0b4ab5da9..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/examples/example-not-acceptable-error.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "message": "Could not find acceptable representation", - "supportedMediaTypes": [ - "application/json" - ] -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/examples/example-not-found-error.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/examples/example-not-found-error.json deleted file mode 100644 index 2d6d616b8..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/examples/example-not-found-error.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "message": "Resource not found.", - "errors": [ - { - "message": "Unable to find the resource requested resource: {resource}.", - "key": "common.api.resource", - "context": { - "resource": "aResource" - } - } - ] -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/examples/example-unauthorized-alt-error.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/examples/example-unauthorized-alt-error.json deleted file mode 100644 index 6b692d0b3..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/examples/example-unauthorized-alt-error.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "message": "Access to requested resource denied.", - "errors": [ - { - "message": "Resource access denied due to invalid credentials.", - "key": "common.api.token", - "context": { - "accessToken": "expired" - } - } - ] -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/examples/example-unauthorized-error.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/examples/example-unauthorized-error.json deleted file mode 100644 index 44f8e8dc6..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/examples/example-unauthorized-error.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "message": "You are not authorized to perform this action" -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/examples/example-unsupported-media-type-error.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/examples/example-unsupported-media-type-error.json deleted file mode 100644 index 9dba54d8f..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/examples/example-unsupported-media-type-error.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "message": "Unsupported media type.", - "errors": [ - { - "message": "The request entity has a media type {mediaType} which the resource does not support.", - "key": "common.api.mediaType", - "context": { - "mediaType": "application/javascript" - } - } - ] -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/schemas/bad-request-error.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/schemas/bad-request-error.json deleted file mode 100644 index d6314386c..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/schemas/bad-request-error.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.presentation.errors.BadRequestException", - "properties": { - "message": { - "type": "string", - "description": "Any further information" - }, - "errors": { - "type": "array", - "description": "Detailed error information", - "items": { - "$ref": "error-item.json" - } - } - }, - "required": [ - "message" - ] -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/schemas/bb-access-control.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/schemas/bb-access-control.json deleted file mode 100644 index 629f43147..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/schemas/bb-access-control.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "resource": { - "type": "string", - "description": "Resource being protected, e.g. 'User'" - }, - "function": { - "type": "string", - "description": "Business function, e.g. 'Manage Users'" - }, - "privilege": { - "type": "string", - "description": "The privilege required, e.g. 'view'" - } - }, - "required": [ - "resource", - "function", - "privilege" - ] -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/schemas/bb-api-deprecation.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/schemas/bb-api-deprecation.json deleted file mode 100644 index 9d7339566..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/schemas/bb-api-deprecation.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "deprecatedFromVersion": { - "type": "string", - "description": "Version of the product from which the endpoint has been deprecated and should no longer be used" - }, - "removedFromVersion": { - "type": "string", - "description": "Version of the product from which the API endpoint will be removed" - }, - "reason": { - "type": "string", - "description": "The reason the API endpoint was deprecated" - }, - "description": { - "type": "string", - "description": "Any further information, e.g. migration information" - } - }, - "required": [ - "deprecatedFromVersion", - "removedFromVersion", - "reason", - "description" - ] -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/schemas/currency.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/schemas/currency.json deleted file mode 100644 index 457bd84ed..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/schemas/currency.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "title": "Monetary Amount", - "description": "Schema defining monetary amount in given currency.", - "javaType": "com.backbase.rest.spec.common.types.Currency", - "properties": { - "amount": { - "type": "string", - "javaType": "java.math.BigDecimal", - "description": "The amount in the specified currency" - }, - "currencyCode": { - "type": "string", - "description": "The alpha-3 code (complying with ISO 4217) of the currency that qualifies the amount", - "pattern": "^[A-Z]{3}$" - } - }, - "required": [ - "amount", - "currencyCode" - ] -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/schemas/error-item.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/schemas/error-item.json deleted file mode 100644 index 4868a1047..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/schemas/error-item.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "description": "A validation error", - "javaInterfaces": [ - "java.io.Serializable", - "Cloneable" - ], - "properties": { - "message": { - "type": "string", - "description": "Default Message. Any further information." - }, - "key": { - "type": "string", - "description": "{capability-name}.api.{api-key-name}. For generated validation errors this is the path in the document the error resolves to. e.g. object name + '.' + field" - }, - "context": { - "type": "object", - "description": "Context can be anything used to construct localised messages.", - "javaType": "java.util.Map" - } - } -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/schemas/forbidden-error.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/schemas/forbidden-error.json deleted file mode 100644 index 671b17956..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/schemas/forbidden-error.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.presentation.errors.ForbiddenException", - "properties": { - "message": { - "type": "string", - "description": "Any further information" - }, - "errors": { - "type": "array", - "description": "Detailed error information", - "items": { - "$ref": "error-item.json" - } - } - } -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/schemas/internal-server-error.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/schemas/internal-server-error.json deleted file mode 100644 index d7d6cafd8..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/schemas/internal-server-error.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.presentation.errors.InternalServerErrorException", - "description": "Represents HTTP 500 Internal Server Error", - "properties": { - "message": { - "type": "string", - "description": "Further Information" - } - }, - "required": [ - "message" - ] -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/schemas/not-acceptable-error.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/schemas/not-acceptable-error.json deleted file mode 100644 index f39202d2b..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/schemas/not-acceptable-error.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.presentation.errors.NotAcceptableException", - "properties": { - "message": { - "type": "string" - }, - "supportedMediaTypes": { - "type": "array", - "description": "List of supported media types for this endpoint", - "items": { - "type": "string" - } - } - } -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/schemas/not-found-error.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/schemas/not-found-error.json deleted file mode 100644 index 3ce00ba4f..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/schemas/not-found-error.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.presentation.errors.NotFoundException", - "properties": { - "message": { - "type": "string", - "description": "Any further information" - }, - "errors": { - "type": "array", - "description": "Detailed error information", - "items": { - "$ref": "error-item.json" - } - } - } -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/schemas/unauthorized-alt-error.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/schemas/unauthorized-alt-error.json deleted file mode 100644 index 388b7326b..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/schemas/unauthorized-alt-error.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.presentation.errors.UnauthorizedException", - "properties": { - "message": { - "type": "string", - "description": "Any further information" - }, - "errors": { - "type": "array", - "description": "Detailed error information", - "items": { - "$ref": "error-item.json" - } - } - } -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/schemas/unauthorized-error.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/schemas/unauthorized-error.json deleted file mode 100644 index 5c30948ac..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/schemas/unauthorized-error.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "message": { - "type": "string" - } - }, - "required": [ - "message" - ] -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/schemas/unsupported-media-type-error.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/schemas/unsupported-media-type-error.json deleted file mode 100644 index 87e2ebba6..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/lib/types/schemas/unsupported-media-type-error.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.presentation.errors.UnsupportedMediaTypeException", - "properties": { - "message": { - "type": "string", - "description": "Any further information" - }, - "errors": { - "type": "array", - "description": "Detailed error information", - "items": { - "$ref": "error-item.json" - } - } - } -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/presentation-client-api.raml b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/presentation-client-api.raml deleted file mode 100644 index d3523898a..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/presentation-client-api.raml +++ /dev/null @@ -1,226 +0,0 @@ -#%RAML 1.0 ---- -#=============================================================== -# Messages - RAML example http://raml.org/ -# References: -# - RAML Specification - https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md -#=============================================================== -title: Wallet Test Client API -uses: - traits: lib/traits/traits.raml - bb: lib/annotations/annotations.raml - common: bbt-common.raml -version: v1 -baseUri: "client-api/{version}" -mediaType: application/json -protocols: [ HTTP, HTTPS ] -#=============================================================== -# API resource definitions -#=============================================================== -securedBy: [ bb.bbAccessControl ] -(bb.x-bb-api-type): [user] -/wallet: - displayName: Wallet - /paymentcards: - displayName: Payment Cards - get: - (bb.x-bb-access-control): - resource: WALLET - function: MANAGE_PAYMENT_CARDS - privilege: READ_PAYMENT_CARD - is: [traits.BadRequestError, traits.NotAcceptableError, traits.orderable: {fieldsList: nameOnCard}, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: "Returns available payment card details for user, optionally filtered by nameOnCard" - queryParameters: - nameOnCard: - description: "Filter by the cardholder's name (case-insensitive), can be the first one or more characters of one of the words/names" - required: false - type: string - example: "Smi" - dateTimeOnly: - description: Creation date in datetime-only format - required: false - type: datetime-only - example: 2017-10-04T14:54:36 - dateTime: - description: Creation date in Zoned RFC3339 Date-time format - required: false - type: datetime - format: rfc3339 - example: 2017-10-04T14:54:36Z - dateTime2616: - description: Zoned RFC2616 Date-time param example - required: false - type: datetime - format: rfc2616 - example: Wed, 4 Jul 2001 12:08:56 PDT - date: - description: Date-only param example - required: false - type: date-only - example: 2017-10-04 - time: - description: time-only param example - required: false - type: time-only - example: 14:54:36 - responses: - 200: - body: - application/json: - type: common.PaymentCards - example: !include examples/body/paymentcards-get.json - text/csv: - application/xml: - post: - (bb.x-bb-access-control): - resource: WALLET - function: MANAGE_PAYMENT_CARDS - privilege: WRITE_PAYMENT_CARD - is: [traits.BadRequestError, traits.InternalServerError, traits.idempotent, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Adds a payment card to the user's wallet - body: - application/json: - type: common.PaymentCard - example: !include examples/body/paymentcard-item.json - responses: - 201: - description: request to create payment card accepted - body: - application/json: - schema: !include schemas/body/paymentcard-id.json - example: !include examples/body/paymentcard-created.json - /{cardId}: - displayName: Payment Card - uriParameters: - cardId: - type: string - get: - (bb.x-bb-access-control): - resource: WALLET - function: MANAGE_PAYMENT_CARDS - privilege: READ_PAYMENT_CARD - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Returns details of a specific payment card - responses: - 200: - body: - application/json: - type: common.PaymentCard - example: !include examples/body/paymentcard-item.json - delete: - (bb.x-bb-access-control): - resource: WALLET - function: MANAGE_PAYMENT_CARDS - privilege: DELETE_PAYMENT_CARD - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Deletes a payment card with a given id - responses: - 204: - description: Payment card is succesfully deleted -/bbt: - description: API for test operations. - displayName: BBT - /build-info: - get: - description: "Build Information" - responses: - 200: - body: - application/json: - schema: !include schemas/body/build-info.json - example: !include examples/body/example-build-info.json -/patch: - description: PATCH endpoint for test operations - displayName: patch - patch: - is: [traits.BadRequestError, traits.InternalServerError, traits.idempotent, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: "Patch Test" - responses: - 200: - body: - text/plain: - schema: !include schemas/body/patch-response.json -/test: - /required-boolean-query-param: - description: arbitrary tests - displayName: required boolean query param - get: - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - queryParameters: - bool: - description: Required boolean parameter with no default value - required: true - type: boolean - example: false - responses: - 200: - body: - application/json: - schema: !include schemas/body/test-response.json - /values: - description: Test Values - displayName: Test Values - get: - is: [traits.InternalServerError] - responses: - 200: - body: - application/json: - schema: !include schemas/body/test-values-response.json - example: !include examples/body/test-values-response.json - /headers: - description: Test header propagation - displayName: Test header propagation - get: - is: [traits.InternalServerError] - queryParameters: - addHops: - description: number of additional hops to perform - required: false - type: integer - responses: - 200: - body: - application/json: - schema: common.TestHeadersResponseBody - example: !include examples/body/test-headers-response.json - /date-query-params: - description: | - Tests for date/time query parameters in service-apis. Sends the same query parameters to the equivalent endpoint - in the pandp service which echoes the given values back in the response body. Values echoed by the pandp service - are then returned in the response to this request. - displayName: dateQueryParam - get: - queryParameters: - dateTimeOnly: - description: Creation date in datetime-only format - required: false - type: datetime-only - example: 2017-10-04T14:54:36 - dateTime: - description: Creation date in Zoned RFC3339 Date-time format - required: false - type: datetime - format: rfc3339 - example: 2017-10-04T14:54:36Z - dateTime2616: - description: Zoned RFC2616 Date-time param example - required: false - type: datetime - format: rfc2616 - example: Wed, 4 Jul 2001 12:08:56 PDT - date: - description: Date-only param example - required: false - type: date-only - example: 2017-10-04 - time: - description: time-only param example - required: false - type: time-only - example: 14:54:36 - responses: - 200: - body: - application/json: - schema: !include common-schemas/body/date-query-params.json diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/presentation-integration-api.raml b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/presentation-integration-api.raml deleted file mode 100644 index a477df038..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/presentation-integration-api.raml +++ /dev/null @@ -1,32 +0,0 @@ -#%RAML 1.0 ---- -#=============================================================== -# Integration API example -#=============================================================== -title: Example -version: v1 -baseUri: "integration-api/{version}" -mediaType: application/json -protocols: [ HTTP, HTTPS ] -#=============================================================== -# API documentation - Overall documentation. -#=============================================================== -documentation: - - title: Example - content: Test Schema to test an integration-api -#=============================================================== -# API resource definitions -#=============================================================== -/items: - description: Retrieve all items. - displayName: items - uriParameters: null - get: - description: "Retrieve list of all items." - responses: - 200: - description: Test Schema - body: - application/json: - schema: !include schemas/body/item.json - example: !include examples/body/item.json \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/presentation-service-api.raml b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/presentation-service-api.raml deleted file mode 100644 index db9214ea5..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/presentation-service-api.raml +++ /dev/null @@ -1,122 +0,0 @@ -#%RAML 1.0 ---- -#=============================================================== -# Messages - RAML example http://raml.org/ -# References: -# - RAML Specification - https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md -#=============================================================== -title: Wallet Test Service API -uses: - traits: lib/traits/traits.raml - bb: lib/annotations/annotations.raml - common: bbt-common.raml -version: v1 -baseUri: "service-api/{version}" -mediaType: application/json -protocols: [ HTTP, HTTPS ] -#=============================================================== -# API resource definitions -#=============================================================== -securedBy: [ bb.bbAccessControl ] -(bb.x-bb-api-type): [system] -/wallet: - displayName: WalletService - /admin/{userId}: - uriParameters: - userId: - type: string - /paymentcards: - displayName: Payment Cards - get: - is: [traits.BadRequestError, traits.NotAcceptableError, traits.orderable: {fieldsList: nameOnCard}, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: "Returns available payment card details for user, optionally filtered by nameOnCard" - queryParameters: - nameOnCard: - description: "Filter by the cardholder's name (case-insensitive), can be the first one or more characters of one of the words/names" - required: false - type: string - example: "Smi" - dateTimeOnly: - description: Creation date in datetime-only format - required: false - type: datetime-only - example: 2017-10-04T14:54:36 - dateTime: - description: Creation date in Zoned RFC3339 Date-time format - required: false - type: datetime - format: rfc3339 - example: 2017-10-04T14:54:36Z - dateTime2616: - description: Zoned RFC2616 Date-time param example - required: false - type: datetime - format: rfc2616 - example: Wed, 4 Jul 2001 12:08:56 PDT - date: - description: Date-only param example - required: false - type: date-only - example: 2017-10-04 - time: - description: time-only param example - required: false - type: time-only - example: 14:54:36 - responses: - 200: - body: - application/json: - type: common.PaymentCards - example: !include examples/body/paymentcards-get.json - post: - is: [traits.BadRequestError, traits.InternalServerError, traits.idempotent, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Adds a payment card to the user's wallet - body: - application/json: - type: common.PaymentCard - example: !include examples/body/paymentcard-item.json - responses: - 201: - description: request to create payment card accepted - body: - application/json: - schema: !include schemas/body/paymentcard-id.json - example: !include examples/body/paymentcard-created.json - /{cardId}: - displayName: Payment Card - uriParameters: - cardId: - type: string - get: - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Returns details of a specific payment card - responses: - 200: - body: - application/json: - type: common.PaymentCard - example: !include examples/body/paymentcard-item.json - delete: - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Deletes a payment card with a given id - responses: - 204: - description: Payment card is succesfully deleted -/testQuery: - /required-boolean-query-param: - description: arbitrary tests - displayName: required boolean query param - get: - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - queryParameters: - bool: - description: Required boolean parameter with no default value - required: true - type: boolean - example: false - responses: - 200: - body: - application/json: - schema: !include schemas/body/test-response.json \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/schemas/body/build-info.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/schemas/body/build-info.json deleted file mode 100644 index 8ed0b3e16..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/schemas/body/build-info.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "build-info": { - "javaType": "java.util.Map", - "type": "object" - } - } -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/schemas/body/item.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/schemas/body/item.json deleted file mode 100644 index 176cb4743..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/schemas/body/item.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "description": "this models a simple item.", - "properties": { - "name": { - "type": "string" - }, - "description": { - "type": "string" - } - }, - "required": [ - "name" - ] -} diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/schemas/body/patch-response.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/schemas/body/patch-response.json deleted file mode 100644 index a427bffd5..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/schemas/body/patch-response.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "message": { - "type": "string" - } - } -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/schemas/body/paymentcard-id.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/schemas/body/paymentcard-id.json deleted file mode 100644 index cc79400fb..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/schemas/body/paymentcard-id.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "id": { - "type": "string" - } - } -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/schemas/body/paymentcards-query.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/schemas/body/paymentcards-query.json deleted file mode 100644 index fd251f418..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/schemas/body/paymentcards-query.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "nameOnCard": { - "type": "string" - }, - "creationDate" : { - "type": "string", - "format": "date-time" - } - }, - "required": [] -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/schemas/body/test-response.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/schemas/body/test-response.json deleted file mode 100644 index a427bffd5..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/schemas/body/test-response.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "message": { - "type": "string" - } - } -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/schemas/body/test-values-response.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/schemas/body/test-values-response.json deleted file mode 100644 index 2b72f6913..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/schemas/body/test-values-response.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "message": { - "type": "string" - }, - "number": { - "type": "string", - "javaType": "java.math.BigDecimal" - } - } -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/schemas/errors/error.json b/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/schemas/errors/error.json deleted file mode 100644 index 362d7e72d..000000000 --- a/boat-maven-plugin/src/it/example/boat-export/raml-specs/raml-spec/src/main/resources/schemas/errors/error.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "message": { - "type": "string" - }, - "errorCode": { - "type": "string" - } - }, - "required": [ - "message", - "errorCode" - ] -} \ No newline at end of file diff --git a/boat-maven-plugin/src/it/example/boat-generate/angular/pom.xml b/boat-maven-plugin/src/it/example/boat-generate/angular/pom.xml index 960b2f16f..e08a14f71 100644 --- a/boat-maven-plugin/src/it/example/boat-generate/angular/pom.xml +++ b/boat-maven-plugin/src/it/example/boat-generate/angular/pom.xml @@ -46,6 +46,9 @@ ${project.basedir}/target/http-module delete=delete,function=function,new=new npmName=${codegen.npmPackage.name},npmVersion=${codegen.npmPackage.version},withMocks=${codegen.generateMocks},buildDist=${codegen.buildDist},serviceSuffix=${codegen.serviceSuffix},apiModulePrefix=${codegen.apiModulePrefix} + + 11.0.0 + @@ -53,7 +56,7 @@ com.github.eirslett frontend-maven-plugin - 1.10.4 + 1.12.1 ${project.basedir}/target/http-module diff --git a/boat-maven-plugin/src/it/example/boat-generate/java-clients/java/pom.xml b/boat-maven-plugin/src/it/example/boat-generate/java-clients/java/pom.xml index 6753422e9..cfe4ca197 100644 --- a/boat-maven-plugin/src/it/example/boat-generate/java-clients/java/pom.xml +++ b/boat-maven-plugin/src/it/example/boat-generate/java-clients/java/pom.xml @@ -15,7 +15,7 @@ BOAT :: Generate :: Java Client - ApiClient.java,BeanValidationException.java,RFC3339DateFormat.java,ServerConfiguration.java,ServerVariable.java,StringUtil.java,Authentication.java,HttpBasicAuth.java,HttpBearerAuth.java,ApiKeyAuth.java,ApiException.java,Pair.java + ApiClient.java,BeanValidationException.java,RFC3339DateFormat.java,ServerConfiguration.java,ServerVariable.java,StringUtil.java,Authentication.java,HttpBasicAuth.java,HttpBearerAuth.java,ApiKeyAuth.java,ApiException.java,Pair.java,ApiResponse.java,JavaTimeFormatter.java diff --git a/boat-maven-plugin/src/it/example/boat-generate/java-clients/rest-template-embedded/pom.xml b/boat-maven-plugin/src/it/example/boat-generate/java-clients/rest-template-embedded/pom.xml index b83ada293..24a7873d0 100644 --- a/boat-maven-plugin/src/it/example/boat-generate/java-clients/rest-template-embedded/pom.xml +++ b/boat-maven-plugin/src/it/example/boat-generate/java-clients/rest-template-embedded/pom.xml @@ -54,13 +54,13 @@ - javax.annotation - javax.annotation-api + jakarta.annotation + jakarta.annotation-api - javax.validation - validation-api + jakarta.validation + jakarta.validation-api diff --git a/boat-maven-plugin/src/it/example/boat-generate/java-server/models/pom.xml b/boat-maven-plugin/src/it/example/boat-generate/java-server/models/pom.xml index 1529d147e..1e426ca12 100644 --- a/boat-maven-plugin/src/it/example/boat-generate/java-server/models/pom.xml +++ b/boat-maven-plugin/src/it/example/boat-generate/java-server/models/pom.xml @@ -48,8 +48,30 @@ - javax.annotation - javax.annotation-api + jakarta.persistence + jakarta.persistence-api + 3.1.0 + + + jakarta.servlet + jakarta.servlet-api + 6.0.0 + + + jakarta.annotation + jakarta.annotation-api + 2.1.1 + + + jakarta.validation + jakarta.validation-api + 3.0.2 + + + + io.swagger.core.v3 + swagger-annotations + 2.2.7 @@ -82,6 +104,8 @@ true true false + true + true com.backbase.oss.boat.example.petstore.model com.backbase.oss.boat.example.petstore.api diff --git a/boat-maven-plugin/src/it/example/boat-generate/java-server/pom.xml b/boat-maven-plugin/src/it/example/boat-generate/java-server/pom.xml index ebd720191..e9801bf3d 100644 --- a/boat-maven-plugin/src/it/example/boat-generate/java-server/pom.xml +++ b/boat-maven-plugin/src/it/example/boat-generate/java-server/pom.xml @@ -24,6 +24,8 @@ models webflux webmvc + spring-embedded + spring-boot-3 diff --git a/boat-maven-plugin/src/it/example/boat-generate/java-server/spring-boot-3/pom.xml b/boat-maven-plugin/src/it/example/boat-generate/java-server/spring-boot-3/pom.xml new file mode 100644 index 000000000..152e8fbf0 --- /dev/null +++ b/boat-maven-plugin/src/it/example/boat-generate/java-server/spring-boot-3/pom.xml @@ -0,0 +1,68 @@ + + + 4.0.0 + + + com.backbase.oss.boat.example + java-server + 1.0.0-SNAPSHOT + + + spring-embedded-sb3 + + BOAT :: Generate :: Server Stubs Spring Embedded SB3 + + + + com.backbase.oss.boat.example + models + 1.0.0-SNAPSHOT + + + + org.springframework.boot + spring-boot-starter-web + + + + jakarta.validation + jakarta.validation-api + + + + org.hibernate.validator + hibernate-validator + 8.0.0.Final + + + + + jar + + + + + com.backbase.oss + boat-maven-plugin + + + java-server + generate-sources + + generate-spring-boot-embedded + + + https://raw.githubusercontent.com/OAI/OpenAPI-Specification/master/examples/v3.0/petstore-expanded.yaml + com.backbase.oss.boat.example.petstore.model + com.backbase.oss.boat.example.petstore.api + + + + + + + + + diff --git a/boat-maven-plugin/src/it/example/boat-generate/java-server/spring-embedded/pom.xml b/boat-maven-plugin/src/it/example/boat-generate/java-server/spring-embedded/pom.xml new file mode 100644 index 000000000..f042348c0 --- /dev/null +++ b/boat-maven-plugin/src/it/example/boat-generate/java-server/spring-embedded/pom.xml @@ -0,0 +1,68 @@ + + + 4.0.0 + + + com.backbase.oss.boat.example + java-server + 1.0.0-SNAPSHOT + + + spring-embedded + + BOAT :: Generate :: Server Stubs Spring Embedded + + + + com.backbase.oss.boat.example + models + 1.0.0-SNAPSHOT + + + + org.springframework.boot + spring-boot-starter-web + + + + jakarta.validation + jakarta.validation-api + + + + org.hibernate.validator + hibernate-validator + 8.0.0.Final + + + + + jar + + + + + com.backbase.oss + boat-maven-plugin + + + java-server + generate-sources + + generate-spring-boot-embedded + + + https://raw.githubusercontent.com/OAI/OpenAPI-Specification/master/examples/v3.0/petstore-expanded.yaml + com.backbase.oss.boat.example.petstore.model + com.backbase.oss.boat.example.petstore.api + + + + + + + + + diff --git a/boat-maven-plugin/src/it/example/boat-generate/java-server/webflux/pom.xml b/boat-maven-plugin/src/it/example/boat-generate/java-server/webflux/pom.xml index de9a80c0e..533df8faf 100644 --- a/boat-maven-plugin/src/it/example/boat-generate/java-server/webflux/pom.xml +++ b/boat-maven-plugin/src/it/example/boat-generate/java-server/webflux/pom.xml @@ -32,6 +32,8 @@ org.springframework spring-core + + jar @@ -63,6 +65,8 @@ true true false + true + true com.backbase.oss.boat.example.petstore.model com.backbase.oss.boat.example.petstore.api diff --git a/boat-maven-plugin/src/it/example/boat-generate/java-server/webmvc/pom.xml b/boat-maven-plugin/src/it/example/boat-generate/java-server/webmvc/pom.xml index 378c79dd8..13b28ea46 100644 --- a/boat-maven-plugin/src/it/example/boat-generate/java-server/webmvc/pom.xml +++ b/boat-maven-plugin/src/it/example/boat-generate/java-server/webmvc/pom.xml @@ -26,6 +26,8 @@ spring-boot-starter-web + + jar @@ -57,6 +59,8 @@ true true false + true + true com.backbase.oss.boat.example.petstore.model com.backbase.oss.boat.example.petstore.api diff --git a/boat-maven-plugin/src/it/example/pom.xml b/boat-maven-plugin/src/it/example/pom.xml index 197a3c8b3..84d3ae222 100644 --- a/boat-maven-plugin/src/it/example/pom.xml +++ b/boat-maven-plugin/src/it/example/pom.xml @@ -11,7 +11,7 @@ @pom.version@ - + 0.2.3 2.13.3 @@ -45,7 +45,6 @@ boat-multiple-executions boat-artifact-input boat-doc - boat-export boat-generate boat-lint boat-yard @@ -108,6 +107,13 @@ 2.0.1.Final + + jakarta.validation + jakarta.validation-api + 3.0.2 + provided + + org.hibernate.validator hibernate-validator @@ -120,6 +126,12 @@ 1.3.2 + + jakarta.annotation + jakarta.annotation-api + 2.1.1 + + org.springframework.boot spring-boot-starter-webflux diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/AbstractGenerateMojo.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/AbstractGenerateMojo.java index 1d7385642..b8fdffb99 100644 --- a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/AbstractGenerateMojo.java +++ b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/AbstractGenerateMojo.java @@ -21,6 +21,8 @@ public void execute(String generatorName, String library, boolean isEmbedded, bo options.put("useBeanValidation", "true"); options.put("useClassLevelBeanValidation", "false"); options.put("useOptional", "false"); + options.put("useJakartaEe", "true"); + options.put("useSpringBoot3", "true"); this.generatorName = generatorName; this.generateSupportingFiles = generateSupportingFiles; @@ -32,7 +34,7 @@ public void execute(String generatorName, String library, boolean isEmbedded, bo this.configOptions = options; if(isEmbedded) { - this.supportingFilesToGenerate = "ApiClient.java,BeanValidationException.java,RFC3339DateFormat.java,ServerConfiguration.java,ServerVariable.java,StringUtil.java,Authentication.java,HttpBasicAuth.java,HttpBearerAuth.java,ApiKeyAuth.java"; + this.supportingFilesToGenerate = "ApiClient.java,BeanValidationException.java,RFC3339DateFormat.java,ServerConfiguration.java,ServerVariable.java,StringUtil.java,Authentication.java,HttpBasicAuth.java,HttpBearerAuth.java,ApiKeyAuth.java,JavaTimeFormatter.java"; } super.execute(); } diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/AbstractRamlToOpenApi.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/AbstractRamlToOpenApi.java deleted file mode 100644 index caa0fab21..000000000 --- a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/AbstractRamlToOpenApi.java +++ /dev/null @@ -1,477 +0,0 @@ -package com.backbase.oss.boat; - -import com.backbase.oss.boat.serializer.SerializerUtils; -import com.backbase.oss.boat.transformers.AdditionalPropertiesAdder; -import com.backbase.oss.boat.transformers.Decomposer; -import com.backbase.oss.boat.transformers.Deprecator; -import com.backbase.oss.boat.transformers.LicenseAdder; -import io.swagger.v3.oas.models.OpenAPI; -import io.swagger.v3.oas.models.Operation; -import io.swagger.v3.oas.models.PathItem; -import io.swagger.v3.oas.models.info.Info; -import io.swagger.v3.oas.models.servers.Server; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.stream.Collectors; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang3.ArrayUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.maven.model.Dependency; -import org.apache.maven.plugin.AbstractMojo; -import org.apache.maven.plugin.MojoExecutionException; -import org.apache.maven.plugins.annotations.Component; -import org.apache.maven.plugins.annotations.Parameter; -import org.apache.maven.project.MavenProject; -import org.codehaus.plexus.util.DirectoryScanner; -import org.codehaus.plexus.util.Expand; -import org.eclipse.aether.RepositorySystemSession; -import org.eclipse.aether.artifact.DefaultArtifact; -import org.eclipse.aether.impl.ArtifactResolver; -import org.eclipse.aether.impl.MetadataResolver; -import org.eclipse.aether.repository.RemoteRepository; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -abstract class AbstractRamlToOpenApi extends AbstractMojo { - - protected final Map success = new LinkedHashMap<>(); - protected final Map failed = new LinkedHashMap<>(); - - private static Logger log = LoggerFactory.getLogger(AbstractRamlToOpenApi.class); - - @Parameter(defaultValue = "${project}", readonly = true) - protected MavenProject project; - - @Parameter(property = "includeGroupId", defaultValue = "com.backbase.") - protected String includeGroupIds; - - @Parameter(property = "xLogoUrl") - protected String xLogoUrl; - - @Parameter(property = "xLogoAltText") - protected String xLogoAltText; - - @Parameter(property = "licenseName") - protected String licenseName; - - @Parameter(property = "licenseUrl") - protected String licenseUrl; - - @Parameter(property = "markdown") - protected String markdownTop; - - @Parameter(property = "markdownBottom") - protected String markdownBottom; - - @Parameter(property = "servers") - protected List servers = Collections.emptyList(); - - @Parameter(property = "convertJsonExamplesToYaml", defaultValue = "true") - protected boolean convertJsonExamplesToYaml; - - @Parameter(property = "addJavaTypeExtensions", defaultValue = "true") - protected boolean addJavaTypeExtensions; - - @Parameter(property = "appendDeprecatedMetadataInDescription", defaultValue = "true") - protected boolean appendDeprecatedMetadataInDescription = true; - - @Parameter(property = "decompose", defaultValue = "true") - protected boolean decompose; - - @Parameter(name = "removeDeprecated", defaultValue = "false") - protected boolean removeDeprecated; - - @Parameter(property = "includeVersionInOutputDirectory", defaultValue = "true") - protected boolean includeVersionInOutputDirectory; - - @Parameter(property = "addAdditionalProperties") - protected List addAdditionalProperties = new ArrayList<>(); - - @Parameter(property = "additionalPropertiesType", defaultValue = "object") - protected String additionalPropertiesType; - - @Parameter(property = "continueOnError", defaultValue = "true") - protected boolean continueOnError; - - /** - * Target directory for generated code. Use location relative to the project.baseDir. Default value is - * "target/openapi". - */ - @Parameter(property = "output", defaultValue = "${project.build.directory}/openapi") - protected File output = new File("${project.build.directory}/openapi"); - - @Component - protected ArtifactResolver artifactResolver; - - @Component - protected MetadataResolver metadataResolver; - - /** - * Used to look up Artifacts in the remote repository. - */ - @Parameter(defaultValue = "${repositorySystemSession}", readonly = true) - protected RepositorySystemSession repositorySession; - - /** - * List of Remote Repositories used by the resolver. - */ - @Parameter(defaultValue = "${project.remoteProjectRepositories}", readonly = true) - protected List remoteRepositories; - - @Parameter(defaultValue = "**/*-api.raml,**/api.raml") - protected String ramlFileFilters; - - - protected boolean isRamlSpec(File file) { - return file.getName().equals("api.raml") - || file.getName().endsWith("-api.raml") - || file.getName().endsWith("service-api.raml") - || file.getName().endsWith("client-api.raml") - || file.getName().endsWith("integration-api.raml"); - } - - protected File export(String version, File ramlFile, File outputDirectory) - throws ExportException, IOException { - getLog().info("Exporting " + ramlFile.getAbsolutePath() + " to: " + outputDirectory); - - OpenAPI openApi = convert(version, ramlFile); - - String yaml = SerializerUtils.toYamlString(openApi); - - if (!outputDirectory.exists()) { - outputDirectory.mkdirs(); - } - File file = new File(outputDirectory, "openapi.yaml"); - Files.write(file.toPath(), yaml.getBytes()); - - File indexFile = new File(outputDirectory, "index.html"); - InputStream resourceAsStream = getClass().getResourceAsStream("/index.html"); - String index = IOUtils.toString(resourceAsStream, StandardCharsets.UTF_8); - index = StringUtils.replace(index, "@title@", openApi.getInfo().getTitle()); - Files.write(indexFile.toPath(), index.getBytes()); - - success.put(file, openApi); - - return file; - } - - - protected OpenAPI convert(String version, File ramlFile) throws ExportException { - ExporterOptions options = new ExporterOptions() - .addJavaTypeExtensions(addJavaTypeExtensions) - .convertExamplesToYaml(convertJsonExamplesToYaml); - - if (removeDeprecated) { - options.getTransformers().add(new Deprecator()); - } - if (decompose) { - options.getTransformers().add(new Decomposer()); - } - if (!addAdditionalProperties.isEmpty()) { - options.getTransformers() - .add(new AdditionalPropertiesAdder(addAdditionalProperties, additionalPropertiesType)); - } - - if (licenseName != null && licenseUrl != null) { - options.getTransformers().add(new LicenseAdder(licenseName, licenseUrl)); - } - - OpenAPI openApi = Exporter.export(ramlFile, options); - pimpInfo(version, openApi); - if (appendDeprecatedMetadataInDescription) { - // Iterate over all operations and update the description - openApi.getPaths().values().forEach(pathItem -> pathItem.readOperationsMap().entrySet() - .stream() - .filter(this::isDeprecated) - .forEach(httpMethodOperationEntry -> { - Operation operation = httpMethodOperationEntry.getValue(); - Optional deprecatedInformationOptional = generateMarkdownForDeprecationExtention(operation); - - deprecatedInformationOptional.ifPresent(deprecatedInformation -> { - log.debug("Inserting deprecated information: \n{}", deprecatedInformation); - if (operation.getDescription() == null) { - operation.setDescription(deprecatedInformation); - } else { - operation.setDescription(operation.getDescription() + "\n" + deprecatedInformation); - } - }); - pathItem.operation(httpMethodOperationEntry.getKey(), operation); - } - )); - } - return openApi; - } - - private boolean isDeprecated(Map.Entry httpMethodOperationEntry) { - Operation value = httpMethodOperationEntry.getValue(); - return value.getDeprecated() != null && value.getDeprecated().equals(Boolean.TRUE); - } - - private Optional generateMarkdownForDeprecationExtention(Operation operation) { - if (operation.getExtensions() == null) { - return Optional.empty(); - } - - String deprecatedFromVersion = (String) operation.getExtensions() - .get("x-BbApiDeprecation-deprecatedFromVersion"); - String removedFromVersion = (String) operation.getExtensions().get("x-BbApiDeprecation-removedFromVersion"); - String reason = (String) operation.getExtensions().get("x-BbApiDeprecation-reason"); - String description = (String) operation.getExtensions().get("x-BbApiDeprecation-description"); - - if (deprecatedFromVersion == null && removedFromVersion == null && reason == null && description == null) { - return Optional.empty(); - } - - StringBuilder sb = new StringBuilder("## Deprecated\n"); - if (deprecatedFromVersion != null) { - sb.append("* **Deprecated from:** ").append(deprecatedFromVersion).append("\n"); - } - if (removedFromVersion != null) { - sb.append("* **Removed from:** ").append(removedFromVersion).append("\n"); - } - if (reason != null) { - sb.append("* **Reason:** ").append(reason).append("\n"); - } - if (description != null) { - sb.append("\n### Migration Information\n "); - sb.append(description); - } - return Optional.of(sb.toString()); - - } - - private void pimpInfo(String version, OpenAPI openApi) { - Info info = openApi.getInfo(); - if (version != null) { - log.info("Overriding version: {}", version); - info.setVersion(version); - - } - if (StringUtils.isNotEmpty(xLogoUrl)) { - Map xLogo = new HashMap<>(); - xLogo.put("url", xLogoUrl); - if (StringUtils.isNotEmpty(xLogoAltText)) { - xLogo.put("altText", xLogoAltText); - } - info.addExtension("x-logo", xLogo); - } - - if (StringUtils.isNotEmpty(markdownTop)) { - if (info.getDescription() != null) { - info.setDescription(markdownTop + "\n" + info.getDescription()); - } else { - info.setDescription(markdownTop); - } - } - - if (StringUtils.isNotEmpty(markdownBottom)) { - if (info.getDescription() != null) { - info.setDescription(info.getDescription() + "\n" + markdownBottom); - } else { - info.setDescription(markdownBottom); - } - } - - if (!servers.isEmpty()) { - openApi.setServers(servers); - } - } - - protected void writeSummary(String title) { - int total = success.size() + failed.size(); - - if (total == 0) { - getLog().warn("Nothing to export"); - return; - } - - int percent = (failed.size() * 100) / total; - - log.info(title); - log.info("\t Total: {} Success: {} Failed: {} ({}%)", total, success.size(), failed.size(), percent); - if (!success.isEmpty()) { - log.info("Success:"); - for (Map.Entry entry : success.entrySet()) { - log.info("\t{} --> {}", entry.getKey(), entry.getValue().getInfo().getTitle()); - } - } - - if (!failed.isEmpty()) { - log.warn("Failed:"); - for (Map.Entry entry : failed.entrySet()) { - log.warn("\t{} Failed. Exception: {}", entry.getKey(), entry.getValue()); - } - } - - } - - public void setProject(MavenProject project) { - this.project = project; - } - - public Map getSuccess() { - return success; - } - - public Map getFailed() { - return failed; - } - - - protected List exportArtifact(String groupId, String artifactId, String version, File artifactFile, - File outputDirectory) throws MojoExecutionException { - - log.info("Converting RAML specs from Artifact {}:{}:{} from: {}", groupId, artifactId, version, artifactFile); - - File specUnzipDirectory = new File(project.getBuild().getDirectory() + "/raml/" + version, artifactId); - unzipSpec(artifactFile, specUnzipDirectory); - File[] files = findAllRamlSpecs(specUnzipDirectory); - ArrayUtils.reverse(files); - List exported = new ArrayList<>(); - for (File file : files) { - - // If specs are 2 level deep, append directory name - String ramlName = StringUtils.substringBeforeLast(file.getName(), "."); - File fileParent = file.getParentFile(); - - try { - File parent; - File openApiOutputDirectory; - if (!fileParent.equals(specUnzipDirectory)) { - parent = new File(outputDirectory, artifactId + File.separator + fileParent.getName() + File.separator + ramlName); - openApiOutputDirectory = parent; - } else { - parent = new File(outputDirectory, artifactId + File.separator + ramlName); - openApiOutputDirectory = new File(parent, ramlName); - } - - if (includeVersionInOutputDirectory) { - openApiOutputDirectory = new File(openApiOutputDirectory, version); - } - - File exportedTo = export(version, file, openApiOutputDirectory); - exported.add(exportedTo); - - } catch (Exception e) { - - if (!continueOnError) { - throw new MojoExecutionException("Failed to export RAML: " + file.getAbsolutePath(), e); - } else { - getLog().error( - "Failed to export RAML Spec: " + file + " due to: [" + e.getClass() + "] " + e.getMessage()); - failed.put(artifactId + ":" + ramlName, e.getMessage()); - } - - } - } - getLog().info("Exported RAML Spec: " + artifactId + " to: " + outputDirectory); - return exported; - } - - private File[] findAllRamlSpecs(File specUnzipDirectory) { - DirectoryScanner directoryScanner = new DirectoryScanner(); - directoryScanner.setBasedir(specUnzipDirectory); - directoryScanner.setIncludes(ramlFileFilters.replace(" ", "").split(",")); - directoryScanner.scan(); - - String[] includedFiles = directoryScanner.getIncludedFiles(); - return Arrays.stream(includedFiles).map(pathname -> new File(specUnzipDirectory, pathname)) - .collect(Collectors.toList()).toArray(new File[]{}); - } - - private void unzipSpec(File inputFile, File unzipDirectory) throws MojoExecutionException { - - unzipDirectory.mkdirs(); - try { - unzip(inputFile, unzipDirectory); - } catch (Exception e) { - throw new MojoExecutionException("Error extracting spec: " + inputFile, e); - } - } - - private void unzip(File source, File out) throws Exception { - Expand expand = new Expand(); - expand.setSrc(source); - expand.setDest(out); - expand.setOverwrite(true); - expand.execute(); - } - - public static void setLog(Logger log) { - AbstractRamlToOpenApi.log = log; - } - - public void setIncludeGroupIds(String includeGroupIds) { - this.includeGroupIds = includeGroupIds; - } - - public void setxLogoUrl(String xLogoUrl) { - this.xLogoUrl = xLogoUrl; - } - - public void setxLogoAltText(String xLogoAltText) { - this.xLogoAltText = xLogoAltText; - } - - public void setLicenseName(String licenseName) { - this.licenseName = licenseName; - } - - public void setLicenseUrl(String licenseUrl) { - this.licenseUrl = licenseUrl; - } - - public void setMarkdownTop(String markdownTop) { - this.markdownTop = markdownTop; - } - - public void setMarkdownBottom(String markdownBottom) { - this.markdownBottom = markdownBottom; - } - - public void setConvertJsonExamplesToYaml(boolean convertJsonExamplesToYaml) { - this.convertJsonExamplesToYaml = convertJsonExamplesToYaml; - } - - public void setAppendDeprecatedMetadataInDescription(boolean appendDeprecatedMetadataInDescription) { - this.appendDeprecatedMetadataInDescription = appendDeprecatedMetadataInDescription; - } - - public void setDecompose(boolean decompose) { - this.decompose = decompose; - } - - public void setOutput(File output) { - this.output = output; - } - - public List getServers() { - return servers; - } - - public void setServers(List servers) { - this.servers = servers; - } - - protected DefaultArtifact createNewDefaultArtifact(Dependency dependency) { - return new DefaultArtifact(dependency.getGroupId() - , dependency.getArtifactId() - , (org.codehaus.plexus.util.StringUtils.isNotEmpty(dependency.getClassifier()) ? dependency.getClassifier() - : null) - , (org.codehaus.plexus.util.StringUtils.isNotEmpty(dependency.getType()) ? dependency.getType() : null) - , dependency.getVersion()); - } - - -} diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/ExportBomMojo.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/ExportBomMojo.java deleted file mode 100644 index 94a6a149c..000000000 --- a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/ExportBomMojo.java +++ /dev/null @@ -1,348 +0,0 @@ -package com.backbase.oss.boat; - -import com.backbase.oss.boat.diff.BatchOpenApiDiff; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileReader; -import java.io.IOException; -import java.nio.file.Files; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Map.Entry; -import java.util.Optional; -import java.util.Properties; -import java.util.Set; -import java.util.TreeMap; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.tuple.Pair; -import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader; -import org.apache.maven.artifact.versioning.DefaultArtifactVersion; -import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; -import org.apache.maven.artifact.versioning.VersionRange; -import org.apache.maven.model.Dependency; -import org.apache.maven.model.Model; -import org.apache.maven.model.Profile; -import org.apache.maven.model.io.xpp3.MavenXpp3Reader; -import org.apache.maven.plugin.MojoExecutionException; -import org.apache.maven.plugins.annotations.Mojo; -import org.apache.maven.plugins.annotations.Parameter; -import org.apache.maven.plugins.annotations.ResolutionScope; -import org.codehaus.plexus.util.xml.pull.XmlPullParserException; -import org.eclipse.aether.artifact.DefaultArtifact; -import org.eclipse.aether.metadata.DefaultMetadata; -import org.eclipse.aether.metadata.Metadata; -import org.eclipse.aether.repository.RemoteRepository; -import org.eclipse.aether.resolution.ArtifactResult; -import org.eclipse.aether.resolution.MetadataRequest; -import org.eclipse.aether.resolution.MetadataResult; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@Mojo(name = "export-bom", requiresDependencyResolution = ResolutionScope.RUNTIME, threadSafe = true) -/** - * Converts all RAML Spec dependencies to OpenAPI Specs. - */ -public class ExportBomMojo extends AbstractRamlToOpenApi { - - public static final String X_CHANGELOG = "x-changelog"; - - private static final Logger log = LoggerFactory.getLogger(ExportBomMojo.class); - - @Parameter(property = "includeVersionsRegEx", defaultValue = "^(\\d+\\.)?(\\d+\\.)?(\\d+\\.)?(\\*|\\d+)$") - private String includeVersionsRegEx; - - @Parameter(property = "includeArtifactIdRegEx", defaultValue = "(\\w-spec)$") - private String includeArtifactIdRegEx; - - @Parameter(property = "spec-bom") - private Dependency specBom; - - @Parameter(name = "addChangeLog", defaultValue = "true") - private boolean addChangeLog; - - public void setSpecBom(Dependency specBom){this.specBom = specBom;} - - - @Override - public void execute() throws MojoExecutionException { - - Set metadataRequests = remoteRepositories.stream() - .map(remoteRepository -> createMetadataRequest(remoteRepository, "maven-metadata.xml")) - .collect(Collectors.toSet()); - metadataRequests.add(createMetadataRequest(null, "maven-metadata.xml")); - VersionRange versionRange = getVersionRange(); - - log.info("Checking BOM Meta Data for: {}:{}", specBom.getGroupId(), specBom.getArtifactId()); - - List metadataResults = metadataResolver.resolveMetadata(repositorySession, metadataRequests); - - List remoteMetaData = metadataResults.stream() - .filter(MetadataResult::isResolved) - .collect(Collectors.toList()); - - if (remoteMetaData.isEmpty()) { - log.warn("Failed to resolve meta data for: {}:{}. Exiting", specBom.getGroupId(), specBom.getArtifactId()); - return; - } - - List metaDataList = remoteMetaData.stream() - .map(metadataResult -> metadataResult.getMetadata().getFile()) - .collect(Collectors.toList()); - - log.info("Resolved meta data for: {}:{} in: {}", specBom.getGroupId(), specBom.getArtifactId(), metaDataList); - - List versions = metaDataList.stream() - .map(this::parseMetadataFile) - .flatMap(metadata -> metadata.getVersioning().getVersions().stream()) - .filter(version -> { - if (!StringUtils.isEmpty(includeVersionsRegEx)) { - return version.matches(includeVersionsRegEx); - } else { - return true; - } - } - ) - .collect(Collectors.toList()); - - log.info("Resolved versions: {}", versions); - - List>>> versionCapabilitySpecs = versions.stream() - .map(DefaultArtifactVersion::new) - .filter(versionRange::containsVersion) - .distinct() - .map(this::convertToArtifact) - .map(defaultArtifact -> new ArtifactRepositoryResolver(artifactResolver,repositorySession,remoteRepositories).resolveArtifactFromRepositories(defaultArtifact)) - .map(this::parsePomFile) - .map(this::groupArtifactsPerVersionAndCapability) - .collect(Collectors.toList()); - - if (versionCapabilitySpecs.isEmpty()) { - log.info("No specs found in bom!"); - return; - } - log.info("Converting {} RAML specs found in bom", versionCapabilitySpecs.size()); - - export(versionCapabilitySpecs); - writeSummary("Converted RAML Specs to OpenAPI Summary"); - if (addChangeLog && !versionCapabilitySpecs.isEmpty()) { - try { - success.clear(); - failed.clear(); - BatchOpenApiDiff.diff(output.toPath(), success, failed, true, true); - writeSummary("Calculated Change log for APIs"); - } catch (Exception e) { - throw new MojoExecutionException("Cannot create diff", e); - } - } - } - - - private Pair>> groupArtifactsPerVersionAndCapability(Model model) { - - Set dependencies = getAllDependenciesFromBom(model); - - TreeMap> collect = dependencies.stream() - .filter(this::isIncludedSpec) - .map(this::createNewDefaultArtifact) - .distinct() - .map(defaultArtifact -> new ArtifactRepositoryResolver(artifactResolver,repositorySession,remoteRepositories).resolveArtifactFromRepositories(defaultArtifact)) - .collect(Collectors - .groupingBy(artifactResult -> artifactResult.getArtifact().getGroupId(), TreeMap::new, - Collectors.toSet())); - - return Pair.of(model.getVersion(), - collect); - } - - private Set getAllDependenciesFromBom(Model model) { - Set dependencies = new HashSet<>(); - if (model.getDependencyManagement() != null) { - dependencies.addAll(model.getDependencyManagement().getDependencies()); - } - if (model.getDependencies() != null) { - dependencies.addAll(model.getDependencies()); - } - if (model.getProfiles() != null) { - model.getProfiles().forEach(profile -> dependencies.addAll(profile.getDependencies())); - } - return dependencies; - } - - protected void export(List>>> versionCapabilitySpecs) - throws MojoExecutionException { - for (Pair>> versionSpecs : versionCapabilitySpecs) { - String version = versionSpecs.getKey(); - - for (Entry> entry : versionSpecs.getValue().entrySet()) { - String capabilty = entry.getKey(); - Set specs = entry.getValue(); - - File capabilityDirectory = new File(output, capabilty); - try { - Files.createDirectories(capabilityDirectory.toPath()); - } catch (IOException e) { - throw new MojoExecutionException("Cannot create output directory: " + capabilityDirectory); - } - - specs.stream().filter(ArtifactResult::isResolved) - .map(ArtifactResult::getArtifact) - .forEach(artifact -> { - try { - List files = exportArtifact(artifact.getGroupId(), artifact.getArtifactId(), version, - artifact.getFile(), capabilityDirectory); - - log.info("Successfully exported artifact: {} to: {}", artifact, files); - } catch (MojoExecutionException e) { - log.error("Failed to export artifact: {}", artifact, e); - } - }); - - specs.stream().filter(ArtifactResult::isMissing) - .forEach(artifactResult -> log.error("Failed to resolve: {}", artifactResult)); - - } - } - - } - - private boolean isIncludedSpec(Dependency dependency) { - String artifactId = dependency.getArtifactId(); - return artifactId.endsWith("-spec"); - } - - - private VersionRange getVersionRange() throws MojoExecutionException { - try { - return VersionRange.createFromVersionSpec(specBom.getVersion()); - } catch (InvalidVersionSpecificationException e) { - throw new MojoExecutionException("Cannot parse version: " + specBom.getVersion()); - } - } - - private MetadataRequest createMetadataRequest(RemoteRepository remoteRepository, String type) { - MetadataRequest metadataRequest = new MetadataRequest(); - if (remoteRepository != null) { - metadataRequest.setRepository(remoteRepository); - } - metadataRequest.setMetadata(new DefaultMetadata(specBom.getGroupId(), specBom.getArtifactId(), - type, Metadata.Nature.RELEASE_OR_SNAPSHOT)); - return metadataRequest; - } - - private org.apache.maven.artifact.repository.metadata.Metadata parseMetadataFile(File mavenDataFile) { - MetadataXpp3Reader metadataXpp3Reader = new MetadataXpp3Reader(); - try { - FileInputStream in = new FileInputStream(mavenDataFile); - return metadataXpp3Reader.read(in); - } catch (IOException | XmlPullParserException e) { - throw new IllegalArgumentException("Cannot read metadata from: " + mavenDataFile, e); - } - } - - public Model parsePomFile(ArtifactResult pom) { - File pomFile = pom.getArtifact().getFile(); - MavenXpp3Reader reader = new MavenXpp3Reader(); - Model model; - try { - model = reader.read(new FileReader(pomFile)); - } catch (Exception e) { - throw new IllegalArgumentException("Cannot read pom file"); - } - // Merge dependencies version numbers inside the poms - Properties properties = model.getProperties(); - List dependencyManagementDependencies = new ArrayList<>(); - if (model.getDependencyManagement() != null) { - dependencyManagementDependencies = model.getDependencyManagement().getDependencies().stream() - .map(dependency -> resolvePropertyPlaceholderVersion(properties, dependency)) - .collect(Collectors.toList()); - } - if (model.getDependencies() != null) { - for (Dependency dependency : model.getDependencies()) { - if (dependency.getVersion() == null) { - setManagedVersionDependency(dependencyManagementDependencies, dependency); - } else { - resolvePropertyPlaceholderVersion(properties, dependency); - } - } - - } - if (model.getProfiles() != null) { - for (Profile profile : model.getProfiles()) { - log.info("Exporting spec from profile: {}", profile.getId()); - List profileDependencies = profile.getDependencies().stream() - .map(dependency -> resolvePropertyPlaceholderVersion(properties, dependency)) - .collect(Collectors.toList()); - - for (Dependency dependency : profileDependencies) { - setManagedVersionDependency(dependencyManagementDependencies, dependency); - } - } - } - return model; - } - - private Dependency resolvePropertyPlaceholderVersion(Properties properties, Dependency dependency) { - if (dependency.getVersion() != null && dependency.getVersion().contains("$")) { - dependency.setVersion(replacePlaceholders(properties, dependency.getVersion())); - } - return dependency; - } - - private void setManagedVersionDependency - (List dependencyManagementDependencies, - org.apache.maven.model.Dependency profileDependency) { - if(profileDependency.getVersion()!=null) { - return; - } - Optional managedDependency = resolveDependencyVersion( - dependencyManagementDependencies, profileDependency); - managedDependency.ifPresent(dependency -> profileDependency.setVersion(dependency.getVersion())); - } - - private Optional resolveDependencyVersion( - List dependencyManagementDependencies, - org.apache.maven.model.Dependency profileDependency) { - return dependencyManagementDependencies.stream(). - filter(dependency -> - profileDependency.getArtifactId().equals(dependency.getArtifactId()) - && profileDependency.getGroupId().equals(dependency.getGroupId()) - && profileDependency.getType().equals(dependency.getType()) - - ).findFirst(); - } - - private String replacePlaceholders(Properties properties, String template) { - Pattern pattern = Pattern.compile("\\$\\{(.+?)\\}"); - Matcher matcher = pattern.matcher(template); - // StringBuilder cannot be used here because Matcher expects StringBuffer - StringBuffer buffer = new StringBuffer(); - while (matcher.find()) { - if (properties.containsKey(matcher.group(1))) { - String replacement = properties.get(matcher.group(1)).toString(); - // quote to work properly with $ and {,} signs - matcher.appendReplacement(buffer, - replacement != null ? Matcher.quoteReplacement(replacement) : "null"); - } - } - matcher.appendTail(buffer); - String s = buffer.toString(); - log.debug("Replaced placeholder: {} with: {}", template, s); - return s; - - } - - protected DefaultArtifact convertToArtifact(DefaultArtifactVersion defaultArtifactVersion) { - return new DefaultArtifact(specBom.getGroupId() - , specBom.getArtifactId() - , - (org.codehaus.plexus.util.StringUtils.isNotEmpty(specBom.getClassifier()) ? specBom.getClassifier() - : null) - , (org.codehaus.plexus.util.StringUtils.isNotEmpty(specBom.getType()) ? specBom.getType() : null) - , defaultArtifactVersion.toString()); - } - -} diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/ExportDependenciesMojo.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/ExportDependenciesMojo.java deleted file mode 100644 index 22ed6af6a..000000000 --- a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/ExportDependenciesMojo.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.backbase.oss.boat; - -import java.io.File; -import java.util.List; -import java.util.stream.Collectors; -import lombok.extern.slf4j.Slf4j; -import org.apache.maven.artifact.Artifact; -import org.apache.maven.plugin.MojoExecutionException; -import org.apache.maven.plugins.annotations.Mojo; -import org.apache.maven.plugins.annotations.ResolutionScope; - -/** - * Exports project dependencies where the ArtifactId ends with "-spec". - */ -@Mojo(name = "export-dep", requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME, threadSafe = true) -@Slf4j -public class ExportDependenciesMojo extends AbstractRamlToOpenApi { - - @Override - public void execute() throws MojoExecutionException { - - List artifacts = project.getArtifacts().stream() - .filter(dependency -> dependency.getGroupId().startsWith(includeGroupIds)) - .filter(dependency -> dependency.getArtifactId().endsWith("-spec") || dependency.getArtifactId().endsWith("-specs")) - .collect(Collectors.toList()); - - for (Artifact artifact : artifacts) { - export(artifact); - } - - writeSummary("Exported Project Dependencies"); - } - - - private void export(Artifact artifact) throws MojoExecutionException { - File outputDirectory = new File(this.output, artifact.getGroupId().replace('.', '/')); - log.info("Export artifact: {} to: {}", artifact.getFile(), outputDirectory); - exportArtifact(artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion(), artifact.getFile(), outputDirectory); - } - -} diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/ExportMojo.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/ExportMojo.java deleted file mode 100644 index 8ed928177..000000000 --- a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/ExportMojo.java +++ /dev/null @@ -1,106 +0,0 @@ -package com.backbase.oss.boat; - -import java.io.File; -import org.apache.commons.lang3.StringUtils; -import org.apache.maven.plugin.MojoExecutionException; -import org.apache.maven.plugins.annotations.Mojo; -import org.apache.maven.plugins.annotations.Parameter; - -/** - * Converts a RAML spec to an OpenAPI spec. - */ -@Mojo(name = "export", threadSafe = true) -public class ExportMojo extends AbstractRamlToOpenApi { - - /** - * Source directory to scan for raml files. Use location relative to the project.baseDir. Default is - * 'src/main/resources'. - */ - @Parameter(property = "input", defaultValue = "src/main/resources") - protected File input; - - - /** - * Explicit RAML File location - */ - @Parameter(property = "inputFile") - protected File inputFile; - - /** - * Fails on errors by default, but can be set to ignore. - */ - @Parameter(property = "failOnError", defaultValue = "true") - private boolean failOnError = true; - - @Override - public void execute() throws MojoExecutionException { - File[] files; - if (inputFile != null) { - getLog().info("Converting RAML Input File: " + inputFile); - files = new File[]{inputFile}; - } else { - getLog().info("Converting RAML specs from Input Directory: " + input); - files = getFilesFromInputDirectoru(); - if(files == null) - return; - } - - for (File file : files) { - String ramlName = StringUtils.substringBeforeLast(file.getName(), "."); - try { - File outputDirectory = new File(output, ramlName); - export(null, file, outputDirectory); - getLog().info("Exported RAML Spec: " + ramlName); - } catch (Exception e) { - failed.put(ramlName, e.getMessage()); - String msg = "Failed to export RAML Spec: " + file.getName() - + " due to: [" + e.getClass() + "] " + e.getMessage(); - getLog().error(msg); - if (failOnError) { - throw new MojoExecutionException(msg, e); - } - } - } - - writeSummary("Converted RAML Specs to OpenAPI Summary"); - } - - - private File[] getFilesFromInputDirectoru() throws MojoExecutionException { - if (!input.exists()) { - String msg = "Input does not exist: " + input.getAbsolutePath(); - getLog().error(msg); - if (failOnError) { - throw new MojoExecutionException(msg); - } - } - - File[] files = input.listFiles(this::isRamlSpec); - if (files == null || files.length == 0) { - String msg = "Failed to find raml files in " + input.getAbsolutePath(); - getLog().error(msg); - if (failOnError) { - throw new MojoExecutionException(msg); - } - return new File[0]; - } - return files; - } - - public File getInput() { - return input; - } - - public void setInput(File input) { - this.input = input; - } - - public boolean isFailOnError() { - return failOnError; - } - - public void setFailOnError(boolean failOnError) { - this.failOnError = failOnError; - } - -} diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateMojo.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateMojo.java index bda698604..58f9cfefd 100644 --- a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateMojo.java +++ b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateMojo.java @@ -64,8 +64,11 @@ import static org.openapitools.codegen.config.CodegenConfiguratorUtils.applyInstantiationTypesKvpList; import static org.openapitools.codegen.config.CodegenConfiguratorUtils.applyLanguageSpecificPrimitivesCsv; import static org.openapitools.codegen.config.CodegenConfiguratorUtils.applyLanguageSpecificPrimitivesCsvList; +import static org.openapitools.codegen.config.CodegenConfiguratorUtils.applyOpenAPINormalizerKvpList; import static org.openapitools.codegen.config.CodegenConfiguratorUtils.applyReservedWordsMappingsKvp; import static org.openapitools.codegen.config.CodegenConfiguratorUtils.applyReservedWordsMappingsKvpList; +import static org.openapitools.codegen.config.CodegenConfiguratorUtils.applySchemaMappingsKvp; +import static org.openapitools.codegen.config.CodegenConfiguratorUtils.applySchemaMappingsKvpList; import static org.openapitools.codegen.config.CodegenConfiguratorUtils.applyServerVariablesKvp; import static org.openapitools.codegen.config.CodegenConfiguratorUtils.applyServerVariablesKvpList; import static org.openapitools.codegen.config.CodegenConfiguratorUtils.applyTypeMappingsKvp; @@ -98,6 +101,8 @@ private static String trimCSV(String text) { public static final String SERVER_VARIABLES = "server-variables"; public static final String RESERVED_WORDS_MAPPINGS = "reserved-words-mappings"; + public static final String SCHEMA_MAPPING = "schema-mappings"; + /** * The build context is only avail when running from within eclipse. It is used to update the * eclipse-m2e-layer when the plugin is executed inside the IDE. @@ -471,7 +476,14 @@ private static String trimCSV(String text) { @Parameter(name = "writeDebugFiles") protected boolean writeDebugFiles = false; + @Parameter(name = "openapiNormalizer", property = "openapi.generator.maven.plugin.openapiNormalizer") + private List openapiNormalizer; + /** + * A map of scheme and the new one + */ + @Parameter(name = "schemaMappings", property = "openapi.generator.maven.plugin.schemaMappings") + private List schemaMappings; public void setBuildContext(BuildContext buildContext) { this.buildContext = buildContext; @@ -773,6 +785,12 @@ public void execute() throws MojoExecutionException, MojoFailureException { applyReservedWordsMappingsKvp(configOptions.get(RESERVED_WORDS_MAPPINGS) .toString(), configurator); } + + // Retained for backwards-compatibility with configOptions -> schema-mappings + if (schemaMappings == null && configOptions.containsKey(SCHEMA_MAPPING)) { + applySchemaMappingsKvp(configOptions.get(SCHEMA_MAPPING).toString(), + configurator); + } } // Apply Instantiation Types @@ -814,6 +832,15 @@ public void execute() throws MojoExecutionException, MojoFailureException { applyReservedWordsMappingsKvpList(reservedWordsMappings, configurator); } + if (openapiNormalizer != null && (configOptions == null || !configOptions.containsKey("openapi-normalizer"))) { + applyOpenAPINormalizerKvpList(openapiNormalizer, configurator); + } + + // Apply Schema Mappings + if (schemaMappings != null && (configOptions == null || !configOptions.containsKey(SCHEMA_MAPPING))) { + applySchemaMappingsKvpList(schemaMappings, configurator); + } + if (environmentVariables != null) { for (Entry entry : environmentVariables.entrySet()) { @@ -825,7 +852,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { value = ""; } GlobalSettings.setProperty(key, value); - configurator.addSystemProperty(key, value); + configurator.addGlobalProperty(key, value); } } diff --git a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/ValidateMojo.java b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/ValidateMojo.java index 75ae3e0cd..84d1b27e7 100644 --- a/boat-maven-plugin/src/main/java/com/backbase/oss/boat/ValidateMojo.java +++ b/boat-maven-plugin/src/main/java/com/backbase/oss/boat/ValidateMojo.java @@ -63,12 +63,13 @@ private void validate(File inputFile) throws MojoFailureException { SwaggerParseResult swaggerParseResult = openAPIParser.readLocation(inputFile.toURI().toString(), new ArrayList<>(), parseOptions); - if (swaggerParseResult.getMessages().isEmpty()) { + if (swaggerParseResult.getMessages() != null && swaggerParseResult.getMessages().isEmpty()) { log.info("OpenAPI: {} is valid", swaggerParseResult.getOpenAPI().getInfo().getTitle()); } else { - for (String message : swaggerParseResult.getMessages()) { - processMessages(message, inputFile, swaggerParseResult); - } + if (swaggerParseResult.getMessages() != null) + for (String message : swaggerParseResult.getMessages()) { + processMessages(message, inputFile, swaggerParseResult); + } if (failOnWarning) { throw new MojoFailureException("Validation errors validating OpenAPI"); } diff --git a/boat-maven-plugin/src/test/java/com/backbase/oss/boat/ExportBomMojoTests.java b/boat-maven-plugin/src/test/java/com/backbase/oss/boat/ExportBomMojoTests.java deleted file mode 100644 index 80dade2a9..000000000 --- a/boat-maven-plugin/src/test/java/com/backbase/oss/boat/ExportBomMojoTests.java +++ /dev/null @@ -1,152 +0,0 @@ -package com.backbase.oss.boat; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import java.io.File; -import java.util.Collections; -import java.util.List; -import org.apache.maven.model.Build; -import org.apache.maven.model.Dependency; -import org.apache.maven.plugin.MojoExecutionException; -import org.apache.maven.plugin.MojoFailureException; -import org.apache.maven.project.MavenProject; -import org.codehaus.plexus.logging.console.ConsoleLogger; -import org.eclipse.aether.RepositorySystemSession; -import org.eclipse.aether.artifact.DefaultArtifact; -import org.eclipse.aether.impl.ArtifactResolver; -import org.eclipse.aether.impl.MetadataResolver; -import org.eclipse.aether.metadata.Metadata; -import org.eclipse.aether.resolution.ArtifactResolutionException; -import org.eclipse.aether.resolution.ArtifactResult; -import org.eclipse.aether.resolution.MetadataResult; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import org.sonatype.plexus.build.incremental.DefaultBuildContext; - -@ExtendWith(MockitoExtension.class) -class ExportBomMojoTests { - @Mock - ArtifactResolver artifactResolver; - @Mock - ArtifactResult artifactResult; - @Mock - MetadataResolver metadataResolver; - - @Mock - MetadataResult metadataResult; - @Mock - Metadata metadatamock; - - - @Test - void testExportBomEmptyMeta() throws MojoExecutionException { - artifactResolver = mock(ArtifactResolver.class); - artifactResult = mock( ArtifactResult.class); - metadataResolver = mock(MetadataResolver.class); - - when(metadataResolver.resolveMetadata(any(),any())).thenReturn(Collections.singletonList(metadataResult)); - - ExportBomMojo mojo = new ExportBomMojo(); - File output = new File("target/boat-bom-export"); - if (!output.exists()) { - output.mkdirs(); - } - - DefaultBuildContext defaultBuildContext = new DefaultBuildContext(); - defaultBuildContext.enableLogging(new ConsoleLogger()); - - mojo.getLog(); - mojo.artifactResolver = artifactResolver; - mojo.metadataResolver = metadataResolver; - mojo.setSpecBom(new Dependency()); - - - Build build = new Build(); - build.setDirectory("target"); - - MavenProject project = new MavenProject(); - mojo.remoteRepositories = Collections.emptyList(); - project.setBuild(build); - mojo.project = project; - mojo.repositorySession = mock(RepositorySystemSession.class); - mojo.execute(); - - assertThat(output).isEmptyDirectory(); - - } - - @Test - void testExportBomUseOfArtifactResolver() throws MojoFailureException, MojoExecutionException, ArtifactResolutionException { - File versionFile = getFile("/export-bom/maven-metadata-test-example.xml"); - String groupId="test.groupId"; - String artifactId = "raml-bom"; - String type = "pom"; - String version= "[1.0.0,)"; - - File pomFile = getFile("/export-bom/raml-spec-bom/pom.xml"); - artifactResolver = mock(ArtifactResolver.class); - artifactResult = mock( ArtifactResult.class); - org.eclipse.aether.artifact.Artifact artifact; //= mock(org.eclipse.aether.artifact.Artifact.class); - artifact = new DefaultArtifact(groupId, artifactId, "", type, version,Collections.emptyMap(), pomFile); - - - when(artifactResolver.resolveArtifact(any(),any())).thenReturn(artifactResult); - when(artifactResult.getArtifact()).thenReturn(artifact); - //when(artifact.getFile()).thenReturn(pomFile); - - - when(metadataResolver.resolveMetadata(any(),any())).thenReturn(Collections.singletonList(metadataResult)); - - ExportBomMojo mojo = new ExportBomMojo(); - File output = new File("target/boat-bom-export"); - if (!output.exists()) { - output.mkdirs(); - } - when(metadataResult.isResolved()).thenReturn(true); - - - doReturn(metadatamock).when(metadataResult).getMetadata(); - doReturn(versionFile).when(metadatamock).getFile(); - - DefaultBuildContext defaultBuildContext = new DefaultBuildContext(); - defaultBuildContext.enableLogging(new ConsoleLogger()); - - mojo.getLog(); - mojo.artifactResolver = artifactResolver; - mojo.metadataResolver = metadataResolver; - Dependency dependency = new Dependency(); - - dependency.setType(type); - dependency.setGroupId(groupId); - dependency.setArtifactId(artifactId); - dependency.setVersion(version); - mojo.setSpecBom(dependency); - - - Build build = new Build(); - build.setDirectory("target"); - - MavenProject project = new MavenProject(); - mojo.remoteRepositories = Collections.emptyList(); - - project.setBuild(build); - mojo.project = project; - mojo.repositorySession = mock(RepositorySystemSession.class); - mojo.execute(); - - assertThat(output).isEmptyDirectory(); - - } - private File getFile(String fileName) { - return new File(getClass().getResource(fileName).getFile()); - } - -} diff --git a/boat-maven-plugin/src/test/java/com/backbase/oss/boat/ExportDependencyMojoTests.java b/boat-maven-plugin/src/test/java/com/backbase/oss/boat/ExportDependencyMojoTests.java deleted file mode 100644 index b87a812c7..000000000 --- a/boat-maven-plugin/src/test/java/com/backbase/oss/boat/ExportDependencyMojoTests.java +++ /dev/null @@ -1,140 +0,0 @@ -package com.backbase.oss.boat; - -import java.io.File; -import java.util.Collections; -import java.util.Locale; -import java.util.TimeZone; - -import lombok.extern.slf4j.Slf4j; -import org.apache.maven.artifact.DefaultArtifact; -import org.apache.maven.artifact.handler.DefaultArtifactHandler; -import org.apache.maven.model.Build; -import org.apache.maven.model.Dependency; -import org.apache.maven.plugin.MojoExecutionException; -import org.apache.maven.project.MavenProject; -import org.codehaus.plexus.logging.console.ConsoleLogger; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.sonatype.plexus.build.incremental.DefaultBuildContext; - -import static org.junit.jupiter.api.Assertions.assertTrue; - -@Slf4j -class ExportDependencyMojoTests { - - @BeforeAll - static void setupLocale() { - Locale.setDefault(Locale.ENGLISH); - TimeZone.setDefault(TimeZone.getTimeZone("Europe/London")); - } - - @Test - void testAggregatedInputFile() throws MojoExecutionException, ExportException { - - ExportDependenciesMojo mojo = new ExportDependenciesMojo(); - - DefaultBuildContext defaultBuildContext = new DefaultBuildContext(); - defaultBuildContext.enableLogging(new ConsoleLogger(2, "BOAT")); - - String groupId = "test.groupId"; - String artifactId = "artifact-spec"; - String version = "2.19.0"; - String scope = "provided"; - String type = "jar"; - - Dependency specDependency = new Dependency(); - specDependency.setGroupId(groupId); - specDependency.setArtifactId(artifactId); - specDependency.setVersion(version); - - DefaultArtifactHandler artifactHandler = new DefaultArtifactHandler(); - DefaultArtifact specArtifact = new DefaultArtifact(groupId, artifactId, version, scope, type, null, - artifactHandler); - specArtifact.setFile(getFile("/raml-examples/aggregated-spec.zip")); - - Build build = new Build(); - build.setDirectory("target"); - - - MavenProject project = new MavenProject(); - project.setArtifacts(Collections.singleton(specArtifact)); - project.setDependencies(Collections.singletonList(specDependency)); - - project.setBuild(build); - - mojo.project = project; - mojo.includeGroupIds = "test."; - mojo.ramlFileFilters = "**/*-api.raml,**/api.raml"; - mojo.output = new File("target/export-aggregated-dep"); - mojo.continueOnError = false; - mojo.execute(); - - assertTrue(new File("target/export-aggregated-dep/test/groupId/artifact-spec/backbase-wallet/presentation-client-api/openapi.yaml").exists()); - - } - - @Test - void testInputFile() throws MojoExecutionException, ExportException { - String groupId = "test.groupId"; - String artifactId = "artifact-spec"; - String version = "2.19.0"; - String scope = "provided"; - String type = "jar"; - - testExportDep(groupId, artifactId, version, scope, type); - } - - @Test - void testInputFile2() throws MojoExecutionException, ExportException { - String groupId = "test.groupId"; - String artifactId = "artifact-specs"; - String version = "2.19.0"; - String scope = "provided"; - String type = "jar"; - - testExportDep(groupId, artifactId, version, scope, type); - } - - private void testExportDep(String groupId, String artifactId, String version, String scope, String type) - throws MojoExecutionException { - ExportDependenciesMojo mojo = new ExportDependenciesMojo(); - - DefaultBuildContext defaultBuildContext = new DefaultBuildContext(); - defaultBuildContext.enableLogging(new ConsoleLogger(2, "BOAT")); - - Dependency specDependency = new Dependency(); - specDependency.setGroupId(groupId); - specDependency.setArtifactId(artifactId); - specDependency.setVersion(version); - - DefaultArtifactHandler artifactHandler = new DefaultArtifactHandler(); - DefaultArtifact specArtifact = new DefaultArtifact(groupId, artifactId, version, scope, type, null, - artifactHandler); - specArtifact.setFile(getFile("/raml-examples/backbase-wallet.zip")); - - Build build = new Build(); - build.setDirectory("target"); - - MavenProject project = new MavenProject(); - project.setArtifacts(Collections.singleton(specArtifact)); - project.setDependencies(Collections.singletonList(specDependency)); - - project.setBuild(build); - - mojo.project = project; - mojo.includeGroupIds = "test."; - mojo.ramlFileFilters = "**/*-api.raml,**/api.raml"; - mojo.output = new File("target/export-dep"); - mojo.continueOnError = false; - mojo.execute(); - - assertTrue(new File("target/export-dep/test/groupId/artifact-spec/backbase-wallet/presentation-client-api/openapi.yaml").exists()); - } - - private File getFile(String fileName) { - return new File(getClass().getResource(fileName).getFile()); - } - - -} diff --git a/boat-maven-plugin/src/test/java/com/backbase/oss/boat/ExportMojoTests.java b/boat-maven-plugin/src/test/java/com/backbase/oss/boat/ExportMojoTests.java deleted file mode 100644 index 4a467063b..000000000 --- a/boat-maven-plugin/src/test/java/com/backbase/oss/boat/ExportMojoTests.java +++ /dev/null @@ -1,132 +0,0 @@ -package com.backbase.oss.boat; - -import com.backbase.oss.boat.loader.OpenAPILoader; -import com.backbase.oss.boat.loader.OpenAPILoaderException; -import io.swagger.v3.oas.models.OpenAPI; -import java.io.File; -import java.util.Locale; -import java.util.TimeZone; - -import lombok.extern.slf4j.Slf4j; -import org.apache.maven.plugin.MojoExecutionException; -import org.apache.maven.project.MavenProject; -import org.codehaus.plexus.logging.console.ConsoleLogger; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.sonatype.plexus.build.incremental.DefaultBuildContext; - -import static org.junit.jupiter.api.Assertions.*; - -@Slf4j -class ExportMojoTests { - - @BeforeAll - static void setupLocale() { - Locale.setDefault(Locale.ENGLISH); - TimeZone.setDefault(TimeZone.getTimeZone("Europe/London")); - } - - @Test - void testInputFile() throws MojoExecutionException { - - ExportMojo mojo = new ExportMojo(); - - File input = getFile("/raml-examples/helloworld/helloworld.raml"); - File output = new File("target"); - if (!output.exists()) { - output.mkdirs(); - } - - File outputYaml = new File(output, "helloworld/openapi.yaml"); - outputYaml.delete(); - - DefaultBuildContext defaultBuildContext = new DefaultBuildContext(); - defaultBuildContext.enableLogging(new ConsoleLogger(2, "BOAT")); - - mojo.getLog(); - mojo.project = new MavenProject(); - mojo.inputFile = input; - mojo.output = output; - mojo.execute(); - - assertTrue(outputYaml.exists()); - - } - - @Test - void testLicenceAdder() throws MojoExecutionException, OpenAPILoaderException { - - ExportMojo mojo = new ExportMojo(); - - File input = getFile("/raml-examples/helloworld/helloworld.raml"); - File output = new File("target"); - if (!output.exists()) { - output.mkdirs(); - } - - File outputYaml = new File(output, "helloworld/openapi.yaml"); - outputYaml.delete(); - - DefaultBuildContext defaultBuildContext = new DefaultBuildContext(); - defaultBuildContext.enableLogging(new ConsoleLogger(2, "BOAT")); - - mojo.getLog(); - mojo.project = new MavenProject(); - mojo.inputFile = input; - mojo.output = output; - mojo.licenseName = "testLicence"; - mojo.licenseUrl= "testUrl"; - mojo.execute(); - - assertTrue(outputYaml.exists()); - OpenAPI load = OpenAPILoader.load(outputYaml, false, false); - assertEquals("testLicence",load.getInfo().getLicense().getName() ); - assertEquals("testUrl",load.getInfo().getLicense().getUrl()); - } - - @Test - void testInputDir() throws MojoExecutionException { - ExportMojo mojo = new ExportMojo(); - - File input = getFile("/raml-examples/backbase-wallet"); - File output = new File("target"); - if (!output.exists()) { - output.mkdirs(); - } - - DefaultBuildContext defaultBuildContext = new DefaultBuildContext(); - defaultBuildContext.enableLogging(new ConsoleLogger(2, "BOAT")); - - mojo.getLog(); - mojo.project = new MavenProject(); - mojo.input = input; - mojo.output = output; - mojo.execute(); - - assertTrue(new File("target/presentation-client-api/openapi.yaml").exists()); - assertTrue(new File("target/presentation-integration-api/openapi.yaml").exists()); - assertTrue(new File("target/presentation-service-api/openapi.yaml").exists()); - - } - - @Test - void testErrorCatching(){ - ExportMojo mojo = new ExportMojo(); - mojo.inputFile=null; - // tests for valid file path that contains no raml spec - mojo.input=getFile("/raml-examples/export-mojo-error-catching/error"); - - assertThrows(MojoExecutionException.class,mojo::execute); - // tests for invalid path - mojo.input = new File("bad-file-path"); - assertThrows(MojoExecutionException.class,mojo::execute); - - mojo.inputFile = getFile("/raml-examples/export-mojo-error-catching/invalid-presentation-client-api.raml"); - assertThrows(MojoExecutionException.class,mojo::execute); - - } - - private File getFile(String fileName) { - return new File(getClass().getResource(fileName).getFile()); - } -} diff --git a/boat-maven-plugin/src/test/java/com/backbase/oss/boat/GeneratorTests.java b/boat-maven-plugin/src/test/java/com/backbase/oss/boat/GeneratorTests.java index 839e21df8..3557c9861 100644 --- a/boat-maven-plugin/src/test/java/com/backbase/oss/boat/GeneratorTests.java +++ b/boat-maven-plugin/src/test/java/com/backbase/oss/boat/GeneratorTests.java @@ -310,46 +310,6 @@ void testAngularExamplesInComponents() { assertDoesNotThrow(mojo::execute, "Angular client generation should not throw exceptions"); } - @Test - void testBeanValidation() throws MojoExecutionException, MojoFailureException { - GenerateMojo mojo = new GenerateMojo(); - - String inputFile = getClass().getResource("/oas-examples/petstore.yaml").getFile(); - File input = new File(inputFile); - File output = new File("target/spring-mvc"); - if (!output.exists()) { - output.mkdirs(); - } - - DefaultBuildContext defaultBuildContext = new DefaultBuildContext(); - defaultBuildContext.enableLogging(new ConsoleLogger()); - - Map configOption = new HashMap<>(); - configOption.put("library", "spring-mvc"); - configOption.put("dateLibrary", "java8"); - configOption.put("apiPackage", "com.backbase.accesscontrol.service.rest.spec.api"); - configOption.put("modelPackage", "com.backbase.accesscontrol.service.rest.spec.model"); - configOption.put("useBeanValidation", "true"); - configOption.put("useClassLevelBeanValidation", "false"); - - - mojo.getLog(); - mojo.buildContext = defaultBuildContext; - mojo.project = new MavenProject(); - mojo.generatorName = "spring"; - mojo.configOptions = configOption; - mojo.inputSpec = input.getAbsolutePath(); - mojo.output = output; - mojo.skip = false; - mojo.skipIfSpecIsUnchanged = false; - mojo.execute(); - String[] actualFilesGenerated = output.list(); - Arrays.sort(actualFilesGenerated); - String[] expected = {".openapi-generator", ".openapi-generator-ignore", "README.md", "pom.xml", "src"}; - assertArrayEquals(expected, actualFilesGenerated); - - } - @Test void testWebClient() throws MojoExecutionException { GenerateWebClientEmbeddedMojo mojo = new GenerateWebClientEmbeddedMojo(); diff --git a/boat-maven-plugin/src/test/java/com/backbase/oss/boat/ValidateMojoTests.java b/boat-maven-plugin/src/test/java/com/backbase/oss/boat/ValidateMojoTests.java index 8e6891036..44f5fa609 100644 --- a/boat-maven-plugin/src/test/java/com/backbase/oss/boat/ValidateMojoTests.java +++ b/boat-maven-plugin/src/test/java/com/backbase/oss/boat/ValidateMojoTests.java @@ -24,31 +24,6 @@ void testValidation() throws MojoFailureException { } - @Test - void testValidationCatches() throws MojoFailureException, MojoExecutionException { - - - ValidateMojo mojo = new ValidateMojo(); - mojo.setInput(new File("bad.yaml")); - mojo.setFailOnWarning(true); - - assertThrows(MojoFailureException.class, mojo::execute); - - String spec = System.getProperty("spec", getClass().getResource("/raml-examples/export-mojo-error-catching/error").getFile()); - - File input = new File(spec); - - - mojo.setInput(input); - mojo.setFailOnWarning(true); - - assertThrows(MojoFailureException.class, mojo::execute); - mojo.setFailOnWarning(false); - assertDoesNotThrow(() -> mojo.execute()); - - - } - @Test void testValidatingDirectory() throws MojoFailureException { String spec = System.getProperty("spec", getClass().getResource("/oas-examples/").getFile()); diff --git a/boat-maven-plugin/src/test/java/com/backbase/oss/boat/transformers/ExporterTest.java b/boat-maven-plugin/src/test/java/com/backbase/oss/boat/transformers/ExporterTest.java deleted file mode 100644 index 7e555333d..000000000 --- a/boat-maven-plugin/src/test/java/com/backbase/oss/boat/transformers/ExporterTest.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.backbase.oss.boat.transformers; - -import com.backbase.oss.boat.ExportException; -import com.backbase.oss.boat.Exporter; -import com.backbase.oss.boat.serializer.SerializerUtils; -import io.swagger.v3.oas.models.OpenAPI; -import io.swagger.v3.parser.OpenAPIV3Parser; -import io.swagger.v3.parser.core.models.ParseOptions; -import io.swagger.v3.parser.core.models.SwaggerParseResult; -import java.io.File; -import java.io.IOException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Collections; - -import org.junit.jupiter.api.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - - -class ExporterTest extends AbstractBoatEngineTests { - - Logger log = LoggerFactory.getLogger(ExporterTest.class); - - @Test - void testBackbaseWalletApi() throws Exception { - - File inputFile = getFile("/raml-examples/backbase-wallet/presentation-client-api.raml"); - OpenAPI openAPI = Exporter.export(inputFile, true, Collections.singletonList(new Decomposer())); - String export = SerializerUtils.toYamlString(openAPI); - validateExport(export); - } - - - protected SwaggerParseResult validateExport(String export) throws IOException, ExportException { - if (export == null) { - throw new ExportException("Invalid Export"); - } - - String child = "openapi.yaml"; - - writeOutput(export, child); - - OpenAPIV3Parser openAPIParser = new OpenAPIV3Parser(); - ParseOptions parseOptions = new ParseOptions(); - SwaggerParseResult swaggerParseResult = openAPIParser.readContents(export, new ArrayList<>(), parseOptions); - for (String message : swaggerParseResult.getMessages()) { - log.error("Error parsing Open API: {}", message); - } - assertTrue(swaggerParseResult.getMessages().isEmpty()); - - return swaggerParseResult; - } - - - protected File getFile(String name) { - URL resource = getClass().getResource(name); - assert resource != null; - return new File(resource.getFile()); - } - - -} diff --git a/boat-maven-plugin/src/test/resources/export-bom/maven-metadata-test-example.xml b/boat-maven-plugin/src/test/resources/export-bom/maven-metadata-test-example.xml deleted file mode 100644 index 971aae3d4..000000000 --- a/boat-maven-plugin/src/test/resources/export-bom/maven-metadata-test-example.xml +++ /dev/null @@ -1,15 +0,0 @@ - - test.groupId - openapi-zips - [1.0.0,) - - 1.0.0 - 1.0.0 - - 1.0.0 - - 20150509185437 - - diff --git a/boat-maven-plugin/src/test/resources/export-bom/raml-spec-bom/pom.xml b/boat-maven-plugin/src/test/resources/export-bom/raml-spec-bom/pom.xml deleted file mode 100644 index 51b78d2fd..000000000 --- a/boat-maven-plugin/src/test/resources/export-bom/raml-spec-bom/pom.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - 4.0.0 - - com.backbase.oss.boat.example - raml-spec-bom - 1.0.0-SNAPSHOT - - - 1.0.0-SNAPSHOT - - - pom - - BOAT :: RAML Bill-Of-Materials - - - - - com.backbase.oss.boat.example - raml-spec - ${raml-spec.version} - - - - - - - - diff --git a/boat-maven-plugin/src/test/resources/raml-examples/aggregated-spec.zip b/boat-maven-plugin/src/test/resources/raml-examples/aggregated-spec.zip deleted file mode 100644 index 83973febb..000000000 Binary files a/boat-maven-plugin/src/test/resources/raml-examples/aggregated-spec.zip and /dev/null differ diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet.zip b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet.zip deleted file mode 100644 index f9f9498b8..000000000 Binary files a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet.zip and /dev/null differ diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/bbt-common.raml b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/bbt-common.raml deleted file mode 100644 index 281655811..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/bbt-common.raml +++ /dev/null @@ -1,7 +0,0 @@ -#%RAML 1.0 Library -schemas: - ObjectWrappingException: !include common-schemas/body/object-wrapping-exception.json -types: - PaymentCard: !include common-schemas/body/paymentcard-item.json - PaymentCards: !include common-schemas/body/paymentcards-get.json - TestHeadersResponseBody: !include common-schemas/body/test-headers-response.json \ No newline at end of file diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/date-query-params.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/date-query-params.json deleted file mode 100644 index 377c9a7fc..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/date-query-params.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType":"com.backbase.buildingblocks.test.data.DateTimeTestResponse", - "properties": { - "dateTimeOnly": { - "type": "string" - }, - "dateTimeOnlyParsedValue": { - "type": "string" - }, - "dateTime": { - "type": "string" - }, - "dateTimeParsedValue": { - "type": "string" - }, - "dateTime2616": { - "type": "string" - }, - "dateTime2616ParsedValue": { - "type": "string" - }, - "date": { - "type": "string" - }, - "dateParsedValue": { - "type": "string" - }, - "time": { - "type": "string" - }, - "timeParsedValue": { - "type": "string" - }, - "formatDateTime": { - "description": "The dateTime parameter formatted as 'date-time', java.util.Date or java.time.ZoneDateTime", - "type": "string", - "format": "date-time" - }, - "formatDate": { - "description": "The date parameter formatted as 'date', String or java.time.LocalDate", - "type": "string", - "format": "date" - }, - "formatTime": { - "description": "The time parameter formatted as 'time', String or java.time.LocalTime", - "type": "string", - "format": "time" - }, - "formatUtcMillisec": { - "description": "The dateTime parameter formatted as 'date', long", - "type": "string", - "format": "utc-millisec" - } - } -} \ No newline at end of file diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/object-wrapping-exception.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/object-wrapping-exception.json deleted file mode 100644 index 4a3a7e1dd..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/object-wrapping-exception.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.test.exceptions.ObjectWrappingException", - "properties": { - "message": { - "type": "string" - }, - "data": { - "type": "object" - } - } -} diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/paymentcard-item.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/paymentcard-item.json deleted file mode 100644 index 8542e05cb..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/paymentcard-item.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType":"com.backbase.buildingblocks.test.data.PaymentCard", - "properties": { - "id": { - "type": "string" - }, - "pan": { - "type": "string", - "description": "Must be sixteen digits, optionally in blocks of 4 separated by a dash", - "maxLength": 19 - }, - "cvc": { - "type": "string", - "description": "Card Verification Code", - "minLength": 3, - "maxLength": 3 - }, - "startDate": { - "type": "string", - "description": "Must be in one of these four formats: MM/YY MMYY MMYYYY MM/YYYY", - "pattern": "^(0[1-9]|1[0-2])\/?([0-9]{4}|[0-9]{2})$" - }, - "expiryDate": { - "type": "string", - "description": "Must be in one of these four formats: MM/YY MMYY MMYYYY MM/YYYY", - "pattern": "^(0[1-9]|1[0-2])\/?([0-9]{4}|[0-9]{2})$" - }, - "nameOnCard": { - "type": "string" - }, - "creationDate" : { - "type":"string", - "format":"date-time" - }, - "balance" : { - "type": "object", - "$ref": "../../lib/types/schemas/currency.json" - }, - "apr": { - "type": "number", - "javaType": "java.math.BigDecimal" - }, - "cardtype" : { - "type" : "string", - "default" : "CREDIT", - "enum" : ["CREDIT", "DEBIT", "PREPAID"] - } - }, - "required": [ - "id", - "pan", - "cvc", - "startDate", - "expiryDate", - "nameOnCard" - ] -} diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/paymentcards-get.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/paymentcards-get.json deleted file mode 100644 index 16c29a9f7..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/paymentcards-get.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "array", - "items": { - "$ref": "paymentcard-item.json" - } -} \ No newline at end of file diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/test-headers-response.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/test-headers-response.json deleted file mode 100644 index 4c0635545..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/test-headers-response.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType":"com.backbase.buildingblocks.test.data.TestHeadersResponse", - "additionalProperties": false, - "properties": { - "requests": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "url": { - "type": "string" - }, - "headers": { - "type": "object", - "javaType": "java.util.Map" - } - } - } - } - } - } \ No newline at end of file diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/events/add-paymentcard-command.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/events/add-paymentcard-command.json deleted file mode 100644 index 1296ef118..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/events/add-paymentcard-command.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "required": true, - "properties": { - "paymentcard": { - "type": "object", - "$ref": "../common-schemas/body/paymentcard-item.json" - } - } -} \ No newline at end of file diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/events/delete-paymentcard-command.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/events/delete-paymentcard-command.json deleted file mode 100644 index 81b24e284..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/events/delete-paymentcard-command.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "required": true, - "properties": { - "paymentcard": { - "type": "object", - "$ref": "../schemas/body/paymentcard-id.json" - } - } -} \ No newline at end of file diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/events/get-paymentcards-command.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/events/get-paymentcards-command.json deleted file mode 100644 index 2d04dc7a3..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/events/get-paymentcards-command.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "required": true, - "properties": { - "queryParams": { - "type": "object", - "$ref": "../schemas/body/paymentcards-query.json" - } - } -} \ No newline at end of file diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/events/paymentcard-added-event.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/events/paymentcard-added-event.json deleted file mode 100644 index d1efda594..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/events/paymentcard-added-event.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "required": true, - "properties": { - "paymentcard": { - "type": "object", - "$ref": "../common-schemas/body/paymentcard-item.json" - }, - "emitDateTime": { - "description": "The dateTime parameter formatted as 'date-time', java.util.Date or java.time.ZoneDateTime", - "type": "string", - "format": "date-time" - }, - "emitDate": { - "description": "The date parameter formatted as 'date', String or java.time.LocalDate", - "type": "string", - "format": "date" - }, - "emitTime": { - "description": "The time parameter formatted as 'time', String or java.time.LocalTime", - "type": "string", - "format": "time" - }, - "emitMillisec": { - "description": "The dateTime parameter formatted as 'date', long", - "type": "string", - "format": "utc-millisec" - } - } -} \ No newline at end of file diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/events/paymentcard-deleted-event.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/events/paymentcard-deleted-event.json deleted file mode 100644 index d1efda594..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/events/paymentcard-deleted-event.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "required": true, - "properties": { - "paymentcard": { - "type": "object", - "$ref": "../common-schemas/body/paymentcard-item.json" - }, - "emitDateTime": { - "description": "The dateTime parameter formatted as 'date-time', java.util.Date or java.time.ZoneDateTime", - "type": "string", - "format": "date-time" - }, - "emitDate": { - "description": "The date parameter formatted as 'date', String or java.time.LocalDate", - "type": "string", - "format": "date" - }, - "emitTime": { - "description": "The time parameter formatted as 'time', String or java.time.LocalTime", - "type": "string", - "format": "time" - }, - "emitMillisec": { - "description": "The dateTime parameter formatted as 'date', long", - "type": "string", - "format": "utc-millisec" - } - } -} \ No newline at end of file diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/events/paymentcards-retrieved-event.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/events/paymentcards-retrieved-event.json deleted file mode 100644 index 2cbadf471..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/events/paymentcards-retrieved-event.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "required": true, - "properties": { - "queryParams": { - "type": "object", - "$ref": "../schemas/body/paymentcards-query.json" - }, - "results": { - "type": "array", - "items": { - "$ref": "../common-schemas/body/paymentcard-item.json" - } - }, - "emitDateTime": { - "description": "The dateTime parameter formatted as 'date-time', java.util.Date or java.time.ZoneDateTime", - "type": "string", - "format": "date-time" - }, - "emitDate": { - "description": "The date parameter formatted as 'date', String or java.time.LocalDate", - "type": "string", - "format": "date" - }, - "emitTime": { - "description": "The time parameter formatted as 'time', String or java.time.LocalTime", - "type": "string", - "format": "time" - }, - "emitMillisec": { - "description": "The dateTime parameter formatted as 'date', long", - "type": "string", - "format": "utc-millisec" - } - } -} \ No newline at end of file diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/examples/body/example-build-info.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/examples/body/example-build-info.json deleted file mode 100644 index 5cc40dd5d..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/examples/body/example-build-info.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "build-info": { - "build.version": "1.1.111-SNAPSHOT" - } -} diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/examples/body/item.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/examples/body/item.json deleted file mode 100644 index 89a3fdb1f..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/examples/body/item.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "Example", - "description": "Example description" -} diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/examples/body/paymentcard-created.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/examples/body/paymentcard-created.json deleted file mode 100644 index 3706a5fbc..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/examples/body/paymentcard-created.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "id": "a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1" -} \ No newline at end of file diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/examples/body/paymentcard-item.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/examples/body/paymentcard-item.json deleted file mode 100644 index 72777d92d..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/examples/body/paymentcard-item.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "id": "a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1", - "pan": "5434111122223333", - "cvc": "123", - "startDate": "0116", - "expiryDate": "1219", - "nameOnCard": "Mr Timmy Tester", - "creationDate": "2011-05-30T12:13:14+03:00", - "balance": { - "amount": "1000", - "currencyCode": "EUR" - }, - "apr": 12.75 -} \ No newline at end of file diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/examples/body/paymentcards-get.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/examples/body/paymentcards-get.json deleted file mode 100644 index a7d5dc369..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/examples/body/paymentcards-get.json +++ /dev/null @@ -1,44 +0,0 @@ -[ - { - "id": "a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1", - "pan": "5434111122223333", - "cvc": "123", - "startDate": "0116", - "expiryDate": "1219", - "nameOnCard": "Mr Timmy Tester", - "creationDate": "2011-05-30T12:13:14+03:00", - "balance": { - "amount": "2001", - "currencyCode": "EUR" - }, - "apr": 12.75 - }, - { - "id": "d593c212-70ad-41a6-a547-d5d9232414cb", - "pan": "5434111122224444", - "cvc": "101", - "startDate": "0216", - "expiryDate": "0120", - "nameOnCard": "Mr Timmothy Tester", - "creationDate": "2011-05-30T12:13:14+03:00", - "balance": { - "amount": "4.4399999999999995", - "currencyCode": "GBP" - }, - "apr": 12.75 - }, - { - "id": "9635966b-28e9-4479-8121-bb7bc9beeb62", - "pan": "5434121212121212", - "cvc": "121", - "startDate": "0115", - "expiryDate": "1218", - "nameOnCard": "Mr Timmy Tester", - "creationDate": "2011-05-30T12:13:14+03:00", - "balance": { - "amount": "1981", - "currencyCode": "EUR" - }, - "apr": 12.75 - } -] \ No newline at end of file diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/examples/body/test-headers-response.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/examples/body/test-headers-response.json deleted file mode 100644 index bcc24c481..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/examples/body/test-headers-response.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "requests" : [ - { - "name": "building-blocks-test-wallet-presentation-service", - "url": "/client-api/v1/test/headers", - "headers": { - "correlation-id": [ "2ed475b714a3945a" ], - "accept": [ "application/json" ], - "x-bbt-test": [ "X-BBT-contentVal2" ], - "connection": [ "keep-alive" ] - } - }, - { - "name": "building-blocks-test-wallet-pandp-service", - "url": "/service-api/v1/test/headers", - "headers": { - "authorization": [ "Bearer eyJh" ], - "accept": [ "application/xml, text/xml, application/json, application/*+xml, application/*+json" ], - "content-type": [ "application/json" ], - "x-cxt-user-token": [ "Bearer ey" ], - "x-cxt-remote-user": [ "admin" ], - "x-cxt-requestuuid": [ "72002652-131a-4f28-bd00-16b8080932f5" ], - "correlation-id": [ "2ed475b714a3945a" ], - "x-bbt-test": [ "X-BBT-contentVal2" ] - } - }, - { - "name": "building-blocks-test-wallet-pandp-service", - "url": "/service-api/v1/test/headers", - "headers": { - "authorization": [ "Bearer eyJh" ], - "accept": [ "application/xml, text/xml, application/json, application/*+xml, application/*+json" ], - "content-type": [ "application/json" ], - "x-cxt-user-token": [ "Bearer ey" ], - "x-cxt-remote-user": [ "admin" ], - "x-cxt-requestuuid": [ "72002652-131a-4f28-bd00-16b8080932f5" ], - "correlation-id": [ "2ed475b714a3945a" ], - "x-bbt-test": [ "X-BBT-contentVal2" ] - } - } - ] -} \ No newline at end of file diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/examples/body/test-values-response.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/examples/body/test-values-response.json deleted file mode 100644 index eb5f7bd7b..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/examples/body/test-values-response.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "message": "a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1", - "number": "102.4" -} \ No newline at end of file diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/examples/errors/error.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/examples/errors/error.json deleted file mode 100644 index 26d84f14d..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/examples/errors/error.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "message": "Description of error", - "errorCode" : "EXAMPLE-000001" -} \ No newline at end of file diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/annotations/annotations.raml b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/annotations/annotations.raml deleted file mode 100644 index ea6032759..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/annotations/annotations.raml +++ /dev/null @@ -1,38 +0,0 @@ -#%RAML 1.0 Library - -securitySchemes: -# Custom 'bbAccessControl' security schema -# RAML 1-0 does not allow settings in an x-other security scheme, so no opportunity to describe extra information here - bbAccessControl: - displayName: Backbase Access Control - description: | - This API is secured by DBS Access Control - type: x-bb-access-control - -# RAML annotation and associated types that can be included in API specification files -annotationTypes: - x-bb-api-type: - displayName: API Type - description: | - Signals whether this API endpoint is intended for use by users (HTTP APIs exposed by presentation services) or by - systems (HTTP APIs exposed by inbound integration services) - type: array - items: - type: string - enum: [user, system] - x-bb-access-control: - displayName: Backbase Access Control - description: | - Describes which Resource, Function and Privilege need to be granted to the user to allow access to this API - type: BB-Access-Control - x-bb-api-deprecation: - displayName: API Deprecation - description: | - Signals that the API endpoint is deprecated, providing details on when the API was deprecated, when it will be - removed, the reason for deprecation and a more general description in Markdown that can be used to provide more - information on the deprecation and migration strategy - type: BB-Api-Deprecation - -schemas: - BB-Access-Control: !include ../types/schemas/bb-access-control.json - BB-Api-Deprecation: !include ../types/schemas/bb-api-deprecation.json \ No newline at end of file diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/traits/traits.raml b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/traits/traits.raml deleted file mode 100644 index 1cfe6eb99..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/traits/traits.raml +++ /dev/null @@ -1,132 +0,0 @@ -#%RAML 1.0 Library -schemas: - Bad-Request-Error: !include ../types/schemas/bad-request-error.json - Unauthorized-Error: !include ../types/schemas/unauthorized-error.json - Unauthorized-Alt-Error: !include ../types/schemas/unauthorized-alt-error.json - Not-Acceptable-Error: !include ../types/schemas/not-acceptable-error.json - Internal-Server-Error: !include ../types/schemas/internal-server-error.json - Forbidden-Error: !include ../types/schemas/forbidden-error.json - Not-Found-Error: !include ../types/schemas/not-found-error.json - Unsupported-Media-Type-Error: !include ../types/schemas/unsupported-media-type-error.json -traits: - idempotent: - headers: - X-Request-Id: - description: Correlates HTTP requests between a client and server. - required: false - example: f058ebd6-02f7-4d3f-942e-904344e8cde5 - pageable: - queryParameters: - from: - description: Page Number. Skip over pages of elements by specifying a start value for the query - type: integer - required: false - example: 20 - default: 0 - cursor: - description: | - Record UUID. As an alternative for specifying 'from' this allows to point to the record to start the selection from. - type: string - required: false - example: 76d5be8b-e80d-4842-8ce6-ea67519e8f74 - default: "" - size: - description: | - Limit the number of elements on the response. When used in combination with cursor, the value - is allowed to be a negative number to indicate requesting records upwards from the starting point indicated - by the cursor. - type: integer - required: false - example: 80 - default: 10 - orderable: - queryParameters: - orderBy: - description: | - Order by field: <> - type: string - required: false - direction: - description: Direction - enum: [ASC, DESC] - default: DESC - required: false - challengeable: - headers: - X-MFA: - description: Challenge payload response - required: false - example: sms challenge="123456789" - responses: - 401: - description: Unauthorized - headers: - WWW-Authenticate: - description: Comma separated challenges - required: false - example: sms challenge="", pki challenge="Z8nlwZe0daUNWCWIbfJe3iIgauh" - body: - application/json: - type: Unauthorized-Error - BadRequestError: - responses: - 400: - description: BadRequest - body: - application/json: - type: Bad-Request-Error - example: !include ../types/examples/example-bad-request-error.json - UnauthorizedError: - responses: - 401: - description: Unauthorized - headers: - WWW-Authenticate: - description: Indicates the authentication scheme(s) and parameters applicable to the target resource - required: false - example: | - WWW-Authenticate: Newauth realm="apps", type=1, title="Login to \"apps\"", Basic realm="simple" - body: - application/json: - type: Unauthorized-Alt-Error - example: !include ../types/examples/example-unauthorized-alt-error.json - ForbiddenError: - responses: - 403: - description: Forbidden - body: - application/json: - type: Forbidden-Error - example: !include ../types/examples/example-forbidden-error.json - NotFoundError: - responses: - 404: - description: NotFound - body: - application/json: - type: Not-Found-Error - example: !include ../types/examples/example-not-found-error.json - NotAcceptableError: - responses: - 406: - description: NotAcceptable - body: - application/json: - type: Not-Acceptable-Error - example: !include ../types/examples/example-not-acceptable-error.json - UnsupportedMediaTypeError: - responses: - 415: - description: UnsupportedMediaType - body: - application/json: - type: Unsupported-Media-Type-Error - example: !include ../types/examples/example-unsupported-media-type-error.json - InternalServerError: - responses: - 500: - description: InternalServerError - body: - application/json: - type: Internal-Server-Error - example: !include ../types/examples/example-internal-server-error.json diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-bad-request-error.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-bad-request-error.json deleted file mode 100644 index 77243186b..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-bad-request-error.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "message": "Bad Request", - "errors": [ - { - "message": "Value Exceeded. Must be between {min} and {max}.", - "key": "common.api.shoesize", - "context": { - "max": "50", - "min": "1" - } - } - ] -} diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-currency.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-currency.json deleted file mode 100644 index ff365438f..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-currency.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "amount": "1.12", - "currencyCode": "TST" -} \ No newline at end of file diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-forbidden-error.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-forbidden-error.json deleted file mode 100644 index e26366a7c..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-forbidden-error.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "message": "Access to requested resource denied.", - "errors": [ - { - "message": "Resource access denied due to an insufficient user quota of {quota}.", - "key": "common.api.quota", - "context": { - "quota": "someQuota" - } - } - ] -} diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-internal-server-error.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-internal-server-error.json deleted file mode 100644 index c6701087a..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-internal-server-error.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "message": "Description of error" -} \ No newline at end of file diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-not-acceptable-error.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-not-acceptable-error.json deleted file mode 100644 index 0b4ab5da9..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-not-acceptable-error.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "message": "Could not find acceptable representation", - "supportedMediaTypes": [ - "application/json" - ] -} diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-not-found-error.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-not-found-error.json deleted file mode 100644 index 2d6d616b8..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-not-found-error.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "message": "Resource not found.", - "errors": [ - { - "message": "Unable to find the resource requested resource: {resource}.", - "key": "common.api.resource", - "context": { - "resource": "aResource" - } - } - ] -} diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-unauthorized-alt-error.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-unauthorized-alt-error.json deleted file mode 100644 index 6b692d0b3..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-unauthorized-alt-error.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "message": "Access to requested resource denied.", - "errors": [ - { - "message": "Resource access denied due to invalid credentials.", - "key": "common.api.token", - "context": { - "accessToken": "expired" - } - } - ] -} diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-unauthorized-error.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-unauthorized-error.json deleted file mode 100644 index 44f8e8dc6..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-unauthorized-error.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "message": "You are not authorized to perform this action" -} diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-unsupported-media-type-error.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-unsupported-media-type-error.json deleted file mode 100644 index 9dba54d8f..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-unsupported-media-type-error.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "message": "Unsupported media type.", - "errors": [ - { - "message": "The request entity has a media type {mediaType} which the resource does not support.", - "key": "common.api.mediaType", - "context": { - "mediaType": "application/javascript" - } - } - ] -} diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/bad-request-error.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/bad-request-error.json deleted file mode 100644 index d6314386c..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/bad-request-error.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.presentation.errors.BadRequestException", - "properties": { - "message": { - "type": "string", - "description": "Any further information" - }, - "errors": { - "type": "array", - "description": "Detailed error information", - "items": { - "$ref": "error-item.json" - } - } - }, - "required": [ - "message" - ] -} diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/bb-access-control.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/bb-access-control.json deleted file mode 100644 index 629f43147..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/bb-access-control.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "resource": { - "type": "string", - "description": "Resource being protected, e.g. 'User'" - }, - "function": { - "type": "string", - "description": "Business function, e.g. 'Manage Users'" - }, - "privilege": { - "type": "string", - "description": "The privilege required, e.g. 'view'" - } - }, - "required": [ - "resource", - "function", - "privilege" - ] -} diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/bb-api-deprecation.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/bb-api-deprecation.json deleted file mode 100644 index 9d7339566..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/bb-api-deprecation.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "deprecatedFromVersion": { - "type": "string", - "description": "Version of the product from which the endpoint has been deprecated and should no longer be used" - }, - "removedFromVersion": { - "type": "string", - "description": "Version of the product from which the API endpoint will be removed" - }, - "reason": { - "type": "string", - "description": "The reason the API endpoint was deprecated" - }, - "description": { - "type": "string", - "description": "Any further information, e.g. migration information" - } - }, - "required": [ - "deprecatedFromVersion", - "removedFromVersion", - "reason", - "description" - ] -} diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/currency.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/currency.json deleted file mode 100644 index 457bd84ed..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/currency.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "title": "Monetary Amount", - "description": "Schema defining monetary amount in given currency.", - "javaType": "com.backbase.rest.spec.common.types.Currency", - "properties": { - "amount": { - "type": "string", - "javaType": "java.math.BigDecimal", - "description": "The amount in the specified currency" - }, - "currencyCode": { - "type": "string", - "description": "The alpha-3 code (complying with ISO 4217) of the currency that qualifies the amount", - "pattern": "^[A-Z]{3}$" - } - }, - "required": [ - "amount", - "currencyCode" - ] -} \ No newline at end of file diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/error-item.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/error-item.json deleted file mode 100644 index 4868a1047..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/error-item.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "description": "A validation error", - "javaInterfaces": [ - "java.io.Serializable", - "Cloneable" - ], - "properties": { - "message": { - "type": "string", - "description": "Default Message. Any further information." - }, - "key": { - "type": "string", - "description": "{capability-name}.api.{api-key-name}. For generated validation errors this is the path in the document the error resolves to. e.g. object name + '.' + field" - }, - "context": { - "type": "object", - "description": "Context can be anything used to construct localised messages.", - "javaType": "java.util.Map" - } - } -} diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/forbidden-error.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/forbidden-error.json deleted file mode 100644 index 671b17956..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/forbidden-error.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.presentation.errors.ForbiddenException", - "properties": { - "message": { - "type": "string", - "description": "Any further information" - }, - "errors": { - "type": "array", - "description": "Detailed error information", - "items": { - "$ref": "error-item.json" - } - } - } -} diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/internal-server-error.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/internal-server-error.json deleted file mode 100644 index d7d6cafd8..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/internal-server-error.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.presentation.errors.InternalServerErrorException", - "description": "Represents HTTP 500 Internal Server Error", - "properties": { - "message": { - "type": "string", - "description": "Further Information" - } - }, - "required": [ - "message" - ] -} \ No newline at end of file diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/not-acceptable-error.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/not-acceptable-error.json deleted file mode 100644 index f39202d2b..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/not-acceptable-error.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.presentation.errors.NotAcceptableException", - "properties": { - "message": { - "type": "string" - }, - "supportedMediaTypes": { - "type": "array", - "description": "List of supported media types for this endpoint", - "items": { - "type": "string" - } - } - } -} diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/not-found-error.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/not-found-error.json deleted file mode 100644 index 3ce00ba4f..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/not-found-error.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.presentation.errors.NotFoundException", - "properties": { - "message": { - "type": "string", - "description": "Any further information" - }, - "errors": { - "type": "array", - "description": "Detailed error information", - "items": { - "$ref": "error-item.json" - } - } - } -} diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/unauthorized-alt-error.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/unauthorized-alt-error.json deleted file mode 100644 index 388b7326b..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/unauthorized-alt-error.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.presentation.errors.UnauthorizedException", - "properties": { - "message": { - "type": "string", - "description": "Any further information" - }, - "errors": { - "type": "array", - "description": "Detailed error information", - "items": { - "$ref": "error-item.json" - } - } - } -} diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/unauthorized-error.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/unauthorized-error.json deleted file mode 100644 index 5c30948ac..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/unauthorized-error.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "message": { - "type": "string" - } - }, - "required": [ - "message" - ] -} diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/unsupported-media-type-error.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/unsupported-media-type-error.json deleted file mode 100644 index 87e2ebba6..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/unsupported-media-type-error.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.presentation.errors.UnsupportedMediaTypeException", - "properties": { - "message": { - "type": "string", - "description": "Any further information" - }, - "errors": { - "type": "array", - "description": "Detailed error information", - "items": { - "$ref": "error-item.json" - } - } - } -} diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/presentation-client-api.raml b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/presentation-client-api.raml deleted file mode 100644 index d3523898a..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/presentation-client-api.raml +++ /dev/null @@ -1,226 +0,0 @@ -#%RAML 1.0 ---- -#=============================================================== -# Messages - RAML example http://raml.org/ -# References: -# - RAML Specification - https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md -#=============================================================== -title: Wallet Test Client API -uses: - traits: lib/traits/traits.raml - bb: lib/annotations/annotations.raml - common: bbt-common.raml -version: v1 -baseUri: "client-api/{version}" -mediaType: application/json -protocols: [ HTTP, HTTPS ] -#=============================================================== -# API resource definitions -#=============================================================== -securedBy: [ bb.bbAccessControl ] -(bb.x-bb-api-type): [user] -/wallet: - displayName: Wallet - /paymentcards: - displayName: Payment Cards - get: - (bb.x-bb-access-control): - resource: WALLET - function: MANAGE_PAYMENT_CARDS - privilege: READ_PAYMENT_CARD - is: [traits.BadRequestError, traits.NotAcceptableError, traits.orderable: {fieldsList: nameOnCard}, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: "Returns available payment card details for user, optionally filtered by nameOnCard" - queryParameters: - nameOnCard: - description: "Filter by the cardholder's name (case-insensitive), can be the first one or more characters of one of the words/names" - required: false - type: string - example: "Smi" - dateTimeOnly: - description: Creation date in datetime-only format - required: false - type: datetime-only - example: 2017-10-04T14:54:36 - dateTime: - description: Creation date in Zoned RFC3339 Date-time format - required: false - type: datetime - format: rfc3339 - example: 2017-10-04T14:54:36Z - dateTime2616: - description: Zoned RFC2616 Date-time param example - required: false - type: datetime - format: rfc2616 - example: Wed, 4 Jul 2001 12:08:56 PDT - date: - description: Date-only param example - required: false - type: date-only - example: 2017-10-04 - time: - description: time-only param example - required: false - type: time-only - example: 14:54:36 - responses: - 200: - body: - application/json: - type: common.PaymentCards - example: !include examples/body/paymentcards-get.json - text/csv: - application/xml: - post: - (bb.x-bb-access-control): - resource: WALLET - function: MANAGE_PAYMENT_CARDS - privilege: WRITE_PAYMENT_CARD - is: [traits.BadRequestError, traits.InternalServerError, traits.idempotent, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Adds a payment card to the user's wallet - body: - application/json: - type: common.PaymentCard - example: !include examples/body/paymentcard-item.json - responses: - 201: - description: request to create payment card accepted - body: - application/json: - schema: !include schemas/body/paymentcard-id.json - example: !include examples/body/paymentcard-created.json - /{cardId}: - displayName: Payment Card - uriParameters: - cardId: - type: string - get: - (bb.x-bb-access-control): - resource: WALLET - function: MANAGE_PAYMENT_CARDS - privilege: READ_PAYMENT_CARD - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Returns details of a specific payment card - responses: - 200: - body: - application/json: - type: common.PaymentCard - example: !include examples/body/paymentcard-item.json - delete: - (bb.x-bb-access-control): - resource: WALLET - function: MANAGE_PAYMENT_CARDS - privilege: DELETE_PAYMENT_CARD - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Deletes a payment card with a given id - responses: - 204: - description: Payment card is succesfully deleted -/bbt: - description: API for test operations. - displayName: BBT - /build-info: - get: - description: "Build Information" - responses: - 200: - body: - application/json: - schema: !include schemas/body/build-info.json - example: !include examples/body/example-build-info.json -/patch: - description: PATCH endpoint for test operations - displayName: patch - patch: - is: [traits.BadRequestError, traits.InternalServerError, traits.idempotent, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: "Patch Test" - responses: - 200: - body: - text/plain: - schema: !include schemas/body/patch-response.json -/test: - /required-boolean-query-param: - description: arbitrary tests - displayName: required boolean query param - get: - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - queryParameters: - bool: - description: Required boolean parameter with no default value - required: true - type: boolean - example: false - responses: - 200: - body: - application/json: - schema: !include schemas/body/test-response.json - /values: - description: Test Values - displayName: Test Values - get: - is: [traits.InternalServerError] - responses: - 200: - body: - application/json: - schema: !include schemas/body/test-values-response.json - example: !include examples/body/test-values-response.json - /headers: - description: Test header propagation - displayName: Test header propagation - get: - is: [traits.InternalServerError] - queryParameters: - addHops: - description: number of additional hops to perform - required: false - type: integer - responses: - 200: - body: - application/json: - schema: common.TestHeadersResponseBody - example: !include examples/body/test-headers-response.json - /date-query-params: - description: | - Tests for date/time query parameters in service-apis. Sends the same query parameters to the equivalent endpoint - in the pandp service which echoes the given values back in the response body. Values echoed by the pandp service - are then returned in the response to this request. - displayName: dateQueryParam - get: - queryParameters: - dateTimeOnly: - description: Creation date in datetime-only format - required: false - type: datetime-only - example: 2017-10-04T14:54:36 - dateTime: - description: Creation date in Zoned RFC3339 Date-time format - required: false - type: datetime - format: rfc3339 - example: 2017-10-04T14:54:36Z - dateTime2616: - description: Zoned RFC2616 Date-time param example - required: false - type: datetime - format: rfc2616 - example: Wed, 4 Jul 2001 12:08:56 PDT - date: - description: Date-only param example - required: false - type: date-only - example: 2017-10-04 - time: - description: time-only param example - required: false - type: time-only - example: 14:54:36 - responses: - 200: - body: - application/json: - schema: !include common-schemas/body/date-query-params.json diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/presentation-integration-api.raml b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/presentation-integration-api.raml deleted file mode 100644 index a477df038..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/presentation-integration-api.raml +++ /dev/null @@ -1,32 +0,0 @@ -#%RAML 1.0 ---- -#=============================================================== -# Integration API example -#=============================================================== -title: Example -version: v1 -baseUri: "integration-api/{version}" -mediaType: application/json -protocols: [ HTTP, HTTPS ] -#=============================================================== -# API documentation - Overall documentation. -#=============================================================== -documentation: - - title: Example - content: Test Schema to test an integration-api -#=============================================================== -# API resource definitions -#=============================================================== -/items: - description: Retrieve all items. - displayName: items - uriParameters: null - get: - description: "Retrieve list of all items." - responses: - 200: - description: Test Schema - body: - application/json: - schema: !include schemas/body/item.json - example: !include examples/body/item.json \ No newline at end of file diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/presentation-service-api.raml b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/presentation-service-api.raml deleted file mode 100644 index db9214ea5..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/presentation-service-api.raml +++ /dev/null @@ -1,122 +0,0 @@ -#%RAML 1.0 ---- -#=============================================================== -# Messages - RAML example http://raml.org/ -# References: -# - RAML Specification - https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md -#=============================================================== -title: Wallet Test Service API -uses: - traits: lib/traits/traits.raml - bb: lib/annotations/annotations.raml - common: bbt-common.raml -version: v1 -baseUri: "service-api/{version}" -mediaType: application/json -protocols: [ HTTP, HTTPS ] -#=============================================================== -# API resource definitions -#=============================================================== -securedBy: [ bb.bbAccessControl ] -(bb.x-bb-api-type): [system] -/wallet: - displayName: WalletService - /admin/{userId}: - uriParameters: - userId: - type: string - /paymentcards: - displayName: Payment Cards - get: - is: [traits.BadRequestError, traits.NotAcceptableError, traits.orderable: {fieldsList: nameOnCard}, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: "Returns available payment card details for user, optionally filtered by nameOnCard" - queryParameters: - nameOnCard: - description: "Filter by the cardholder's name (case-insensitive), can be the first one or more characters of one of the words/names" - required: false - type: string - example: "Smi" - dateTimeOnly: - description: Creation date in datetime-only format - required: false - type: datetime-only - example: 2017-10-04T14:54:36 - dateTime: - description: Creation date in Zoned RFC3339 Date-time format - required: false - type: datetime - format: rfc3339 - example: 2017-10-04T14:54:36Z - dateTime2616: - description: Zoned RFC2616 Date-time param example - required: false - type: datetime - format: rfc2616 - example: Wed, 4 Jul 2001 12:08:56 PDT - date: - description: Date-only param example - required: false - type: date-only - example: 2017-10-04 - time: - description: time-only param example - required: false - type: time-only - example: 14:54:36 - responses: - 200: - body: - application/json: - type: common.PaymentCards - example: !include examples/body/paymentcards-get.json - post: - is: [traits.BadRequestError, traits.InternalServerError, traits.idempotent, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Adds a payment card to the user's wallet - body: - application/json: - type: common.PaymentCard - example: !include examples/body/paymentcard-item.json - responses: - 201: - description: request to create payment card accepted - body: - application/json: - schema: !include schemas/body/paymentcard-id.json - example: !include examples/body/paymentcard-created.json - /{cardId}: - displayName: Payment Card - uriParameters: - cardId: - type: string - get: - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Returns details of a specific payment card - responses: - 200: - body: - application/json: - type: common.PaymentCard - example: !include examples/body/paymentcard-item.json - delete: - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Deletes a payment card with a given id - responses: - 204: - description: Payment card is succesfully deleted -/testQuery: - /required-boolean-query-param: - description: arbitrary tests - displayName: required boolean query param - get: - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - queryParameters: - bool: - description: Required boolean parameter with no default value - required: true - type: boolean - example: false - responses: - 200: - body: - application/json: - schema: !include schemas/body/test-response.json \ No newline at end of file diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/schemas/body/build-info.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/schemas/body/build-info.json deleted file mode 100644 index 8ed0b3e16..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/schemas/body/build-info.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "build-info": { - "javaType": "java.util.Map", - "type": "object" - } - } -} diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/schemas/body/item.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/schemas/body/item.json deleted file mode 100644 index 176cb4743..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/schemas/body/item.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "description": "this models a simple item.", - "properties": { - "name": { - "type": "string" - }, - "description": { - "type": "string" - } - }, - "required": [ - "name" - ] -} diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/schemas/body/patch-response.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/schemas/body/patch-response.json deleted file mode 100644 index a427bffd5..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/schemas/body/patch-response.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "message": { - "type": "string" - } - } -} \ No newline at end of file diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/schemas/body/paymentcard-id.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/schemas/body/paymentcard-id.json deleted file mode 100644 index cc79400fb..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/schemas/body/paymentcard-id.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "id": { - "type": "string" - } - } -} \ No newline at end of file diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/schemas/body/paymentcards-query.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/schemas/body/paymentcards-query.json deleted file mode 100644 index fd251f418..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/schemas/body/paymentcards-query.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "nameOnCard": { - "type": "string" - }, - "creationDate" : { - "type": "string", - "format": "date-time" - } - }, - "required": [] -} \ No newline at end of file diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/schemas/body/test-response.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/schemas/body/test-response.json deleted file mode 100644 index a427bffd5..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/schemas/body/test-response.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "message": { - "type": "string" - } - } -} \ No newline at end of file diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/schemas/body/test-values-response.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/schemas/body/test-values-response.json deleted file mode 100644 index 2b72f6913..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/schemas/body/test-values-response.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "message": { - "type": "string" - }, - "number": { - "type": "string", - "javaType": "java.math.BigDecimal" - } - } -} \ No newline at end of file diff --git a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/schemas/errors/error.json b/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/schemas/errors/error.json deleted file mode 100644 index 362d7e72d..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/backbase-wallet/schemas/errors/error.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "message": { - "type": "string" - }, - "errorCode": { - "type": "string" - } - }, - "required": [ - "message", - "errorCode" - ] -} \ No newline at end of file diff --git a/boat-maven-plugin/src/test/resources/raml-examples/export-mojo-error-catching/error b/boat-maven-plugin/src/test/resources/raml-examples/export-mojo-error-catching/error deleted file mode 100644 index e69de29bb..000000000 diff --git a/boat-maven-plugin/src/test/resources/raml-examples/export-mojo-error-catching/invalid-presentation-client-api.raml b/boat-maven-plugin/src/test/resources/raml-examples/export-mojo-error-catching/invalid-presentation-client-api.raml deleted file mode 100644 index 1b6a87ffe..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/export-mojo-error-catching/invalid-presentation-client-api.raml +++ /dev/null @@ -1,218 +0,0 @@ -#%RAML 1.0 ---- -#=============================================================== -# Messages - RAML example http://raml.org/ -# References: -# - RAML Specification - https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md -#=============================================================== - -uses: - traits: lib/traits/traits.raml - bb: lib/annotations/?.raml - common: bbt-error.raml -version: v1 -baseUri: "client-api/{version}" -mediaType: application/json -protocols: [ HTTP, HTTPS ] -#=============================================================== -# API resource definitions -#=============================================================== -securedBy: [ bb.bbAccessControl ] -(bb.x-bb-api-type): [user] -/wallet: - displayName: Wallet - /paymentcards: - displayName: Payment Cards - (bb.x-bb-access-control): - badValue: WALLET - function: MANAGE_PAYMENT_CARDS - privilege: READ_PAYMENT_CARD - is: [traits.BadRequestError, traits.NotAcceptableError, traits.orderable: {fieldsList: nameOnCard}, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: "Returns available payment card details for user, optionally filtered by nameOnCard" - queryParameters: - nameOnCard: - description: "Filter by the cardholder's name (case-insensitive), can be the first one or more characters of one of the words/names" - required: false - type: xml - example: "Smi" - dateTimeOnly: - description: Creation date in datetime-only format - required: false - type: datetime-only - example: 2017-10-04T14:54:36 - dateTime: - description: Creation date in Zoned RFC3339 Date-time format - required: false - type: datetime - format: rfc3339 - example: 2017-10-04T14:54:36Z - dateTime2616: - description: Zoned RFC2616 Date-time param example - required: false - type: datetime - format: rfc2616 - example: Wed, 4 Jul 2001 12:08:56 PDT - date: - description: Date-only param example - required: false - type: date-only - example: 2017-10-04 - time: - description: time-only param example - required: false - type: time-only - example: 14:54:36 - responses: - 200: - body: - application/json: - type: common.PaymentCards - example: !include examples/body/paymentcards-get.json - text/csv: - application/xml: - post: - (bb.x-bb-access-control): - resource: WALLET - function: MANAGE_PAYMENT_CARDS - privilege: WRITE_PAYMENT_CARD - is: [traits.BadRequestError, traits.InternalServerError, traits.idempotent, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Adds a payment card to the user's wallet - body: - application/json: - type: common.PaymentCard - example: !include examples/body/paymentcard-item.json - responses: - 201: - description: request to create payment card accepted - body: - application/json: - schema: !include schemas/body/paymentcard-id.json - example: !include examples/body/paymentcard-created.json - /{cardId}: - displayName: Payment Card - uriParameters: - cardId: - type: xml - get: - (bb.x-bb-access-control): - resource: WALLET - function: MANAGE_PAYMENT_CARDS - privilege: READ_PAYMENT_CARD - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Returns details of a specific payment card - responses: - 200: - body: - application/json: - type: common.PaymentCard - example: !include examples/body/paymentcard-item.json - delete: - (bb.x-bb-access-control): - resource: WALLET - function: MANAGE_PAYMENT_CARDS - privilege: DELETE_PAYMENT_CARD - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Deletes a payment card with a given id - responses: - 204: - description: Payment card is succesfully deleted -/bbt: - description: API for test operations. - displayName: BBT - /build-info: - get: - description: "Build Information" - responses: - 200: - body: - application/json: - schema: !include schemas/body/build-info.json - example: !include examples/body/example-build-info.json -/patch: - description: PATCH endpoint for test operations - displayName: patch - patch: - is: [traits.BadRequestError, traits.InternalServerError, traits.idempotent, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: "Patch Test" - responses: - 200: - body: - text/plain: - schema: !include schemas/body/patch-response.json -/test: - /required-boolean-query-param: - description: arbitrary tests - displayName: required boolean query param - get: - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - queryParameters: - bool: - description: Required boolean parameter with no default value - required: true - type: boolean - example: false - responses: - 200: - body: - application/json: - schema: !include schemas/body/test-response.json - /values: - description: Test Values - displayName: Test Values - get: - is: [traits.InternalServerError] - responses: - 200: - body: - application/json: - schema: !include schemas/body/test-values-response.json - example: !include examples/body/test-values-response.json - /headers: - description: Test header propagation - displayName: Test header propagation - get: - is: [traits.InternalServerError] - queryParameters: - addHops: - description: number of additional hops to perform - required: false - type: integer - responses: - 200: - body: - application/json: - schema: common.TestHeadersResponseBody - example: !include examples/body/test-headers-response.json - /date-query-params: - description: | - Tests for date/time query parameters in service-apis. Sends the same query parameters to the equivalent endpoint - in the pandp service which echoes the given values back in the response body. Values echoed by the pandp service - are then returned in the response to this request. - displayName: dateQueryParam - get: - queryParameters: - dateTimeOnly: - description: Creation date in datetime-only format - required: false - type: datetime-only - example: 2017-10-04T14:54:36 - dateTime: - description: Creation date in Zoned RFC3339 Date-time format - required: false - type: datetime - format: rfc3339 - example: 2017-10-04T14:54:36Z - dateTime2616: - description: Zoned RFC2616 Date-time param example - required: false - type: datetime - format: rfc2616 - example: Wed, 4 Jul 2001 12:08:56 PDT - date: - description: Date-only param example - req - responses: - 200: - body: - application/json: - schema: !include common-schemas/body/date-query-params.json diff --git a/boat-maven-plugin/src/test/resources/raml-examples/helloworld/helloworld.raml b/boat-maven-plugin/src/test/resources/raml-examples/helloworld/helloworld.raml deleted file mode 100644 index d81c6ce7e..000000000 --- a/boat-maven-plugin/src/test/resources/raml-examples/helloworld/helloworld.raml +++ /dev/null @@ -1,23 +0,0 @@ -#%RAML 1.0 -title: Hello world # required title - -/helloworld: # optional resource - get: # HTTP method declaration - responses: # declare a response - 200: # HTTP status code - body: # declare content of response - application/json: # media type - type: | # structural definition of a response (schema or type) - { - "title": "Hello world Response", - "type": "object", - "properties": { - "message": { - "type": "string" - } - } - } - example: | # example of how a response looks - { - "message": "Hello world" - } diff --git a/boat-quay/boat-quay-lint/pom.xml b/boat-quay/boat-quay-lint/pom.xml index b04c40044..f425a2f5a 100644 --- a/boat-quay/boat-quay-lint/pom.xml +++ b/boat-quay/boat-quay-lint/pom.xml @@ -5,7 +5,7 @@ com.backbase.oss boat-quay - 0.16.12-SNAPSHOT + 0.17.0-SNAPSHOT boat-quay-lint @@ -17,7 +17,7 @@ ${basedir}/../${aggregate.report.dir} - 1.7.22 + 1.8.0 false diff --git a/boat-quay/boat-quay-rules/pom.xml b/boat-quay/boat-quay-rules/pom.xml index 794d36b05..29c0439c0 100644 --- a/boat-quay/boat-quay-rules/pom.xml +++ b/boat-quay/boat-quay-rules/pom.xml @@ -5,7 +5,7 @@ com.backbase.oss boat-quay - 0.16.12-SNAPSHOT + 0.17.0-SNAPSHOT boat-quay-rules @@ -17,7 +17,6 @@ ${basedir}/../${aggregate.report.dir} - 1.7.22 false 1.0-rc7 1.7.20 @@ -93,7 +92,7 @@ org.assertj assertj-core - 3.23.1 + 3.24.2 diff --git a/boat-quay/boat-quay-rules/src/main/kotlin/com/backbase/oss/boat/quay/ruleset/BoatRuleSet.kt b/boat-quay/boat-quay-rules/src/main/kotlin/com/backbase/oss/boat/quay/ruleset/BoatRuleSet.kt index 03d192ee2..e2af3272e 100644 --- a/boat-quay/boat-quay-rules/src/main/kotlin/com/backbase/oss/boat/quay/ruleset/BoatRuleSet.kt +++ b/boat-quay/boat-quay-rules/src/main/kotlin/com/backbase/oss/boat/quay/ruleset/BoatRuleSet.kt @@ -10,7 +10,7 @@ class BoatRuleSet : AbstractRuleSet() { override fun url(rule: Rule): URI { val heading = "${rule.id}: ${rule.title}" val ref = heading - .toLowerCase() + .lowercase() .replace(Regex("[^a-z0-9]+"), "-") return url.resolve("#$ref") } diff --git a/boat-quay/boat-quay-rules/src/main/kotlin/com/backbase/oss/boat/quay/ruleset/UniqueOperationIdRule.kt b/boat-quay/boat-quay-rules/src/main/kotlin/com/backbase/oss/boat/quay/ruleset/UniqueOperationIdRule.kt index 5e43ce610..edd67f204 100644 --- a/boat-quay/boat-quay-rules/src/main/kotlin/com/backbase/oss/boat/quay/ruleset/UniqueOperationIdRule.kt +++ b/boat-quay/boat-quay-rules/src/main/kotlin/com/backbase/oss/boat/quay/ruleset/UniqueOperationIdRule.kt @@ -19,9 +19,9 @@ class UniqueOperationIdRule() { context.api.paths.orEmpty().values .flatMap { it?.readOperations().orEmpty() } .filter { operation -> - val exist = operationIds.contains(operation.operationId.toLowerCase()) + val exist = operationIds.contains(operation.operationId.lowercase()) if (!exist) { - operationIds.add(operation.operationId.toLowerCase()) + operationIds.add(operation.operationId.lowercase()) } exist; } diff --git a/boat-quay/boat-quay-rules/src/main/kotlin/com/backbase/oss/boat/quay/ruleset/UseBackbaseWellUnderstoodHttpStatusCodesRule.kt b/boat-quay/boat-quay-rules/src/main/kotlin/com/backbase/oss/boat/quay/ruleset/UseBackbaseWellUnderstoodHttpStatusCodesRule.kt index d4e367a90..9874533d2 100644 --- a/boat-quay/boat-quay-rules/src/main/kotlin/com/backbase/oss/boat/quay/ruleset/UseBackbaseWellUnderstoodHttpStatusCodesRule.kt +++ b/boat-quay/boat-quay-rules/src/main/kotlin/com/backbase/oss/boat/quay/ruleset/UseBackbaseWellUnderstoodHttpStatusCodesRule.kt @@ -47,7 +47,7 @@ class UseBackbaseWellUnderstoodHttpStatusCodesRule(config: Config) { private fun isAllowed(method: PathItem.HttpMethod, statusCode: String): Boolean { - val allowedMethods = wellUnderstoodResponseCodesAndVerbs[statusCode.toLowerCase()].orEmpty() + val allowedMethods = wellUnderstoodResponseCodesAndVerbs[statusCode.lowercase()].orEmpty() return allowedMethods.contains(method.name) || allowedMethods.contains("ALL") } diff --git a/boat-quay/pom.xml b/boat-quay/pom.xml index 47bd31cf2..d6cb58292 100644 --- a/boat-quay/pom.xml +++ b/boat-quay/pom.xml @@ -5,7 +5,7 @@ com.backbase.oss backbase-openapi-tools - 0.16.12-SNAPSHOT + 0.17.0-SNAPSHOT @@ -19,7 +19,7 @@ ${basedir}/../${aggregate.report.dir} - 1.4.10 + 1.8.0 false 1.0-rc7 diff --git a/boat-scaffold/README.md b/boat-scaffold/README.md index b786d5550..6738ccc1b 100644 --- a/boat-scaffold/README.md +++ b/boat-scaffold/README.md @@ -1,6 +1,6 @@ # Boat OpenAPI generator -The Boat OpenAPI generator is based on the official Open API Generator, version 4.0.3 and it provides several fixes and additional features. +The Boat OpenAPI generator is based on the official Open API Generator, version 6.2.1, and it provides several fixes and additional features. The `boat` plugin has multiple goals: ## Spring Code Generator diff --git a/boat-scaffold/pom.xml b/boat-scaffold/pom.xml index c7b1594aa..4ece94e9f 100644 --- a/boat-scaffold/pom.xml +++ b/boat-scaffold/pom.xml @@ -5,7 +5,7 @@ com.backbase.oss backbase-openapi-tools - 0.16.12-SNAPSHOT + 0.17.0-SNAPSHOT boat-scaffold @@ -99,9 +99,15 @@ com.backbase.oss boat-trail-resources - 0.16.12-SNAPSHOT + 0.17.0-SNAPSHOT test + + commons-lang + commons-lang + 2.6 + compile + diff --git a/boat-scaffold/src/main/java/com/backbase/oss/codegen/AbstractDocumentationGenerator.java b/boat-scaffold/src/main/java/com/backbase/oss/codegen/AbstractDocumentationGenerator.java index 992290d66..96337b8ae 100644 --- a/boat-scaffold/src/main/java/com/backbase/oss/codegen/AbstractDocumentationGenerator.java +++ b/boat-scaffold/src/main/java/com/backbase/oss/codegen/AbstractDocumentationGenerator.java @@ -1,78 +1,64 @@ package com.backbase.oss.codegen; +import com.backbase.oss.codegen.marina.BoatHandlebarsEngineAdapter; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; -import java.io.InputStream; import java.nio.file.Path; import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Map; -import java.util.Set; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; -import org.openapitools.codegen.AbstractGenerator; import org.openapitools.codegen.ClientOptInput; import org.openapitools.codegen.CodegenConfig; -import org.openapitools.codegen.CodegenConstants; import org.openapitools.codegen.Generator; -import org.openapitools.codegen.GlobalSupportingFile; import org.openapitools.codegen.SupportingFile; +import org.openapitools.codegen.TemplateManager; +import org.openapitools.codegen.api.TemplatePathLocator; import org.openapitools.codegen.api.TemplatingEngineAdapter; -import org.openapitools.codegen.config.GlobalSettings; -import org.openapitools.codegen.ignore.CodegenIgnoreProcessor; -import org.openapitools.codegen.templating.HandlebarsEngineAdapter; +import org.openapitools.codegen.templating.CommonTemplateContentLocator; +import org.openapitools.codegen.templating.GeneratorTemplateContentLocator; +import org.openapitools.codegen.templating.TemplateManagerOptions; @Slf4j -public abstract class AbstractDocumentationGenerator extends AbstractGenerator implements Generator { - - protected final CodegenConfig config; - protected final String input; - protected final String output; +public abstract class AbstractDocumentationGenerator implements Generator { + protected CodegenConfig config; + protected String input; + protected ClientOptInput opts; + protected TemplateManager templateProcessor; protected final ObjectMapper objectMapper = new ObjectMapper(); - protected CodegenIgnoreProcessor ignoreProcessor; - private final TemplatingEngineAdapter templatingEngine = new HandlebarsEngineAdapter(); - - protected AbstractDocumentationGenerator(CodegenConfig config) { - this.config = config; - this.input = config.getInputSpec(); - this.output = config.getOutputDir(); - if (this.ignoreProcessor == null) { - this.ignoreProcessor = new CodegenIgnoreProcessor(this.config.getOutputDir()); - } - } - - + @SuppressWarnings("deprecation") @Override public Generator opts(ClientOptInput opts) { + this.opts = opts; + this.input = opts.getConfig().getInputSpec(); + this.config = opts.getConfig(); + TemplateManagerOptions templateManagerOptions = new TemplateManagerOptions( + this.config.isEnableMinimalUpdate(), + this.config.isSkipOverwrite()); + + TemplatingEngineAdapter templatingEngine = new BoatHandlebarsEngineAdapter(); + + TemplatePathLocator commonTemplateLocator = new CommonTemplateContentLocator(); + TemplatePathLocator generatorTemplateLocator = new GeneratorTemplateContentLocator(this.config); + this.templateProcessor = new TemplateManager( + templateManagerOptions, + templatingEngine, + new TemplatePathLocator[]{generatorTemplateLocator, commonTemplateLocator} + ); return this; } - - @SuppressWarnings("unchecked") - protected Map convertToBundle(Object object) throws JsonProcessingException { - String model = objectMapper.writeValueAsString(object); - return objectMapper.readValue(model, Map.class); - } - protected List processTemplates(Map bundle) { List files = new ArrayList<>(); - Set supportingFilesToGenerate = null; - String supportingFiles = GlobalSettings.getProperty(CodegenConstants.SUPPORTING_FILES); - if (supportingFiles != null && !supportingFiles.isEmpty()) { - supportingFilesToGenerate = new HashSet<>(Arrays.asList(supportingFiles.split(","))); - } - for (SupportingFile support : config.supportingFiles()) { try { - processSupport(support, supportingFilesToGenerate, bundle, files); + processSupport(support, bundle, files); } catch (Exception e) { throw new CodegenException("Could not generate supporting file '" + support + "'", e); } @@ -80,113 +66,42 @@ protected List processTemplates(Map bundle) { return files; } - - private void processSupport(SupportingFile support, Set supportingFilesToGenerate, Map bundle, List files) throws IOException { + private void processSupport(SupportingFile support, Map bundle, List files) throws IOException { String outputFolder = config.outputFolder(); - if (StringUtils.isNotEmpty(support.folder)) { - outputFolder += File.separator + support.folder; + if (StringUtils.isNotEmpty(support.getFolder())) { + outputFolder += File.separator + support.getFolder(); } File of = new File(outputFolder); if (!of.isDirectory() && !of.mkdirs()) { log.debug("Output directory {} not created. It {}.", outputFolder, of.exists() ? "already exists." : "may not have appropriate permissions."); } - String outputFilename = new File(support.destinationFilename).isAbsolute() // split - ? support.destinationFilename - : outputFolder + File.separator + support.destinationFilename.replace('/', File.separatorChar); + String outputFilename = new File(support.getDestinationFilename()).isAbsolute() // split + ? support.getDestinationFilename() + : outputFolder + File.separator + support.getDestinationFilename().replace('/', File.separatorChar); if (!config.shouldOverwrite(outputFilename)) { log.info("Skipped overwriting {}", outputFilename); return; } - String templateFile; - if (support instanceof GlobalSupportingFile) { - templateFile = config.getCommonTemplateDir() + File.separator + support.templateFile; - } else { - templateFile = getFullTemplateFile(config, support.templateFile); - } - - if (!shouldGenerate(supportingFilesToGenerate, support)) { - return; - } - - if (ignoreProcessor.allowsFile(new File(outputFilename))) { - ignoreProcessorAllowsFile(support, outputFilename, bundle, files, templateFile); + File generated = processTemplateToFile(bundle, support.getTemplateFile(), outputFilename); + files.add(generated); - } else { - log.info("Skipped generation of {} due to rule in .openapi-generator-ignore", outputFilename); - } } - private boolean shouldGenerate(Set supportingFilesToGenerate, SupportingFile support) { - boolean shouldGenerate = true; - if (supportingFilesToGenerate != null && !supportingFilesToGenerate.isEmpty()) { - shouldGenerate = supportingFilesToGenerate.contains(support.destinationFilename); + protected File processTemplateToFile(Map templateData, String templateName, String outputFilename) throws IOException { + String adjustedOutputFilename = outputFilename.replace("//", "/").replace('/', File.separatorChar); + File target = new File(adjustedOutputFilename); + Path outDir = java.nio.file.Paths.get(this.config.getOutputDir()).toAbsolutePath(); + Path absoluteTarget = target.toPath().toAbsolutePath(); + if (!absoluteTarget.startsWith(outDir)) { + throw new CodegenException(String.format(Locale.ROOT, "Target files must be generated within the output directory; absoluteTarget=%s outDir=%s", absoluteTarget, outDir)); } - return shouldGenerate; + return this.templateProcessor.write(templateData, templateName, target); } - private void ignoreProcessorAllowsFile(SupportingFile support, String outputFilename, Map bundle, List files, String templateFile) throws IOException { - // support.templateFile is the unmodified/original supporting file name (e.g. build.sh.mustache) - // templatingEngine.templateExists dispatches resolution to this, performing template-engine specific inspect of support file extensions. - if (templatingEngine.templateExists(this, support.templateFile)) { - String templateContent = templatingEngine.compileTemplate(this, bundle, support.templateFile); - writeToFile(outputFilename, templateContent); - File written = new File(outputFilename); - files.add(written); - if (config.isEnablePostProcessFile()) { - config.postProcessFile(written, "supporting-mustache"); - } - } else { - InputStream in = null; - - try { - in = new FileInputStream(templateFile); - } catch (Exception e) { - // continue - } - if (in == null) { - in = this.getClass().getClassLoader().getResourceAsStream(getCPResourcePath(templateFile)); - } - File outputFile = writeInputStreamToFile(outputFilename, in, templateFile); - files.add(outputFile); - if (config.isEnablePostProcessFile() && !dryRun) { - config.postProcessFile(outputFile, "supporting-common"); - } - } - } - - protected File writeInputStreamToFile(String filename, InputStream in, String templateFile) throws IOException { - if (in != null) { - byte[] bytes = IOUtils.toByteArray(in); - return writeToFile(filename, bytes); - } else { - log.error("can't open '{}' for input; cannot write '{}'", templateFile, filename); - return null; - } - } - - protected File processTemplateToFile(Map bundle, Path template) throws IOException { - String templateContent = templatingEngine.compileTemplate(this, bundle, template.toString()); - String outputFilename = StringUtils.substringBeforeLast(template.getFileName().toString(), ".") + ".html"; - File templateOutputFile = new File(this.output, outputFilename); - writeToFile(templateOutputFile.toString(), templateContent); - return templateOutputFile; - } - - - @Override - public boolean getEnableMinimalUpdate() { - return false; - } - - @Override - public String getFullTemplateContents(String templateName) { - return readTemplate(getFullTemplateFile(config, templateName)); - } - - @Override - public Path getFullTemplatePath(String name) { - String fullPath = getFullTemplateFile(config, name); - return java.nio.file.Paths.get(fullPath); + @SuppressWarnings("unchecked") + protected Map convertToBundle(Object object) throws JsonProcessingException { + String model = objectMapper.writeValueAsString(object); + return objectMapper.readValue(model, Map.class); } } diff --git a/boat-scaffold/src/main/java/com/backbase/oss/codegen/CodegenException.java b/boat-scaffold/src/main/java/com/backbase/oss/codegen/CodegenException.java index 187ff7285..4db4f4bd6 100644 --- a/boat-scaffold/src/main/java/com/backbase/oss/codegen/CodegenException.java +++ b/boat-scaffold/src/main/java/com/backbase/oss/codegen/CodegenException.java @@ -8,4 +8,8 @@ public CodegenException(String message) { public CodegenException(String message, Throwable cause) { super(message, cause); } + + public CodegenException(Throwable e) { + super(e); + } } diff --git a/boat-scaffold/src/main/java/com/backbase/oss/codegen/angular/BoatAngularCodegenOperation.java b/boat-scaffold/src/main/java/com/backbase/oss/codegen/angular/BoatAngularCodegenOperation.java index 4bf720cc6..5925ea21b 100644 --- a/boat-scaffold/src/main/java/com/backbase/oss/codegen/angular/BoatAngularCodegenOperation.java +++ b/boat-scaffold/src/main/java/com/backbase/oss/codegen/angular/BoatAngularCodegenOperation.java @@ -1,5 +1,9 @@ package com.backbase.oss.codegen.angular; +import com.backbase.oss.codegen.CodegenException; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.Arrays; import lombok.EqualsAndHashCode; import lombok.Getter; import org.openapitools.codegen.CodegenOperation; @@ -10,73 +14,24 @@ public class BoatAngularCodegenOperation extends CodegenOperation { public final String pattern; + @SuppressWarnings("java:S3011") public BoatAngularCodegenOperation(CodegenOperation o) { + for (Field field : o.getClass().getDeclaredFields()) { + if (Modifier.isPublic(field.getModifiers()) && !Modifier.isFinal(field.getModifiers())) { + Arrays.stream(this.getClass().getFields()).filter(ff -> ff.getName().equals(field.getName())) + .findFirst().ifPresent(p -> { + try { + if (p.canAccess(this)) { + p.set(this, field.get(o)); + } + } catch (IllegalAccessException e) { + throw new CodegenException(e); + } + }); + } + } this.responseHeaders.addAll(o.responseHeaders); - this.hasAuthMethods = o.hasAuthMethods; - this.hasConsumes = o.hasConsumes; - this.hasProduces = o.hasProduces; - this.hasParams = o.hasParams; - this.hasOptionalParams = o.hasOptionalParams; - this.hasRequiredParams = o.hasRequiredParams; - this.returnTypeIsPrimitive = o.returnTypeIsPrimitive; - this.returnSimpleType = o.returnSimpleType; - this.subresourceOperation = o.subresourceOperation; - this.isMapContainer = o.isMapContainer; - this.isListContainer = o.isListContainer; - this.isMultipart = o.isMultipart; - this.hasMore = o.hasMore; - this.isResponseBinary = o.isResponseBinary; - this.isResponseFile = o.isResponseFile; - this.hasReference = o.hasReference; - this.isRestfulIndex = o.isRestfulIndex; - this.isRestfulShow = o.isRestfulShow; - this.isRestfulCreate = o.isRestfulCreate; - this.isRestfulUpdate = o.isRestfulUpdate; - this.isRestfulDestroy = o.isRestfulDestroy; - this.isRestful = o.isRestful; - this.isDeprecated = o.isDeprecated; - this.isCallbackRequest = o.isCallbackRequest; - this.path = o.path; - this.operationId = o.operationId; - this.returnType = o.returnType; - this.httpMethod = o.httpMethod; - this.returnBaseType = o.returnBaseType; - this.returnContainer = o.returnContainer; - this.summary = o.summary; - this.unescapedNotes = o.unescapedNotes; - this.notes = o.notes; - this.baseName = o.baseName; - this.defaultResponse = o.defaultResponse; - this.discriminator = o.discriminator; - this.consumes = o.consumes; - this.produces = o.produces; - this.prioritizedContentTypes = o.prioritizedContentTypes; - this.servers = o.servers; - this.bodyParam = o.bodyParam; - this.allParams = o.allParams; - this.bodyParams = o.bodyParams; - this.pathParams = o.pathParams; - this.queryParams = o.queryParams; - this.headerParams = o.headerParams; - this.formParams = o.formParams; - this.cookieParams = o.cookieParams; - this.requiredParams = o.requiredParams; - this.optionalParams = o.optionalParams; - this.authMethods = o.authMethods; - this.tags = o.tags; - this.responses = o.responses; - this.callbacks = o.callbacks; - this.imports = o.imports; - this.examples = o.examples; - this.requestBodyExamples = o.requestBodyExamples; - this.externalDocs = o.externalDocs; - this.vendorExtensions = o.vendorExtensions; - this.nickname = o.nickname; - this.operationIdOriginal = o.operationIdOriginal; - this.operationIdLowerCase = o.operationIdLowerCase; - this.operationIdCamelCase = o.operationIdCamelCase; - this.operationIdSnakeCase = o.operationIdSnakeCase; - this.pattern = o.path; + } } diff --git a/boat-scaffold/src/main/java/com/backbase/oss/codegen/angular/BoatAngularGenerator.java b/boat-scaffold/src/main/java/com/backbase/oss/codegen/angular/BoatAngularGenerator.java index d59c3fe7a..f49cb6270 100644 --- a/boat-scaffold/src/main/java/com/backbase/oss/codegen/angular/BoatAngularGenerator.java +++ b/boat-scaffold/src/main/java/com/backbase/oss/codegen/angular/BoatAngularGenerator.java @@ -43,6 +43,10 @@ import org.openapitools.codegen.SupportingFile; import org.openapitools.codegen.languages.AbstractTypeScriptClientCodegen; import org.openapitools.codegen.meta.features.DocumentationFeature; +import org.openapitools.codegen.model.ModelMap; +import org.openapitools.codegen.model.ModelsMap; +import org.openapitools.codegen.model.OperationsMap; +import org.openapitools.codegen.utils.CamelizeOption; import org.openapitools.codegen.utils.ModelUtils; import org.openapitools.codegen.utils.SemVer; import static org.openapitools.codegen.utils.StringUtils.camelize; @@ -128,7 +132,7 @@ public void preprocessOpenAPI(OpenAPI openAPI) { @Override protected void addAdditionPropertiesToCodeGenModel(CodegenModel codegenModel, Schema schema) { - codegenModel.additionalPropertiesType = getTypeDeclaration(ModelUtils.getAdditionalProperties(schema)); + codegenModel.additionalPropertiesType = getTypeDeclaration(ModelUtils.getAdditionalProperties(openAPI, schema)); addImport(codegenModel, codegenModel.additionalPropertiesType); } @@ -367,7 +371,7 @@ public void postProcessParameter(CodegenParameter parameter) { } @Override - public Map postProcessOperationsWithModels(Map operations, List allModels) { + public OperationsMap postProcessOperationsWithModels(OperationsMap operations, List allModels) { String operationKey = "operations"; Map objs = (Map) operations.get(operationKey); Map> pathOperations = new HashMap<>(); @@ -475,7 +479,7 @@ private void processCodgenOperation(CodegenOperation op, Map postProcessModels(Map objs) { - Map result = super.postProcessModels(objs); + public ModelsMap postProcessModels(ModelsMap objs) { + ModelsMap result = super.postProcessModels(objs); return postProcessModelsEnum(result); } @Override - public Map postProcessAllModels(Map objs) { - Map result = super.postProcessAllModels(objs); - for (Map.Entry entry : result.entrySet()) { - Map inner = (Map) entry.getValue(); + public Map postProcessAllModels(Map objs) { + Map result = super.postProcessAllModels(objs); + for (Map.Entry entry : result.entrySet()) { + Map inner = entry.getValue(); List> models = (List>) inner.get("models"); for (Map mo : models) { CodegenModel cm = (CodegenModel) mo.get("model"); @@ -633,7 +637,7 @@ private void validateClassSuffixArgument(String argument, String value) { */ private String convertUsingFileNamingConvention(String originalName) { String name = this.removeModelPrefixSuffix(originalName); - return camelize(name, true); + return camelize(name, CamelizeOption.LOWERCASE_FIRST_LETTER); } @Override diff --git a/boat-scaffold/src/main/java/com/backbase/oss/codegen/doc/BoatCodegenParameter.java b/boat-scaffold/src/main/java/com/backbase/oss/codegen/doc/BoatCodegenParameter.java index ea2a9ea9e..0dde7d51d 100644 --- a/boat-scaffold/src/main/java/com/backbase/oss/codegen/doc/BoatCodegenParameter.java +++ b/boat-scaffold/src/main/java/com/backbase/oss/codegen/doc/BoatCodegenParameter.java @@ -1,13 +1,18 @@ package com.backbase.oss.codegen.doc; +import com.backbase.oss.codegen.CodegenException; import com.fasterxml.jackson.databind.node.ObjectNode; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.examples.Example; import io.swagger.v3.oas.models.media.MediaType; import io.swagger.v3.oas.models.parameters.Parameter; import io.swagger.v3.oas.models.parameters.RequestBody; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.stream.Collectors; import lombok.Data; @@ -49,14 +54,13 @@ public BoatCodegenParameter() { } + @SuppressWarnings("java:S3776") public static BoatCodegenParameter fromCodegenParameter(CodegenParameter codegenParameter) { // Standard properties BoatCodegenParameter output = new BoatCodegenParameter(); output.isFile = codegenParameter.isFile; - output.hasMore = codegenParameter.hasMore; output.isContainer = codegenParameter.isContainer; - output.secondaryParam = codegenParameter.secondaryParam; output.baseName = codegenParameter.baseName; output.paramName = codegenParameter.paramName; output.dataType = codegenParameter.dataType; @@ -132,8 +136,8 @@ public static BoatCodegenParameter fromCodegenParameter(CodegenParameter codegen output.isEmail = codegenParameter.isEmail; output.isFreeFormObject = codegenParameter.isFreeFormObject; output.isAnyType = codegenParameter.isAnyType; - output.isListContainer = codegenParameter.isListContainer; - output.isMapContainer = codegenParameter.isMapContainer; + output.isContainer = codegenParameter.isContainer; + output.isMap = codegenParameter.isMap; output.isExplode = codegenParameter.isExplode; output.style = codegenParameter.style; @@ -151,7 +155,9 @@ public static BoatCodegenParameter fromCodegenParameter(CodegenParameter codegen } } } - + if (output.getContent() == null) { + output.setContent(new LinkedHashMap<>()); + } return output; } diff --git a/boat-scaffold/src/main/java/com/backbase/oss/codegen/doc/BoatCodegenResponse.java b/boat-scaffold/src/main/java/com/backbase/oss/codegen/doc/BoatCodegenResponse.java index 45fd5bf97..d819ae1b0 100644 --- a/boat-scaffold/src/main/java/com/backbase/oss/codegen/doc/BoatCodegenResponse.java +++ b/boat-scaffold/src/main/java/com/backbase/oss/codegen/doc/BoatCodegenResponse.java @@ -41,7 +41,6 @@ public BoatCodegenResponse(CodegenResponse o, String responseCode, ApiResponse r this.is4xx = o.is4xx; this.is5xx = o.is5xx; this.message = o.message; - this.hasMore = o.hasMore; this.dataType = o.dataType; this.baseType = o.baseType; this.containerType = o.containerType; @@ -65,8 +64,8 @@ public BoatCodegenResponse(CodegenResponse o, String responseCode, ApiResponse r this.isDefault = o.isDefault; this.simpleType = o.simpleType; this.primitiveType = o.primitiveType; - this.isMapContainer = o.isMapContainer; - this.isListContainer = o.isListContainer; + this.isMap = o.isMap; + this.isArray = o.isArray; this.isBinary = o.isBinary; this.isFile = o.isFile; this.schema = o.schema; diff --git a/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatJavaCodeGen.java b/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatJavaCodeGen.java index 5965fb1c6..ccb5119c6 100644 --- a/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatJavaCodeGen.java +++ b/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatJavaCodeGen.java @@ -1,12 +1,9 @@ package com.backbase.oss.codegen.java; -import static java.lang.String.format; - import lombok.Getter; import lombok.Setter; import org.openapitools.codegen.CliOption; import org.openapitools.codegen.CodegenModel; -import org.openapitools.codegen.CodegenParameter; import org.openapitools.codegen.CodegenProperty; import org.openapitools.codegen.languages.JavaClientCodegen; @@ -24,10 +21,7 @@ public class BoatJavaCodeGen extends JavaClientCodegen { public static final String REST_TEMPLATE_BEAN_NAME = "restTemplateBeanName"; public static final String CREATE_API_COMPONENT = "createApiComponent"; public static final String USE_PROTECTED_FIELDS = "useProtectedFields"; - - private static final String JAVA_UTIL_SET_NEW = "new " + "java.util.LinkedHashSet<>()"; private static final String JAVA_UTIL_SET = "java.util.Set"; - private static final String JAVA_UTIL_SET_GEN = "java.util.Set<%s>"; @Setter @Getter @@ -52,14 +46,15 @@ public class BoatJavaCodeGen extends JavaClientCodegen { protected boolean createApiComponent = true; public BoatJavaCodeGen() { + this.useJakartaEe = true; + this.openapiNormalizer.put("REF_AS_PARENT_IN_ALLOF", "true"); + this.embeddedTemplateDir = this.templateDir = NAME; this.cliOptions.add(CliOption.newBoolean(USE_CLASS_LEVEL_BEAN_VALIDATION, "Add @Validated to class-level Api interfaces", this.useClassLevelBeanValidation)); this.cliOptions.add(CliOption.newBoolean(USE_WITH_MODIFIERS, "Whether to use \"with\" prefix for POJO modifiers", this.useWithModifiers)); - this.cliOptions.add(CliOption.newBoolean(USE_SET_FOR_UNIQUE_ITEMS, - "Use java.util.Set for arrays that have uniqueItems set to true", this.useSetForUniqueItems)); this.cliOptions.add(CliOption.newBoolean(USE_JACKSON_CONVERSION, "Whether to use Jackson to convert query parameters to String", this.useJacksonConversion)); this.cliOptions.add(CliOption.newBoolean(USE_DEFAULT_API_CLIENT, @@ -112,9 +107,10 @@ public void processOpts() { } if (!getLibrary().startsWith("jersey")) { - this.supportingFiles.removeIf(f -> f.templateFile.equals("ServerConfiguration.mustache")); - this.supportingFiles.removeIf(f -> f.templateFile.equals("ServerVariable.mustache")); + this.supportingFiles.removeIf(f -> f.getTemplateFile().equals("ServerConfiguration.mustache")); + this.supportingFiles.removeIf(f -> f.getTemplateFile().equals("ServerVariable.mustache")); } + } private void processRestTemplateOpts() { @@ -128,7 +124,7 @@ private void processRestTemplateOpts() { } writePropertyBack(USE_JACKSON_CONVERSION, this.useJacksonConversion); if (this.useJacksonConversion) { - this.supportingFiles.removeIf(f -> f.templateFile.equals("RFC3339DateFormat.mustache")); + this.supportingFiles.removeIf(f -> f.getTemplateFile().equals("RFC3339DateFormat.mustache")); } if (this.additionalProperties.containsKey(USE_DEFAULT_API_CLIENT)) { @@ -148,29 +144,21 @@ private void processRestTemplateOpts() { public void postProcessModelProperty(CodegenModel model, CodegenProperty p) { super.postProcessModelProperty(model, p); - if (p.isContainer && this.useSetForUniqueItems && p.getUniqueItems()) { - p.containerType = "set"; - p.baseType = JAVA_UTIL_SET; - p.dataType = format(JAVA_UTIL_SET_GEN, p.items.dataType); - p.datatypeWithEnum = format(JAVA_UTIL_SET_GEN, p.items.datatypeWithEnum); - p.defaultValue = JAVA_UTIL_SET_NEW; + if (!fullJavaUtil) { + if ("array".equals(p.containerType)) { + model.imports.add(instantiationTypes.get("array")); + } else if ("set".equals(p.containerType)) { + model.imports.add(instantiationTypes.get("set")); + boolean canNotBeWrappedToNullable = !openApiNullable || !p.isNullable; + if (canNotBeWrappedToNullable) { + model.imports.add("JsonDeserialize"); + p.vendorExtensions.put("x-setter-extra-annotation", "@JsonDeserialize(as = " + instantiationTypes.get("set") + ".class)"); + } + } else if ("map".equals(p.containerType)) { + model.imports.add(instantiationTypes.get("map")); + } } } - @Override - public void postProcessParameter(CodegenParameter p) { - super.postProcessParameter(p); - - if (p.isContainer && this.useSetForUniqueItems && p.getUniqueItems()) { - // XXX the model set baseType to the container type, why is this different? - - p.baseType = p.dataType.replaceAll("^([^<]+)<.+>$", "$1"); - p.baseType = JAVA_UTIL_SET; - p.dataType = format(JAVA_UTIL_SET_GEN, p.items.dataType); - p.datatypeWithEnum = format(JAVA_UTIL_SET_GEN, p.items.datatypeWithEnum); - p.defaultValue = JAVA_UTIL_SET_NEW; - - } - } } diff --git a/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatSpringCodeGen.java b/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatSpringCodeGen.java index 9fbb36840..079680dc1 100644 --- a/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatSpringCodeGen.java +++ b/boat-scaffold/src/main/java/com/backbase/oss/codegen/java/BoatSpringCodeGen.java @@ -1,11 +1,16 @@ package com.backbase.oss.codegen.java; +import static java.util.Arrays.stream; +import static java.util.stream.Collectors.joining; +import static org.openapitools.codegen.utils.StringUtils.camelize; + import com.samskivert.mustache.Mustache; import com.samskivert.mustache.Template.Fragment; +import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.servers.Server; import java.io.IOException; import java.io.Writer; -import static java.util.Arrays.stream; -import static java.util.stream.Collectors.joining; +import java.util.List; import java.util.stream.IntStream; import lombok.Getter; import lombok.Setter; @@ -13,14 +18,15 @@ import org.openapitools.codegen.CliOption; import org.openapitools.codegen.CodegenConstants; import org.openapitools.codegen.CodegenModel; +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 static org.openapitools.codegen.utils.StringUtils.camelize; public class BoatSpringCodeGen extends SpringCodegen { + public static final String NAME = "boat-spring"; public static final String USE_CLASS_LEVEL_BEAN_VALIDATION = "useClassLevelBeanValidation"; @@ -28,7 +34,6 @@ public class BoatSpringCodeGen extends SpringCodegen { public static final String ADD_BINDING_RESULT = "addBindingResult"; public static final String USE_LOMBOK_ANNOTATIONS = "useLombokAnnotations"; public static final String USE_SET_FOR_UNIQUE_ITEMS = "useSetForUniqueItems"; - public static final String OPENAPI_NULLABLE = "openApiNullable"; public static final String USE_WITH_MODIFIERS = "useWithModifiers"; public static final String USE_PROTECTED_FIELDS = "useProtectedFields"; public static final String UNIQUE_BASE_TYPE = "java.util.Set"; @@ -115,13 +120,6 @@ static int indentLevel(String text) { @Getter protected boolean useSetForUniqueItems; - /** - * Enable OpenAPI Jackson Nullable library - */ - @Setter - @Getter - protected boolean openApiNullable = true; - /** * Whether to use {@code with} prefix for pojos modifiers. */ @@ -130,7 +128,9 @@ static int indentLevel(String text) { protected boolean useWithModifiers; public BoatSpringCodeGen() { + super(); this.embeddedTemplateDir = this.templateDir = NAME; + this.openapiNormalizer.put("REF_AS_PARENT_IN_ALLOF", "true"); this.cliOptions.add(CliOption.newBoolean(USE_CLASS_LEVEL_BEAN_VALIDATION, "Add @Validated to class-level Api interfaces.", this.useClassLevelBeanValidation)); @@ -143,8 +143,6 @@ public BoatSpringCodeGen() { "Add Lombok to class-level Api models. Defaults to false.", this.useLombokAnnotations)); this.cliOptions.add(CliOption.newBoolean(USE_SET_FOR_UNIQUE_ITEMS, "Use java.util.Set for arrays that have uniqueItems set to true.", this.useSetForUniqueItems)); - this.cliOptions.add(CliOption.newBoolean(OPENAPI_NULLABLE, - "Enable OpenAPI Jackson Nullable library.", this.openApiNullable)); this.cliOptions.add(CliOption.newBoolean(USE_WITH_MODIFIERS, "Whether to use \"with\" prefix for POJO modifiers.", this.useWithModifiers)); this.cliOptions.add(CliOption.newString(USE_PROTECTED_FIELDS, @@ -184,12 +182,12 @@ public void processOpts() { final String supFiles = GlobalSettings.getProperty(CodegenConstants.SUPPORTING_FILES); // cleared by false final boolean useApiUtil = supFiles != null && (supFiles.isEmpty() - ? needApiUtil() // set to empty by true - : supFiles.contains("ApiUtil.java")); // set by + ? needApiUtil() // set to empty by true + : supFiles.contains("ApiUtil.java")); // set by if (!useApiUtil) { this.supportingFiles - .removeIf(sf -> "apiUtil.mustache".equals(sf.templateFile)); + .removeIf(sf -> "apiUtil.mustache".equals(sf.getTemplateFile())); } writePropertyBack("useApiUtil", useApiUtil); @@ -209,9 +207,6 @@ public void processOpts() { if (this.additionalProperties.containsKey(USE_SET_FOR_UNIQUE_ITEMS)) { this.useSetForUniqueItems = convertPropertyToBoolean(USE_SET_FOR_UNIQUE_ITEMS); } - if (this.additionalProperties.containsKey(OPENAPI_NULLABLE)) { - this.openApiNullable = convertPropertyToBoolean(OPENAPI_NULLABLE); - } if (this.additionalProperties.containsKey(USE_WITH_MODIFIERS)) { this.useWithModifiers = convertPropertyToBoolean(USE_WITH_MODIFIERS); } @@ -225,7 +220,6 @@ public void processOpts() { writePropertyBack(ADD_SERVLET_REQUEST, this.addServletRequest); writePropertyBack(ADD_BINDING_RESULT, this.addBindingResult); writePropertyBack(USE_LOMBOK_ANNOTATIONS, this.useLombokAnnotations); - writePropertyBack(OPENAPI_NULLABLE, this.openApiNullable); writePropertyBack(USE_SET_FOR_UNIQUE_ITEMS, this.useSetForUniqueItems); writePropertyBack(USE_WITH_MODIFIERS, this.useWithModifiers); @@ -277,4 +271,21 @@ private boolean needApiUtil() { return this.apiTemplateFiles.containsKey("api.mustache") && this.apiTemplateFiles.containsKey("apiDelegate.mustache"); } + + /** + This method has been overridden in order to add a parameter to codegen operation for adding HttpServletRequest to + the service interface. There is a relevant httpServletParam.mustache file. + */ + @Override + public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, List servers) { + final CodegenOperation codegenOperation = super.fromOperation(path, httpMethod, operation, servers); + if (this.addServletRequest) { + final CodegenParameter codegenParameter = new CodegenParameter() { + public boolean isHttpServletRequest = true; + }; + codegenParameter.paramName = "httpServletRequest"; + codegenOperation.allParams.add(codegenParameter); + } + return codegenOperation; + } } diff --git a/boat-scaffold/src/main/java/com/backbase/oss/codegen/lint/BoatLintGenerator.java b/boat-scaffold/src/main/java/com/backbase/oss/codegen/lint/BoatLintGenerator.java index 369b0aa09..be8aecf7d 100644 --- a/boat-scaffold/src/main/java/com/backbase/oss/codegen/lint/BoatLintGenerator.java +++ b/boat-scaffold/src/main/java/com/backbase/oss/codegen/lint/BoatLintGenerator.java @@ -18,12 +18,7 @@ public class BoatLintGenerator extends AbstractDocumentationGenerator { public BoatLintGenerator(BoatLintConfig config) { - super(config); - } - - @Override - public Generator opts(ClientOptInput opts) { - return this; + this.opts(new ClientOptInput().config(config)); } public List generate() { @@ -52,7 +47,7 @@ public List generate(BoatLintReport boatLintReport) { // After processing our model, convert it into a map Map bundle = convertToBundle(boatLintReport); List files = processTemplates(bundle); - log.info("Finished creating BOAT Lint for portal: {} in: {} ", boatLintReport.getTitle(), output); + log.info("Finished creating BOAT Lint for portal: {} files: {} ", boatLintReport.getTitle(), files); return files; } diff --git a/boat-scaffold/src/main/java/com/backbase/oss/codegen/marina/BoatHandlebarsEngineAdapter.java b/boat-scaffold/src/main/java/com/backbase/oss/codegen/marina/BoatHandlebarsEngineAdapter.java index b08fa96b9..16e7b38ac 100644 --- a/boat-scaffold/src/main/java/com/backbase/oss/codegen/marina/BoatHandlebarsEngineAdapter.java +++ b/boat-scaffold/src/main/java/com/backbase/oss/codegen/marina/BoatHandlebarsEngineAdapter.java @@ -1,12 +1,13 @@ package com.backbase.oss.codegen.marina; import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.MapperFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; -import com.github.jknack.handlebars.*; -import com.github.jknack.handlebars.context.FieldValueResolver; +import com.github.jknack.handlebars.Context; +import com.github.jknack.handlebars.Handlebars; +import com.github.jknack.handlebars.Helper; +import com.github.jknack.handlebars.Jackson2Helper; +import com.github.jknack.handlebars.Template; import com.github.jknack.handlebars.context.JavaBeanValueResolver; import com.github.jknack.handlebars.context.MapValueResolver; import com.github.jknack.handlebars.helper.ConditionalHelpers; @@ -14,24 +15,23 @@ import com.github.jknack.handlebars.io.AbstractTemplateLoader; import com.github.jknack.handlebars.io.TemplateLoader; import com.github.jknack.handlebars.io.TemplateSource; -import lombok.extern.slf4j.Slf4j; -import org.openapitools.codegen.api.TemplatingGenerator; -import org.openapitools.codegen.templating.HandlebarsEngineAdapter; - import java.io.IOException; import java.util.Locale; import java.util.Map; +import lombok.extern.slf4j.Slf4j; +import org.openapitools.codegen.api.TemplatingExecutor; +import org.openapitools.codegen.templating.HandlebarsEngineAdapter; @Slf4j public class BoatHandlebarsEngineAdapter extends HandlebarsEngineAdapter { @Override - public String compileTemplate(TemplatingGenerator generator, - Map bundle, String templateFile) throws IOException { + public String compileTemplate(TemplatingExecutor executor, Map bundle, String templateFile) + throws IOException { TemplateLoader loader = new AbstractTemplateLoader() { @Override public TemplateSource sourceAt(String location) { - return findTemplate(generator, location); + return findTemplate(executor, location); } }; diff --git a/boat-scaffold/src/main/java/com/backbase/oss/codegen/yard/BoatYardGenerator.java b/boat-scaffold/src/main/java/com/backbase/oss/codegen/yard/BoatYardGenerator.java index 0199efb8a..bc0b55101 100644 --- a/boat-scaffold/src/main/java/com/backbase/oss/codegen/yard/BoatYardGenerator.java +++ b/boat-scaffold/src/main/java/com/backbase/oss/codegen/yard/BoatYardGenerator.java @@ -27,18 +27,13 @@ public class BoatYardGenerator extends AbstractDocumentationGenerator { public BoatYardGenerator(BoatYardConfig config) { - super(config); + this.opts(new ClientOptInput().config(config)); } private BoatYardConfig getBoatYardConfig() { return (BoatYardConfig) config; } - @Override - public Generator opts(ClientOptInput opts) { - return this; - } - public List generate() { return getYardModel().getPortals().stream() .flatMap(portal -> generate(portal).stream()) diff --git a/boat-scaffold/src/main/templates/boat-angular/api.service.mustache b/boat-scaffold/src/main/templates/boat-angular/api.service.mustache index 3adf3afe0..4baa444ae 100644 --- a/boat-scaffold/src/main/templates/boat-angular/api.service.mustache +++ b/boat-scaffold/src/main/templates/boat-angular/api.service.mustache @@ -178,7 +178,7 @@ export class {{classname}} { * @deprecated This endpoint is deprecated {{/isDeprecated}} */ - public {{nickname}}({{#allParams.0}}requestParameters: {{#prefixParameterInterfaces}}{{classname}}{{/prefixParameterInterfaces}}{{operationIdCamelCase}}RequestParams, {{/allParams.0}}observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: {{#produces}}'{{mediaType}}'{{#hasMore}} | {{/hasMore}}{{/produces}}{{^produces}}undefined{{/produces}}}): Observable { + public {{nickname}}({{#allParams.0}}requestParameters: {{#prefixParameterInterfaces}}{{classname}}{{/prefixParameterInterfaces}}{{operationIdCamelCase}}RequestParams, {{/allParams.0}}observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: {{#produces}}'{{mediaType}}'{{^-last}} | {{/-last}}{{/produces}}{{^produces}}undefined{{/produces}}}): Observable { {{#allParams}} const _{{paramName}} = requestParameters["{{paramName}}"]; {{#required}} @@ -262,7 +262,7 @@ export class {{classname}} { // to determine the Accept header const httpHeaderAccepts: string[] = [ {{#produces}} - '{{{mediaType}}}'{{#hasMore}},{{/hasMore}} + '{{{mediaType}}}'{{^-last}},{{/-last}} {{/produces}} ]; httpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts); @@ -276,7 +276,7 @@ export class {{classname}} { // to determine the Content-Type header const consumes: string[] = [ {{#consumes}} - '{{{mediaType}}}'{{#hasMore}},{{/hasMore}} + '{{{mediaType}}}'{{^-last}},{{/-last}} {{/consumes}} ]; {{/bodyParam}} @@ -285,7 +285,7 @@ export class {{classname}} { // to determine the Content-Type header const consumes: string[] = [ {{#consumes}} - '{{{mediaType}}}'{{#hasMore}},{{/hasMore}} + '{{{mediaType}}}'{{^-last}},{{/-last}} {{/consumes}} ]; {{/bodyParam}} diff --git a/boat-scaffold/src/main/templates/boat-angular/apiInterface.mustache b/boat-scaffold/src/main/templates/boat-angular/apiInterface.mustache new file mode 100644 index 000000000..3a2124949 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-angular/apiInterface.mustache @@ -0,0 +1,51 @@ +{{>licenseInfo}} +import { HttpHeaders } from '@angular/common/http'; + +import { Observable } from 'rxjs'; + +{{#imports}} +import { {{classname}} } from '../model/models'; +{{/imports}} + + +import { {{configurationClassName}} } from '../configuration'; + +{{#operations}} + +{{#useSingleRequestParameter}} +{{#operation}} +{{#allParams.0}} +export interface {{#prefixParameterInterfaces}}{{classname}}{{/prefixParameterInterfaces}}{{operationIdCamelCase}}RequestParams { +{{#allParams}} + {{paramName}}{{^required}}?{{/required}}: {{{dataType}}}{{#isNullable}} | null{{/isNullable}}; +{{/allParams}} +} + +{{/allParams.0}} +{{/operation}} +{{/useSingleRequestParameter}} + +{{#description}} + /** + * {{&description}} + */ +{{/description}} +export interface {{classname}}Interface { + defaultHeaders: HttpHeaders; + configuration: {{configurationClassName}}; + +{{#operation}} + /** + * {{summary}} + * {{notes}} + {{^useSingleRequestParameter}} + {{#allParams}}* @param {{paramName}} {{description}} + {{/allParams}}{{/useSingleRequestParameter}}{{#useSingleRequestParameter}}{{#allParams.0}}* @param requestParameters + {{/allParams.0}}{{/useSingleRequestParameter}}{{#isDeprecated}} + * @deprecated + {{/isDeprecated}}*/ + {{nickname}}({{^useSingleRequestParameter}}{{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/allParams}}{{/useSingleRequestParameter}}{{#useSingleRequestParameter}}{{#allParams.0}}requestParameters: {{#prefixParameterInterfaces}}{{classname}}{{/prefixParameterInterfaces}}{{operationIdCamelCase}}RequestParams, {{/allParams.0}}{{/useSingleRequestParameter}}extraHttpRequestParams?: any): Observable<{{{returnType}}}{{^returnType}}{}{{/returnType}}>; + +{{/operation}} +} +{{/operations}} diff --git a/boat-scaffold/src/main/templates/boat-angular/apis.mustache b/boat-scaffold/src/main/templates/boat-angular/apis.mustache new file mode 100644 index 000000000..ad8785cf8 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-angular/apis.mustache @@ -0,0 +1,12 @@ +{{#apiInfo}} +{{#apis}} +{{#operations}} +export * from './{{ classFilename }}'; +import { {{ classname }} } from './{{ classFilename }}'; +{{/operations}} +{{#withInterfaces}} +export * from './{{ classFilename }}Interface'; +{{/withInterfaces}} +{{/apis}} +export const APIS = [{{#apis}}{{#operations}}{{ classname }}{{/operations}}{{^-last}}, {{/-last}}{{/apis}}]; +{{/apiInfo}} diff --git a/boat-scaffold/src/main/templates/boat-angular/index.mustache b/boat-scaffold/src/main/templates/boat-angular/index.mustache new file mode 100644 index 000000000..104dd3d21 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-angular/index.mustache @@ -0,0 +1,6 @@ +export * from './api/api'; +export * from './model/models'; +export * from './variables'; +export * from './configuration'; +export * from './api.module'; +export * from './param'; diff --git a/boat-scaffold/src/main/templates/boat-angular/param.mustache b/boat-scaffold/src/main/templates/boat-angular/param.mustache new file mode 100644 index 000000000..78a2d20a6 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-angular/param.mustache @@ -0,0 +1,69 @@ +/** + * Standard parameter styles defined by OpenAPI spec + */ +export type StandardParamStyle = + | 'matrix' + | 'label' + | 'form' + | 'simple' + | 'spaceDelimited' + | 'pipeDelimited' + | 'deepObject' + ; + +/** + * The OpenAPI standard {@link StandardParamStyle}s may be extended by custom styles by the user. + */ +export type ParamStyle = StandardParamStyle | string; + +/** + * Standard parameter locations defined by OpenAPI spec + */ +export type ParamLocation = 'query' | 'header' | 'path' | 'cookie'; + +/** + * Standard types as defined in OpenAPI Specification: Data Types + */ +export type StandardDataType = + | "integer" + | "number" + | "boolean" + | "string" + | "object" + | "array" + ; + +/** + * Standard {@link DataType}s plus your own types/classes. + */ +export type DataType = StandardDataType | string; + +/** + * Standard formats as defined in OpenAPI Specification: Data Types + */ +export type StandardDataFormat = + | "int32" + | "int64" + | "float" + | "double" + | "byte" + | "binary" + | "date" + | "date-time" + | "password" + ; + +export type DataFormat = StandardDataFormat | string; + +/** + * The parameter to encode. + */ +export interface Param { + name: string; + value: unknown; + in: ParamLocation; + style: ParamStyle, + explode: boolean; + dataType: DataType; + dataFormat: DataFormat | undefined; +} diff --git a/boat-scaffold/src/main/templates/boat-java/ApiClient.mustache b/boat-scaffold/src/main/templates/boat-java/ApiClient.mustache index 8b71c1551..69494573c 100644 --- a/boat-scaffold/src/main/templates/boat-java/ApiClient.mustache +++ b/boat-scaffold/src/main/templates/boat-java/ApiClient.mustache @@ -1,21 +1,13 @@ {{>licenseInfo}} package {{invokerPackage}}; -{{#threetenbp}} -import org.threeten.bp.*; - -{{/threetenbp}} import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; {{#joda}} import com.fasterxml.jackson.datatype.joda.JodaModule; {{/joda}} -{{#java8}} import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -{{/java8}} -{{#threetenbp}} -import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule; -{{/threetenbp}} +import java.time.OffsetDateTime; import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider; import com.sun.jersey.api.client.Client; @@ -53,15 +45,21 @@ import java.io.UnsupportedEncodingException; import java.text.DateFormat; import {{invokerPackage}}.auth.Authentication; +{{#hasHttpBasicMethods}} import {{invokerPackage}}.auth.HttpBasicAuth; +{{/hasHttpBasicMethods}} +{{#hasHttpBearerMethods}} import {{invokerPackage}}.auth.HttpBearerAuth; +{{/hasHttpBearerMethods}} +{{#hasApiKeyMethods}} import {{invokerPackage}}.auth.ApiKeyAuth; +{{/hasApiKeyMethods}} {{#hasOAuthMethods}} import {{invokerPackage}}.auth.OAuth; {{/hasOAuthMethods}} {{>generatedAnnotation}} -public class ApiClient { +public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} { private Map defaultHeaderMap = new HashMap(); private Map defaultCookieMap = new HashMap(); private String basePath = "{{{basePath}}}"; @@ -116,22 +114,13 @@ public class ApiClient { {{#joda}} objectMapper.registerModule(new JodaModule()); {{/joda}} - {{#java8}} objectMapper.registerModule(new JavaTimeModule()); - {{/java8}} - {{#threetenbp}} - ThreeTenModule module = new ThreeTenModule(); - module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT); - module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME); - module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); - objectMapper.registerModule(module); - {{/threetenbp}} objectMapper.setDateFormat(ApiClient.buildDefaultDateFormat()); dateFormat = ApiClient.buildDefaultDateFormat(); // Set default User-Agent. - setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}"); + setUserAgent("{{{httpUserAgent}}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}"); // Setup authentications (key: authentication name, value: authentication). authentications = new HashMap();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} @@ -267,6 +256,25 @@ public class ApiClient { return authentications.get(authName); } + {{#hasHttpBearerMethods}} + /** + * Helper method to set access token for the first Bearer authentication. + * @param bearerToken Bearer token + * @return API client + */ + public void setBearerToken(String bearerToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBearerAuth) { + ((HttpBearerAuth) auth).setBearerToken(bearerToken); + return; + } + } + throw new RuntimeException("No Bearer authentication configured!"); + } + + {{/hasHttpBearerMethods}} + + {{#hasHttpBasicMethods}} /** * Helper method to set username for the first HTTP basic authentication. * @param username Username @@ -295,6 +303,9 @@ public class ApiClient { throw new RuntimeException("No HTTP basic authentication configured!"); } + {{/hasHttpBasicMethods}} + + {{#hasApiKeyMethods}} /** * Helper method to set API key value for the first API key authentication. * @param apiKey the API key @@ -323,6 +334,8 @@ public class ApiClient { throw new RuntimeException("No API key authentication configured!"); } + {{/hasApiKeyMethods}} + {{#hasOAuthMethods}} /** * Helper method to set access token for the first OAuth2 authentication. @@ -340,20 +353,6 @@ public class ApiClient { {{/hasOAuthMethods}} - /** - * Helper method to set access token for the first Bearer authentication. - * @param bearerToken Bearer token - */ - public void setBearerToken(String bearerToken) { - for (Authentication auth : authentications.values()) { - if (auth instanceof HttpBearerAuth) { - ((HttpBearerAuth) auth).setBearerToken(bearerToken); - return; - } - } - throw new RuntimeException("No Bearer authentication configured!"); - } - /** * Set the User-Agent header's value (by adding to the default header map). * @param userAgent User agent @@ -484,7 +483,9 @@ public class ApiClient { return ""; } else if (param instanceof Date) { return formatDate((Date) param); - } else if (param instanceof Collection) { + } {{#jsr310}}else if (param instanceof OffsetDateTime) { + return formatOffsetDateTime((OffsetDateTime) param); + } {{/jsr310}}else if (param instanceof Collection) { StringBuilder b = new StringBuilder(); for(Object o : (Collection)param) { if(b.length() > 0) { @@ -882,4 +883,4 @@ public class ApiClient { return encodedFormParams; } -} +} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/BeanValidationException.mustache b/boat-scaffold/src/main/templates/boat-java/BeanValidationException.mustache index ab8ef30b6..179abe2fa 100644 --- a/boat-scaffold/src/main/templates/boat-java/BeanValidationException.mustache +++ b/boat-scaffold/src/main/templates/boat-java/BeanValidationException.mustache @@ -2,12 +2,17 @@ package {{invokerPackage}}; import java.util.Set; +{{^useJakartaEe}} import javax.validation.ConstraintViolation; import javax.validation.ValidationException; - +{{/useJakartaEe}} +{{#useJakartaEe}} +import jakarta.validation.ConstraintViolation; +import jakarta.validation.ValidationException; +{{/useJakartaEe}} public class BeanValidationException extends ValidationException { /** - * + * */ private static final long serialVersionUID = -5294733947409491364L; Set> violations; @@ -24,4 +29,4 @@ public class BeanValidationException extends ValidationException { this.violations = violations; } -} +} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/JSON.mustache b/boat-scaffold/src/main/templates/boat-java/JSON.mustache index 590ba386e..d315850bb 100644 --- a/boat-scaffold/src/main/templates/boat-java/JSON.mustache +++ b/boat-scaffold/src/main/templates/boat-java/JSON.mustache @@ -19,11 +19,6 @@ import org.joda.time.format.DateTimeFormatter; import org.joda.time.format.DateTimeFormatterBuilder; import org.joda.time.format.ISODateTimeFormat; {{/joda}} -{{#threetenbp}} -import org.threeten.bp.LocalDate; -import org.threeten.bp.OffsetDateTime; -import org.threeten.bp.format.DateTimeFormatter; -{{/threetenbp}} {{#models.0}} import {{modelPackage}}.*; @@ -36,11 +31,9 @@ import java.lang.reflect.Type; import java.text.DateFormat; import java.text.ParseException; import java.text.ParsePosition; -{{#java8}} import java.time.LocalDate; import java.time.OffsetDateTime; import java.time.format.DateTimeFormatter; -{{/java8}} import java.util.Date; import java.util.Locale; import java.util.Map; @@ -61,14 +54,15 @@ public class JSON { {{/jsr310}} private ByteArrayAdapter byteArrayAdapter = new ByteArrayAdapter(); + @SuppressWarnings("unchecked") public static GsonBuilder createGson() { GsonFireBuilder fireBuilder = new GsonFireBuilder() {{#models}} {{#model}} {{#discriminator}} - .registerTypeSelector({{classname}}.class, new TypeSelector() { + .registerTypeSelector({{classname}}.class, new TypeSelector<{{classname}}>() { @Override - public Class getClassForElement(JsonElement readElement) { + public Class getClassForElement(JsonElement readElement) { Map classByDiscriminatorValue = new HashMap(); {{#mappedModels}} classByDiscriminatorValue.put("{{mappingName}}"{{^discriminatorCaseSensitive}}.toUpperCase(Locale.ROOT){{/discriminatorCaseSensitive}}, {{modelName}}.class); @@ -148,6 +142,13 @@ public class JSON { return this; } + /** + * Configure the parser to be liberal in what it accepts. + * + * @param lenientOnJson Set it to true to ignore some syntax errors + * @return JSON + * @see https://www.javadoc.io/doc/com.google.code.gson/gson/2.8.5/com/google/gson/stream/JsonReader.html + */ public JSON setLenientOnJson(boolean lenientOnJson) { isLenientOnJson = lenientOnJson; return this; @@ -176,7 +177,7 @@ public class JSON { try { if (isLenientOnJson) { JsonReader jsonReader = new JsonReader(new StringReader(body)); - // see https://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/stream/JsonReader.html#setLenient(boolean) + // see https://www.javadoc.io/doc/com.google.code.gson/gson/2.8.5/com/google/gson/stream/JsonReader.html jsonReader.setLenient(true); return gson.fromJson(jsonReader, returnType); } else { @@ -535,4 +536,4 @@ public class JSON { return this; } -} +} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/JavaTimeFormatter.mustache b/boat-scaffold/src/main/templates/boat-java/JavaTimeFormatter.mustache new file mode 100644 index 000000000..f3fb34e55 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/JavaTimeFormatter.mustache @@ -0,0 +1,53 @@ +{{>licenseInfo}} +package {{invokerPackage}}; + +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; + +/** + * Class that add parsing/formatting support for Java 8+ {@code OffsetDateTime} class. + * It's generated for java clients when {@code AbstractJavaCodegen#dateLibrary} specified as {@code java8}. + */ +{{>generatedAnnotation}} +public class JavaTimeFormatter { + + private DateTimeFormatter offsetDateTimeFormatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME; + + /** + * Get the date format used to parse/format {@code OffsetDateTime} parameters. + * @return DateTimeFormatter + */ + public DateTimeFormatter getOffsetDateTimeFormatter() { + return offsetDateTimeFormatter; + } + + /** + * Set the date format used to parse/format {@code OffsetDateTime} parameters. + * @param offsetDateTimeFormatter {@code DateTimeFormatter} + */ + public void setOffsetDateTimeFormatter(DateTimeFormatter offsetDateTimeFormatter) { + this.offsetDateTimeFormatter = offsetDateTimeFormatter; + } + + /** + * Parse the given string into {@code OffsetDateTime} object. + * @param str String + * @return {@code OffsetDateTime} + */ + public OffsetDateTime parseOffsetDateTime(String str) { + try { + return OffsetDateTime.parse(str, offsetDateTimeFormatter); + } catch (DateTimeParseException e) { + throw new RuntimeException(e); + } + } + /** + * Format the given {@code OffsetDateTime} object into string. + * @param offsetDateTime {@code OffsetDateTime} + * @return {@code OffsetDateTime} in string format + */ + public String formatOffsetDateTime(OffsetDateTime offsetDateTime) { + return offsetDateTimeFormatter.format(offsetDateTime); + } +} diff --git a/boat-scaffold/src/main/templates/boat-java/README.mustache b/boat-scaffold/src/main/templates/boat-java/README.mustache index 917f873d5..777e2c860 100644 --- a/boat-scaffold/src/main/templates/boat-java/README.mustache +++ b/boat-scaffold/src/main/templates/boat-java/README.mustache @@ -8,7 +8,7 @@ - Build date: {{generatedDate}} {{/hideGenerationTimestamp}} -{{#appDescriptionWithNewLines}}{{{appDescriptionWithNewLines}}}{{/appDescriptionWithNewLines}} +{{{appDescriptionWithNewLines}}} {{#infoUrl}} For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}) @@ -20,8 +20,13 @@ Building the API client library requires: -1. Java {{#supportJava6}}1.6{{/supportJava6}}{{^supportJava6}}{{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}}{{/supportJava6}}+ +1. Java 1.8+ +{{#jersey2}} +2. Maven (3.8.3+)/Gradle (7.2+) +{{/jersey2}} +{{^jersey2}} 2. Maven/Gradle +{{/jersey2}} ## Installation @@ -57,7 +62,14 @@ Add this dependency to your project's POM: Add this dependency to your project's build file: ```groovy -compile "{{{groupId}}}:{{{artifactId}}}:{{{artifactVersion}}}" + repositories { + mavenCentral() // Needed if the '{{{artifactId}}}' jar has been published to maven central. + mavenLocal() // Needed if the '{{{artifactId}}}' jar has been published to the local maven repo. + } + + dependencies { + implementation "{{{groupId}}}:{{{artifactId}}}:{{{artifactVersion}}}" + } ``` ### Others @@ -73,6 +85,33 @@ Then manually install the following JARs: - `target/{{{artifactId}}}-{{{artifactVersion}}}.jar` - `target/lib/*.jar` +{{#jersey2}} +## Usage + +To add a HTTP proxy for the API client, use `ClientConfig`: +```java +{{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}} +import org.glassfish.jersey.apache.connector.ApacheConnectorProvider; +import org.glassfish.jersey.client.ClientConfig; +import org.glassfish.jersey.client.ClientProperties; +import {{{invokerPackage}}}.*; +import {{{package}}}.{{{classname}}}; + +... + +ApiClient defaultClient = Configuration.getDefaultApiClient(); +ClientConfig clientConfig = defaultClient.getClientConfig(); +clientConfig.connectorProvider(new ApacheConnectorProvider()); +clientConfig.property(ClientProperties.PROXY_URI, "http://proxy_url_here"); +clientConfig.property(ClientProperties.PROXY_USERNAME, "proxy_username"); +clientConfig.property(ClientProperties.PROXY_PASSWORD, "proxy_password"); +defaultClient.setClientConfig(clientConfig); + +{{{classname}}} apiInstance = new {{{classname}}}(defaultClient); +{{/-first}}{{/operation}}{{/operations}}{{/-first}}{{/apis}}{{/apiInfo}} +``` + +{{/jersey2}} ## Getting Started Please follow the [installation](#installation) instruction and execute the following Java code: @@ -104,7 +143,24 @@ public class {{{classname}}}Example { //{{{name}}}.setApiKeyPrefix("Token");{{/isApiKey}}{{#isOAuth}} // Configure OAuth2 access token for authorization: {{{name}}} OAuth {{{name}}} = (OAuth) defaultClient.getAuthentication("{{{name}}}"); - {{{name}}}.setAccessToken("YOUR ACCESS TOKEN");{{/isOAuth}} + {{{name}}}.setAccessToken("YOUR ACCESS TOKEN");{{/isOAuth}}{{#isHttpSignature}} + // Configure HTTP signature authorization: {{{name}}} + HttpSignatureAuth {{{name}}} = (HttpSignatureAuth) defaultClient.getAuthentication("{{{name}}}"); + // All the HTTP signature parameters below should be customized to your environment. + // Configure the keyId + {{{name}}}.setKeyId("YOUR KEY ID"); + // Configure the signature algorithm + {{{name}}}.setSigningAlgorithm(SigningAlgorithm.HS2019); + // Configure the specific cryptographic algorithm + {{{name}}}.setAlgorithm(Algorithm.ECDSA_SHA256); + // Configure the cryptographic algorithm parameters, if applicable + {{{name}}}.setAlgorithmParameterSpec(null); + // Set the cryptographic digest algorithm. + {{{name}}}.setDigestAlgorithm("SHA-256"); + // Set the HTTP headers that should be included in the HTTP signature. + {{{name}}}.setHeaders(Arrays.asList("date", "host")); + // Set the private key used to sign the HTTP messages + {{{name}}}.setPrivateKey();{{/isHttpSignature}} {{/authMethods}} {{/hasAuthMethods}} @@ -113,7 +169,7 @@ public class {{{classname}}}Example { {{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} {{/allParams}} try { - {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}} + {{#returnType}}{{{.}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}});{{#returnType}} System.out.println(result);{{/returnType}} } catch (ApiException e) { System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); @@ -133,7 +189,7 @@ All URIs are relative to *{{basePath}}* Class | Method | HTTP request | Description ------------ | ------------- | ------------- | ------------- -{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{commonPath}}{{path}} | {{summary}} {{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} ## Documentation for Models @@ -175,5 +231,5 @@ It's recommended to create an instance of `ApiClient` per thread in a multithrea ## Author -{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}} -{{/hasMore}}{{/apis}}{{/apiInfo}} +{{#apiInfo}}{{#apis}}{{#-last}}{{infoEmail}} +{{/-last}}{{/apis}}{{/apiInfo}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/RFC3339DateFormat.mustache b/boat-scaffold/src/main/templates/boat-java/RFC3339DateFormat.mustache index 16fd2a495..311616a4e 100644 --- a/boat-scaffold/src/main/templates/boat-java/RFC3339DateFormat.mustache +++ b/boat-scaffold/src/main/templates/boat-java/RFC3339DateFormat.mustache @@ -1,21 +1,46 @@ {{>licenseInfo}} package {{invokerPackage}}; -import com.fasterxml.jackson.databind.util.ISO8601DateFormat; -import com.fasterxml.jackson.databind.util.ISO8601Utils; +import com.fasterxml.jackson.databind.util.StdDateFormat; +import java.text.DateFormat; import java.text.FieldPosition; +import java.text.ParsePosition; import java.util.Date; +import java.text.DecimalFormat; +import java.util.GregorianCalendar; +import java.util.TimeZone; +public class RFC3339DateFormat extends DateFormat { + private static final long serialVersionUID = 1L; + private static final TimeZone TIMEZONE_Z = TimeZone.getTimeZone("UTC"); -public class RFC3339DateFormat extends ISO8601DateFormat { + private final StdDateFormat fmt = new StdDateFormat() + .withTimeZone(TIMEZONE_Z) + .withColonInTimeZone(true); + + public RFC3339DateFormat() { + this.calendar = new GregorianCalendar(); + this.numberFormat = new DecimalFormat(); + } + + @Override + public Date parse(String source) { + return parse(source, new ParsePosition(0)); + } + + @Override + public Date parse(String source, ParsePosition pos) { + return fmt.parse(source, pos); + } - // Same as ISO8601DateFormat but serializing milliseconds. @Override public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) { - String value = ISO8601Utils.format(date, true); - toAppendTo.append(value); - return toAppendTo; + return fmt.format(date, toAppendTo, fieldPosition); } + @Override + public Object clone() { + return super.clone(); + } } \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/ServerConfiguration.mustache b/boat-scaffold/src/main/templates/boat-java/ServerConfiguration.mustache index f976c542b..e324da7a8 100644 --- a/boat-scaffold/src/main/templates/boat-java/ServerConfiguration.mustache +++ b/boat-scaffold/src/main/templates/boat-java/ServerConfiguration.mustache @@ -12,7 +12,7 @@ public class ServerConfiguration { /** * @param URL A URL to the target host. - * @param description A describtion of the host designated by the URL. + * @param description A description of the host designated by the URL. * @param variables A map between a variable name and its value. The value is used for substitution in the server's URL template. */ public ServerConfiguration(String URL, String description, Map variables) { @@ -39,10 +39,10 @@ public class ServerConfiguration { if (variables != null && variables.containsKey(name)) { value = variables.get(name); if (serverVariable.enumValues.size() > 0 && !serverVariable.enumValues.contains(value)) { - throw new RuntimeException("The variable " + name + " in the server URL has invalid value " + value + "."); + throw new IllegalArgumentException("The variable " + name + " in the server URL has invalid value " + value + "."); } } - url = url.replaceAll("\\{" + name + "\\}", value); + url = url.replace("{" + name + "}", value); } return url; } @@ -55,4 +55,4 @@ public class ServerConfiguration { public String URL() { return URL(null); } -} +} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/additionalEnumTypeAnnotations.mustache b/boat-scaffold/src/main/templates/boat-java/additionalEnumTypeAnnotations.mustache new file mode 100644 index 000000000..aa524798b --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/additionalEnumTypeAnnotations.mustache @@ -0,0 +1,2 @@ +{{#additionalEnumTypeAnnotations}}{{{.}}} +{{/additionalEnumTypeAnnotations}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/additionalOneOfTypeAnnotations.mustache b/boat-scaffold/src/main/templates/boat-java/additionalOneOfTypeAnnotations.mustache new file mode 100644 index 000000000..283f8f91e --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/additionalOneOfTypeAnnotations.mustache @@ -0,0 +1,2 @@ +{{#additionalOneOfTypeAnnotations}}{{{.}}} +{{/additionalOneOfTypeAnnotations}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/api.mustache b/boat-scaffold/src/main/templates/boat-java/api.mustache index 4057af777..099d41cd2 100644 --- a/boat-scaffold/src/main/templates/boat-java/api.mustache +++ b/boat-scaffold/src/main/templates/boat-java/api.mustache @@ -54,7 +54,7 @@ public class {{classname}} { * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/isContainer}}{{/required}} {{/allParams}} {{#returnType}} - * @return {{returnType}} + * @return {{.}} {{/returnType}} * @throws ApiException if fails to make API call {{#isDeprecated}} @@ -68,7 +68,7 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { + public {{#returnType}}{{{.}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { Object localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; {{#allParams}}{{#required}} // verify the required parameter '{{paramName}}' is set @@ -88,7 +88,7 @@ public class {{classname}} { {{javaUtilPrefix}}Map localVarFormParams = new {{javaUtilPrefix}}HashMap(); {{#queryParams}} - {{#collectionFormat}}localVarCollectionQueryParams.addAll(apiClient.parameterToPairs("{{{collectionFormat}}}", {{/collectionFormat}}{{^collectionFormat}}localVarQueryParams.addAll(apiClient.parameterToPair({{/collectionFormat}}"{{baseName}}", {{paramName}})); + {{#collectionFormat}}localVarCollectionQueryParams.addAll(apiClient.parameterToPairs("{{{.}}}", {{/collectionFormat}}{{^collectionFormat}}localVarQueryParams.addAll(apiClient.parameterToPair({{/collectionFormat}}"{{baseName}}", {{paramName}})); {{/queryParams}} {{#headerParams}}if ({{paramName}} != null) @@ -104,16 +104,16 @@ public class {{classname}} { {{/formParams}} final String[] localVarAccepts = { - {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} + {{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}} }; final String localVarAccept = apiClient.selectHeaderAccept(localVarAccepts); final String[] localVarContentTypes = { - {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} + {{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}} }; final String localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes); - String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{^-last}}, {{/-last}}{{/authMethods}} }; {{#returnType}} GenericType<{{{returnType}}}> localVarReturnType = new GenericType<{{{returnType}}}>() {}; @@ -124,4 +124,4 @@ public class {{classname}} { } {{/operation}} } -{{/operations}} +{{/operations}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/apiException.mustache b/boat-scaffold/src/main/templates/boat-java/apiException.mustache index 5b450c9ba..30e171fba 100644 --- a/boat-scaffold/src/main/templates/boat-java/apiException.mustache +++ b/boat-scaffold/src/main/templates/boat-java/apiException.mustache @@ -37,7 +37,7 @@ public class ApiException extends{{#useRuntimeException}} RuntimeException {{/us } public ApiException(int code, Map> responseHeaders, String responseBody) { - this((String) null, (Throwable) null, code, responseHeaders, responseBody); + this("Response Code: " + code + " Response Body: " + responseBody, (Throwable) null, code, responseHeaders, responseBody); } public ApiException(int code, String message) { @@ -77,4 +77,13 @@ public class ApiException extends{{#useRuntimeException}} RuntimeException {{/us public String getResponseBody() { return responseBody; } -} + + @Override + public String toString() { + return "ApiException{" + + "code=" + code + + ", responseHeaders=" + responseHeaders + + ", responseBody='" + responseBody + '\'' + + '}'; + } +} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/apiOperation.mustache b/boat-scaffold/src/main/templates/boat-java/apiOperation.mustache new file mode 100644 index 000000000..97adb0ea2 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/apiOperation.mustache @@ -0,0 +1,28 @@ +{{>licenseInfo}} +package {{invokerPackage}}; + +import io.swagger.v3.oas.models.Operation; + +public class ApiOperation { + private final String path; + private final String method; + private final Operation operation; + + public ApiOperation(String path, String method, Operation operation) { + this.path = path; + this.method = method; + this.operation = operation; + } + + public Operation getOperation() { + return operation; + } + + public String getPath() { + return path; + } + + public String getMethod() { + return method; + } +} diff --git a/boat-scaffold/src/main/templates/boat-java/api_doc.mustache b/boat-scaffold/src/main/templates/boat-java/api_doc.mustache index edc837f48..680095472 100644 --- a/boat-scaffold/src/main/templates/boat-java/api_doc.mustache +++ b/boat-scaffold/src/main/templates/boat-java/api_doc.mustache @@ -1,12 +1,12 @@ # {{classname}}{{#description}} -{{description}}{{/description}} +{{.}}{{/description}} All URIs are relative to *{{basePath}}* -Method | HTTP request | Description -------------- | ------------- | ------------- -{{#operations}}{{#operation}}[**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +| Method | HTTP request | Description | +|------------- | ------------- | -------------| +{{#operations}}{{#operation}}| [**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{commonPath}}{{path}} | {{summary}} | {{/operation}}{{/operations}} {{#operations}} @@ -14,11 +14,11 @@ Method | HTTP request | Description ## {{operationId}} -> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) +> {{#returnType}}{{.}} {{/returnType}}{{operationId}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}}) {{summary}}{{#notes}} -{{notes}}{{/notes}} +{{.}}{{/notes}} ### Example @@ -60,7 +60,7 @@ public class Example { {{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} {{/allParams}} try { - {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}} + {{#returnType}}{{{.}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}});{{#returnType}} System.out.println(result);{{/returnType}} } catch (ApiException e) { System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); @@ -76,9 +76,9 @@ public class Example { ### Parameters {{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{#allParams}}{{#-last}} -Name | Type | Description | Notes -------------- | ------------- | ------------- | -------------{{/-last}}{{/allParams}} -{{#allParams}} **{{paramName}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}[**{{dataType}}**]({{baseType}}.md){{/isFile}}{{/isPrimitiveType}}| {{description}} |{{^required}} [optional]{{/required}}{{^isContainer}}{{#defaultValue}} [default to {{defaultValue}}]{{/defaultValue}}{{/isContainer}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}} +| Name | Type | Description | Notes | +|------------- | ------------- | ------------- | -------------|{{/-last}}{{/allParams}} +{{#allParams}}| **{{paramName}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}[**{{dataType}}**]({{baseType}}.md){{/isFile}}{{/isPrimitiveType}}| {{description}} |{{^required}} [optional]{{/required}}{{^isContainer}}{{#defaultValue}} [default to {{.}}]{{/defaultValue}}{{/isContainer}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}} | {{/allParams}} ### Return type @@ -91,10 +91,11 @@ Name | Type | Description | Notes ### HTTP request headers -- **Content-Type**: {{#consumes}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} -- **Accept**: {{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}{{^produces}}Not defined{{/produces}} +- **Content-Type**: {{#consumes}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} +- **Accept**: {{#produces}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/produces}}{{^produces}}Not defined{{/produces}} {{#responses.0}} + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -104,4 +105,4 @@ Name | Type | Description | Notes {{/responses.0}} {{/operation}} -{{/operations}} +{{/operations}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/api_test.mustache b/boat-scaffold/src/main/templates/boat-java/api_test.mustache index 7011191c8..176be8069 100644 --- a/boat-scaffold/src/main/templates/boat-java/api_test.mustache +++ b/boat-scaffold/src/main/templates/boat-java/api_test.mustache @@ -9,6 +9,8 @@ import org.junit.Test; import org.junit.Ignore; import org.junit.Assert; +import java.time.LocalDate; +import java.time.OffsetDateTime; {{^fullJavaUtil}} import java.util.ArrayList; import java.util.HashMap; @@ -27,11 +29,11 @@ public class {{classname}}Test { {{#operation}} /** {{#summary}} - * {{summary}} + * {{.}} * {{/summary}} {{#notes}} - * {{notes}} + * {{.}} * {{/notes}} * @throws ApiException @@ -42,10 +44,10 @@ public class {{classname}}Test { //{{#allParams}} //{{{dataType}}} {{paramName}} = null; //{{/allParams}} - //{{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + //{{#returnType}}{{{.}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); // TODO: test validations } {{/operation}} {{/operations}} -} +} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/auth/HttpBasicAuth.mustache b/boat-scaffold/src/main/templates/boat-java/auth/HttpBasicAuth.mustache index 4d362cbaf..9dfe714b5 100644 --- a/boat-scaffold/src/main/templates/boat-java/auth/HttpBasicAuth.mustache +++ b/boat-scaffold/src/main/templates/boat-java/auth/HttpBasicAuth.mustache @@ -4,21 +4,12 @@ package {{invokerPackage}}.auth; import {{invokerPackage}}.Pair; -{{^java8}} -import com.migcomponents.migbase64.Base64; -{{/java8}} -{{#java8}} import java.util.Base64; import java.nio.charset.StandardCharsets; -{{/java8}} import java.util.Map; import java.util.List; -{{^java8}} -import java.io.UnsupportedEncodingException; -{{/java8}} - {{>generatedAnnotation}} public class HttpBasicAuth implements Authentication { private String username; @@ -46,15 +37,6 @@ public class HttpBasicAuth implements Authentication { return; } String str = (username == null ? "" : username) + ":" + (password == null ? "" : password); -{{^java8}} - try { - headerParams.put("Authorization", "Basic " + Base64.encodeToString(str.getBytes("UTF-8"), false)); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); - } -{{/java8}} -{{#java8}} headerParams.put("Authorization", "Basic " + Base64.getEncoder().encodeToString(str.getBytes(StandardCharsets.UTF_8))); -{{/java8}} } -} +} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/auth/OAuthFlow.mustache b/boat-scaffold/src/main/templates/boat-java/auth/OAuthFlow.mustache index 002e9572f..3f14c64b1 100644 --- a/boat-scaffold/src/main/templates/boat-java/auth/OAuthFlow.mustache +++ b/boat-scaffold/src/main/templates/boat-java/auth/OAuthFlow.mustache @@ -2,6 +2,13 @@ package {{invokerPackage}}.auth; +/** + * OAuth flows that are supported by this client + */ +{{>generatedAnnotation}} public enum OAuthFlow { - accessCode, implicit, password, application -} + ACCESS_CODE, //called authorizationCode in OpenAPI 3.0 + IMPLICIT, + PASSWORD, + APPLICATION //called clientCredentials in OpenAPI 3.0 +} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/beanValidation.mustache b/boat-scaffold/src/main/templates/boat-java/beanValidation.mustache index 1bc9afa8f..47f7109e5 100644 --- a/boat-scaffold/src/main/templates/boat-java/beanValidation.mustache +++ b/boat-scaffold/src/main/templates/boat-java/beanValidation.mustache @@ -1,5 +1,7 @@ {{#required}} +{{^isReadOnly}} @NotNull +{{/isReadOnly}} {{/required}} {{#isContainer}} {{^isPrimitiveType}} diff --git a/boat-scaffold/src/main/templates/boat-java/beanValidationCore.mustache b/boat-scaffold/src/main/templates/boat-java/beanValidationCore.mustache index ae26b2739..ff4ffe26c 100644 --- a/boat-scaffold/src/main/templates/boat-java/beanValidationCore.mustache +++ b/boat-scaffold/src/main/templates/boat-java/beanValidationCore.mustache @@ -1,20 +1,20 @@ -{{#pattern}} @Pattern(regexp="{{{pattern}}}"){{/pattern}}{{! +{{#pattern}}{{^isByteArray}} @Pattern(regexp="{{{pattern}}}"){{/isByteArray}}{{/pattern}}{{! minLength && maxLength set }}{{#minLength}}{{#maxLength}} @Size(min={{minLength}},max={{maxLength}}){{/maxLength}}{{/minLength}}{{! minLength set, maxLength not }}{{#minLength}}{{^maxLength}} @Size(min={{minLength}}){{/maxLength}}{{/minLength}}{{! minLength not set, maxLength set -}}{{^minLength}}{{#maxLength}} @Size(max={{maxLength}}){{/maxLength}}{{/minLength}}{{! +}}{{^minLength}}{{#maxLength}} @Size(max={{.}}){{/maxLength}}{{/minLength}}{{! @Size: minItems && maxItems set }}{{#minItems}}{{#maxItems}} @Size(min={{minItems}},max={{maxItems}}){{/maxItems}}{{/minItems}}{{! @Size: minItems set, maxItems not }}{{#minItems}}{{^maxItems}} @Size(min={{minItems}}){{/maxItems}}{{/minItems}}{{! @Size: minItems not set && maxItems set -}}{{^minItems}}{{#maxItems}} @Size(max={{maxItems}}){{/maxItems}}{{/minItems}}{{! +}}{{^minItems}}{{#maxItems}} @Size(max={{.}}){{/maxItems}}{{/minItems}}{{! check for integer or long / all others=decimal type with @Decimal* isInteger set -}}{{#isInteger}}{{#minimum}} @Min({{minimum}}){{/minimum}}{{#maximum}} @Max({{maximum}}){{/maximum}}{{/isInteger}}{{! +}}{{#isInteger}}{{#minimum}} @Min({{.}}){{/minimum}}{{#maximum}} @Max({{.}}){{/maximum}}{{/isInteger}}{{! isLong set -}}{{#isLong}}{{#minimum}} @Min({{minimum}}L){{/minimum}}{{#maximum}} @Max({{maximum}}L){{/maximum}}{{/isLong}}{{! +}}{{#isLong}}{{#minimum}} @Min({{.}}L){{/minimum}}{{#maximum}} @Max({{.}}L){{/maximum}}{{/isLong}}{{! Not Integer, not Long => we have a decimal value! }}{{^isInteger}}{{^isLong}}{{#minimum}} @DecimalMin({{#exclusiveMinimum}}value={{/exclusiveMinimum}}"{{minimum}}"{{#exclusiveMinimum}},inclusive=false{{/exclusiveMinimum}}){{/minimum}}{{#maximum}} @DecimalMax({{#exclusiveMaximum}}value={{/exclusiveMaximum}}"{{maximum}}"{{#exclusiveMaximum}},inclusive=false{{/exclusiveMaximum}}){{/maximum}}{{/isLong}}{{/isInteger}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/beanValidationQueryParams.mustache b/boat-scaffold/src/main/templates/boat-java/beanValidationQueryParams.mustache index f8eef8f94..0f99bffde 100644 --- a/boat-scaffold/src/main/templates/boat-java/beanValidationQueryParams.mustache +++ b/boat-scaffold/src/main/templates/boat-java/beanValidationQueryParams.mustache @@ -1 +1 @@ -{{#required}} @NotNull{{/required}}{{>beanValidationCore}} \ No newline at end of file +{{#required}} @NotNull {{/required}}{{>beanValidationCore}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/build.gradle.mustache b/boat-scaffold/src/main/templates/boat-java/build.gradle.mustache index c1bf968db..4d3e795a0 100644 --- a/boat-scaffold/src/main/templates/boat-java/build.gradle.mustache +++ b/boat-scaffold/src/main/templates/boat-java/build.gradle.mustache @@ -6,8 +6,7 @@ version = '{{artifactVersion}}' buildscript { repositories { - maven { url "https://repo1.maven.org/maven2" } - jcenter() + mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:2.3.+' @@ -16,8 +15,7 @@ buildscript { } repositories { - maven { url "https://repo1.maven.org/maven2" } - jcenter() + mavenCentral() } if(hasProperty('target') && target == 'android') { @@ -34,20 +32,8 @@ if(hasProperty('target') && target == 'android') { } compileOptions { - {{#supportJava6}} - sourceCompatibility JavaVersion.VERSION_1_6 - targetCompatibility JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} - {{#java8}} sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 - {{/java8}} - {{^java8}} - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 - {{/java8}} - {{/supportJava6}} } // Rename the aar correctly @@ -62,7 +48,7 @@ if(hasProperty('target') && target == 'android') { } dependencies { - provided 'javax.annotation:jsr250-api:1.0' + provided "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version" } } @@ -90,26 +76,18 @@ if(hasProperty('target') && target == 'android') { } else { apply plugin: 'java' - apply plugin: 'maven' - - {{#supportJava6}} - sourceCompatibility = JavaVersion.VERSION_1_6 - targetCompatibility = JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} - {{#java8}} + apply plugin: 'maven-publish' + sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 - {{/java8}} - {{^java8}} - sourceCompatibility = JavaVersion.VERSION_1_7 - targetCompatibility = JavaVersion.VERSION_1_7 - {{/java8}} - {{/supportJava6}} - - install { - repositories.mavenInstaller { - pom.artifactId = '{{artifactId}}' + + publishing { + publications { + maven(MavenPublication) { + artifactId = '{{artifactId}}' + + from components.java + } } } @@ -117,7 +95,7 @@ if(hasProperty('target') && target == 'android') { main = System.getProperty('mainClass') classpath = sourceSets.main.runtimeClasspath } - + task sourcesJar(type: Jar, dependsOn: classes) { classifier = 'sources' from sourceSets.main.allSource @@ -135,40 +113,34 @@ if(hasProperty('target') && target == 'android') { } ext { - swagger_annotations_version = "1.5.22" - jackson_version = "2.10.3" - jackson_databind_version = "2.10.3" - jackson_databind_nullable_version = "0.2.1" - {{#threetenbp}} - jackson_threetenbp_version = "2.9.10" - {{/threetenbp}} + swagger_annotations_version = "1.6.3" + jackson_version = "2.12.6" + jackson_databind_version = "2.12.6.1" + {{#openApiNullable}} + jackson_databind_nullable_version = "0.2.4" + {{/openApiNullable}} + jakarta_annotation_version = "1.3.5" jersey_version = "1.19.4" jodatime_version = "2.9.9" - junit_version = "4.13" + junit_version = "4.13.2" } dependencies { - compile "io.swagger:swagger-annotations:$swagger_annotations_version" - compile "com.google.code.findbugs:jsr305:3.0.2" - compile "com.sun.jersey:jersey-client:$jersey_version" - compile "com.sun.jersey.contribs:jersey-multipart:$jersey_version" - compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" - compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" - compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation "com.sun.jersey:jersey-client:$jersey_version" + implementation "com.sun.jersey.contribs:jersey-multipart:$jersey_version" + implementation "com.fasterxml.jackson.core:jackson-core:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" + implementation "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" + {{#openApiNullable}} + implementation "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + {{/openApiNullable}} {{#joda}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + implementation "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" {{/joda}} - {{#java8}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" - {{/java8}} - {{#threetenbp}} - compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_threetenbp_version" - {{/threetenbp}} - {{^java8}} - compile "com.brsanthu:migbase64:2.2" - {{/java8}} - testCompile "junit:junit:$junit_version" -} - + implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + implementation "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version" + testImplementation "junit:junit:$junit_version" +} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/generatedAnnotation.mustache b/boat-scaffold/src/main/templates/boat-java/generatedAnnotation.mustache index a47b6faa8..b3147c04f 100644 --- a/boat-scaffold/src/main/templates/boat-java/generatedAnnotation.mustache +++ b/boat-scaffold/src/main/templates/boat-java/generatedAnnotation.mustache @@ -1 +1 @@ -{{^hideGenerationTimestamp}}@javax.annotation.Generated(value = "{{generatorClass}}", date = "{{generatedDate}}"){{/hideGenerationTimestamp}} \ No newline at end of file +{{^hideGenerationTimestamp}}@{{^useJakartaEe}}javax{{/useJakartaEe}}{{#useJakartaEe}}jakarta{{/useJakartaEe}}.annotation.Generated(value = "{{generatorClass}}", date = "{{generatedDate}}"){{/hideGenerationTimestamp}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/git_push.sh.mustache b/boat-scaffold/src/main/templates/boat-java/git_push.sh.mustache index 8b3f689c9..9ff0e8c65 100755 --- a/boat-scaffold/src/main/templates/boat-java/git_push.sh.mustache +++ b/boat-scaffold/src/main/templates/boat-java/git_push.sh.mustache @@ -1,7 +1,7 @@ #!/bin/sh # ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/ # -# Usage example: /bin/sh ./git_push.sh wing328 openapi-pestore-perl "minor update" "gitlab.com" +# Usage example: /bin/sh ./git_push.sh wing328 openapi-petstore-perl "minor update" "gitlab.com" git_user_id=$1 git_repo_id=$2 @@ -38,14 +38,14 @@ git add . git commit -m "$release_note" # Sets the new remote -git_remote=`git remote` +git_remote=$(git remote) if [ "$git_remote" = "" ]; then # git remote not defined if [ "$GIT_TOKEN" = "" ]; then echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment." git remote add origin https://${git_host}/${git_user_id}/${git_repo_id}.git else - git remote add origin https://${git_user_id}:${GIT_TOKEN}@${git_host}/${git_user_id}/${git_repo_id}.git + git remote add origin https://${git_user_id}:"${GIT_TOKEN}"@${git_host}/${git_user_id}/${git_repo_id}.git fi fi @@ -54,5 +54,4 @@ git pull origin master # Pushes (Forces) the changes in the local repository up to the remote repository echo "Git pushing to https://${git_host}/${git_user_id}/${git_repo_id}.git" -git push origin master 2>&1 | grep -v 'To https' - +git push origin master 2>&1 | grep -v 'To https' \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/gradle-wrapper.jar b/boat-scaffold/src/main/templates/boat-java/gradle-wrapper.jar new file mode 100644 index 000000000..7454180f2 Binary files /dev/null and b/boat-scaffold/src/main/templates/boat-java/gradle-wrapper.jar differ diff --git a/boat-scaffold/src/main/templates/boat-java/gradle-wrapper.properties.mustache b/boat-scaffold/src/main/templates/boat-java/gradle-wrapper.properties.mustache index 94920145f..7c08e4f06 100644 --- a/boat-scaffold/src/main/templates/boat-java/gradle-wrapper.properties.mustache +++ b/boat-scaffold/src/main/templates/boat-java/gradle-wrapper.properties.mustache @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists +zipStorePath=wrapper/dists \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/gradle.properties.mustache b/boat-scaffold/src/main/templates/boat-java/gradle.properties.mustache index 05644f075..bf46cf4d6 100644 --- a/boat-scaffold/src/main/templates/boat-java/gradle.properties.mustache +++ b/boat-scaffold/src/main/templates/boat-java/gradle.properties.mustache @@ -1,2 +1,9 @@ -# Uncomment to build for Android -#target = android \ No newline at end of file +# This file is automatically generated by OpenAPI Generator (https://github.com/openAPITools/openapi-generator). +# To include other gradle properties as part of the code generation process, please use the `gradleProperties` option. +# +# Gradle properties reference: https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_configuration_properties +# For example, uncomment below to build for Android +#target = android +{{#gradleProperties}} +{{{.}}} +{{/gradleProperties}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/gradlew.bat.mustache b/boat-scaffold/src/main/templates/boat-java/gradlew.bat.mustache index 9618d8d96..806627401 100644 --- a/boat-scaffold/src/main/templates/boat-java/gradlew.bat.mustache +++ b/boat-scaffold/src/main/templates/boat-java/gradlew.bat.mustache @@ -29,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" +set DEFAULT_JVM_OPTS=-Dfile.encoding=UTF-8 "-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -51,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -61,28 +64,14 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell @@ -97,4 +86,4 @@ exit /b 1 :mainEnd if "%OS%"=="Windows_NT" endlocal -:omega +:omega \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/gradlew.mustache b/boat-scaffold/src/main/templates/boat-java/gradlew.mustache index 2fe81a7d9..1a33e4365 100755 --- a/boat-scaffold/src/main/templates/boat-java/gradlew.mustache +++ b/boat-scaffold/src/main/templates/boat-java/gradlew.mustache @@ -1,7 +1,7 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,78 +17,113 @@ # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +DEFAULT_JVM_OPTS='-Dfile.encoding=UTF-8 "-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -97,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -105,79 +140,95 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=`expr $i + 1` + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' -exec "$JAVACMD" "$@" +exec "$JAVACMD" "$@" \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/jackson_annotations.mustache b/boat-scaffold/src/main/templates/boat-java/jackson_annotations.mustache index ac01b293c..ccde126f5 100644 --- a/boat-scaffold/src/main/templates/boat-java/jackson_annotations.mustache +++ b/boat-scaffold/src/main/templates/boat-java/jackson_annotations.mustache @@ -5,15 +5,15 @@ * Else use custom behaviour, IOW use whatever is defined on the object mapper }} @JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}}) - @JsonInclude({{#isMapContainer}}{{#items.isNullable}}content = JsonInclude.Include.ALWAYS, {{/items.isNullable}}{{/isMapContainer}}value = JsonInclude.Include.{{#required}}ALWAYS{{/required}}{{^required}}USE_DEFAULTS{{/required}}) + @JsonInclude({{#isMap}}{{#items.isNullable}}content = JsonInclude.Include.ALWAYS, {{/items.isNullable}}{{/isMap}}value = JsonInclude.Include.{{#required}}ALWAYS{{/required}}{{^required}}USE_DEFAULTS{{/required}}) {{#withXml}} {{^isContainer}} - @JacksonXmlProperty({{#isXmlAttribute}}isAttribute = true, {{/isXmlAttribute}}{{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}localName = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + @JacksonXmlProperty({{#isXmlAttribute}}isAttribute = true, {{/isXmlAttribute}}{{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}localName = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") {{/isContainer}} {{#isContainer}} {{#isXmlWrapped}} // items.xmlName={{items.xmlName}} - @JacksonXmlElementWrapper(useWrapping = {{isXmlWrapped}}, {{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}localName = "{{#items.xmlName}}{{items.xmlName}}{{/items.xmlName}}{{^items.xmlName}}{{items.baseName}}{{/items.xmlName}}") + @JacksonXmlElementWrapper(useWrapping = {{isXmlWrapped}}, {{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}localName = "{{#items.xmlName}}{{items.xmlName}}{{/items.xmlName}}{{^items.xmlName}}{{items.baseName}}{{/items.xmlName}}") {{/isXmlWrapped}} {{/isContainer}} {{/withXml}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/apache-httpclient/ApiClient.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/apache-httpclient/ApiClient.mustache new file mode 100644 index 000000000..1a07e1cbd --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/apache-httpclient/ApiClient.mustache @@ -0,0 +1,1089 @@ +{{>licenseInfo}} +package {{invokerPackage}}; + +import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.databind.*; +{{#joda}} +import com.fasterxml.jackson.datatype.joda.JodaModule; +{{/joda}} +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import java.time.OffsetDateTime; +import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JavaType; + +import org.apache.http.Header; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.NameValuePair; +import org.apache.http.ParseException; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.RequestBuilder; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.FileEntity; +import org.apache.http.entity.StringEntity; +import org.apache.http.entity.mime.MultipartEntityBuilder; +import org.apache.http.impl.client.BasicCookieStore; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.cookie.BasicClientCookie; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; +import org.apache.http.cookie.Cookie; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.Map.Entry; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.Date; +import java.util.TimeZone; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import java.net.URLEncoder; + +import java.io.File; +import java.io.InputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; +import java.nio.file.Paths; +import java.lang.reflect.Type; +import java.net.URI; + +import java.text.DateFormat; + +import {{invokerPackage}}.auth.Authentication; +{{#hasHttpBasicMethods}} +import {{invokerPackage}}.auth.HttpBasicAuth; +{{/hasHttpBasicMethods}} +{{#hasHttpBearerMethods}} +import {{invokerPackage}}.auth.HttpBearerAuth; +{{/hasHttpBearerMethods}} +{{#hasApiKeyMethods}} +import {{invokerPackage}}.auth.ApiKeyAuth; +{{/hasApiKeyMethods}} +{{#hasOAuthMethods}} +import {{invokerPackage}}.auth.OAuth; +{{/hasOAuthMethods}} + +{{>generatedAnnotation}} +public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} { + private Map defaultHeaderMap = new HashMap(); + private Map defaultCookieMap = new HashMap(); + private String basePath = "{{{basePath}}}"; + protected List servers = new ArrayList({{#servers}}{{#-first}}Arrays.asList( +{{/-first}} new ServerConfiguration( + "{{{url}}}", + "{{{description}}}{{^description}}No description provided{{/description}}", + new HashMap(){{#variables}}{{#-first}} {{ +{{/-first}} put("{{{name}}}", new ServerVariable( + "{{{description}}}{{^description}}No description provided{{/description}}", + "{{{defaultValue}}}", + new HashSet( + {{#enumValues}} + {{#-first}} + Arrays.asList( + {{/-first}} + "{{{.}}}"{{^-last}},{{/-last}} + {{#-last}} + ) + {{/-last}} + {{/enumValues}} + ) + )); + {{#-last}} + }}{{/-last}}{{/variables}} + ){{^-last}},{{/-last}} + {{#-last}} + ){{/-last}}{{/servers}}); + protected Integer serverIndex = 0; + protected Map serverVariables = null; + private boolean debugging = false; + private int connectionTimeout = 0; + + private CloseableHttpClient httpClient; + private ObjectMapper objectMapper; + protected String tempFolderPath = null; + + private Map authentications; + + private int statusCode; + private Map> responseHeaders; + + private DateFormat dateFormat; + + // Methods that can have a request body + private static List bodyMethods = Arrays.asList("POST", "PUT", "DELETE", "PATCH"); + + public ApiClient(CloseableHttpClient httpClient) { + objectMapper = new ObjectMapper(); + objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + objectMapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); + objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + objectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + {{#joda}} + objectMapper.registerModule(new JodaModule()); + {{/joda}} + objectMapper.registerModule(new JavaTimeModule()); + objectMapper.setDateFormat(ApiClient.buildDefaultDateFormat()); + + dateFormat = ApiClient.buildDefaultDateFormat(); + + // Set default User-Agent. + setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}"); + + // Setup authentications (key: authentication name, value: authentication). + authentications = new HashMap();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} + authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} + // Prevent the authentications from being modified. + authentications = Collections.unmodifiableMap(authentications); + + this.httpClient = httpClient; + } + + public ApiClient() { + this(HttpClients.createDefault()); + } + + public static DateFormat buildDefaultDateFormat() { + return new RFC3339DateFormat(); + } + + /** + * Returns the current object mapper used for JSON serialization/deserialization. + *

+ * Note: If you make changes to the object mapper, remember to set it back via + * setObjectMapper in order to trigger HTTP client rebuilding. + *

+ * @return Object mapper + */ + public ObjectMapper getObjectMapper() { + return objectMapper; + } + + /** + * Sets the object mapper. + * + * @param objectMapper object mapper + * @return API client + */ + public ApiClient setObjectMapper(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + return this; + } + + public CloseableHttpClient getHttpClient() { + return httpClient; + } + + /** + * Sets the HTTP client. + * + * @param httpClient HTTP client + * @return API client + */ + public ApiClient setHttpClient(CloseableHttpClient httpClient) { + this.httpClient = httpClient; + return this; + } + + public String getBasePath() { + return basePath; + } + + /** + * Sets the base path. + * + * @param basePath base path + * @return API client + */ + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + this.serverIndex = null; + return this; + } + + public List getServers() { + return servers; + } + + /** + * Sets the server. + * + * @param servers a list of server configuration + * @return API client + */ + public ApiClient setServers(List servers) { + this.servers = servers; + return this; + } + + public Integer getServerIndex() { + return serverIndex; + } + + /** + * Sets the server index. + * + * @param serverIndex server index + * @return API client + */ + public ApiClient setServerIndex(Integer serverIndex) { + this.serverIndex = serverIndex; + return this; + } + + public Map getServerVariables() { + return serverVariables; + } + + /** + * Sets the server variables. + * + * @param serverVariables server variables + * @return API client + */ + public ApiClient setServerVariables(Map serverVariables) { + this.serverVariables = serverVariables; + return this; + } + + /** + * Gets the status code of the previous request + * + * @return Status code + */ + public int getStatusCode() { + return statusCode; + } + + /** + * Gets the response headers of the previous request + * @return Response headers + */ + public Map> getResponseHeaders() { + return responseHeaders; + } + + /** + * Get authentications (key: authentication name, value: authentication). + * @return Map of authentication + */ + public Map getAuthentications() { + return authentications; + } + + /** + * Get authentication for the given name. + * + * @param authName The authentication name + * @return The authentication, null if not found + */ + public Authentication getAuthentication(String authName) { + return authentications.get(authName); + } + + /** + * The path of temporary folder used to store downloaded files from endpoints + * with file response. The default value is null, i.e. using + * the system's default temporary folder. + * + * @return Temp folder path + */ + public String getTempFolderPath() { + return tempFolderPath; + } + + {{#hasHttpBearerMethods}} + /** + * Helper method to set access token for the first Bearer authentication. + * @param bearerToken Bearer token + * @return API client + */ + public ApiClient setBearerToken(String bearerToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBearerAuth) { + ((HttpBearerAuth) auth).setBearerToken(bearerToken); + return this; + } + } + throw new RuntimeException("No Bearer authentication configured!"); + } + + {{/hasHttpBearerMethods}} + + {{#hasHttpBasicMethods}} + /** + * Helper method to set username for the first HTTP basic authentication. + * @param username Username + * @return API client + */ + public ApiClient setUsername(String username) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setUsername(username); + return this; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + /** + * Helper method to set password for the first HTTP basic authentication. + * @param password Password + * @return API client + */ + public ApiClient setPassword(String password) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setPassword(password); + return this; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + {{/hasHttpBasicMethods}} + + {{#hasApiKeyMethods}} + /** + * Helper method to set API key value for the first API key authentication. + * @param apiKey the API key + * @return API client + */ + public ApiClient setApiKey(String apiKey) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKey(apiKey); + return this; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set API key prefix for the first API key authentication. + * @param apiKeyPrefix API key prefix + * @return API client + */ + public ApiClient setApiKeyPrefix(String apiKeyPrefix) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix); + return this; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + {{/hasApiKeyMethods}} + + {{#hasOAuthMethods}} + /** + * Helper method to set access token for the first OAuth2 authentication. + * @param accessToken Access token + * @return API client + */ + public ApiClient setAccessToken(String accessToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setAccessToken(accessToken); + return this; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + {{/hasOAuthMethods}} + + /** + * Set the User-Agent header's value (by adding to the default header map). + * @param userAgent User agent + * @return API client + */ + public ApiClient setUserAgent(String userAgent) { + addDefaultHeader("User-Agent", userAgent); + return this; + } + + /** + * Set temp folder path + * @param tempFolderPath Temp folder path + * @return API client + */ + public ApiClient setTempFolderPath(String tempFolderPath) { + this.tempFolderPath = tempFolderPath; + return this; + } + + /** + * Add a default header. + * + * @param key The header's key + * @param value The header's value + * @return API client + */ + public ApiClient addDefaultHeader(String key, String value) { + defaultHeaderMap.put(key, value); + return this; + } + + /** + * Add a default cookie. + * + * @param key The cookie's key + * @param value The cookie's value + * @return API client + */ + public ApiClient addDefaultCookie(String key, String value) { + defaultCookieMap.put(key, value); + return this; + } + + /** + * Check that whether debugging is enabled for this API client. + * @return True if debugging is on + */ + public boolean isDebugging() { + return debugging; + } + + /** + * Enable/disable debugging for this API client. + * + * @param debugging To enable (true) or disable (false) debugging + * @return API client + */ + public ApiClient setDebugging(boolean debugging) { + // TODO: implement debugging mode + this.debugging = debugging; + return this; + } + + /** + * Connect timeout (in milliseconds). + * @return Connection timeout + */ + public int getConnectTimeout() { + return connectionTimeout; + } + + /** + * Set the connect timeout (in milliseconds). + * A value of 0 means no timeout, otherwise values must be between 1 and + * {@link Integer#MAX_VALUE}. + * @param connectionTimeout Connection timeout in milliseconds + * @return API client + */ + public ApiClient setConnectTimeout(int connectionTimeout) { + this.connectionTimeout = connectionTimeout; + return this; + } + + /** + * Get the date format used to parse/format date parameters. + * @return Date format + */ + public DateFormat getDateFormat() { + return dateFormat; + } + + /** + * Set the date format used to parse/format date parameters. + * @param dateFormat Date format + * @return API client + */ + public ApiClient setDateFormat(DateFormat dateFormat) { + this.dateFormat = dateFormat; + // Also set the date format for model (de)serialization with Date properties. + this.objectMapper.setDateFormat((DateFormat) dateFormat.clone()); + return this; + } + + /** + * Parse the given string into Date object. + * @param str String + * @return Date + */ + public Date parseDate(String str) { + try { + return dateFormat.parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(e); + } + } + + /** + * Format the given Date object into string. + * @param date Date + * @return Date in string format + */ + public String formatDate(Date date) { + return dateFormat.format(date); + } + + /** + * Format the given parameter object into string. + * @param param Object + * @return Object in string format + */ + public String parameterToString(Object param) { + if (param == null) { + return ""; + } else if (param instanceof Date) { + return formatDate((Date) param); + } {{#jsr310}}else if (param instanceof OffsetDateTime) { + return formatOffsetDateTime((OffsetDateTime) param); + } {{/jsr310}}else if (param instanceof Collection) { + StringBuilder b = new StringBuilder(); + for(Object o : (Collection)param) { + if(b.length() > 0) { + b.append(','); + } + b.append(String.valueOf(o)); + } + return b.toString(); + } else { + return String.valueOf(param); + } + } + + /** + * Formats the specified query parameter to a list containing a single {@code Pair} object. + * + * Note that {@code value} must not be a collection. + * + * @param name The name of the parameter. + * @param value The value of the parameter. + * @return A list containing a single {@code Pair} object. + */ + public List parameterToPair(String name, Object value) { + List params = new ArrayList(); + + // preconditions + if (name == null || name.isEmpty() || value == null || value instanceof Collection) { + return params; + } + + params.add(new Pair(name, escapeString(parameterToString(value)))); + return params; + } + + /** + * Formats the specified collection query parameters to a list of {@code Pair} objects. + * + * Note that the values of each of the returned Pair objects are percent-encoded. + * + * @param collectionFormat The collection format of the parameter. + * @param name The name of the parameter. + * @param value The value of the parameter. + * @return A list of {@code Pair} objects. + */ + public List parameterToPairs(String collectionFormat, String name, Collection value) { + List params = new ArrayList(); + + // preconditions + if (name == null || name.isEmpty() || value == null) { + return params; + } + + // create the params based on the collection format + if ("multi".equals(collectionFormat)) { + for (Object item : value) { + params.add(new Pair(name, escapeString(parameterToString(item)))); + } + return params; + } + + // collectionFormat is assumed to be "csv" by default + String delimiter = ","; + + // escape all delimiters except commas, which are URI reserved + // characters + if ("ssv".equals(collectionFormat)) { + delimiter = escapeString(" "); + } else if ("tsv".equals(collectionFormat)) { + delimiter = escapeString("\t"); + } else if ("pipes".equals(collectionFormat)) { + delimiter = escapeString("|"); + } + + StringBuilder sb = new StringBuilder() ; + for (Object item : value) { + sb.append(delimiter); + sb.append(escapeString(parameterToString(item))); + } + + params.add(new Pair(name, sb.substring(delimiter.length()))); + + return params; + } + + /** + * Check if the given MIME is a JSON MIME. + * JSON MIME examples: + * application/json + * application/json; charset=UTF8 + * APPLICATION/JSON + * application/vnd.company+json + * @param mime MIME + * @return True if MIME type is boolean + */ + public boolean isJsonMime(String mime) { + String jsonMime = "(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$"; + return mime != null && (mime.matches(jsonMime) || mime.equals("*/*")); + } + + /** + * Select the Accept header's value from the given accepts array: + * if JSON exists in the given array, use it; + * otherwise use all of them (joining into a string) + * + * @param accepts The accepts array to select from + * @return The Accept header to use. If the given array is empty, + * null will be returned (not to set the Accept header explicitly). + */ + public String selectHeaderAccept(String[] accepts) { + if (accepts.length == 0) { + return null; + } + for (String accept : accepts) { + if (isJsonMime(accept)) { + return accept; + } + } + return StringUtil.join(accepts, ","); + } + + /** + * Select the Content-Type header's value from the given array: + * if JSON exists in the given array, use it; + * otherwise use the first one of the array. + * + * @param contentTypes The Content-Type array to select from + * @return The Content-Type header to use. If the given array is empty, + * or matches "any", JSON will be used. + */ + public String selectHeaderContentType(String[] contentTypes) { + if (contentTypes.length == 0 || contentTypes[0].equals("*/*")) { + return "application/json"; + } + for (String contentType : contentTypes) { + if (isJsonMime(contentType)) { + return contentType; + } + } + return contentTypes[0]; + } + + /** + * Escape the given string to be used as URL query value. + * @param str String + * @return Escaped string + */ + public String escapeString(String str) { + try { + return URLEncoder.encode(str, "utf8").replaceAll("\\+", "%20"); + } catch (UnsupportedEncodingException e) { + return str; + } + } + + /** + * Transforms response headers into map. + * + * @param headers HTTP headers + * @return a map of string array + */ + protected Map> transformResponseHeaders(Header[] headers) { + Map> headersMap = new HashMap<>(); + for (Header header : headers) { + List valuesList = headersMap.get(header.getName()); + if (valuesList != null) { + valuesList.add(header.getValue()); + } else { + valuesList = new ArrayList<>(); + valuesList.add(header.getValue()); + headersMap.put(header.getName(), valuesList); + } + } + return headersMap; + } + + /** + * Parse content type object from header value + */ + private ContentType getContentType(String headerValue) throws ApiException { + try { + return ContentType.parse(headerValue); + } catch (ParseException e) { + throw new ApiException("Could not parse content type " + headerValue); + } + } + + /** + * Get content type of a response or null if one was not provided + */ + private String getResponseMimeType(HttpResponse response) throws ApiException { + Header contentTypeHeader = response.getFirstHeader("Content-Type"); + if (contentTypeHeader != null) { + return getContentType(contentTypeHeader.getValue()).getMimeType(); + } + return null; + } + + /** + * Serialize the given Java object into string according the given + * Content-Type (only JSON is supported for now). + * @param obj Object + * @param contentType Content type + * @param formParams Form parameters + * @return Object + * @throws ApiException API exception + */ + public HttpEntity serialize(Object obj, Map formParams, ContentType contentType) throws ApiException { + String mimeType = contentType.getMimeType(); + if (isJsonMime(mimeType)) { + try { + return new StringEntity(objectMapper.writeValueAsString(obj), contentType); + } catch (JsonProcessingException e) { + throw new ApiException(e); + } + } else if (mimeType.equals(ContentType.MULTIPART_FORM_DATA.getMimeType())) { + MultipartEntityBuilder multiPartBuilder = MultipartEntityBuilder.create(); + for (Entry paramEntry : formParams.entrySet()) { + Object value = paramEntry.getValue(); + if (value instanceof File) { + multiPartBuilder.addBinaryBody(paramEntry.getKey(), (File) value); + } else if (value instanceof byte[]) { + multiPartBuilder.addBinaryBody(paramEntry.getKey(), (byte[]) value); + } else { + Charset charset = contentType.getCharset(); + if (charset != null) { + ContentType customContentType = ContentType.create(ContentType.TEXT_PLAIN.getMimeType(), charset); + multiPartBuilder.addTextBody(paramEntry.getKey(), parameterToString(paramEntry.getValue()), + customContentType); + } else { + multiPartBuilder.addTextBody(paramEntry.getKey(), parameterToString(paramEntry.getValue())); + } + } + } + return multiPartBuilder.build(); + } else if (mimeType.equals(ContentType.APPLICATION_FORM_URLENCODED.getMimeType())) { + List formValues = new ArrayList<>(); + for (Entry paramEntry : formParams.entrySet()) { + formValues.add(new BasicNameValuePair(paramEntry.getKey(), parameterToString(paramEntry.getValue()))); + } + return new UrlEncodedFormEntity(formValues, contentType.getCharset()); + } else { + // Handle files with unknown content type + if (obj instanceof File) { + return new FileEntity((File) obj, contentType); + } else if (obj instanceof byte[]) { + return new ByteArrayEntity((byte[]) obj, contentType); + } + throw new ApiException("Serialization for content type '" + contentType + "' not supported"); + } + } + + /** + * Deserialize response body to Java object according to the Content-Type. + * + * @param Type + * @param response Response + * @param valueType Return type + * @return Deserialized object + * @throws ApiException API exception + * @throws IOException IO exception + */ + @SuppressWarnings("unchecked") + public T deserialize(HttpResponse response, TypeReference valueType) throws ApiException, IOException { + if (valueType == null) { + return null; + } + HttpEntity entity = response.getEntity(); + Type valueRawType = valueType.getType(); + if (valueRawType.equals(byte[].class)) { + return (T) EntityUtils.toByteArray(entity); + } else if (valueRawType.equals(File.class)) { + return (T) downloadFileFromResponse(response); + } + String mimeType = getResponseMimeType(response); + if (mimeType == null || isJsonMime(mimeType)) { + // Assume json if no mime type + return objectMapper.readValue(entity.getContent(), valueType); + } else if ("text/plain".equalsIgnoreCase(mimeType)) { + // convert input stream to string + java.util.Scanner s = new java.util.Scanner(entity.getContent()).useDelimiter("\\A"); + return (T) (s.hasNext() ? s.next() : ""); + } else { + throw new ApiException( + "Deserialization for content type '" + mimeType + "' not supported for type '" + valueType + "'", + response.getStatusLine().getStatusCode(), + responseHeaders, + EntityUtils.toString(entity) + ); + } + } + + private File downloadFileFromResponse(HttpResponse response) throws IOException { + Header contentDispositionHeader = response.getFirstHeader("Content-Disposition"); + String contentDisposition = contentDispositionHeader == null ? null : contentDispositionHeader.getValue(); + File file = prepareDownloadFile(contentDisposition); + Files.copy(response.getEntity().getContent(), file.toPath(), StandardCopyOption.REPLACE_EXISTING); + return file; + } + + protected File prepareDownloadFile(String contentDisposition) throws IOException { + String filename = null; + if (contentDisposition != null && !"".equals(contentDisposition)) { + // Get filename from the Content-Disposition header. + Pattern pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?"); + Matcher matcher = pattern.matcher(contentDisposition); + if (matcher.find()) + filename = matcher.group(1); + } + + String prefix; + String suffix = null; + if (filename == null) { + prefix = "download-"; + suffix = ""; + } else { + int pos = filename.lastIndexOf('.'); + if (pos == -1) { + prefix = filename + "-"; + } else { + prefix = filename.substring(0, pos) + "-"; + suffix = filename.substring(pos); + } + // Files.createTempFile requires the prefix to be at least three characters long + if (prefix.length() < 3) + prefix = "download-"; + } + + if (tempFolderPath == null) + return Files.createTempFile(prefix, suffix).toFile(); + else + return Files.createTempFile(Paths.get(tempFolderPath), prefix, suffix).toFile(); + } + + /** + * Build full URL by concatenating base path, the given sub path and query parameters. + * + * @param path The sub path + * @param queryParams The query parameters + * @param collectionQueryParams The collection query parameters + * @return The full URL + */ + private String buildUrl(String path, List queryParams, List collectionQueryParams) { + String baseURL; + if (serverIndex != null) { + if (serverIndex < 0 || serverIndex >= servers.size()) { + throw new ArrayIndexOutOfBoundsException(String.format( + "Invalid index %d when selecting the host settings. Must be less than %d", serverIndex, servers.size() + )); + } + baseURL = servers.get(serverIndex).URL(serverVariables); + } else { + baseURL = basePath; + } + + final StringBuilder url = new StringBuilder(); + url.append(baseURL).append(path); + + if (queryParams != null && !queryParams.isEmpty()) { + // support (constant) query string in `path`, e.g. "/posts?draft=1" + String prefix = path.contains("?") ? "&" : "?"; + for (Pair param : queryParams) { + if (param.getValue() != null) { + if (prefix != null) { + url.append(prefix); + prefix = null; + } else { + url.append("&"); + } + String value = parameterToString(param.getValue()); + // query parameter value already escaped as part of parameterToPair + url.append(escapeString(param.getName())).append("=").append(value); + } + } + } + + if (collectionQueryParams != null && !collectionQueryParams.isEmpty()) { + String prefix = url.toString().contains("?") ? "&" : "?"; + for (Pair param : collectionQueryParams) { + if (param.getValue() != null) { + if (prefix != null) { + url.append(prefix); + prefix = null; + } else { + url.append("&"); + } + String value = parameterToString(param.getValue()); + // collection query parameter value already escaped as part of parameterToPairs + url.append(escapeString(param.getName())).append("=").append(value); + } + } + } + + return url.toString(); + } + + protected boolean isSuccessfulStatus(int statusCode) { + return statusCode >= 200 && statusCode < 300; + } + + protected boolean isBodyAllowed(String method) { + return bodyMethods.contains(method); + } + + protected Cookie buildCookie(String key, String value, URI uri) { + BasicClientCookie cookie = new BasicClientCookie(key, value); + cookie.setDomain(uri.getHost()); + cookie.setPath("/"); + return cookie; + } + + protected T processResponse(CloseableHttpResponse response, TypeReference returnType) throws ApiException, IOException { + statusCode = response.getStatusLine().getStatusCode(); + if (statusCode == HttpStatus.SC_NO_CONTENT) { + return null; + } + + responseHeaders = transformResponseHeaders(response.getAllHeaders()); + if (isSuccessfulStatus(statusCode)) { + return this.deserialize(response, returnType); + } else { + String message = EntityUtils.toString(response.getEntity()); + throw new ApiException(message, statusCode, responseHeaders, message); + } + } + + /** + * Invoke API by sending HTTP request with the given options. + * + * @param Type + * @param path The sub-path of the HTTP URL + * @param method The request method, one of "GET", "POST", "PUT", and "DELETE" + * @param queryParams The query parameters + * @param collectionQueryParams The collection query parameters + * @param body The request body object - if it is not binary, otherwise null + * @param headerParams The header parameters + * @param cookieParams The cookie parameters + * @param formParams The form parameters + * @param accept The request's Accept header + * @param contentType The request's Content-Type header + * @param authNames The authentications to apply + * @param returnType Return type + * @return The response body in type of string + * @throws ApiException API exception + */ + public T invokeAPI( + String path, + String method, + List queryParams, + List collectionQueryParams, + Object body, + Map headerParams, + Map cookieParams, + Map formParams, + String accept, + String contentType, + String[] authNames, + TypeReference returnType) throws ApiException { + if (body != null && !formParams.isEmpty()) { + throw new ApiException("Cannot have body and form params"); + } + + updateParamsForAuth(authNames, queryParams, headerParams, cookieParams); + final String url = buildUrl(path, queryParams, collectionQueryParams); + + RequestBuilder builder = RequestBuilder.create(method); + builder.setUri(url); + + RequestConfig config = RequestConfig.custom() + .setConnectionRequestTimeout(connectionTimeout) + .build(); + builder.setConfig(config); + + if (accept != null) { + builder.addHeader("Accept", accept); + } + for (Entry keyValue : headerParams.entrySet()) { + builder.addHeader(keyValue.getKey(), keyValue.getValue()); + } + for (Map.Entry keyValue : defaultHeaderMap.entrySet()) { + if (!headerParams.containsKey(keyValue.getKey())) { + builder.addHeader(keyValue.getKey(), keyValue.getValue()); + } + } + + BasicCookieStore store = new BasicCookieStore(); + for (Entry keyValue : cookieParams.entrySet()) { + store.addCookie(buildCookie(keyValue.getKey(), keyValue.getValue(), builder.getUri())); + } + for (Entry keyValue : defaultCookieMap.entrySet()) { + if (!cookieParams.containsKey(keyValue.getKey())) { + store.addCookie(buildCookie(keyValue.getKey(), keyValue.getValue(), builder.getUri())); + } + } + + HttpClientContext context = HttpClientContext.create(); + context.setCookieStore(store); + + ContentType contentTypeObj = getContentType(contentType); + if (body != null || !formParams.isEmpty()) { + if (isBodyAllowed(method)) { + // Add entity if we have content and a valid method + builder.setEntity(serialize(body, formParams, contentTypeObj)); + } else { + throw new ApiException("method " + method + " does not support a request body"); + } + } else { + // for empty body + builder.setEntity(serialize(null, null, contentTypeObj)); + } + + try (CloseableHttpResponse response = httpClient.execute(builder.build(), context)) { + return processResponse(response, returnType); + } catch (IOException e) { + throw new ApiException(e); + } + } + + /** + * Update query and header parameters based on authentication settings. + * + * @param authNames The authentications to apply + * @param queryParams Query parameters + * @param headerParams Header parameters + * @param cookieParams Cookie parameters + */ + private void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams, Map cookieParams) { + for (String authName : authNames) { + Authentication auth = authentications.get(authName); + if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); + auth.applyToParams(queryParams, headerParams, cookieParams); + } + } +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/apache-httpclient/README.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/apache-httpclient/README.mustache new file mode 100644 index 000000000..c6ae4fa23 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/apache-httpclient/README.mustache @@ -0,0 +1,196 @@ +# {{artifactId}} + +{{appName}} + +- API version: {{appVersion}} +{{^hideGenerationTimestamp}} + +- Build date: {{generatedDate}} +{{/hideGenerationTimestamp}} + +{{#appDescriptionWithNewLines}}{{{appDescriptionWithNewLines}}}{{/appDescriptionWithNewLines}} + +{{#infoUrl}} + For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}) +{{/infoUrl}} + +*Automatically generated by the [OpenAPI Generator](https://openapi-generator.tech)* + +## Requirements + +Building the API client library requires: + +1. Java 1.8+ +2. Maven/Gradle + +## Installation + +To install the API client library to your local Maven repository, simply execute: + +```shell +mvn clean install +``` + +To deploy it to a remote Maven repository instead, configure the settings of the repository and execute: + +```shell +mvn clean deploy +``` + +Refer to the [OSSRH Guide](http://central.sonatype.org/pages/ossrh-guide.html) for more information. + +### Maven users + +Add this dependency to your project's POM: + +```xml + + {{{groupId}}} + {{{artifactId}}} + {{{artifactVersion}}} + compile + +``` + +### Gradle users + +Add this dependency to your project's build file: + +```groovy +compile "{{{groupId}}}:{{{artifactId}}}:{{{artifactVersion}}}" +``` + +### Others + +At first generate the JAR by executing: + +```shell +mvn clean package +``` + +Then manually install the following JARs: + +- `target/{{{artifactId}}}-{{{artifactVersion}}}.jar` +- `target/lib/*.jar` + +## Getting Started + +Please follow the [installation](#installation) instruction and execute the following Java code: + +```java +{{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}} +import {{{invokerPackage}}}.*; +import {{{invokerPackage}}}.auth.*; +import {{{modelPackage}}}.*; +import {{{package}}}.{{{classname}}}; + +public class {{{classname}}}Example { + + public static void main(String[] args) { + ApiClient defaultClient = Configuration.getDefaultApiClient(); + defaultClient.setBasePath("{{{basePath}}}"); + {{#hasAuthMethods}}{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + // Configure HTTP basic authorization: {{{name}}} + HttpBasicAuth {{{name}}} = (HttpBasicAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setUsername("YOUR USERNAME"); + {{{name}}}.setPassword("YOUR PASSWORD");{{/isBasicBasic}}{{#isBasicBearer}} + // Configure HTTP bearer authorization: {{{name}}} + HttpBearerAuth {{{name}}} = (HttpBearerAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setBearerToken("BEARER TOKEN");{{/isBasicBearer}}{{/isBasic}}{{#isApiKey}} + // Configure API key authorization: {{{name}}} + ApiKeyAuth {{{name}}} = (ApiKeyAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setApiKey("YOUR API KEY"); + // Uncomment the following line to set a prefix for the API key, e.g. "Token" (defaults to null) + //{{{name}}}.setApiKeyPrefix("Token");{{/isApiKey}}{{#isOAuth}} + // Configure OAuth2 access token for authorization: {{{name}}} + OAuth {{{name}}} = (OAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setAccessToken("YOUR ACCESS TOKEN");{{/isOAuth}}{{#isHttpSignature}} + // Configure HTTP signature authorization: {{{name}}} + HttpSignatureAuth {{{name}}} = (HttpSignatureAuth) defaultClient.getAuthentication("{{{name}}}"); + // All the HTTP signature parameters below should be customized to your environment. + // Configure the keyId + {{{name}}}.setKeyId("YOUR KEY ID"); + // Configure the signature algorithm + {{{name}}}.setSigningAlgorithm(SigningAlgorithm.HS2019); + // Configure the specific cryptographic algorithm + {{{name}}}.setAlgorithm(Algorithm.ECDSA_SHA256); + // Configure the cryptographic algorithm parameters, if applicable + {{{name}}}.setAlgorithmParameterSpec(null); + // Set the cryptographic digest algorithm. + {{{name}}}.setDigestAlgorithm("SHA-256"); + // Set the HTTP headers that should be included in the HTTP signature. + {{{name}}}.setHeaders(Arrays.asList("date", "host")); + // Set the private key used to sign the HTTP messages + {{{name}}}.setPrivateKey();{{/isHttpSignature}} + {{/authMethods}} + {{/hasAuthMethods}} + + {{{classname}}} apiInstance = new {{{classname}}}(defaultClient); + {{#allParams}} + {{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} + {{/allParams}} + try { + {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}});{{#returnType}} + System.out.println(result);{{/returnType}} + } catch (ApiException e) { + System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); + System.err.println("Status code: " + e.getCode()); + System.err.println("Reason: " + e.getResponseBody()); + System.err.println("Response headers: " + e.getResponseHeaders()); + e.printStackTrace(); + } + } +} +{{/-first}}{{/operation}}{{/operations}}{{/-first}}{{/apis}}{{/apiInfo}} +``` + +## Documentation for API Endpoints + +All URIs are relative to *{{basePath}}* + +Class | Method | HTTP request | Description +------------ | ------------- | ------------- | ------------- +{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{commonPath}}{{path}} | {{#summary}}{{summary}}{{/summary}} +{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} + +## Documentation for Models + +{{#models}}{{#model}} - [{{classname}}]({{modelDocPath}}{{classname}}.md) +{{/model}}{{/models}} + +## Documentation for Authorization + +{{^authMethods}}All endpoints do not require authorization. +{{/authMethods}}Authentication schemes defined for the API: +{{#authMethods}}### {{name}} + +{{#isApiKey}} + +- **Type**: API key +- **API key parameter name**: {{keyParamName}} +- **Location**: {{#isKeyInQuery}}URL query string{{/isKeyInQuery}}{{#isKeyInHeader}}HTTP header{{/isKeyInHeader}} +{{/isApiKey}} +{{#isBasic}} + +- **Type**: HTTP basic authentication +{{/isBasic}} +{{#isOAuth}} + +- **Type**: OAuth +- **Flow**: {{flow}} +- **Authorization URL**: {{authorizationUrl}} +- **Scopes**: {{^scopes}}N/A{{/scopes}} +{{#scopes}} - {{scope}}: {{description}} +{{/scopes}} +{{/isOAuth}} + +{{/authMethods}} + +## Recommendation + +It's recommended to create an instance of `ApiClient` per thread in a multithreaded environment to avoid any potential issues. + +## Author + +{{#apiInfo}}{{#apis}}{{#-last}}{{infoEmail}} +{{/-last}}{{/apis}}{{/apiInfo}} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/apache-httpclient/api.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/apache-httpclient/api.mustache new file mode 100644 index 000000000..772878710 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/apache-httpclient/api.mustache @@ -0,0 +1,157 @@ +{{>licenseInfo}} +package {{package}}; + +import com.fasterxml.jackson.core.type.TypeReference; + +import {{invokerPackage}}.ApiException; +import {{invokerPackage}}.ApiClient; +import {{invokerPackage}}.Configuration; +import {{modelPackage}}.*; +import {{invokerPackage}}.Pair; + +{{#imports}}import {{import}}; +{{/imports}} + + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +{{>generatedAnnotation}} +{{#operations}} +public class {{classname}} { + private ApiClient apiClient; + + public {{classname}}() { + this(Configuration.getDefaultApiClient()); + } + + public {{classname}}(ApiClient apiClient) { + this.apiClient = apiClient; + } + + public ApiClient getApiClient() { + return apiClient; + } + + public void setApiClient(ApiClient apiClient) { + this.apiClient = apiClient; + } + + {{#operation}} + /** + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/isContainer}}{{/required}} + {{/allParams}} + {{#returnType}} + * @return {{returnType}} + {{/returnType}} + * @throws ApiException if fails to make API call + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { + Object localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; + {{#allParams}}{{#required}} + // verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + throw new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{operationId}}"); + } + {{/required}}{{/allParams}} + // create path and map variables + String localVarPath = "{{{path}}}"{{#pathParams}} + .replaceAll("\\{" + "{{baseName}}" + "\\}", apiClient.escapeString({{{paramName}}}.toString())){{/pathParams}}; + + // query params + {{javaUtilPrefix}}List localVarQueryParams = new {{javaUtilPrefix}}ArrayList(); + {{javaUtilPrefix}}List localVarCollectionQueryParams = new {{javaUtilPrefix}}ArrayList(); + {{javaUtilPrefix}}Map localVarHeaderParams = new {{javaUtilPrefix}}HashMap(); + {{javaUtilPrefix}}Map localVarCookieParams = new {{javaUtilPrefix}}HashMap(); + {{javaUtilPrefix}}Map localVarFormParams = new {{javaUtilPrefix}}HashMap(); + + {{#queryParams}} + {{#isDeepObject}} + {{#collectionFormat}}localVarCollectionQueryParams.addAll(apiClient.parameterToPairs("{{{collectionFormat}}}", {{/collectionFormat}}{{^collectionFormat}}localVarQueryParams.addAll(apiClient.parameterToPair({{/collectionFormat}}"{{baseName}}", {{paramName}})); + {{/isDeepObject}} + {{^isDeepObject}} + {{#isExplode}} + {{#hasVars}} + {{#vars}} + {{#isArray}} + localVarQueryParams.addAll(apiClient.parameterToPairs("multi", "{{baseName}}", {{paramName}}.{{getter}}())); + {{/isArray}} + {{^isArray}} + localVarQueryParams.addAll(apiClient.parameterToPair("{{baseName}}", {{paramName}}.{{getter}}())); + {{/isArray}} + {{/vars}} + {{/hasVars}} + {{^hasVars}} + {{#collectionFormat}}localVarCollectionQueryParams.addAll(apiClient.parameterToPairs("{{{collectionFormat}}}", {{/collectionFormat}}{{^collectionFormat}}localVarQueryParams.addAll(apiClient.parameterToPair({{/collectionFormat}}"{{baseName}}", {{paramName}})); + {{/hasVars}} + {{/isExplode}} + {{^isExplode}} + {{#collectionFormat}}localVarCollectionQueryParams.addAll(apiClient.parameterToPairs("{{{collectionFormat}}}", {{/collectionFormat}}{{^collectionFormat}}localVarQueryParams.addAll(apiClient.parameterToPair({{/collectionFormat}}"{{baseName}}", {{paramName}})); + {{/isExplode}} + {{/isDeepObject}} + {{/queryParams}} + {{#headerParams}}if ({{paramName}} != null) + localVarHeaderParams.put("{{baseName}}", apiClient.parameterToString({{paramName}})); + {{/headerParams}} + + {{#cookieParams}}if ({{paramName}} != null) + localVarCookieParams.put("{{baseName}}", apiClient.parameterToString({{paramName}})); + {{/cookieParams}} + + {{#formParams}}if ({{paramName}} != null) + localVarFormParams.put("{{baseName}}", {{paramName}}); + {{/formParams}} + + final String[] localVarAccepts = { + {{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}} + }; + final String localVarAccept = apiClient.selectHeaderAccept(localVarAccepts); + + final String[] localVarContentTypes = { + {{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}} + }; + final String localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes); + + String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{^-last}}, {{/-last}}{{/authMethods}} }; + + {{#returnType}} + TypeReference<{{{returnType}}}> localVarReturnType = new TypeReference<{{{returnType}}}>() {}; + return apiClient.invokeAPI( + {{/returnType}} + {{^returnType}} + apiClient.invokeAPI( + {{/returnType}} + localVarPath, + "{{httpMethod}}", + localVarQueryParams, + localVarCollectionQueryParams, + localVarPostBody, + localVarHeaderParams, + localVarCookieParams, + localVarFormParams, + localVarAccept, + localVarContentType, + localVarAuthNames, + {{#returnType}}localVarReturnType{{/returnType}}{{^returnType}}null{{/returnType}} + ); + } + {{/operation}} +} +{{/operations}} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/apache-httpclient/api_test.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/apache-httpclient/api_test.mustache new file mode 100644 index 000000000..ca6173a61 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/apache-httpclient/api_test.mustache @@ -0,0 +1,54 @@ +{{>licenseInfo}} + +package {{package}}; + +import {{invokerPackage}}.ApiException; +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.Test; +import org.junit.Ignore; +import org.junit.Assert; + +import java.time.LocalDate; +import java.time.OffsetDateTime; +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +{{/fullJavaUtil}} +/** + * API tests for {{classname}} + */ +@Ignore +public class {{classname}}Test { + + private final {{classname}} api = new {{classname}}(); + + {{#operations}} + {{#operation}} + /** + {{#summary}} + * {{summary}} + * + {{/summary}} + {{#notes}} + * {{notes}} + * + {{/notes}} + * @throws ApiException + * if the Api call fails + */ + @Test + public void {{operationId}}Test() throws ApiException { + {{#allParams}} + {{{dataType}}} {{paramName}} = null; + {{/allParams}} + {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + + // TODO: test validations + } + {{/operation}} + {{/operations}} +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/apache-httpclient/build.gradle.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/apache-httpclient/build.gradle.mustache new file mode 100644 index 000000000..6c7379be3 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/apache-httpclient/build.gradle.mustache @@ -0,0 +1,146 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + mavenCentral() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.3.+' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' + } +} + +repositories { + mavenCentral() +} + +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 25 + buildToolsVersion '25.0.2' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 25 + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version" + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven-publish' + + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + + publishing { + publications { + maven(MavenPublication) { + artifactId = '{{artifactId}}' + + from components.java + } + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } + + task sourcesJar(type: Jar, dependsOn: classes) { + classifier = 'sources' + from sourceSets.main.allSource + } + + task javadocJar(type: Jar, dependsOn: javadoc) { + classifier = 'javadoc' + from javadoc.destinationDir + } + + artifacts { + archives sourcesJar + archives javadocJar + } +} + +ext { + swagger_annotations_version = "1.6.6" + jackson_version = "2.14.1" + jackson_databind_version = "2.14.1" + {{#openApiNullable}} + jackson_databind_nullable_version = "0.2.4" + {{/openApiNullable}} + jakarta_annotation_version = "1.3.5" + httpclient_version = "4.5.13" + jodatime_version = "2.9.9" + junit_version = "4.13.2" +} + +dependencies { + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation "org.apache.httpcomponents:httpclient:$httpclient_version" + implementation "org.apache.httpcomponents:httpmime:$httpclient_version" + implementation "com.fasterxml.jackson.core:jackson-core:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" + implementation "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" + {{#openApiNullable}} + implementation "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + {{/openApiNullable}} + {{#joda}} + implementation "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + {{/joda}} + implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + implementation "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version" + testImplementation "junit:junit:$junit_version" +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/apache-httpclient/pom.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/apache-httpclient/pom.mustache new file mode 100644 index 000000000..6e5abf83f --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/apache-httpclient/pom.mustache @@ -0,0 +1,352 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + {{artifactUrl}} + {{artifactDescription}} + + {{scmConnection}} + {{scmDeveloperConnection}} + {{scmUrl}} + +{{#parentOverridden}} + + {{{parentGroupId}}} + {{{parentArtifactId}}} + {{{parentVersion}}} + +{{/parentOverridden}} + + + + {{licenseName}} + {{licenseUrl}} + repo + + + + + + {{developerName}} + {{developerEmail}} + {{developerOrganization}} + {{developerOrganizationUrl}} + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.10.1 + + 1.8 + 1.8 + true + 128m + 512m + + -Xlint:all + -J-Xss4m + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.1.0 + + + enforce-maven + + enforce + + + + + 2.2.0 + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M7 + + + + loggerPath + conf/log4j.properties + + + -Xms512m -Xmx1500m + methods + 10 + pertest + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.3.0 + + + + test-jar + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.3.0 + + + add_sources + generate-sources + + add-source + + + + src/main/java + + + + + add_test_sources + generate-test-sources + + add-test-source + + + + src/test/java + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.4.1 + + none + 1.8 + + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.1 + + + attach-sources + + jar-no-fork + + + + + + + + + + sign-artifacts + + + + org.apache.maven.plugins + maven-gpg-plugin + 3.0.1 + + + sign-artifacts + verify + + sign + + + + + + + + + + + {{#swagger1AnnotationLibrary}} + + io.swagger + swagger-annotations + ${swagger-annotations-version} + + {{/swagger1AnnotationLibrary}} + + + + com.google.code.findbugs + jsr305 + 3.0.2 + + + + + + org.apache.httpcomponents + httpclient + ${httpclient-version} + + + org.apache.httpcomponents + httpmime + ${httpclient-version} + + + + + com.fasterxml.jackson.core + jackson-core + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-databind-version} + + + com.fasterxml.jackson.jaxrs + jackson-jaxrs-json-provider + ${jackson-version} + + {{#withXml}} + + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + ${jackson-version} + + + {{/withXml}} + {{#joda}} + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-version} + + {{/joda}} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + + {{#useBeanValidation}} + + + jakarta.validation + jakarta.validation-api + ${beanvalidation-version} + provided + + {{/useBeanValidation}} + {{#performBeanValidation}} + + + org.hibernate + hibernate-validator + 5.4.3.Final + + {{/performBeanValidation}} + {{#parcelableModel}} + + + com.google.android + android + 4.1.1.4 + provided + + {{/parcelableModel}} + {{#openApiNullable}} + + org.openapitools + jackson-databind-nullable + ${jackson-databind-nullable-version} + + {{/openApiNullable}} + + jakarta.annotation + jakarta.annotation-api + ${jakarta-annotation-version} + provided + + + + junit + junit + ${junit-version} + test + + + + UTF-8 + {{#swagger1AnnotationLibrary}} + 1.6.6 + {{/swagger1AnnotationLibrary}} + 4.5.13 + 2.14.1 + 2.14.1 + {{#openApiNullable}} + 0.2.4 + {{/openApiNullable}} + 1.3.5 + {{#useBeanValidation}} + 3.0.2 + {{/useBeanValidation}} + 4.13.2 + + diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/ApiClient.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/ApiClient.mustache index 47e993012..cc9599940 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/feign/ApiClient.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/ApiClient.mustache @@ -2,29 +2,21 @@ package {{invokerPackage}}; import java.util.LinkedHashMap; import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; -{{#hasOAuthMethods}} -import org.apache.oltu.oauth2.client.request.OAuthClientRequest.AuthenticationRequestBuilder; -import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder; -{{/hasOAuthMethods}} - -{{#threetenbp}} -import org.threeten.bp.*; -{{/threetenbp}} +import feign.okhttp.OkHttpClient; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; +{{#openApiNullable}} import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} {{#joda}} import com.fasterxml.jackson.datatype.joda.JodaModule; {{/joda}} -{{#java8}} import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -{{/java8}} -{{#threetenbp}} -import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule; -{{/threetenbp}} import feign.Feign; import feign.RequestInterceptor; @@ -32,13 +24,25 @@ import feign.form.FormEncoder; import feign.jackson.JacksonDecoder; import feign.jackson.JacksonEncoder; import feign.slf4j.Slf4jLogger; -import {{invokerPackage}}.auth.*; +import {{invokerPackage}}.auth.HttpBasicAuth; +import {{invokerPackage}}.auth.HttpBearerAuth; +import {{invokerPackage}}.auth.ApiKeyAuth; +import {{invokerPackage}}.ApiResponseDecoder; + {{#hasOAuthMethods}} +import {{invokerPackage}}.auth.ApiErrorDecoder; +import {{invokerPackage}}.auth.OAuth; import {{invokerPackage}}.auth.OAuth.AccessTokenListener; +import {{invokerPackage}}.auth.OAuthFlow; +import {{invokerPackage}}.auth.OauthPasswordGrant; +import {{invokerPackage}}.auth.OauthClientCredentialsGrant; +import feign.Retryer; {{/hasOAuthMethods}} {{>generatedAnnotation}} public class ApiClient { + private static final Logger log = Logger.getLogger(ApiClient.class.getName()); + public interface Api {} protected ObjectMapper objectMapper; @@ -50,14 +54,20 @@ public class ApiClient { objectMapper = createObjectMapper(); apiAuthorizations = new LinkedHashMap(); feignBuilder = Feign.builder() + .client(new OkHttpClient()) .encoder(new FormEncoder(new JacksonEncoder(objectMapper))) - .decoder(new JacksonDecoder(objectMapper)) + .decoder(new ApiResponseDecoder(objectMapper)) + {{#hasOAuthMethods}} + .errorDecoder(new ApiErrorDecoder()) + .retryer(new Retryer.Default(0, 0, 2)) + {{/hasOAuthMethods}} .logger(new Slf4jLogger()); } public ApiClient(String[] authNames) { this(); for(String authName : authNames) { + log.log(Level.FINE, "Creating authentication {0}", authName); {{#hasAuthMethods}} RequestInterceptor auth; {{#authMethods}}if ("{{name}}".equals(authName)) { @@ -73,7 +83,7 @@ public class ApiClient { auth = new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"); {{/isApiKey}} {{#isOAuth}} - auth = new OAuth(OAuthFlow.{{flow}}, "{{authorizationUrl}}", "{{tokenUrl}}", "{{#scopes}}{{scope}}{{#hasMore}}, {{/hasMore}}{{/scopes}}"); + auth = buildOauthRequestInterceptor(OAuthFlow.{{#lambda.uppercase}}{{#lambda.snakecase}}{{flow}}{{/lambda.snakecase}}{{/lambda.uppercase}}, "{{{authorizationUrl}}}", "{{{tokenUrl}}}", "{{#scopes}}{{scope}}{{^-last}}, {{/-last}}{{/scopes}}"); {{/isOAuth}} } else {{/authMethods}}{ throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names"); @@ -104,36 +114,6 @@ public class ApiClient { this.setApiKey(apiKey); } - /** - * Helper constructor for single basic auth or password oauth2 - * @param authName - * @param username - * @param password - */ - public ApiClient(String authName, String username, String password) { - this(authName); - this.setCredentials(username, password); - } - - {{#hasOAuthMethods}} - /** - * Helper constructor for single password oauth2 - * @param authName - * @param clientId - * @param secret - * @param username - * @param password - */ - public ApiClient(String authName, String clientId, String secret, String username, String password) { - this(authName); - this.getTokenEndPoint() - .setClientId(clientId) - .setClientSecret(secret) - .setUsername(username) - .setPassword(password); - } - - {{/hasOAuthMethods}} public String getBasePath() { return basePath; } @@ -171,25 +151,35 @@ public class ApiClient { {{#joda}} objectMapper.registerModule(new JodaModule()); {{/joda}} - {{#java8}} objectMapper.registerModule(new JavaTimeModule()); - {{/java8}} - {{#threetenbp}} - ThreeTenModule module = new ThreeTenModule(); - module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT); - module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME); - module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); - objectMapper.registerModule(module); - {{/threetenbp}} + {{#openApiNullable}} JsonNullableModule jnm = new JsonNullableModule(); objectMapper.registerModule(jnm); + {{/openApiNullable}} return objectMapper; } + {{#hasOAuthMethods}} + private RequestInterceptor buildOauthRequestInterceptor(OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) { + switch (flow) { + case PASSWORD: + return new OauthPasswordGrant(tokenUrl, scopes); + case APPLICATION: + return new OauthClientCredentialsGrant(authorizationUrl, tokenUrl, scopes); + default: + throw new RuntimeException("Oauth flow \"" + flow + "\" is not implemented"); + } + } + + {{/hasOAuthMethods}} public ObjectMapper getObjectMapper(){ return objectMapper; } + public void setObjectMapper(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + /** * Creates a feign client for given API interface. * @@ -236,19 +226,13 @@ public class ApiClient { return contentTypes[0]; } - /** * Helper method to configure the bearer token. * @param bearerToken the bearer token. */ public void setBearerToken(String bearerToken) { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof HttpBearerAuth) { - ((HttpBearerAuth) apiAuthorization).setBearerToken(bearerToken); - return; - } - } - throw new RuntimeException("No Bearer authentication configured!"); + HttpBearerAuth apiAuthorization = getAuthorization(HttpBearerAuth.class); + apiAuthorization.setBearerToken(bearerToken); } /** @@ -256,66 +240,41 @@ public class ApiClient { * @param apiKey API key */ public void setApiKey(String apiKey) { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof ApiKeyAuth) { - ApiKeyAuth keyAuth = (ApiKeyAuth) apiAuthorization; - keyAuth.setApiKey(apiKey); - return ; - } - } - throw new RuntimeException("No API key authentication configured!"); + ApiKeyAuth apiAuthorization = getAuthorization(ApiKeyAuth.class); + apiAuthorization.setApiKey(apiKey); } /** - * Helper method to configure the username/password for basic auth or password OAuth + * Helper method to configure the username/password for basic auth * @param username Username * @param password Password */ public void setCredentials(String username, String password) { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof HttpBasicAuth) { - HttpBasicAuth basicAuth = (HttpBasicAuth) apiAuthorization; - basicAuth.setCredentials(username, password); - return; - } - {{#hasOAuthMethods}} - if (apiAuthorization instanceof OAuth) { - OAuth oauth = (OAuth) apiAuthorization; - oauth.getTokenRequestBuilder().setUsername(username).setPassword(password); - return; - } - {{/hasOAuthMethods}} - } - throw new RuntimeException("No Basic authentication or OAuth configured!"); + HttpBasicAuth apiAuthorization = getAuthorization(HttpBasicAuth.class); + apiAuthorization.setCredentials(username, password); } {{#hasOAuthMethods}} /** - * Helper method to configure the token endpoint of the first oauth found in the apiAuthorizations (there should be only one) - * @return Token request builder + * Helper method to configure the client credentials for Oauth + * @param clientId Client ID + * @param clientSecret Client secret */ - public TokenRequestBuilder getTokenEndPoint() { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof OAuth) { - OAuth oauth = (OAuth) apiAuthorization; - return oauth.getTokenRequestBuilder(); - } - } - return null; + public void setClientCredentials(String clientId, String clientSecret) { + OauthClientCredentialsGrant authorization = getAuthorization(OauthClientCredentialsGrant.class); + authorization.configure(clientId, clientSecret); } /** - * Helper method to configure authorization endpoint of the first oauth found in the apiAuthorizations (there should be only one) - * @return Authentication request builder + * Helper method to configure the username/password for Oauth password grant + * @param username Username + * @param password Password + * @param clientId Client ID + * @param clientSecret Client secret */ - public AuthenticationRequestBuilder getAuthorizationEndPoint() { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof OAuth) { - OAuth oauth = (OAuth) apiAuthorization; - return oauth.getAuthenticationRequestBuilder(); - } - } - return null; + public void setOauthPassword(String username, String password, String clientId, String clientSecret) { + OauthPasswordGrant apiAuthorization = getAuthorization(OauthPasswordGrant.class); + apiAuthorization.configure(username, password, clientId, clientSecret); } /** @@ -323,14 +282,9 @@ public class ApiClient { * @param accessToken Access Token * @param expiresIn Validity period in seconds */ - public void setAccessToken(String accessToken, Long expiresIn) { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof OAuth) { - OAuth oauth = (OAuth) apiAuthorization; - oauth.setAccessToken(accessToken, expiresIn); - return; - } - } + public void setAccessToken(String accessToken, Integer expiresIn) { + OAuth apiAuthorization = getAuthorization(OAuth.class); + apiAuthorization.setAccessToken(accessToken, expiresIn); } /** @@ -340,39 +294,22 @@ public class ApiClient { * @param redirectURI Redirect URI */ public void configureAuthorizationFlow(String clientId, String clientSecret, String redirectURI) { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof OAuth) { - OAuth oauth = (OAuth) apiAuthorization; - oauth.getTokenRequestBuilder() - .setClientId(clientId) - .setClientSecret(clientSecret) - .setRedirectURI(redirectURI); - oauth.getAuthenticationRequestBuilder() - .setClientId(clientId) - .setRedirectURI(redirectURI); - return; - } - } + throw new RuntimeException("Not implemented"); } /** * Configures a listener which is notified when a new access token is received. - * @param accessTokenListener Acesss token listener + * @param accessTokenListener Access token listener */ public void registerAccessTokenListener(AccessTokenListener accessTokenListener) { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof OAuth) { - OAuth oauth = (OAuth) apiAuthorization; - oauth.registerAccessTokenListener(accessTokenListener); - return; - } - } + OAuth apiAuthorization = getAuthorization(OAuth.class); + apiAuthorization.registerAccessTokenListener(accessTokenListener); } {{/hasOAuthMethods}} /** * Gets request interceptor based on authentication name - * @param authName Authentiation name + * @param authName Authentication name * @return Request Interceptor */ public RequestInterceptor getAuthorization(String authName) { @@ -392,4 +329,11 @@ public class ApiClient { feignBuilder.requestInterceptor(authorization); } + private T getAuthorization(Class type) { + return (T) apiAuthorizations.values() + .stream() + .filter(requestInterceptor -> type.isAssignableFrom(requestInterceptor.getClass())) + .findFirst() + .orElseThrow(() -> new RuntimeException("No Oauth authentication or OAuth configured!")); + } } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/ApiResponseDecoder.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/ApiResponseDecoder.mustache new file mode 100644 index 000000000..2ff7a3243 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/ApiResponseDecoder.mustache @@ -0,0 +1,38 @@ +package {{invokerPackage}}; + +import com.fasterxml.jackson.databind.ObjectMapper; +import feign.Response; +import feign.Types; +import feign.jackson.JacksonDecoder; + +import java.io.IOException; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; + +import {{modelPackage}}.ApiResponse; + +public class ApiResponseDecoder extends JacksonDecoder { + + public ApiResponseDecoder(ObjectMapper mapper) { + super(mapper); + } + + @Override + public Object decode(Response response, Type type) throws IOException { + Map> responseHeaders = Collections.unmodifiableMap(response.headers()); + //Detects if the type is an instance of the parameterized class ApiResponse + Type responseBodyType; + if (type instanceof ParameterizedType && Types.getRawType(type).isAssignableFrom(ApiResponse.class)) { + //The ApiResponse class has a single type parameter, the Dto class itself + responseBodyType = ((ParameterizedType) type).getActualTypeArguments()[0]; + Object body = super.decode(response, responseBodyType); + return new ApiResponse(response.status(), responseHeaders, body); + } else { + //The response is not encapsulated in the ApiResponse, decode the Dto as normal + return super.decode(response, type); + } + } +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/README.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/README.mustache index 56560172e..fed3cbebd 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/feign/README.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/README.mustache @@ -32,12 +32,46 @@ After the client library is installed/deployed, you can use it in your Maven pro ``` +And to use the api you can follow the examples bellow: + +```java + + //Set bearer token manually + ApiClient apiClient = new ApiClient("petstore_auth_client"); + apiClient.setBasePath("https://localhost:8243/petstore/1/"); + apiClient.setAccessToken("TOKEN", 10000); + + //Use api key + ApiClient apiClient = new ApiClient("api_key", "API KEY"); + apiClient.setBasePath("https://localhost:8243/petstore/1/"); + + //Use http basic authentication + ApiClient apiClient = new ApiClient("basicAuth"); + apiClient.setBasePath("https://localhost:8243/petstore/1/"); + apiClient.setCredentials("username", "password"); + + //Oauth password + ApiClient apiClient = new ApiClient("oauth_password"); + apiClient.setBasePath("https://localhost:8243/petstore/1/"); + apiClient.setOauthPassword("username", "password", "client_id", "client_secret"); + + //Oauth client credentials flow + ApiClient apiClient = new ApiClient("oauth_client_credentials"); + apiClient.setBasePath("https://localhost:8243/petstore/1/"); + apiClient.setClientCredentials("client_id", "client_secret"); + + PetApi petApi = apiClient.buildClient(PetApi.class); + Pet petById = petApi.getPetById(12345L); + + System.out.println(petById); + } +``` + ## Recommendation It's recommended to create an instance of `ApiClient` per thread in a multithreaded environment to avoid any potential issues. ## Author -{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}} -{{/hasMore}}{{/apis}}{{/apiInfo}} - +{{#apiInfo}}{{#apis}}{{#-last}}{{infoEmail}} +{{/-last}}{{/apis}}{{/apiInfo}} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/api.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/api.mustache index cff48fcd2..d7789e6fe 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/feign/api.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/api.mustache @@ -5,6 +5,7 @@ import {{invokerPackage}}.EncodingUtils; {{#legacyDates}} import {{invokerPackage}}.ParamExpander; {{/legacyDates}} +import {{modelPackage}}.ApiResponse; {{#imports}}import {{import}}; {{/imports}} @@ -28,23 +29,60 @@ public interface {{classname}} extends ApiClient.Api { * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}} {{/allParams}} {{#returnType}} - * @return {{returnType}} + * @return {{.}} {{/returnType}} {{#externalDocs}} - * {{description}} - * @see {{summary}} Documentation + * {{description}} + * @see {{summary}} Documentation {{/externalDocs}} +{{#isDeprecated}} + * @deprecated +{{/isDeprecated}} */ - @RequestLine("{{httpMethod}} {{{path}}}{{#hasQueryParams}}?{{/hasQueryParams}}{{#queryParams}}{{baseName}}={{=<% %>=}}{<%paramName%>}<%={{ }}=%>{{#hasMore}}&{{/hasMore}}{{/queryParams}}") +{{#isDeprecated}} + @Deprecated +{{/isDeprecated}} + @RequestLine("{{httpMethod}} {{{path}}}{{#hasQueryParams}}?{{/hasQueryParams}}{{#queryParams}}{{baseName}}={{=<% %>=}}{<%paramName%>}<%={{ }}=%>{{^-last}}&{{/-last}}{{/queryParams}}") @Headers({ -{{#vendorExtensions.x-contentType}} "Content-Type: {{vendorExtensions.x-contentType}}", -{{/vendorExtensions.x-contentType}} "Accept: {{vendorExtensions.x-accepts}}",{{#headerParams}} - "{{baseName}}: {{=<% %>=}}{<%paramName%>}<%={{ }}=%>"{{#hasMore}}, - {{/hasMore}}{{/headerParams}} +{{#vendorExtensions.x-content-type}} "Content-Type: {{vendorExtensions.x-content-type}}", +{{/vendorExtensions.x-content-type}} "Accept: {{vendorExtensions.x-accepts}}",{{#headerParams}} + "{{baseName}}: {{=<% %>=}}{<%paramName%>}<%={{ }}=%>"{{^-last}}, + {{/-last}}{{/headerParams}} }) - {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isBodyParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{baseName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isBodyParam}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); - {{#hasQueryParams}} + {{#returnType}}{{{.}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isBodyParam}}{{^isFormParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{paramName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isFormParam}}{{#isFormParam}}@Param("{{baseName}}") {{/isFormParam}}{{/isBodyParam}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + /** + * {{summary}} + * Similar to {{operationId}} but it also returns the http response headers . + * {{notes}} +{{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}} +{{/allParams}} +{{#returnType}} + * @return A ApiResponse that wraps the response boyd and the http headers. +{{/returnType}} +{{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation +{{/externalDocs}} +{{#isDeprecated}} + * @deprecated +{{/isDeprecated}} + */ +{{#isDeprecated}} + @Deprecated +{{/isDeprecated}} + @RequestLine("{{httpMethod}} {{{path}}}{{#hasQueryParams}}?{{/hasQueryParams}}{{#queryParams}}{{baseName}}={{=<% %>=}}{<%paramName%>}<%={{ }}=%>{{^-last}}&{{/-last}}{{/queryParams}}") + @Headers({ +{{#vendorExtensions.x-content-type}} "Content-Type: {{vendorExtensions.x-content-type}}", +{{/vendorExtensions.x-content-type}} "Accept: {{vendorExtensions.x-accepts}}",{{#headerParams}} + "{{baseName}}: {{=<% %>=}}{<%paramName%>}<%={{ }}=%>"{{^-last}}, + {{/-last}}{{/headerParams}} + }) + ApiResponse<{{#returnType}}{{{.}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{nickname}}WithHttpInfo({{#allParams}}{{^isBodyParam}}{{^isFormParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{paramName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isFormParam}}{{#isFormParam}}@Param("{{baseName}}") {{/isFormParam}}{{/isBodyParam}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + + + {{#hasQueryParams}} /** * {{summary}} * {{notes}} @@ -66,23 +104,70 @@ public interface {{classname}} extends ApiClient.Api { {{/queryParams}} * {{#returnType}} - * @return {{returnType}} + * @return {{.}} {{/returnType}} {{#externalDocs}} * {{description}} * @see {{summary}} Documentation {{/externalDocs}} + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} */ - @RequestLine("{{httpMethod}} {{{path}}}?{{#queryParams}}{{baseName}}={{=<% %>=}}{<%paramName%>}<%={{ }}=%>{{#hasMore}}&{{/hasMore}}{{/queryParams}}") + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + @RequestLine("{{httpMethod}} {{{path}}}?{{#queryParams}}{{baseName}}={{=<% %>=}}{<%paramName%>}<%={{ }}=%>{{^-last}}&{{/-last}}{{/queryParams}}") @Headers({ -{{#vendorExtensions.x-contentType}} "Content-Type: {{vendorExtensions.x-contentType}}", -{{/vendorExtensions.x-contentType}} "Accept: {{vendorExtensions.x-accepts}}",{{#headerParams}} - "{{baseName}}: {{=<% %>=}}{<%paramName%>}<%={{ }}=%>"{{#hasMore}}, - {{/hasMore}}{{/headerParams}} +{{#vendorExtensions.x-content-type}} "Content-Type: {{vendorExtensions.x-content-type}}", +{{/vendorExtensions.x-content-type}} "Accept: {{vendorExtensions.x-accepts}}",{{#headerParams}} + "{{baseName}}: {{=<% %>=}}{<%paramName%>}<%={{ }}=%>"{{^-last}}, + {{/-last}}{{/headerParams}} }) - {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isQueryParam}}{{^isBodyParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{baseName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isBodyParam}}{{{dataType}}} {{paramName}}, {{/isQueryParam}}{{/allParams}}@QueryMap(encoded=true) Map queryParams); + {{#returnType}}{{{.}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isQueryParam}}{{^isBodyParam}}{{^isFormParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{paramName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isFormParam}}{{#isFormParam}}@Param("{{baseName}}") {{/isFormParam}}{{/isBodyParam}}{{{dataType}}} {{paramName}}, {{/isQueryParam}}{{/allParams}}@QueryMap(encoded=true) Map queryParams); /** + * {{summary}} + * {{notes}} + * Note, this is equivalent to the other {{operationId}} that receives the query parameters as a map, + * but this one also exposes the Http response headers + {{#allParams}} + {{^isQueryParam}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}} + {{/isQueryParam}} + {{/allParams}} + * @param queryParams Map of query parameters as name-value pairs + *

The following elements may be specified in the query map:

+ *
    + {{#queryParams}} + *
  • {{paramName}} - {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}}
  • + {{/queryParams}} + *
+ {{#returnType}} + * @return {{.}} + {{/returnType}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + @RequestLine("{{httpMethod}} {{{path}}}?{{#queryParams}}{{baseName}}={{=<% %>=}}{<%paramName%>}<%={{ }}=%>{{^-last}}&{{/-last}}{{/queryParams}}") + @Headers({ + {{#vendorExtensions.x-content-type}} "Content-Type: {{vendorExtensions.x-content-type}}", + {{/vendorExtensions.x-content-type}} "Accept: {{vendorExtensions.x-accepts}}",{{#headerParams}} + "{{baseName}}: {{=<% %>=}}{<%paramName%>}<%={{ }}=%>"{{^-last}}, + {{/-last}}{{/headerParams}} + }) + ApiResponse<{{#returnType}}{{{.}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{nickname}}WithHttpInfo({{#allParams}}{{^isQueryParam}}{{^isBodyParam}}{{^isFormParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{paramName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isFormParam}}{{#isFormParam}}@Param("{{baseName}}") {{/isFormParam}}{{/isBodyParam}}{{{dataType}}} {{paramName}}, {{/isQueryParam}}{{/allParams}}@QueryMap(encoded=true) Map queryParams); + + + /** * A convenience class for generating query parameters for the * {{operationId}} method in a fluent style. */ diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/api_test.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/api_test.mustache index bcc14a987..c579a5c9d 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/feign/api_test.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/api_test.mustache @@ -3,9 +3,11 @@ package {{package}}; import {{invokerPackage}}.ApiClient; {{#imports}}import {{import}}; {{/imports}} -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeEach; +import java.time.LocalDate; +import java.time.OffsetDateTime; {{^fullJavaUtil}} import java.util.ArrayList; import java.util.HashMap; @@ -16,11 +18,11 @@ import java.util.Map; /** * API tests for {{classname}} */ -public class {{classname}}Test { +class {{classname}}Test { private {{classname}} api; - @Before + @BeforeEach public void setup() { api = new ApiClient().buildClient({{classname}}.class); } @@ -32,11 +34,11 @@ public class {{classname}}Test { * {{notes}} */ @Test - public void {{operationId}}Test() { + void {{operationId}}Test() { {{#allParams}} {{{dataType}}} {{paramName}} = null; {{/allParams}} - // {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + // {{#returnType}}{{{.}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); // TODO: test validations } @@ -51,7 +53,7 @@ public class {{classname}}Test { * listing them out individually. */ @Test - public void {{operationId}}TestQueryMap() { + void {{operationId}}TestQueryMap() { {{#allParams}} {{^isQueryParam}} {{{dataType}}} {{paramName}} = null; @@ -59,9 +61,9 @@ public class {{classname}}Test { {{/allParams}} {{classname}}.{{operationIdCamelCase}}QueryParams queryParams = new {{classname}}.{{operationIdCamelCase}}QueryParams() {{#queryParams}} - .{{paramName}}(null){{^hasMore}};{{/hasMore}} + .{{paramName}}(null){{#-last}};{{/-last}} {{/queryParams}} - // {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{^isQueryParam}}{{paramName}}, {{/isQueryParam}}{{/allParams}}queryParams); + // {{#returnType}}{{{.}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{^isQueryParam}}{{paramName}}, {{/isQueryParam}}{{/allParams}}queryParams); // TODO: test validations } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/ApiErrorDecoder.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/ApiErrorDecoder.mustache new file mode 100644 index 000000000..da87f2563 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/ApiErrorDecoder.mustache @@ -0,0 +1,25 @@ +package {{invokerPackage}}.auth; + +import feign.Response; +import feign.RetryableException; +import feign.codec.ErrorDecoder; + +/** + * Error decoder that makes the HTTP 401 and 403 Retryable. Sometimes the 401 or 403 may indicate an expired token + * All the other HTTP status are handled by the {@link feign.codec.ErrorDecoder.Default} decoder + */ +public class ApiErrorDecoder implements ErrorDecoder { + + private final Default defaultErrorDecoder = new Default(); + + @Override + public Exception decode(String methodKey, Response response) { + //401/403 response codes most likely indicate an expired access token, unless it happens two times in a row + Exception httpException = defaultErrorDecoder.decode(methodKey, response); + if (response.status() == 401 || response.status() == 403) { + return new RetryableException(response.status(), "Received status " + response.status() + " trying to renew access token", + response.request().httpMethod(), httpException, null, response.request()); + } + return httpException; + } +} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/DefaultApi20Impl.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/DefaultApi20Impl.mustache new file mode 100644 index 000000000..72b0a0049 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/DefaultApi20Impl.mustache @@ -0,0 +1,47 @@ +package {{invokerPackage}}.auth; + +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.extractors.OAuth2AccessTokenJsonExtractor; +import com.github.scribejava.core.extractors.TokenExtractor; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignature; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignatureURIQueryParameter; +import com.github.scribejava.core.oauth2.clientauthentication.ClientAuthentication; +import com.github.scribejava.core.oauth2.clientauthentication.RequestBodyAuthenticationScheme; + +{{>generatedAnnotation}} +public class DefaultApi20Impl extends DefaultApi20 { + + private final String accessTokenEndpoint; + private final String authorizationBaseUrl; + + protected DefaultApi20Impl(String authorizationBaseUrl, String accessTokenEndpoint) { + this.authorizationBaseUrl = authorizationBaseUrl; + this.accessTokenEndpoint = accessTokenEndpoint; + } + + @Override + public String getAccessTokenEndpoint() { + return accessTokenEndpoint; + } + + @Override + protected String getAuthorizationBaseUrl() { + return authorizationBaseUrl; + } + + @Override + public BearerSignature getBearerSignature() { + return BearerSignatureURIQueryParameter.instance(); + } + + @Override + public ClientAuthentication getClientAuthentication() { + return RequestBodyAuthenticationScheme.instance(); + } + + @Override + public TokenExtractor getAccessTokenExtractor() { + return OAuth2AccessTokenJsonExtractor.instance(); + } +} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/HttpBasicAuth.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/HttpBasicAuth.mustache index 2b1acb8ff..c308131e8 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/HttpBasicAuth.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/HttpBasicAuth.mustache @@ -11,7 +11,7 @@ public class HttpBasicAuth implements RequestInterceptor { private String username; private String password; - + public String getUsername() { return username; } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/OAuth.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/OAuth.mustache index feefdb939..5416da238 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/OAuth.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/OAuth.mustache @@ -1,205 +1,96 @@ package {{invokerPackage}}.auth; -import java.io.IOException; -import java.util.Collection; -import java.util.Map; -import java.util.Map.Entry; - -import org.apache.oltu.oauth2.client.HttpClient; -import org.apache.oltu.oauth2.client.OAuthClient; -import org.apache.oltu.oauth2.client.request.OAuthClientRequest; -import org.apache.oltu.oauth2.client.request.OAuthClientRequest.AuthenticationRequestBuilder; -import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder; -import org.apache.oltu.oauth2.client.response.OAuthClientResponse; -import org.apache.oltu.oauth2.client.response.OAuthClientResponseFactory; -import org.apache.oltu.oauth2.client.response.OAuthJSONAccessTokenResponse; -import org.apache.oltu.oauth2.common.exception.OAuthProblemException; -import org.apache.oltu.oauth2.common.exception.OAuthSystemException; -import org.apache.oltu.oauth2.common.message.types.GrantType; -import org.apache.oltu.oauth2.common.token.BasicOAuthToken; - -import feign.Client; -{{#useFeign10}} -import feign.Request.HttpMethod; -{{/useFeign10}} -import feign.Request.Options; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.oauth.OAuth20Service; import feign.RequestInterceptor; import feign.RequestTemplate; -import feign.Response; -import feign.RetryableException; -import feign.Util; -import {{invokerPackage}}.StringUtil; - - -public class OAuth implements RequestInterceptor { - static final int MILLIS_PER_SECOND = 1000; - - public interface AccessTokenListener { - void notify(BasicOAuthToken token); - } +import java.util.Collection; - private volatile String accessToken; - private Long expirationTimeMillis; - private OAuthClient oauthClient; - private TokenRequestBuilder tokenRequestBuilder; - private AuthenticationRequestBuilder authenticationRequestBuilder; - private AccessTokenListener accessTokenListener; +{{>generatedAnnotation}} +public abstract class OAuth implements RequestInterceptor { - public OAuth(Client client, TokenRequestBuilder requestBuilder) { - this.oauthClient = new OAuthClient(new OAuthFeignClient(client)); - this.tokenRequestBuilder = requestBuilder; - } + //https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.4 + static final int LEEWAY_SECONDS = 10; - public OAuth(Client client, OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) { - this(client, OAuthClientRequest.tokenLocation(tokenUrl).setScope(scopes)); - - switch(flow) { - case accessCode: - case implicit: - tokenRequestBuilder.setGrantType(GrantType.AUTHORIZATION_CODE); - break; - case password: - tokenRequestBuilder.setGrantType(GrantType.PASSWORD); - break; - case application: - tokenRequestBuilder.setGrantType(GrantType.CLIENT_CREDENTIALS); - break; - default: - break; - } - authenticationRequestBuilder = OAuthClientRequest.authorizationLocation(authorizationUrl); - } + static final int MILLIS_PER_SECOND = 1000; - public OAuth(OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) { - this(new Client.Default(null, null), flow, authorizationUrl, tokenUrl, scopes); - } + public interface AccessTokenListener { + void notify(OAuth2AccessToken token); + } - @Override - public void apply(RequestTemplate template) { - // If the request already have an authorization (eg. Basic auth), do nothing - if (template.headers().containsKey("Authorization")) { - return; - } - // If first time, get the token - if (expirationTimeMillis == null || System.currentTimeMillis() >= expirationTimeMillis) { - updateAccessToken(template); - } - if (getAccessToken() != null) { - template.header("Authorization", "Bearer " + getAccessToken()); - } - } + private volatile String accessToken; + private Long expirationTimeSeconds; + private AccessTokenListener accessTokenListener; - public synchronized void updateAccessToken(RequestTemplate template) { - OAuthJSONAccessTokenResponse accessTokenResponse; - try { - accessTokenResponse = oauthClient.accessToken(tokenRequestBuilder.buildBodyMessage()); - } catch (Exception e) { - {{#useFeign10}} - throw new RetryableException(0, e.getMessage(), HttpMethod.POST, e, null, template.request()); - {{/useFeign10}} - {{^useFeign10}} - throw new RetryableException(e.getMessage(), e,null); - {{/useFeign10}} - } - if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) { - setAccessToken(accessTokenResponse.getAccessToken(), accessTokenResponse.getExpiresIn()); - if (accessTokenListener != null) { - accessTokenListener.notify((BasicOAuthToken) accessTokenResponse.getOAuthToken()); - } - } - } + protected OAuth20Service service; + protected String scopes; + protected String authorizationUrl; + protected String tokenUrl; - public synchronized void registerAccessTokenListener(AccessTokenListener accessTokenListener) { - this.accessTokenListener = accessTokenListener; - } + public OAuth(String authorizationUrl, String tokenUrl, String scopes) { + this.scopes = scopes; + this.authorizationUrl = authorizationUrl; + this.tokenUrl = tokenUrl; + } - public synchronized String getAccessToken() { - return accessToken; + @Override + public void apply(RequestTemplate template) { + // If the request already have an authorization (eg. Basic auth), do nothing + if (requestContainsNonOauthAuthorization(template)) { + return; } - - public synchronized void setAccessToken(String accessToken, Long expiresIn) { - this.accessToken = accessToken; - this.expirationTimeMillis = expiresIn == null ? null : System.currentTimeMillis() + expiresIn * MILLIS_PER_SECOND; + String accessToken = getAccessToken(); + if (accessToken != null) { + template.removeHeader("Authorization"); + template.header("Authorization", "Bearer " + accessToken); } + } - public TokenRequestBuilder getTokenRequestBuilder() { - return tokenRequestBuilder; + private boolean requestContainsNonOauthAuthorization(RequestTemplate template) { + Collection authorizations = template.headers().get("Authorization"); + if (authorizations == null) { + return false; } + return !authorizations.stream() + .anyMatch(authHeader -> !authHeader.equalsIgnoreCase("Bearer")); + } - public void setTokenRequestBuilder(TokenRequestBuilder tokenRequestBuilder) { - this.tokenRequestBuilder = tokenRequestBuilder; + private synchronized void updateAccessToken() { + OAuth2AccessToken accessTokenResponse; + accessTokenResponse = getOAuth2AccessToken(); + if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) { + setAccessToken(accessTokenResponse.getAccessToken(), accessTokenResponse.getExpiresIn()); + if (accessTokenListener != null) { + accessTokenListener.notify(accessTokenResponse); + } } + } - public AuthenticationRequestBuilder getAuthenticationRequestBuilder() { - return authenticationRequestBuilder; - } + abstract OAuth2AccessToken getOAuth2AccessToken(); - public void setAuthenticationRequestBuilder(AuthenticationRequestBuilder authenticationRequestBuilder) { - this.authenticationRequestBuilder = authenticationRequestBuilder; - } + abstract OAuthFlow getFlow(); - public OAuthClient getOauthClient() { - return oauthClient; - } + public synchronized void registerAccessTokenListener(AccessTokenListener accessTokenListener) { + this.accessTokenListener = accessTokenListener; + } - public void setOauthClient(OAuthClient oauthClient) { - this.oauthClient = oauthClient; + public synchronized String getAccessToken() { + // If first time, get the token + if (expirationTimeSeconds == null || System.currentTimeMillis() >= expirationTimeSeconds * MILLIS_PER_SECOND) { + updateAccessToken(); } + return accessToken; + } - public void setOauthClient(Client client) { - this.oauthClient = new OAuthClient( new OAuthFeignClient(client)); - } + /** + * Manually sets the access token + * @param accessToken The access token + * @param expiresIn Seconds until the token expires + */ + public synchronized void setAccessToken(String accessToken, Integer expiresIn) { + this.accessToken = accessToken; + this.expirationTimeSeconds = expiresIn == null ? null : System.currentTimeMillis() / MILLIS_PER_SECOND + expiresIn - LEEWAY_SECONDS; + } - public static class OAuthFeignClient implements HttpClient { - - private Client client; - - public OAuthFeignClient() { - this.client = new Client.Default(null, null); - } - - public OAuthFeignClient(Client client) { - this.client = client; - } - - public T execute(OAuthClientRequest request, Map headers, - String requestMethod, Class responseClass) - throws OAuthSystemException, OAuthProblemException { - - RequestTemplate req = new RequestTemplate() - .append(request.getLocationUri()) - .method(requestMethod) - .body(request.getBody()); - - for (Entry entry : headers.entrySet()) { - req.header(entry.getKey(), entry.getValue()); - } - Response feignResponse; - String body = ""; - try { - feignResponse = client.execute(req.request(), new Options()); - body = Util.toString(feignResponse.body().asReader()); - } catch (IOException e) { - throw new OAuthSystemException(e); - } - - String contentType = null; - Collection contentTypeHeader = feignResponse.headers().get("Content-Type"); - if(contentTypeHeader != null) { - contentType = StringUtil.join(contentTypeHeader.toArray(new String[0]), ";"); - } - - return OAuthClientResponseFactory.createCustomResponse( - body, - contentType, - feignResponse.status(), - responseClass - ); - } - - public void shutdown() { - // Nothing to do here - } - } } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/OauthClientCredentialsGrant.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/OauthClientCredentialsGrant.mustache new file mode 100644 index 000000000..2180273d0 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/OauthClientCredentialsGrant.mustache @@ -0,0 +1,39 @@ +package {{invokerPackage}}.auth; + +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; + +{{>generatedAnnotation}} +public class OauthClientCredentialsGrant extends OAuth { + + public OauthClientCredentialsGrant(String authorizationUrl, String tokenUrl, String scopes) { + super(authorizationUrl, tokenUrl, scopes); + } + + @Override + protected OAuth2AccessToken getOAuth2AccessToken() { + try { + return service.getAccessTokenClientCredentialsGrant(scopes); + } catch (Exception e) { + throw new RuntimeException("Failed to get oauth token", e); + } + } + + @Override + protected OAuthFlow getFlow() { + return OAuthFlow.APPLICATION; + } + + /** + * Configures the client credentials flow + * + * @param clientId + * @param clientSecret + */ + public void configure(String clientId, String clientSecret) { + service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .defaultScope(scopes) + .build(new DefaultApi20Impl(authorizationUrl, tokenUrl)); + } +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/OauthPasswordGrant.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/OauthPasswordGrant.mustache new file mode 100644 index 000000000..522afa08e --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/auth/OauthPasswordGrant.mustache @@ -0,0 +1,48 @@ +package {{invokerPackage}}.auth; + +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; + +{{>generatedAnnotation}} +public class OauthPasswordGrant extends OAuth { + + private String username; + private String password; + + public OauthPasswordGrant(String tokenUrl, String scopes) { + super(null, tokenUrl, scopes); + } + + @Override + protected OAuth2AccessToken getOAuth2AccessToken() { + try { + return service.getAccessTokenPasswordGrant(username, password); + } catch (Exception e) { + throw new RuntimeException("Failed to get oauth token", e); + } + } + + @Override + protected OAuthFlow getFlow() { + return OAuthFlow.PASSWORD; + } + + /** + * Configures Oauth password grant flow + * Note: this flow is deprecated. + * + * @param username + * @param password + * @param clientId + * @param clientSecret + */ + public void configure(String username, String password, String clientId, String clientSecret) { + this.username = username; + this.password = password; + //TODO the clientId and secret are optional according with the RFC + service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .defaultScope(scopes) + .build(new DefaultApi20Impl(authorizationUrl, tokenUrl)); + } +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/build.gradle.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/build.gradle.mustache index 86cdad95f..bb35f8689 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/feign/build.gradle.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/build.gradle.mustache @@ -6,8 +6,7 @@ version = '{{artifactVersion}}' buildscript { repositories { - maven { url "https://repo1.maven.org/maven2" } - jcenter() + mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:2.3.+' @@ -16,7 +15,7 @@ buildscript { } repositories { - jcenter() + mavenCentral() } @@ -33,20 +32,8 @@ if(hasProperty('target') && target == 'android') { targetSdkVersion 25 } compileOptions { - {{#supportJava6}} - sourceCompatibility JavaVersion.VERSION_1_6 - targetCompatibility JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} - {{#java8}} sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 - {{/java8}} - {{^java8}} - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 - {{/java8}} - {{/supportJava6}} } // Rename the aar correctly @@ -61,7 +48,7 @@ if(hasProperty('target') && target == 'android') { } dependencies { - provided 'javax.annotation:jsr250-api:1.0' + provided "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version" } } @@ -89,26 +76,17 @@ if(hasProperty('target') && target == 'android') { } else { apply plugin: 'java' - apply plugin: 'maven' - - {{#supportJava6}} - sourceCompatibility = JavaVersion.VERSION_1_6 - targetCompatibility = JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} - {{#java8}} + apply plugin: 'maven-publish' + sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 - {{/java8}} - {{^java8}} - sourceCompatibility = JavaVersion.VERSION_1_7 - targetCompatibility = JavaVersion.VERSION_1_7 - {{/java8}} - {{/supportJava6}} - - install { - repositories.mavenInstaller { - pom.artifactId = '{{artifactId}}' + + publishing { + publications { + maven(MavenPublication) { + artifactId = '{{artifactId}}' + from components.java + } } } @@ -118,41 +96,51 @@ if(hasProperty('target') && target == 'android') { } } +test { + useJUnitPlatform() +} + ext { swagger_annotations_version = "1.5.24" - jackson_version = "2.10.3" - jackson_databind_version = "2.10.3" - jackson_databind_nullable_version = "0.2.1" - {{#threetenbp}} - jackson_threetenbp_version = "2.9.10" - {{/threetenbp}} - feign_version = "{{#useFeign10}}11.0{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" - feign_form_version = "{{#useFeign10}}3.8.0{{/useFeign10}}{{^useFeign10}}2.1.0{{/useFeign10}}" - junit_version = "4.13" - oltu_version = "1.0.1" + jackson_version = "2.13.4" + jackson_databind_version = "2.13.4.2" + {{#openApiNullable}} + jackson_databind_nullable_version = "0.2.4" + {{/openApiNullable}} + jakarta_annotation_version = "1.3.5" + feign_version = "10.11" + feign_form_version = "3.8.0" + junit_version = "5.7.0" + scribejava_version = "8.0.0" } dependencies { - compile "io.swagger:swagger-annotations:$swagger_annotations_version" - compile "com.google.code.findbugs:jsr305:3.0.2" - compile "io.github.openfeign:feign-core:$feign_version" - compile "io.github.openfeign:feign-jackson:$feign_version" - compile "io.github.openfeign:feign-slf4j:$feign_version" - compile "io.github.openfeign.form:feign-form:$feign_form_version" - compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" - compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation "io.github.openfeign:feign-core:$feign_version" + implementation "io.github.openfeign:feign-jackson:$feign_version" + implementation "io.github.openfeign:feign-slf4j:$feign_version" + implementation "io.github.openfeign:feign-okhttp:$feign_version" + implementation "io.github.openfeign.form:feign-form:$feign_form_version" + implementation "com.fasterxml.jackson.core:jackson-core:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" + {{#openApiNullable}} + implementation "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + {{/openApiNullable}} {{#joda}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + implementation "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" {{/joda}} - {{#java8}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" - {{/java8}} - {{#threetenbp}} - compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_threetenbp_version" - {{/threetenbp}} - compile "org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:$oltu_version" - compile "com.brsanthu:migbase64:2.2" - testCompile "junit:junit:$junit_version" + implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + implementation "com.brsanthu:migbase64:2.2" + implementation "com.github.scribejava:scribejava-core:$scribejava_version" + implementation "com.brsanthu:migbase64:2.2" + implementation "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version" + testImplementation "org.junit.jupiter:junit-jupiter:$junit_version" + testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junit_version" + testImplementation "org.junit.jupiter:junit-jupiter-params:$junit_version" + testImplementation "com.github.tomakehurst:wiremock-jre8:2.27.2" + testImplementation "org.hamcrest:hamcrest:2.2" + testImplementation "commons-io:commons-io:2.8.0" + testImplementation "ch.qos.logback:logback-classic:1.2.3" } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/build.sbt.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/build.sbt.mustache index cd55527b8..da07dcf61 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/feign/build.sbt.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/build.sbt.mustache @@ -10,18 +10,25 @@ lazy val root = (project in file(".")). resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( "io.swagger" % "swagger-annotations" % "1.5.24" % "compile", - "io.github.openfeign" % "feign-core" % "{{#useFeign10}}11.0{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", - "io.github.openfeign" % "feign-jackson" % "{{#useFeign10}}11.0{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", - "io.github.openfeign" % "feign-slf4j" % "{{#useFeign10}}11.0{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}}" % "compile", - "io.github.openfeign.form" % "feign-form" % "{{#useFeign10}}3.8.0{{/useFeign10}}{{^useFeign10}}2.1.0{{/useFeign10}}" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.3" % "compile", - "com.fasterxml.jackson.datatype" % "jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}}" % "2.9.10" % "compile", + "com.google.code.findbugs" % "jsr305" % "3.0.2" % "compile", + "io.github.openfeign" % "feign-core" % "10.11" % "compile", + "io.github.openfeign" % "feign-jackson" % "10.11" % "compile", + "io.github.openfeign" % "feign-slf4j" % "10.11" % "compile", + "io.github.openfeign.form" % "feign-form" % "3.8.0" % "compile", + "io.github.openfeign" % "feign-okhttp" % "10.11" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.13.4" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.13.4" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.13.4.2" % "compile", + "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.10" % "compile", "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile", - "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1" % "compile", + "com.github.scribejava" % "scribejava-core" % "8.0.0" % "compile", "com.brsanthu" % "migbase64" % "2.2" % "compile", - "junit" % "junit" % "4.13" % "test", + "jakarta.annotation" % "jakarta.annotation-api" % "1.3.5" % "compile", + "org.junit.jupiter" % "junit-jupiter" % "5.7.0" % "test", + "org.junit.jupiter" % "junit-jupiter-params" % "5.7.0" % "test", + "com.github.tomakehurst" % "wiremock-jre8" % "2.27.2" % "test", + "org.hamcrest" % "hamcrest" % "2.2" % "test", + "commons-io" % "commons-io" % "2.8.0" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" ) ) diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/model/ApiResponse.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/model/ApiResponse.mustache new file mode 100644 index 000000000..bc460dc59 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/model/ApiResponse.mustache @@ -0,0 +1,43 @@ +package {{modelPackage}}; + +import java.util.Map; +import java.util.List; + +public class ApiResponse{ + + final private int statusCode; + final private Map> headers; + final private T data; + + /** + * @param statusCode The status code of HTTP response + * @param headers The headers of HTTP response + */ + public ApiResponse(int statusCode, Map> headers) { + this(statusCode, headers, null); + } + + /** + * @param statusCode The status code of HTTP response + * @param headers The headers of HTTP response + * @param data The object deserialized from response bod + */ + public ApiResponse(int statusCode, Map> headers, T data) { + this.statusCode = statusCode; + this.headers = headers; + this.data = data; + } + + public int getStatusCode() { + return statusCode; + } + + public Map> getHeaders() { + return headers; + } + + public T getData() { + return data; + } + +} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/model_test.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/model_test.mustache new file mode 100644 index 000000000..0d75e120b --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/model_test.mustache @@ -0,0 +1,48 @@ +{{>licenseInfo}} + +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.jupiter.api.Test; + +{{#fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +/** + * Model tests for {{classname}} + */ +class {{classname}}Test { + {{#models}} + {{#model}} + {{^vendorExtensions.x-is-one-of-interface}} + {{^isEnum}} + private final {{classname}} model = new {{classname}}(); + + {{/isEnum}} + /** + * Model tests for {{classname}} + */ + @Test + void test{{classname}}() { + // TODO: test {{classname}} + } + + {{#allVars}} + /** + * Test the property '{{name}}' + */ + @Test + void {{name}}Test() { + // TODO: test {{name}} + } + + {{/allVars}} + {{/vendorExtensions.x-is-one-of-interface}} + {{/model}} + {{/models}} +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/feign/pom.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/feign/pom.mustache index a40806b32..5a122b321 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/feign/pom.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/feign/pom.mustache @@ -158,9 +158,10 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.1.1 + 3.3.2 none + 1.8 @@ -212,11 +213,13 @@ + {{#swagger1AnnotationLibrary}} io.swagger swagger-annotations ${swagger-annotations-version} + {{/swagger1AnnotationLibrary}} @@ -224,7 +227,7 @@ jsr305 3.0.2 - + io.github.openfeign @@ -246,6 +249,11 @@ feign-form ${feign-form-version} + + io.github.openfeign + feign-okhttp + ${feign-version} + @@ -263,84 +271,99 @@ jackson-databind ${jackson-databind-version} + {{#openApiNullable}} org.openapitools jackson-databind-nullable ${jackson-databind-nullable-version} + {{/openApiNullable}} {{#withXml}} - - - - com.fasterxml.jackson.dataformat - jackson-dataformat-xml - ${jackson-version} - - + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + ${jackson-version} + {{/withXml}} {{#joda}} - - com.fasterxml.jackson.datatype - jackson-datatype-joda - ${jackson-version} - + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-version} + {{/joda}} - {{#java8}} - - com.fasterxml.jackson.datatype - jackson-datatype-jsr310 - ${jackson-version} - - {{/java8}} - {{#threetenbp}} - - com.github.joschi.jackson - jackson-datatype-threetenbp - ${jackson-threetenbp-version} - - {{/threetenbp}} - org.apache.oltu.oauth2 - org.apache.oltu.oauth2.client - ${oltu-version} + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + + + com.github.scribejava + scribejava-core + ${scribejava-version} + + + jakarta.annotation + jakarta.annotation-api + ${jakarta-annotation-version} + provided - junit - junit + ch.qos.logback + logback-classic + 1.2.10 + test + + + org.junit.jupiter + junit-jupiter + ${junit-version} + test + + + org.junit.jupiter + junit-jupiter-params ${junit-version} test - com.squareup.okhttp3 - mockwebserver - 3.6.0 + org.hamcrest + hamcrest + 2.2 + test + + + com.github.tomakehurst + wiremock-jre8 + 2.27.2 test - org.assertj - assertj-core - 1.7.1 + commons-io + commons-io + 2.8.0 test UTF-8 - {{#supportJava6}}1.6{{/supportJava6}}{{^supportJava6}}{{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}}{{/supportJava6}} + 1.8 ${java.version} ${java.version} - 1.5.24 - {{#useFeign10}}11.0{{/useFeign10}}{{^useFeign10}}9.7.0{{/useFeign10}} - {{#useFeign10}}3.8.0{{/useFeign10}}{{^useFeign10}}2.1.0{{/useFeign10}} - 2.10.3 - 0.2.1 - 2.10.3 - {{#threetenbp}} - 2.9.10 - {{/threetenbp}} - 4.13 + 1.6.6 + 10.11 + 3.8.0 + 2.13.4 + {{#openApiNullable}} + 0.2.4 + {{/openApiNullable}} + 2.13.4.2 + 1.3.5 + 5.7.0 1.0.0 - 1.0.1 + 8.0.0 diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/ApiClient.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/ApiClient.mustache index 9df560415..c1b8e1fdd 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/ApiClient.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/ApiClient.mustache @@ -4,19 +4,13 @@ import {{apiPackage}}.*; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; +{{#openApiNullable}} import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} {{#joda}} import com.fasterxml.jackson.datatype.joda.JodaModule; {{/joda}} -{{#java8}} import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -{{/java8}} -{{#threetenbp}} -import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule; -{{/threetenbp}} -{{#threetenbp}} -import org.threeten.bp.*; -{{/threetenbp}} import com.google.api.client.googleapis.util.Utils; import com.google.api.client.http.AbstractHttpContent; import com.google.api.client.http.HttpRequestFactory; @@ -44,18 +38,11 @@ public class ApiClient { {{#joda}} objectMapper.registerModule(new JodaModule()); {{/joda}} - {{#java8}} objectMapper.registerModule(new JavaTimeModule()); - {{/java8}} - {{#threetenbp}} - ThreeTenModule module = new ThreeTenModule(); - module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT); - module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME); - module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); - objectMapper.registerModule(module); - {{/threetenbp}} + {{#openApiNullable}} JsonNullableModule jnm = new JsonNullableModule(); objectMapper.registerModule(jnm); + {{/openApiNullable}} return objectMapper; } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/api.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/api.mustache index 2c13f4eb0..f9af1a4a9 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/api.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/api.mustache @@ -45,43 +45,56 @@ public class {{classname}} { {{#operation}} /**{{#summary}} - * {{summary}}{{/summary}}{{#notes}} - * {{notes}}{{/notes}}{{#responses}} - *

{{code}}{{#message}} - {{message}}{{/message}}{{/responses}}{{#allParams}} + * {{.}}{{/summary}}{{#notes}} + * {{.}}{{/notes}}{{#responses}} + *

{{code}}{{#message}} - {{.}}{{/message}}{{/responses}}{{#allParams}} * @param {{paramName}} {{description}}{{^description}}The {{paramName}} parameter{{/description}}{{/allParams}}{{#returnType}} - * @return {{returnType}}{{/returnType}} + * @return {{.}}{{/returnType}} * @throws IOException if an error occurs while attempting to invoke the API{{#externalDocs}} * {{description}} * @see {{summary}} Documentation - {{/externalDocs}} + {{/externalDocs}}{{#isDeprecated}} + * @deprecated + {{/isDeprecated}} **/ - public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws IOException { - {{#returnType}}HttpResponse response = {{/returnType}}{{operationId}}ForHttpResponse({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}} + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#returnType}}{{{.}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws IOException { + {{#returnType}}HttpResponse response = {{/returnType}}{{operationId}}ForHttpResponse({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});{{#returnType}} TypeReference<{{{returnType}}}> typeRef = new TypeReference<{{{returnType}}}>() {}; return apiClient.getObjectMapper().readValue(response.getContent(), typeRef);{{/returnType}} } /**{{#summary}} - * {{summary}}{{/summary}}{{#notes}} - * {{notes}}{{/notes}}{{#responses}} - *

{{code}}{{#message}} - {{message}}{{/message}}{{/responses}}{{#requiredParams}} + * {{.}}{{/summary}}{{#notes}} + * {{.}}{{/notes}}{{#responses}} + *

{{code}}{{#message}} - {{.}}{{/message}}{{/responses}}{{#requiredParams}} * @param {{paramName}} {{description}}{{^description}}The {{paramName}} parameter{{/description}}{{/requiredParams}} * @param params Map of query params. A collection will be interpreted as passing in multiple instances of the same query param.{{#returnType}} - * @return {{returnType}}{{/returnType}} + * @return {{.}}{{/returnType}} * @throws IOException if an error occurs while attempting to invoke the API{{#externalDocs}} * {{description}} * @see {{summary}} Documentation - {{/externalDocs}} + {{/externalDocs}}{{#isDeprecated}} + * @deprecated + {{/isDeprecated}} **/ - public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#bodyParam}}{{^required}}{{{dataType}}} {{paramName}}, {{/required}}{{/bodyParam}}{{#requiredParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}{{#hasRequiredParams}}, {{/hasRequiredParams}}Map params) throws IOException { - {{#returnType}}HttpResponse response = {{/returnType}}{{operationId}}ForHttpResponse({{#bodyParam}}{{^required}}{{paramName}}, {{/required}}{{/bodyParam}}{{#requiredParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}{{#hasRequiredParams}}, {{/hasRequiredParams}}params);{{#returnType}} + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#returnType}}{{{.}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#bodyParam}}{{^required}}{{{dataType}}} {{paramName}}, {{/required}}{{/bodyParam}}{{#requiredParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/requiredParams}}{{#hasRequiredParams}}, {{/hasRequiredParams}}Map params) throws IOException { + {{#returnType}}HttpResponse response = {{/returnType}}{{operationId}}ForHttpResponse({{#bodyParam}}{{^required}}{{paramName}}, {{/required}}{{/bodyParam}}{{#requiredParams}}{{paramName}}{{^-last}}, {{/-last}}{{/requiredParams}}{{#hasRequiredParams}}, {{/hasRequiredParams}}params);{{#returnType}} TypeReference<{{{returnType}}}> typeRef = new TypeReference<{{{returnType}}}>() {}; return apiClient.getObjectMapper().readValue(response.getContent(), typeRef);{{/returnType}} } - public HttpResponse {{operationId}}ForHttpResponse({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws IOException { + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public HttpResponse {{operationId}}ForHttpResponse({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws IOException { {{#allParams}}{{#required}}// verify the required parameter '{{paramName}}' is set if ({{paramName}} == null) { throw new IllegalArgumentException("Missing the required parameter '{{paramName}}' when calling {{operationId}}"); @@ -112,7 +125,10 @@ public class {{classname}} { return apiClient.getHttpRequestFactory().buildRequest(HttpMethods.{{httpMethod}}, genericUrl, content).execute(); }{{#bodyParam}} - public HttpResponse {{operationId}}ForHttpResponse({{#allParams}}{{#isBodyParam}}java.io.InputStream {{paramName}}{{/isBodyParam}}{{^isBodyParam}}{{{dataType}}} {{paramName}}{{/isBodyParam}}{{#hasMore}}, {{/hasMore}}{{/allParams}}, String mediaType) throws IOException { + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public HttpResponse {{operationId}}ForHttpResponse({{#allParams}}{{#isBodyParam}}java.io.InputStream {{paramName}}{{/isBodyParam}}{{^isBodyParam}}{{{dataType}}} {{paramName}}{{/isBodyParam}}{{^-last}}, {{/-last}}{{/allParams}}, String mediaType) throws IOException { {{#allParams}}{{#required}}// verify the required parameter '{{paramName}}' is set if ({{paramName}} == null) { throw new IllegalArgumentException("Missing the required parameter '{{paramName}}' when calling {{operationId}}"); @@ -145,7 +161,10 @@ public class {{classname}} { return apiClient.getHttpRequestFactory().buildRequest(HttpMethods.{{httpMethod}}, genericUrl, content).execute(); }{{/bodyParam}} - public HttpResponse {{operationId}}ForHttpResponse({{#bodyParam}}{{^required}}{{{dataType}}} {{paramName}}, {{/required}}{{/bodyParam}}{{#requiredParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}{{#hasRequiredParams}}, {{/hasRequiredParams}}Map params) throws IOException { + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public HttpResponse {{operationId}}ForHttpResponse({{#bodyParam}}{{^required}}{{{dataType}}} {{paramName}}, {{/required}}{{/bodyParam}}{{#requiredParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/requiredParams}}{{#hasRequiredParams}}, {{/hasRequiredParams}}Map params) throws IOException { {{#allParams}}{{#required}}// verify the required parameter '{{paramName}}' is set if ({{paramName}} == null) { throw new IllegalArgumentException("Missing the required parameter '{{paramName}}' when calling {{operationId}}"); diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/api_test.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/api_test.mustache index 365106fbe..e81a6cf29 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/api_test.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/api_test.mustache @@ -8,6 +8,8 @@ import org.junit.Test; import org.junit.Ignore; import java.io.IOException; +import java.time.LocalDate; +import java.time.OffsetDateTime; {{^fullJavaUtil}} import java.util.ArrayList; import java.util.HashMap; @@ -37,7 +39,7 @@ public class {{classname}}Test { {{#allParams}} {{{dataType}}} {{paramName}} = null; {{/allParams}} - {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{#returnType}}{{{.}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); // TODO: test validations } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/build.gradle.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/build.gradle.mustache index 0089f90de..c14b05a57 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/build.gradle.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/build.gradle.mustache @@ -6,8 +6,7 @@ version = '{{artifactVersion}}' buildscript { repositories { - maven { url "https://repo1.maven.org/maven2" } - jcenter() + mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:1.5.+' @@ -16,7 +15,7 @@ buildscript { } repositories { - jcenter() + mavenCentral() } @@ -24,7 +23,7 @@ if(hasProperty('target') && target == 'android') { apply plugin: 'com.android.library' apply plugin: 'com.github.dcendents.android-maven' - + android { compileSdkVersion 23 buildToolsVersion '23.0.2' @@ -33,22 +32,10 @@ if(hasProperty('target') && target == 'android') { targetSdkVersion 22 } compileOptions { - {{#supportJava6}} - sourceCompatibility JavaVersion.VERSION_1_6 - targetCompatibility JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} - {{#java8}} sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 - {{/java8}} - {{^java8}} - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 - {{/java8}} - {{/supportJava6}} } - + // Rename the aar correctly libraryVariants.all { variant -> variant.outputs.each { output -> @@ -61,10 +48,10 @@ if(hasProperty('target') && target == 'android') { } dependencies { - provided 'javax.annotation:jsr250-api:1.0' + provided "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version" } } - + afterEvaluate { android.libraryVariants.all { variant -> def task = project.tasks.create "jar${variant.name.capitalize()}", Jar @@ -76,12 +63,12 @@ if(hasProperty('target') && target == 'android') { artifacts.add('archives', task); } } - + task sourcesJar(type: Jar) { from android.sourceSets.main.java.srcDirs classifier = 'sources' } - + artifacts { archives sourcesJar } @@ -89,29 +76,20 @@ if(hasProperty('target') && target == 'android') { } else { apply plugin: 'java' - apply plugin: 'maven' - - {{#supportJava6}} - sourceCompatibility = JavaVersion.VERSION_1_6 - targetCompatibility = JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} - {{#java8}} + apply plugin: 'maven-publish' + sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 - {{/java8}} - {{^java8}} - sourceCompatibility = JavaVersion.VERSION_1_7 - targetCompatibility = JavaVersion.VERSION_1_7 - {{/java8}} - {{/supportJava6}} - - install { - repositories.mavenInstaller { - pom.artifactId = '{{artifactId}}' + + publishing { + publications { + maven(MavenPublication) { + artifactId = '{{artifactId}}' + from components.java + } } } - + task execute(type:JavaExec) { main = System.getProperty('mainClass') classpath = sourceSets.main.runtimeClasspath @@ -119,41 +97,39 @@ if(hasProperty('target') && target == 'android') { } ext { - swagger_annotations_version = "1.5.22" - jackson_version = "2.10.1" - jackson_databind_version = "2.10.1" - jackson_databind_nullable_version = "0.2.1" - google_api_client_version = "1.23.0" + swagger_annotations_version = "1.6.3" + jackson_version = "2.13.4" + jackson_databind_version = "2.13.4.2" + {{#openApiNullable}} + jackson_databind_nullable_version = "0.2.4" + {{/openApiNullable}} + jakarta_annotation_version = "1.3.5" + google_api_client_version = "1.32.2" jersey_common_version = "2.25.1" jodatime_version = "2.9.9" - junit_version = "4.13" - {{#threetenbp}} - jackson_threeten_version = "2.9.10" - {{/threetenbp}} + junit_version = "4.13.2" } dependencies { - compile "io.swagger:swagger-annotations:$swagger_annotations_version" - compile "com.google.code.findbugs:jsr305:3.0.2" - compile "com.google.api-client:google-api-client:${google_api_client_version}" - compile "org.glassfish.jersey.core:jersey-common:${jersey_common_version}" - compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" - compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" - compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" - {{#java8}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" - {{/java8}} + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation "com.google.api-client:google-api-client:${google_api_client_version}" + implementation "org.glassfish.jersey.core:jersey-common:${jersey_common_version}" + implementation "com.fasterxml.jackson.core:jackson-core:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" + implementation "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" + {{#openApiNullable}} + implementation "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + {{/openApiNullable}} + implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" {{#joda}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" - compile "joda-time:joda-time:$jodatime_version" + implementation "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + implementation "joda-time:joda-time:$jodatime_version" {{/joda}} - {{#threetenbp}} - compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_threeten_version" - {{/threetenbp}} {{#withXml}} - compile "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:$jackson_version" + implementation "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:$jackson_version" {{/withXml}} - testCompile "junit:junit:$junit_version" + implementation "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version" + testImplementation "junit:junit:$junit_version" } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/build.sbt.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/build.sbt.mustache index 7d958dfad..78da21f2e 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/build.sbt.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/build.sbt.mustache @@ -12,22 +12,18 @@ lazy val root = (project in file(".")). "io.swagger" % "swagger-annotations" % "1.5.22", "com.google.api-client" % "google-api-client" % "1.23.0", "org.glassfish.jersey.core" % "jersey-common" % "2.25.1", - "com.fasterxml.jackson.core" % "jackson-core" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.13.4" % "compile", "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.1" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.1" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.13.4.2" % "compile", {{#withXml}} "com.fasterxml.jackson.dataformat" % "jackson-dataformat-xml" % "2.9.10" % "compile", {{/withXml}} {{#joda}} "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.9.10" % "compile", {{/joda}} - {{#java8}} "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.10" % "compile", - {{/java8}} - {{#threetenbp}} - "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile", - {{/threetenbp}} - "junit" % "junit" % "4.13" % "test", + "jakarta.annotation" % "jakarta.annotation-api" % "1.3.5" % "compile", + "junit" % "junit" % "4.13.2" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" ) ) diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/pom.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/pom.mustache index 4d6a8c5e1..efd1199b2 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/pom.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/google-api-client/pom.mustache @@ -144,28 +144,17 @@ maven-compiler-plugin 3.6.1 - {{#supportJava6}} - 1.6 - 1.6 - {{/supportJava6}} - {{^supportJava6}} - {{#java8}} - 1.8 - 1.8 - {{/java8}} - {{^java8}} - 1.7 - 1.7 - {{/java8}} - {{/supportJava6}} + 1.8 + 1.8 org.apache.maven.plugins maven-javadoc-plugin - 3.1.1 + 3.3.2 none + 1.8 @@ -217,11 +206,13 @@ + {{#swagger1AnnotationLibrary}} io.swagger swagger-annotations ${swagger-annotations-version} + {{/swagger1AnnotationLibrary}} com.google.code.findbugs @@ -254,13 +245,15 @@ com.fasterxml.jackson.core jackson-databind - ${jackson-version} + ${jackson-databind-version} + {{#openApiNullable}} org.openapitools jackson-databind-nullable ${jackson-databind-nullable-version} + {{/openApiNullable}} {{#withXml}} @@ -269,13 +262,11 @@ ${jackson-version} {{/withXml}} - {{#java8}} com.fasterxml.jackson.datatype jackson-datatype-jsr310 ${jackson-version} - {{/java8}} {{#joda}} com.fasterxml.jackson.datatype @@ -288,13 +279,12 @@ ${jodatime-version} {{/joda}} - {{#threetenbp}} - - com.github.joschi.jackson - jackson-datatype-threetenbp - ${jackson-threetenbp-version} - - {{/threetenbp}} + + jakarta.annotation + jakarta.annotation-api + ${jakarta-annotation-version} + provided + @@ -306,19 +296,19 @@ UTF-8 - 1.5.22 - 1.30.2 + 1.6.6 + 1.32.2 2.25.1 - 2.10.3 - 2.10.3 - 0.2.1 + 2.13.4 + 2.13.4.2 + {{#openApiNullable}} + 0.2.4 + {{/openApiNullable}} {{#joda}} 2.9.9 {{/joda}} - {{#threetenbp}} - 2.9.10 - {{/threetenbp}} + 1.3.5 1.0.0 - 4.13 + 4.13.2 diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/AbstractOpenApiSchema.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/AbstractOpenApiSchema.mustache deleted file mode 100644 index 61fddeca4..000000000 --- a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/AbstractOpenApiSchema.mustache +++ /dev/null @@ -1,55 +0,0 @@ -{{>licenseInfo}} - -package {{invokerPackage}}.model; - -import org.openapitools.client.ApiException; -import java.lang.reflect.Type; -import java.util.Map; -import javax.ws.rs.core.GenericType; - -/** - * Abstract class for oneOf,anyOf schemas defined in OpenAPI spec - */ -{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}} -public abstract class AbstractOpenApiSchema { - - // store the actual instance of the schema/object - private Object instance; - - // schema type (e.g. oneOf, anyOf) - private final String schemaType; - - public AbstractOpenApiSchema(String schemaType) { - this.schemaType = schemaType; - } - - /*** - * Get the list of schemas allowed to be stored in this object - * - * @return an instance of the actual schema/object - */ - public abstract Map getSchemas(); - - /*** - * Get the actual instance - * - * @return an instance of the actual schema/object - */ - public Object getActualInstance() {return instance;} - - /*** - * Set the actual instance - * - * @param instance the actual instance of the schema/object - */ - public void setActualInstance(Object instance) {this.instance = instance;} - - /*** - * Get the schema type (e.g. anyOf, oneOf) - * - * @return the schema type - */ - public String getSchemaType() { - return schemaType; - } -} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/JSON.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/JSON.mustache deleted file mode 100644 index dc3d9893e..000000000 --- a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/JSON.mustache +++ /dev/null @@ -1,72 +0,0 @@ -package {{invokerPackage}}; - -{{#threetenbp}} -import org.threeten.bp.*; -{{/threetenbp}} -import com.fasterxml.jackson.annotation.*; -import com.fasterxml.jackson.databind.*; -import org.openapitools.jackson.nullable.JsonNullableModule; -{{#java8}} -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -{{/java8}} -{{#joda}} -import com.fasterxml.jackson.datatype.joda.JodaModule; -{{/joda}} -{{#threetenbp}} -import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule; -{{/threetenbp}} - -import java.text.DateFormat; - -import javax.ws.rs.ext.ContextResolver; - -{{>generatedAnnotation}} -public class JSON implements ContextResolver { - private ObjectMapper mapper; - - public JSON() { - mapper = new ObjectMapper(); - mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); - mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, true); - mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); - mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); - mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); - mapper.setDateFormat(new RFC3339DateFormat()); - {{#java8}} - mapper.registerModule(new JavaTimeModule()); - {{/java8}} - {{#joda}} - mapper.registerModule(new JodaModule()); - {{/joda}} - {{#threetenbp}} - ThreeTenModule module = new ThreeTenModule(); - module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT); - module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME); - module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); - mapper.registerModule(module); - {{/threetenbp}} - JsonNullableModule jnm = new JsonNullableModule(); - mapper.registerModule(jnm); - } - - /** - * Set the date format for JSON (de)serialization with Date properties. - * @param dateFormat Date format - */ - public void setDateFormat(DateFormat dateFormat) { - mapper.setDateFormat(dateFormat); - } - - @Override - public ObjectMapper getContext(Class type) { - return mapper; - } - - /** - * Get the object mapper - * - * @return object mapper - */ - public ObjectMapper getMapper() { return mapper; } -} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/anyof_model.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/anyof_model.mustache deleted file mode 100644 index a3702d221..000000000 --- a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/anyof_model.mustache +++ /dev/null @@ -1,28 +0,0 @@ -import javax.ws.rs.core.GenericType; -import javax.ws.rs.core.Response; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; - -{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>xmlAnnotation}} -public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-implements}}, {{{.}}}{{/vendorExtensions.x-implements}} { - - // store a list of schema names defined in anyOf - public final static Map schemas = new HashMap(); - - public {{classname}}() { - super("anyOf"); - } - - static { - {{#anyOf}} - schemas.put("{{{.}}}", new GenericType<{{{.}}}>() { - }); - {{/anyOf}} - } - - @Override - public Map getSchemas() { - return {{classname}}.schemas; - } -} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/auth/OAuthFlow.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/auth/OAuthFlow.mustache deleted file mode 100644 index 002e9572f..000000000 --- a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/auth/OAuthFlow.mustache +++ /dev/null @@ -1,7 +0,0 @@ -{{>licenseInfo}} - -package {{invokerPackage}}.auth; - -public enum OAuthFlow { - accessCode, implicit, password, application -} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/build.gradle.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/build.gradle.mustache deleted file mode 100644 index cdb451adb..000000000 --- a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/build.gradle.mustache +++ /dev/null @@ -1,170 +0,0 @@ -apply plugin: 'idea' -apply plugin: 'eclipse' - -group = '{{groupId}}' -version = '{{artifactVersion}}' - -buildscript { - repositories { - maven { url "https://repo1.maven.org/maven2" } - jcenter() - } - dependencies { - classpath 'com.android.tools.build:gradle:2.3.+' - classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' - } -} - -repositories { - jcenter() -} - - -if(hasProperty('target') && target == 'android') { - - apply plugin: 'com.android.library' - apply plugin: 'com.github.dcendents.android-maven' - - android { - compileSdkVersion 25 - buildToolsVersion '25.0.2' - defaultConfig { - minSdkVersion 14 - targetSdkVersion 25 - } - compileOptions { - {{#supportJava6}} - sourceCompatibility JavaVersion.VERSION_1_6 - targetCompatibility JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} - {{#java8}} - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - {{/java8}} - {{^java8}} - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 - {{/java8}} - {{/supportJava6}} - } - - // Rename the aar correctly - libraryVariants.all { variant -> - variant.outputs.each { output -> - def outputFile = output.outputFile - if (outputFile != null && outputFile.name.endsWith('.aar')) { - def fileName = "${project.name}-${variant.baseName}-${version}.aar" - output.outputFile = new File(outputFile.parent, fileName) - } - } - } - - dependencies { - provided 'javax.annotation:jsr250-api:1.0' - } - } - - afterEvaluate { - android.libraryVariants.all { variant -> - def task = project.tasks.create "jar${variant.name.capitalize()}", Jar - task.description = "Create jar artifact for ${variant.name}" - task.dependsOn variant.javaCompile - task.from variant.javaCompile.destinationDir - task.destinationDir = project.file("${project.buildDir}/outputs/jar") - task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" - artifacts.add('archives', task); - } - } - - task sourcesJar(type: Jar) { - from android.sourceSets.main.java.srcDirs - classifier = 'sources' - } - - artifacts { - archives sourcesJar - } - -} else { - - apply plugin: 'java' - apply plugin: 'maven' - {{#supportJava6}} - sourceCompatibility = JavaVersion.VERSION_1_6 - targetCompatibility = JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} - {{#java8}} - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - {{/java8}} - {{^java8}} - sourceCompatibility = JavaVersion.VERSION_1_7 - targetCompatibility = JavaVersion.VERSION_1_7 - {{/java8}} - {{/supportJava6}} - - install { - repositories.mavenInstaller { - pom.artifactId = '{{artifactId}}' - } - } - - task execute(type:JavaExec) { - main = System.getProperty('mainClass') - classpath = sourceSets.main.runtimeClasspath - } -} - -ext { - swagger_annotations_version = "1.5.22" - jackson_version = "2.10.3" - jackson_databind_version = "2.10.3" - jackson_databind_nullable_version = "0.2.1" - {{#supportJava6}} - jersey_version = "2.6" - commons_io_version=2.5 - commons_lang3_version=3.6 - {{/supportJava6}} - {{^supportJava6}} - jersey_version = "2.27" - {{/supportJava6}} - junit_version = "4.13" - {{#threetenbp}} - threetenbp_version = "2.9.10" - {{/threetenbp}} -} - -dependencies { - compile "io.swagger:swagger-annotations:$swagger_annotations_version" - compile "com.google.code.findbugs:jsr305:3.0.2" - compile "org.glassfish.jersey.core:jersey-client:$jersey_version" - compile "org.glassfish.jersey.media:jersey-media-multipart:$jersey_version" - compile "org.glassfish.jersey.media:jersey-media-json-jackson:$jersey_version" - compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" - compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" - {{#joda}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" - {{/joda}} - {{#java8}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" - {{/java8}} - {{#supportJava6}} - compile "commons-io:commons-io:$commons_io_version" - compile "org.apache.commons:commons-lang3:$commons_lang3_version" - {{/supportJava6}} - {{#threetenbp}} - compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$threetenbp_version" - {{/threetenbp}} - {{^java8}} - compile "com.brsanthu:migbase64:2.2" - {{/java8}} - testCompile "junit:junit:$junit_version" -} - -javadoc { - options.tags = [ "http.response.details:a:Http Response Details" ] -} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/build.sbt.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/build.sbt.mustache deleted file mode 100644 index abb91ecdc..000000000 --- a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/build.sbt.mustache +++ /dev/null @@ -1,38 +0,0 @@ -lazy val root = (project in file(".")). - settings( - organization := "{{groupId}}", - name := "{{artifactId}}", - version := "{{artifactVersion}}", - scalaVersion := "2.11.4", - scalacOptions ++= Seq("-feature"), - javacOptions in compile ++= Seq("-Xlint:deprecation"), - publishArtifact in (Compile, packageDoc) := false, - resolvers += Resolver.mavenLocal, - libraryDependencies ++= Seq( - "io.swagger" % "swagger-annotations" % "1.5.22", - "org.glassfish.jersey.core" % "jersey-client" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, - "org.glassfish.jersey.media" % "jersey-media-multipart" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, - "org.glassfish.jersey.media" % "jersey-media-json-jackson" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, - "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.3" % "compile", - {{#joda}} - "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.9.10" % "compile", - {{/joda}} - {{#java8}} - "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.10" % "compile", - {{/java8}} - {{#threetenbp}} - "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile", - {{/threetenbp}} - {{^java8}} - "com.brsanthu" % "migbase64" % "2.2", - {{/java8}} - {{#supportJava6}} - "org.apache.commons" % "commons-lang3" % "3.6", - "commons-io" % "commons-io" % "2.5", - {{/supportJava6}} - "junit" % "junit" % "4.13" % "test", - "com.novocode" % "junit-interface" % "0.10" % "test" - ) - ) diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/oneof_model.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/oneof_model.mustache deleted file mode 100644 index b5d4442e6..000000000 --- a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/oneof_model.mustache +++ /dev/null @@ -1,41 +0,0 @@ -import javax.ws.rs.core.GenericType; -import javax.ws.rs.core.Response; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; - -{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>xmlAnnotation}} -public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-implements}}, {{{.}}}{{/vendorExtensions.x-implements}} { - - // store a list of schema names defined in oneOf - public final static Map schemas = new HashMap(); - - public {{classname}}() { - super("oneOf"); - } - - static { - {{#oneOf}} - schemas.put("{{{.}}}", new GenericType<{{{.}}}>() { - }); - {{/oneOf}} - } - - @Override - public Map getSchemas() { - return {{classname}}.schemas; - } - - @Override - public void setActualInstance(Object instance) { - {{#oneOf}} - if (instance instanceof {{{.}}}) { - super.setActualInstance(instance); - return; - } - - {{/oneOf}} - throw new RuntimeException("Invalid instance type. Must be {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}"); - } - -} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/AbstractOpenApiSchema.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/AbstractOpenApiSchema.mustache new file mode 100644 index 000000000..00253ccee --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/AbstractOpenApiSchema.mustache @@ -0,0 +1,138 @@ +{{>licenseInfo}} + +package {{modelPackage}}; + +import {{invokerPackage}}.ApiException; +import java.util.Objects; +import java.lang.reflect.Type; +import java.util.Map; +import javax.ws.rs.core.GenericType; + +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Abstract class for oneOf,anyOf schemas defined in OpenAPI spec + */ +{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}} +public abstract class AbstractOpenApiSchema { + + // store the actual instance of the schema/object + private Object instance; + + // is nullable + private Boolean isNullable; + + // schema type (e.g. oneOf, anyOf) + private final String schemaType; + + public AbstractOpenApiSchema(String schemaType, Boolean isNullable) { + this.schemaType = schemaType; + this.isNullable = isNullable; + } + + /** + * Get the list of oneOf/anyOf composed schemas allowed to be stored in this object + * + * @return an instance of the actual schema/object + */ + public abstract Map getSchemas(); + + /** + * Get the actual instance + * + * @return an instance of the actual schema/object + */ + @JsonValue + public Object getActualInstance() {return instance;} + + /** + * Set the actual instance + * + * @param instance the actual instance of the schema/object + */ + public void setActualInstance(Object instance) {this.instance = instance;} + + /** + * Get the instant recursively when the schemas defined in oneOf/anyof happen to be oneOf/anyOf schema as well + * + * @return an instance of the actual schema/object + */ + public Object getActualInstanceRecursively() { + return getActualInstanceRecursively(this); + } + + private Object getActualInstanceRecursively(AbstractOpenApiSchema object) { + if (object.getActualInstance() == null) { + return null; + } else if (object.getActualInstance() instanceof AbstractOpenApiSchema) { + return getActualInstanceRecursively((AbstractOpenApiSchema)object.getActualInstance()); + } else { + return object.getActualInstance(); + } + } + + /** + * Get the schema type (e.g. anyOf, oneOf) + * + * @return the schema type + */ + public String getSchemaType() { + return schemaType; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ").append(getClass()).append(" {\n"); + sb.append(" instance: ").append(toIndentedString(instance)).append("\n"); + sb.append(" isNullable: ").append(toIndentedString(isNullable)).append("\n"); + sb.append(" schemaType: ").append(toIndentedString(schemaType)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AbstractOpenApiSchema a = (AbstractOpenApiSchema) o; + return Objects.equals(this.instance, a.instance) && + Objects.equals(this.isNullable, a.isNullable) && + Objects.equals(this.schemaType, a.schemaType); + } + + @Override + public int hashCode() { + return Objects.hash(instance, isNullable, schemaType); + } + + /** + * Is nullable + * + * @return true if it's nullable + */ + public Boolean isNullable() { + if (Boolean.TRUE.equals(isNullable)) { + return Boolean.TRUE; + } else { + return Boolean.FALSE; + } + } + +{{>libraries/jersey2/additional_properties}} + +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/ApiClient.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/ApiClient.mustache index 0111a24c4..2a027220d 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/ApiClient.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/ApiClient.mustache @@ -11,6 +11,9 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; +{{#hasOAuthMethods}} +import com.github.scribejava.core.model.OAuth2AccessToken; +{{/hasOAuthMethods}} import org.glassfish.jersey.client.ClientConfig; import org.glassfish.jersey.client.ClientProperties; import org.glassfish.jersey.client.HttpUrlConnectorProvider; @@ -23,15 +26,20 @@ import org.glassfish.jersey.media.multipart.MultiPartFeature; import java.io.IOException; import java.io.InputStream; -{{^supportJava6}} +import java.net.URI; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import java.security.cert.X509Certificate; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; import java.nio.file.Files; +import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import org.glassfish.jersey.logging.LoggingFeature; -{{/supportJava6}} -{{#supportJava6}} -import org.apache.commons.io.FileUtils; -import org.glassfish.jersey.filter.LoggingFilter; -{{/supportJava6}} +import java.util.logging.Level; +import java.util.logging.Logger; import java.util.Collection; import java.util.Collections; import java.util.Map; @@ -42,7 +50,9 @@ import java.util.List; import java.util.Arrays; import java.util.ArrayList; import java.util.Date; -import java.util.TimeZone; +{{#jsr310}} +import java.time.OffsetDateTime; +{{/jsr310}} import java.net.URLEncoder; @@ -56,17 +66,25 @@ import java.util.regex.Pattern; import {{invokerPackage}}.auth.Authentication; import {{invokerPackage}}.auth.HttpBasicAuth; import {{invokerPackage}}.auth.HttpBearerAuth; +{{#hasHttpSignatureMethods}} +import {{invokerPackage}}.auth.HttpSignatureAuth; +{{/hasHttpSignatureMethods}} import {{invokerPackage}}.auth.ApiKeyAuth; - {{#hasOAuthMethods}} import {{invokerPackage}}.auth.OAuth; {{/hasOAuthMethods}} +/** + *

ApiClient class.

+ */ {{>generatedAnnotation}} -public class ApiClient { +public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} { protected Map defaultHeaderMap = new HashMap(); protected Map defaultCookieMap = new HashMap(); protected String basePath = "{{{basePath}}}"; + protected String userAgent; + private static final Logger log = Logger.getLogger(ApiClient.class.getName()); + protected List servers = new ArrayList({{#servers}}{{#-first}}Arrays.asList( {{/-first}} new ServerConfiguration( "{{{url}}}", @@ -136,6 +154,7 @@ public class ApiClient { protected Map operationServerIndex = new HashMap(); protected Map> operationServerVariables = new HashMap>(); protected boolean debugging = false; + protected ClientConfig clientConfig; protected int connectionTimeout = 0; private int readTimeout = 0; @@ -148,21 +167,70 @@ public class ApiClient { protected DateFormat dateFormat; + /** + * Constructs a new ApiClient with default parameters. + */ public ApiClient() { + this(null); + } + + /** + * Constructs a new ApiClient with the specified authentication parameters. + * + * @param authMap A hash map containing authentication parameters. + */ + public ApiClient(Map authMap) { json = new JSON(); - httpClient = buildHttpClient(debugging); + httpClient = buildHttpClient(); this.dateFormat = new RFC3339DateFormat(); // Set default User-Agent. - setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}"); + setUserAgent("{{{httpUserAgent}}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}"); // Setup authentications (key: authentication name, value: authentication). - authentications = new HashMap();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} - authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} - authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} - authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} - authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} + authentications = new HashMap(); + Authentication auth = null; + {{#authMethods}} + if (authMap != null) { + auth = authMap.get("{{name}}"); + } + {{#isBasic}} + {{#isBasicBasic}} + if (auth instanceof HttpBasicAuth) { + authentications.put("{{name}}", auth); + } else { + authentications.put("{{name}}", new HttpBasicAuth()); + } + {{/isBasicBasic}} + {{#isBasicBearer}} + if (auth instanceof HttpBearerAuth) { + authentications.put("{{name}}", auth); + } else { + authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}")); + } + {{/isBasicBearer}} + {{#isHttpSignature}} + if (auth instanceof HttpSignatureAuth) { + authentications.put("{{name}}", auth); + } + {{/isHttpSignature}} + {{/isBasic}} + {{#isApiKey}} + if (auth instanceof ApiKeyAuth) { + authentications.put("{{name}}", auth); + } else { + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}")); + } + {{/isApiKey}} + {{#isOAuth}} + if (auth instanceof OAuth) { + authentications.put("{{name}}", auth); + } else { + authentications.put("{{name}}", new OAuth(basePath, "{{{tokenUrl}}}")); + } + {{/isOAuth}} + {{/authMethods}} // Prevent the authentications from being modified. authentications = Collections.unmodifiableMap(authentications); @@ -173,59 +241,138 @@ public class ApiClient { /** * Gets the JSON instance to do JSON serialization and deserialization. + * * @return JSON */ public JSON getJSON() { return json; } + /** + *

Getter for the field httpClient.

+ * + * @return a {@link javax.ws.rs.client.Client} object. + */ public Client getHttpClient() { return httpClient; } + /** + *

Setter for the field httpClient.

+ * + * @param httpClient a {@link javax.ws.rs.client.Client} object. + * @return a {@link org.openapitools.client.ApiClient} object. + */ public ApiClient setHttpClient(Client httpClient) { this.httpClient = httpClient; return this; } + /** + * Returns the base URL to the location where the OpenAPI document is being served. + * + * @return The base URL to the target host. + */ public String getBasePath() { return basePath; } + /** + * Sets the base URL to the location where the OpenAPI document is being served. + * + * @param basePath The base URL to the target host. + * @return a {@link org.openapitools.client.ApiClient} object. + */ public ApiClient setBasePath(String basePath) { this.basePath = basePath; + {{#hasOAuthMethods}} + setOauthBasePath(basePath); + {{/hasOAuthMethods}} return this; } + /** + *

Getter for the field servers.

+ * + * @return a {@link java.util.List} of servers. + */ public List getServers() { return servers; } + /** + *

Setter for the field servers.

+ * + * @param servers a {@link java.util.List} of servers. + * @return a {@link org.openapitools.client.ApiClient} object. + */ public ApiClient setServers(List servers) { this.servers = servers; + updateBasePath(); return this; } + /** + *

Getter for the field serverIndex.

+ * + * @return a {@link java.lang.Integer} object. + */ public Integer getServerIndex() { return serverIndex; } + /** + *

Setter for the field serverIndex.

+ * + * @param serverIndex the server index + * @return a {@link org.openapitools.client.ApiClient} object. + */ public ApiClient setServerIndex(Integer serverIndex) { this.serverIndex = serverIndex; + updateBasePath(); return this; } + /** + *

Getter for the field serverVariables.

+ * + * @return a {@link java.util.Map} of server variables. + */ public Map getServerVariables() { return serverVariables; } + /** + *

Setter for the field serverVariables.

+ * + * @param serverVariables a {@link java.util.Map} of server variables. + * @return a {@link org.openapitools.client.ApiClient} object. + */ public ApiClient setServerVariables(Map serverVariables) { this.serverVariables = serverVariables; + updateBasePath(); return this; } + private void updateBasePath() { + if (serverIndex != null) { + setBasePath(servers.get(serverIndex).URL(serverVariables)); + } + } + + {{#hasOAuthMethods}} + private void setOauthBasePath(String basePath) { + for(Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setBasePath(basePath); + } + } + } + + {{/hasOAuthMethods}} /** * Get authentications (key: authentication name, value: authentication). + * * @return Map of authentication object */ public Map getAuthentications() { @@ -244,13 +391,15 @@ public class ApiClient { /** * Helper method to set username for the first HTTP basic authentication. + * * @param username Username + * @return a {@link org.openapitools.client.ApiClient} object. */ - public void setUsername(String username) { + public ApiClient setUsername(String username) { for (Authentication auth : authentications.values()) { if (auth instanceof HttpBasicAuth) { ((HttpBasicAuth) auth).setUsername(username); - return; + return this; } } throw new RuntimeException("No HTTP basic authentication configured!"); @@ -258,13 +407,15 @@ public class ApiClient { /** * Helper method to set password for the first HTTP basic authentication. + * * @param password Password + * @return a {@link org.openapitools.client.ApiClient} object. */ - public void setPassword(String password) { + public ApiClient setPassword(String password) { for (Authentication auth : authentications.values()) { if (auth instanceof HttpBasicAuth) { ((HttpBasicAuth) auth).setPassword(password); - return; + return this; } } throw new RuntimeException("No HTTP basic authentication configured!"); @@ -272,13 +423,15 @@ public class ApiClient { /** * Helper method to set API key value for the first API key authentication. + * * @param apiKey API key + * @return a {@link org.openapitools.client.ApiClient} object. */ - public void setApiKey(String apiKey) { + public ApiClient setApiKey(String apiKey) { for (Authentication auth : authentications.values()) { if (auth instanceof ApiKeyAuth) { ((ApiKeyAuth) auth).setApiKey(apiKey); - return; + return this; } } throw new RuntimeException("No API key authentication configured!"); @@ -288,30 +441,34 @@ public class ApiClient { * Helper method to configure authentications which respects aliases of API keys. * * @param secrets Hash map from authentication name to its secret. + * @return a {@link org.openapitools.client.ApiClient} object. */ - public void configureApiKeys(HashMap secrets) { + public ApiClient configureApiKeys(Map secrets) { for (Map.Entry authEntry : authentications.entrySet()) { Authentication auth = authEntry.getValue(); if (auth instanceof ApiKeyAuth) { String name = authEntry.getKey(); // respect x-auth-id-alias property - name = authenticationLookup.getOrDefault(name, name); + name = authenticationLookup.containsKey(name) ? authenticationLookup.get(name) : name; if (secrets.containsKey(name)) { ((ApiKeyAuth) auth).setApiKey(secrets.get(name)); } } } + return this; } /** * Helper method to set API key prefix for the first API key authentication. + * * @param apiKeyPrefix API key prefix + * @return a {@link org.openapitools.client.ApiClient} object. */ - public void setApiKeyPrefix(String apiKeyPrefix) { + public ApiClient setApiKeyPrefix(String apiKeyPrefix) { for (Authentication auth : authentications.values()) { if (auth instanceof ApiKeyAuth) { ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix); - return; + return this; } } throw new RuntimeException("No API key authentication configured!"); @@ -319,13 +476,15 @@ public class ApiClient { /** * Helper method to set bearer token for the first Bearer authentication. + * * @param bearerToken Bearer token + * @return a {@link org.openapitools.client.ApiClient} object. */ - public void setBearerToken(String bearerToken) { + public ApiClient setBearerToken(String bearerToken) { for (Authentication auth : authentications.values()) { if (auth instanceof HttpBearerAuth) { ((HttpBearerAuth) auth).setBearerToken(bearerToken); - return; + return this; } } throw new RuntimeException("No Bearer authentication configured!"); @@ -334,13 +493,97 @@ public class ApiClient { {{#hasOAuthMethods}} /** * Helper method to set access token for the first OAuth2 authentication. + * * @param accessToken Access token + * @return a {@link org.openapitools.client.ApiClient} object. */ - public void setAccessToken(String accessToken) { + public ApiClient setAccessToken(String accessToken) { for (Authentication auth : authentications.values()) { if (auth instanceof OAuth) { ((OAuth) auth).setAccessToken(accessToken); - return; + return this; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + /** + * Helper method to set the credentials for the first OAuth2 authentication. + * + * @param clientId the client ID + * @param clientSecret the client secret + * @return a {@link org.openapitools.client.ApiClient} object. + */ + public ApiClient setOauthCredentials(String clientId, String clientSecret) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setCredentials(clientId, clientSecret, isDebugging()); + return this; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + /** + * Helper method to set the credentials of a public client for the first OAuth2 authentication. + * + * @param clientId the client ID + * @return a {@link org.openapitools.client.ApiClient} object. + */ + public ApiClient setOauthCredentialsForPublicClient(String clientId) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setCredentialsForPublicClient(clientId, isDebugging()); + return this; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + /** + * Helper method to set the password flow for the first OAuth2 authentication. + * + * @param username the user name + * @param password the user password + * @return a {@link org.openapitools.client.ApiClient} object. + */ + public ApiClient setOauthPasswordFlow(String username, String password) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).usePasswordFlow(username, password); + return this; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + /** + * Helper method to set the authorization code flow for the first OAuth2 authentication. + * + * @param code the authorization code + * @return a {@link org.openapitools.client.ApiClient} object. + */ + public ApiClient setOauthAuthorizationCodeFlow(String code) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).useAuthorizationCodeFlow(code); + return this; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + /** + * Helper method to set the scopes for the first OAuth2 authentication. + * + * @param scope the oauth scope + * @return a {@link org.openapitools.client.ApiClient} object. + */ + public ApiClient setOauthScope(String scope) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setScope(scope); + return this; } } throw new RuntimeException("No OAuth2 authentication configured!"); @@ -349,20 +592,31 @@ public class ApiClient { {{/hasOAuthMethods}} /** * Set the User-Agent header's value (by adding to the default header map). + * * @param userAgent Http user agent - * @return API client + * @return a {@link org.openapitools.client.ApiClient} object. */ public ApiClient setUserAgent(String userAgent) { + this.userAgent = userAgent; addDefaultHeader("User-Agent", userAgent); return this; } + /** + * Get the User-Agent header's value. + * + * @return User-Agent string + */ + public String getUserAgent(){ + return userAgent; + } + /** * Add a default header. * * @param key The header's key * @param value The header's value - * @return API client + * @return a {@link org.openapitools.client.ApiClient} object. */ public ApiClient addDefaultHeader(String key, String value) { defaultHeaderMap.put(key, value); @@ -374,15 +628,38 @@ public class ApiClient { * * @param key The cookie's key * @param value The cookie's value - * @return API client + * @return a {@link org.openapitools.client.ApiClient} object. */ public ApiClient addDefaultCookie(String key, String value) { defaultCookieMap.put(key, value); return this; } + /** + * Gets the client config. + * + * @return Client config + */ + public ClientConfig getClientConfig() { + return clientConfig; + } + + /** + * Set the client config. + * + * @param clientConfig Set the client config + * @return a {@link org.openapitools.client.ApiClient} object. + */ + public ApiClient setClientConfig(ClientConfig clientConfig) { + this.clientConfig = clientConfig; + // Rebuild HTTP Client according to the new "clientConfig" value. + this.httpClient = buildHttpClient(); + return this; + } + /** * Check that whether debugging is enabled for this API client. + * * @return True if debugging is switched on */ public boolean isDebugging() { @@ -393,19 +670,19 @@ public class ApiClient { * Enable/disable debugging for this API client. * * @param debugging To enable (true) or disable (false) debugging - * @return API client + * @return a {@link org.openapitools.client.ApiClient} object. */ public ApiClient setDebugging(boolean debugging) { this.debugging = debugging; // Rebuild HTTP Client according to the new "debugging" value. - this.httpClient = buildHttpClient(debugging); + this.httpClient = buildHttpClient(); return this; } /** * The path of temporary folder used to store downloaded files from endpoints * with file response. The default value is null, i.e. using - * the system's default tempopary folder. + * the system's default temporary folder. * * @return Temp folder path */ @@ -415,8 +692,9 @@ public class ApiClient { /** * Set temp folder path + * * @param tempFolderPath Temp folder path - * @return API client + * @return a {@link org.openapitools.client.ApiClient} object. */ public ApiClient setTempFolderPath(String tempFolderPath) { this.tempFolderPath = tempFolderPath; @@ -425,6 +703,7 @@ public class ApiClient { /** * Connect timeout (in milliseconds). + * * @return Connection timeout */ public int getConnectTimeout() { @@ -435,8 +714,9 @@ public class ApiClient { * Set the connect timeout (in milliseconds). * A value of 0 means no timeout, otherwise values must be between 1 and * {@link Integer#MAX_VALUE}. + * * @param connectionTimeout Connection timeout in milliseconds - * @return API client + * @return a {@link org.openapitools.client.ApiClient} object. */ public ApiClient setConnectTimeout(int connectionTimeout) { this.connectionTimeout = connectionTimeout; @@ -446,6 +726,7 @@ public class ApiClient { /** * read timeout (in milliseconds). + * * @return Read timeout */ public int getReadTimeout() { @@ -456,8 +737,9 @@ public class ApiClient { * Set the read timeout (in milliseconds). * A value of 0 means no timeout, otherwise values must be between 1 and * {@link Integer#MAX_VALUE}. + * * @param readTimeout Read timeout in milliseconds - * @return API client + * @return a {@link org.openapitools.client.ApiClient} object. */ public ApiClient setReadTimeout(int readTimeout) { this.readTimeout = readTimeout; @@ -467,6 +749,7 @@ public class ApiClient { /** * Get the date format used to parse/format date parameters. + * * @return Date format */ public DateFormat getDateFormat() { @@ -475,8 +758,9 @@ public class ApiClient { /** * Set the date format used to parse/format date parameters. + * * @param dateFormat Date format - * @return API client + * @return a {@link org.openapitools.client.ApiClient} object. */ public ApiClient setDateFormat(DateFormat dateFormat) { this.dateFormat = dateFormat; @@ -487,6 +771,7 @@ public class ApiClient { /** * Parse the given string into Date object. + * * @param str String * @return Date */ @@ -500,6 +785,7 @@ public class ApiClient { /** * Format the given Date object into string. + * * @param date Date * @return Date in string format */ @@ -509,6 +795,7 @@ public class ApiClient { /** * Format the given parameter object into string. + * * @param param Object * @return Object in string format */ @@ -517,7 +804,9 @@ public class ApiClient { return ""; } else if (param instanceof Date) { return formatDate((Date) param); - } else if (param instanceof Collection) { + } {{#jsr310}}else if (param instanceof OffsetDateTime) { + return formatOffsetDateTime((OffsetDateTime) param); + } {{/jsr310}}else if (param instanceof Collection) { StringBuilder b = new StringBuilder(); for(Object o : (Collection)param) { if(b.length() > 0) { @@ -533,6 +822,7 @@ public class ApiClient { /* * Format to {@code Pair} objects. + * * @param collectionFormat Collection format * @param name Name * @param value Value @@ -599,6 +889,7 @@ public class ApiClient { * APPLICATION/JSON * application/vnd.company+json * "* / *" is also default to JSON + * * @param mime MIME * @return True if the MIME type is JSON */ @@ -651,6 +942,7 @@ public class ApiClient { /** * Escape the given string to be used as URL query value. + * * @param str String * @return Escaped string */ @@ -665,13 +957,14 @@ public class ApiClient { /** * Serialize the given Java object into string entity according the given * Content-Type (only JSON is supported for now). + * * @param obj Object * @param formParams Form parameters * @param contentType Context type * @return Entity * @throws ApiException API exception */ - public Entity serialize(Object obj, Map formParams, String contentType) throws ApiException { + public Entity serialize(Object obj, Map formParams, String contentType, boolean isBodyNullable) throws ApiException { Entity entity; if (contentType.startsWith("multipart/form-data")) { MultiPart multiPart = new MultiPart(); @@ -695,13 +988,64 @@ public class ApiClient { entity = Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE); } else { // We let jersey handle the serialization - entity = Entity.entity(obj == null ? Entity.text("") : obj, contentType); + if (isBodyNullable) { // payload is nullable + if (obj instanceof String) { + entity = Entity.entity(obj == null ? "null" : "\"" + ((String)obj).replaceAll("\"", Matcher.quoteReplacement("\\\"")) + "\"", contentType); + } else { + entity = Entity.entity(obj == null ? "null" : obj, contentType); + } + } else { + if (obj instanceof String) { + entity = Entity.entity(obj == null ? "" : "\"" + ((String)obj).replaceAll("\"", Matcher.quoteReplacement("\\\"")) + "\"", contentType); + } else { + entity = Entity.entity(obj == null ? "" : obj, contentType); + } + } } return entity; } + /** + * Serialize the given Java object into string according the given + * Content-Type (only JSON, HTTP form is supported for now). + * + * @param obj Object + * @param formParams Form parameters + * @param contentType Context type + * @param isBodyNullable True if the body is nullable + * @return String + * @throws ApiException API exception + */ + public String serializeToString(Object obj, Map formParams, String contentType, boolean isBodyNullable) throws ApiException { + try { + if (contentType.startsWith("multipart/form-data")) { + throw new ApiException("multipart/form-data not yet supported for serializeToString (http signature authentication)"); + } else if (contentType.startsWith("application/x-www-form-urlencoded")) { + String formString = ""; + for (Entry param : formParams.entrySet()) { + formString = param.getKey() + "=" + URLEncoder.encode(parameterToString(param.getValue()), "UTF-8") + "&"; + } + + if (formString.length() == 0) { // empty string + return formString; + } else { + return formString.substring(0, formString.length() - 1); + } + } else { + if (isBodyNullable) { + return obj == null ? "null" : json.getMapper().writeValueAsString(obj); + } else { + return obj == null ? "" : json.getMapper().writeValueAsString(obj); + } + } + } catch (Exception ex) { + throw new ApiException("Failed to perform serializeToString: " + ex.toString()); + } + } + /** * Deserialize response body to Java object according to the Content-Type. + * * @param Type * @param response Response * @param returnType Return type @@ -728,11 +1072,15 @@ public class ApiClient { if (contentTypes != null && !contentTypes.isEmpty()) contentType = String.valueOf(contentTypes.get(0)); + // read the entity stream multiple times + response.bufferEntity(); + return response.readEntity(returnType); } /** * Download file from the given response. + * * @param response Response * @return File * @throws ApiException If fail to read file content from response and write to disk @@ -740,19 +1088,20 @@ public class ApiClient { public File downloadFileFromResponse(Response response) throws ApiException { try { File file = prepareDownloadFile(response); -{{^supportJava6}} Files.copy(response.readEntity(InputStream.class), file.toPath(), StandardCopyOption.REPLACE_EXISTING); -{{/supportJava6}} -{{#supportJava6}} - // Java6 falls back to commons.io for file copying - FileUtils.copyToFile(response.readEntity(InputStream.class), file); -{{/supportJava6}} return file; } catch (IOException e) { throw new ApiException(e); } } + /** + *

Prepare the file for download from the response.

+ * + * @param response a {@link javax.ws.rs.core.Response} object. + * @return a {@link java.io.File} object. + * @throws java.io.IOException if any. + */ public File prepareDownloadFile(Response response) throws IOException { String filename = null; String contentDisposition = (String) response.getHeaders().getFirst("Content-Disposition"); @@ -777,15 +1126,15 @@ public class ApiClient { prefix = filename.substring(0, pos) + "-"; suffix = filename.substring(pos); } - // File.createTempFile requires the prefix to be at least three characters long + // Files.createTempFile requires the prefix to be at least three characters long if (prefix.length() < 3) prefix = "download-"; } if (tempFolderPath == null) - return File.createTempFile(prefix, suffix); + return Files.createTempFile(prefix, suffix).toFile(); else - return File.createTempFile(prefix, suffix, new File(tempFolderPath)); + return Files.createTempFile(Paths.get(tempFolderPath), prefix, suffix).toFile(); } /** @@ -804,33 +1153,39 @@ public class ApiClient { * @param contentType The request's Content-Type header * @param authNames The authentications to apply * @param returnType The return type into which to deserialize the response + * @param isBodyNullable True if the body is nullable * @return The response body in type of string * @throws ApiException API exception */ - public ApiResponse invokeAPI(String operation, String path, String method, List queryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType) throws ApiException { - updateParamsForAuth(authNames, queryParams, headerParams, cookieParams); + public ApiResponse invokeAPI( + String operation, + String path, + String method, + List queryParams, + Object body, + Map headerParams, + Map cookieParams, + Map formParams, + String accept, + String contentType, + String[] authNames, + GenericType returnType, + boolean isBodyNullable) + throws ApiException { // Not using `.target(targetURL).path(path)` below, // to support (constant) query string in `path`, e.g. "/posts?draft=1" String targetURL; - if (serverIndex != null) { - Integer index; - List serverConfigurations; - Map variables; - - if (operationServers.containsKey(operation)) { - index = operationServerIndex.getOrDefault(operation, serverIndex); - variables = operationServerVariables.getOrDefault(operation, serverVariables); - serverConfigurations = operationServers.get(operation); - } else { - index = serverIndex; - variables = serverVariables; - serverConfigurations = servers; - } + if (serverIndex != null && operationServers.containsKey(operation)) { + Integer index = operationServerIndex.containsKey(operation) ? operationServerIndex.get(operation) : serverIndex; + Map variables = operationServerVariables.containsKey(operation) ? + operationServerVariables.get(operation) : serverVariables; + List serverConfigurations = operationServers.get(operation); if (index < 0 || index >= serverConfigurations.size()) { - throw new ArrayIndexOutOfBoundsException(String.format( - "Invalid index %d when selecting the host settings. Must be less than %d", index, serverConfigurations.size() - )); + throw new ArrayIndexOutOfBoundsException( + String.format( + "Invalid index %d when selecting the host settings. Must be less than %d", + index, serverConfigurations.size())); } targetURL = serverConfigurations.get(index).URL(variables) + path; } else { @@ -846,13 +1201,11 @@ public class ApiClient { } } - Invocation.Builder invocationBuilder = target.request().accept(accept); - - for (Entry entry : headerParams.entrySet()) { - String value = entry.getValue(); - if (value != null) { - invocationBuilder = invocationBuilder.header(entry.getKey(), value); - } + Invocation.Builder invocationBuilder; + if (accept != null) { + invocationBuilder = target.request().accept(accept); + } else { + invocationBuilder = target.request(); } for (Entry entry : cookieParams.entrySet()) { @@ -869,51 +1222,68 @@ public class ApiClient { } } - for (Entry entry : defaultHeaderMap.entrySet()) { - String key = entry.getKey(); - if (!headerParams.containsKey(key)) { - String value = entry.getValue(); - if (value != null) { - invocationBuilder = invocationBuilder.header(key, value); - } + Entity entity = serialize(body, formParams, contentType, isBodyNullable); + + // put all headers in one place + Map allHeaderParams = new HashMap<>(defaultHeaderMap); + allHeaderParams.putAll(headerParams); + + // update different parameters (e.g. headers) for authentication + updateParamsForAuth( + authNames, + queryParams, + allHeaderParams, + cookieParams, + {{#hasHttpSignatureMethods}} + serializeToString(body, formParams, contentType, isBodyNullable), + {{/hasHttpSignatureMethods}} + {{^hasHttpSignatureMethods}} + null, + {{/hasHttpSignatureMethods}} + method, + target.getUri()); + + for (Entry entry : allHeaderParams.entrySet()) { + String value = entry.getValue(); + if (value != null) { + invocationBuilder = invocationBuilder.header(entry.getKey(), value); } } - Entity entity = serialize(body, formParams, contentType); - Response response = null; try { - if ("GET".equals(method)) { - response = invocationBuilder.get(); - } else if ("POST".equals(method)) { - response = invocationBuilder.post(entity); - } else if ("PUT".equals(method)) { - response = invocationBuilder.put(entity); - } else if ("DELETE".equals(method)) { - response = invocationBuilder.method("DELETE", entity); - } else if ("PATCH".equals(method)) { - response = invocationBuilder.method("PATCH", entity); - } else if ("HEAD".equals(method)) { - response = invocationBuilder.head(); - } else if ("OPTIONS".equals(method)) { - response = invocationBuilder.options(); - } else if ("TRACE".equals(method)) { - response = invocationBuilder.trace(); - } else { - throw new ApiException(500, "unknown method type " + method); + response = sendRequest(method, invocationBuilder, entity); + + {{#hasOAuthMethods}} + // If OAuth is used and a status 401 is received, renew the access token and retry the request + if (response.getStatusInfo() == Status.UNAUTHORIZED) { + for (String authName : authNames) { + Authentication authentication = authentications.get(authName); + if (authentication instanceof OAuth) { + OAuth2AccessToken accessToken = ((OAuth) authentication).renewAccessToken(); + if (accessToken != null) { + invocationBuilder.header("Authorization", null); + invocationBuilder.header("Authorization", "Bearer " + accessToken.getAccessToken()); + response = sendRequest(method, invocationBuilder, entity); + } + break; + } + } } + {{/hasOAuthMethods}} int statusCode = response.getStatusInfo().getStatusCode(); Map> responseHeaders = buildResponseHeaders(response); - if (response.getStatus() == Status.NO_CONTENT.getStatusCode()) { - return new ApiResponse<{{#supportJava6}}T{{/supportJava6}}>(statusCode, responseHeaders); + if (response.getStatusInfo() == Status.NO_CONTENT) { + return new ApiResponse(statusCode, responseHeaders); } else if (response.getStatusInfo().getFamily() == Status.Family.SUCCESSFUL) { - if (returnType == null) - return new ApiResponse<{{#supportJava6}}T{{/supportJava6}}>(statusCode, responseHeaders); - else - return new ApiResponse<{{#supportJava6}}T{{/supportJava6}}>(statusCode, responseHeaders, deserialize(response, returnType)); + if (returnType == null) { + return new ApiResponse(statusCode, responseHeaders); + } else { + return new ApiResponse(statusCode, responseHeaders, deserialize(response, returnType)); + } } else { String message = "error"; String respBody = null; @@ -926,35 +1296,64 @@ public class ApiClient { } } throw new ApiException( - response.getStatus(), - message, - buildResponseHeaders(response), - respBody); + response.getStatus(), message, buildResponseHeaders(response), respBody); } } finally { try { response.close(); } catch (Exception e) { - // it's not critical, since the response object is local in method invokeAPI; that's fine, just continue + // it's not critical, since the response object is local in method invokeAPI; that's fine, + // just continue } } } + private Response sendRequest(String method, Invocation.Builder invocationBuilder, Entity entity) { + Response response; + if ("POST".equals(method)) { + response = invocationBuilder.post(entity); + } else if ("PUT".equals(method)) { + response = invocationBuilder.put(entity); + } else if ("DELETE".equals(method)) { + response = invocationBuilder.method("DELETE", entity); + } else if ("PATCH".equals(method)) { + response = invocationBuilder.method("PATCH", entity); + } else { + response = invocationBuilder.method(method); + } + return response; + } + /** * @deprecated Add qualified name of the operation as a first parameter. */ @Deprecated - public ApiResponse invokeAPI(String path, String method, List queryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType) throws ApiException { - return invokeAPI(null, path, method, queryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames, returnType); + public ApiResponse invokeAPI(String path, String method, List queryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType, boolean isBodyNullable) throws ApiException { + return invokeAPI(null, path, method, queryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames, returnType, isBodyNullable); } /** * Build the Client used to make HTTP requests. - * @param debugging Debug setting + * * @return Client */ - protected Client buildHttpClient(boolean debugging) { - final ClientConfig clientConfig = new ClientConfig(); + protected Client buildHttpClient() { + // recreate the client config to pickup changes + clientConfig = getDefaultClientConfig(); + + ClientBuilder clientBuilder = ClientBuilder.newBuilder(); + customizeClientBuilder(clientBuilder); + clientBuilder = clientBuilder.withConfig(clientConfig); + return clientBuilder.build(); + } + + /** + * Get the default client config. + * + * @return Client config + */ + public ClientConfig getDefaultClientConfig() { + ClientConfig clientConfig = new ClientConfig(); clientConfig.register(MultiPartFeature.class); clientConfig.register(json); clientConfig.register(JacksonFeature.class); @@ -962,27 +1361,74 @@ public class ApiClient { // turn off compliance validation to be able to send payloads with DELETE calls clientConfig.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true); if (debugging) { -{{^supportJava6}} clientConfig.register(new LoggingFeature(java.util.logging.Logger.getLogger(LoggingFeature.DEFAULT_LOGGER_NAME), java.util.logging.Level.INFO, LoggingFeature.Verbosity.PAYLOAD_ANY, 1024*50 /* Log payloads up to 50K */)); clientConfig.property(LoggingFeature.LOGGING_FEATURE_VERBOSITY, LoggingFeature.Verbosity.PAYLOAD_ANY); // Set logger to ALL java.util.logging.Logger.getLogger(LoggingFeature.DEFAULT_LOGGER_NAME).setLevel(java.util.logging.Level.ALL); -{{/supportJava6}} -{{#supportJava6}} - clientConfig.register(new LoggingFilter(java.util.logging.Logger.getLogger(LoggingFilter.class.getName()), true)); -{{/supportJava6}} } else { // suppress warnings for payloads with DELETE calls: java.util.logging.Logger.getLogger("org.glassfish.jersey.client").setLevel(java.util.logging.Level.SEVERE); } - performAdditionalClientConfiguration(clientConfig); - return ClientBuilder.newClient(clientConfig); + + return clientConfig; } - protected void performAdditionalClientConfiguration(ClientConfig clientConfig) { + /** + * Customize the client builder. + * + * This method can be overridden to customize the API client. For example, this can be used to: + * 1. Set the hostname verifier to be used by the client to verify the endpoint's hostname + * against its identification information. + * 2. Set the client-side key store. + * 3. Set the SSL context that will be used when creating secured transport connections to + * server endpoints from web targets created by the client instance that is using this SSL context. + * 4. Set the client-side trust store. + * + * To completely disable certificate validation (at your own risk), you can + * override this method and invoke disableCertificateValidation(clientBuilder). + * + * @param clientBuilder a {@link javax.ws.rs.client.ClientBuilder} object. + */ + protected void customizeClientBuilder(ClientBuilder clientBuilder) { // No-op extension point } + /** + * Disable X.509 certificate validation in TLS connections. + * + * Please note that trusting all certificates is extremely risky. + * This may be useful in a development environment with self-signed certificates. + * + * @param clientBuilder a {@link javax.ws.rs.client.ClientBuilder} object. + * @throws java.security.KeyManagementException if any. + * @throws java.security.NoSuchAlgorithmException if any. + */ + protected void disableCertificateValidation(ClientBuilder clientBuilder) throws KeyManagementException, NoSuchAlgorithmException { + TrustManager[] trustAllCerts = new X509TrustManager[] { + new X509TrustManager() { + @Override + public X509Certificate[] getAcceptedIssuers() { + return null; + } + @Override + public void checkClientTrusted(X509Certificate[] certs, String authType) { + } + @Override + public void checkServerTrusted(X509Certificate[] certs, String authType) { + } + } + }; + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(null, trustAllCerts, new SecureRandom()); + clientBuilder.sslContext(sslContext); + } + + /** + *

Build the response headers.

+ * + * @param response a {@link javax.ws.rs.core.Response} object. + * @return a {@link java.util.Map} of response headers. + */ protected Map> buildResponseHeaders(Response response) { Map> responseHeaders = new HashMap>(); for (Entry> entry: response.getHeaders().entrySet()) { @@ -1003,12 +1449,17 @@ public class ApiClient { * @param queryParams List of query parameters * @param headerParams Map of header parameters * @param cookieParams Map of cookie parameters + * @param method HTTP method (e.g. POST) + * @param uri HTTP URI */ - protected void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams, Map cookieParams) { + protected void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams, + Map cookieParams, String payload, String method, URI uri) throws ApiException { for (String authName : authNames) { Authentication auth = authentications.get(authName); - if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); - auth.applyToParams(queryParams, headerParams, cookieParams); + if (auth == null) { + continue; + } + auth.applyToParams(queryParams, headerParams, cookieParams, payload, method, uri); } } } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/ApiResponse.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/ApiResponse.mustache index a67b11f05..86c889b0f 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/ApiResponse.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/ApiResponse.mustache @@ -5,7 +5,7 @@ package {{invokerPackage}}; import java.util.List; import java.util.Map; {{#caseInsensitiveResponseHeaders}} -import java.util.Map.Entry; +import java.util.Map.Entry; import java.util.TreeMap; {{/caseInsensitiveResponseHeaders}} @@ -44,14 +44,29 @@ public class ApiResponse { this.data = data; } + /** + * Get the status code + * + * @return status code + */ public int getStatusCode() { return statusCode; } + /** + * Get the headers + * + * @return map of headers + */ public Map> getHeaders() { return headers; } + /** + * Get the data + * + * @return data + */ public T getData() { return data; } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/JSON.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/JSON.mustache index 56ea77278..8de585519 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/JSON.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/JSON.mustache @@ -1,23 +1,25 @@ package {{invokerPackage}}; -{{#threetenbp}} -import org.threeten.bp.*; -{{/threetenbp}} import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; +import com.fasterxml.jackson.databind.json.JsonMapper; +{{#openApiNullable}} import org.openapitools.jackson.nullable.JsonNullableModule; -{{#java8}} +{{/openApiNullable}} import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -{{/java8}} {{#joda}} import com.fasterxml.jackson.datatype.joda.JodaModule; {{/joda}} -{{#threetenbp}} -import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule; -{{/threetenbp}} +{{#models.0}} +import {{modelPackage}}.*; +{{/models.0}} import java.text.DateFormat; - +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import javax.ws.rs.core.GenericType; import javax.ws.rs.ext.ContextResolver; {{>generatedAnnotation}} @@ -27,27 +29,21 @@ public class JSON implements ContextResolver { public JSON() { mapper = new ObjectMapper(); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); + JsonMapper.builder().configure(MapperFeature.ALLOW_COERCION_OF_SCALARS, false); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); + mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, true); mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); mapper.setDateFormat(new RFC3339DateFormat()); - {{#java8}} mapper.registerModule(new JavaTimeModule()); - {{/java8}} {{#joda}} mapper.registerModule(new JodaModule()); {{/joda}} - {{#threetenbp}} - ThreeTenModule module = new ThreeTenModule(); - module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT); - module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME); - module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); - mapper.registerModule(module); - {{/threetenbp}} + {{#openApiNullable}} JsonNullableModule jnm = new JsonNullableModule(); mapper.registerModule(jnm); + {{/openApiNullable}} } /** @@ -62,4 +58,204 @@ public class JSON implements ContextResolver { public ObjectMapper getContext(Class type) { return mapper; } + + /** + * Get the object mapper + * + * @return object mapper + */ + public ObjectMapper getMapper() { return mapper; } + + /** + * Returns the target model class that should be used to deserialize the input data. + * The discriminator mappings are used to determine the target model class. + * + * @param node The input data. + * @param modelClass The class that contains the discriminator mappings. + */ + public static Class getClassForElement(JsonNode node, Class modelClass) { + ClassDiscriminatorMapping cdm = modelDiscriminators.get(modelClass); + if (cdm != null) { + return cdm.getClassForElement(node, new HashSet>()); + } + return null; + } + + /** + * Helper class to register the discriminator mappings. + */ + private static class ClassDiscriminatorMapping { + // The model class name. + Class modelClass; + // The name of the discriminator property. + String discriminatorName; + // The discriminator mappings for a model class. + Map> discriminatorMappings; + + // Constructs a new class discriminator. + ClassDiscriminatorMapping(Class cls, String propertyName, Map> mappings) { + modelClass = cls; + discriminatorName = propertyName; + discriminatorMappings = new HashMap>(); + if (mappings != null) { + discriminatorMappings.putAll(mappings); + } + } + + // Return the name of the discriminator property for this model class. + String getDiscriminatorPropertyName() { + return discriminatorName; + } + + // Return the discriminator value or null if the discriminator is not + // present in the payload. + String getDiscriminatorValue(JsonNode node) { + // Determine the value of the discriminator property in the input data. + if (discriminatorName != null) { + // Get the value of the discriminator property, if present in the input payload. + node = node.get(discriminatorName); + if (node != null && node.isValueNode()) { + String discrValue = node.asText(); + if (discrValue != null) { + return discrValue; + } + } + } + return null; + } + + /** + * Returns the target model class that should be used to deserialize the input data. + * This function can be invoked for anyOf/oneOf composed models with discriminator mappings. + * The discriminator mappings are used to determine the target model class. + * + * @param node The input data. + * @param visitedClasses The set of classes that have already been visited. + */ + Class getClassForElement(JsonNode node, Set> visitedClasses) { + if (visitedClasses.contains(modelClass)) { + // Class has already been visited. + return null; + } + // Determine the value of the discriminator property in the input data. + String discrValue = getDiscriminatorValue(node); + if (discrValue == null) { + return null; + } + Class cls = discriminatorMappings.get(discrValue); + // It may not be sufficient to return this cls directly because that target class + // may itself be a composed schema, possibly with its own discriminator. + visitedClasses.add(modelClass); + for (Class childClass : discriminatorMappings.values()) { + ClassDiscriminatorMapping childCdm = modelDiscriminators.get(childClass); + if (childCdm == null) { + continue; + } + if (!discriminatorName.equals(childCdm.discriminatorName)) { + discrValue = getDiscriminatorValue(node); + if (discrValue == null) { + continue; + } + } + if (childCdm != null) { + // Recursively traverse the discriminator mappings. + Class childDiscr = childCdm.getClassForElement(node, visitedClasses); + if (childDiscr != null) { + return childDiscr; + } + } + } + return cls; + } + } + + /** + * Returns true if inst is an instance of modelClass in the OpenAPI model hierarchy. + * + * The Java class hierarchy is not implemented the same way as the OpenAPI model hierarchy, + * so it's not possible to use the instanceof keyword. + * + * @param modelClass A OpenAPI model class. + * @param inst The instance object. + */ + public static boolean isInstanceOf(Class modelClass, Object inst, Set> visitedClasses) { + if (modelClass.isInstance(inst)) { + // This handles the 'allOf' use case with single parent inheritance. + return true; + } + if (visitedClasses.contains(modelClass)) { + // This is to prevent infinite recursion when the composed schemas have + // a circular dependency. + return false; + } + visitedClasses.add(modelClass); + + // Traverse the oneOf/anyOf composed schemas. + Map descendants = modelDescendants.get(modelClass); + if (descendants != null) { + for (GenericType childType : descendants.values()) { + if (isInstanceOf(childType.getRawType(), inst, visitedClasses)) { + return true; + } + } + } + return false; + } + + /** + * A map of discriminators for all model classes. + */ + private static Map, ClassDiscriminatorMapping> modelDiscriminators = new HashMap, ClassDiscriminatorMapping>(); + + /** + * A map of oneOf/anyOf descendants for each model class. + */ + private static Map, Map> modelDescendants = new HashMap, Map>(); + + /** + * Register a model class discriminator. + * + * @param modelClass the model class + * @param discriminatorPropertyName the name of the discriminator property + * @param mappings a map with the discriminator mappings. + */ + public static void registerDiscriminator(Class modelClass, String discriminatorPropertyName, Map> mappings) { + ClassDiscriminatorMapping m = new ClassDiscriminatorMapping(modelClass, discriminatorPropertyName, mappings); + modelDiscriminators.put(modelClass, m); + } + + /** + * Register the oneOf/anyOf descendants of the modelClass. + * + * @param modelClass the model class + * @param descendants a map of oneOf/anyOf descendants. + */ + public static void registerDescendants(Class modelClass, Map descendants) { + modelDescendants.put(modelClass, descendants); + } + + private static JSON json; + + static + { + json = new JSON(); + } + + /** + * Get the default JSON instance. + * + * @return the default JSON instance + */ + public static JSON getDefault() { + return json; + } + + /** + * Set the default JSON instance. + * + * @param json JSON instance to be used + */ + public static void setDefault(JSON json) { + JSON.json = json; + } } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/additional_properties.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/additional_properties.mustache new file mode 100644 index 000000000..61973dc24 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/additional_properties.mustache @@ -0,0 +1,39 @@ +{{#additionalPropertiesType}} + /** + * A container for additional, undeclared properties. + * This is a holder for any undeclared properties as specified with + * the 'additionalProperties' keyword in the OAS document. + */ + private Map additionalProperties; + + /** + * Set the additional (undeclared) property with the specified name and value. + * If the property does not already exist, create it otherwise replace it. + */ + @JsonAnySetter + public {{classname}} putAdditionalProperty(String key, {{{.}}} value) { + if (this.additionalProperties == null) { + this.additionalProperties = new HashMap(); + } + this.additionalProperties.put(key, value); + return this; + } + + /** + * Return the additional (undeclared) property. + */ + @JsonAnyGetter + public Map getAdditionalProperties() { + return additionalProperties; + } + + /** + * Return the additional (undeclared) property with the specified name. + */ + public {{{.}}} getAdditionalProperty(String key) { + if (this.additionalProperties == null) { + return null; + } + return this.additionalProperties.get(key); + } +{{/additionalPropertiesType}} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/anyof_model.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/anyof_model.mustache new file mode 100644 index 000000000..d5b381987 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/anyof_model.mustache @@ -0,0 +1,202 @@ +import javax.ws.rs.core.GenericType; +import javax.ws.rs.core.Response; +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import {{invokerPackage}}.JSON; + +{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>xmlAnnotation}} +@JsonDeserialize(using={{classname}}.{{classname}}Deserializer.class) +@JsonSerialize(using = {{classname}}.{{classname}}Serializer.class) +public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-implements}}, {{{.}}}{{/vendorExtensions.x-implements}} { + private static final Logger log = Logger.getLogger({{classname}}.class.getName()); + + public static class {{classname}}Serializer extends StdSerializer<{{classname}}> { + public {{classname}}Serializer(Class<{{classname}}> t) { + super(t); + } + + public {{classname}}Serializer() { + this(null); + } + + @Override + public void serialize({{classname}} value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { + jgen.writeObject(value.getActualInstance()); + } + } + + public static class {{classname}}Deserializer extends StdDeserializer<{{classname}}> { + public {{classname}}Deserializer() { + this({{classname}}.class); + } + + public {{classname}}Deserializer(Class vc) { + super(vc); + } + + @Override + public {{classname}} deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { + JsonNode tree = jp.readValueAsTree(); + + Object deserialized = null; + {{#discriminator}} + Class cls = JSON.getClassForElement(tree, {{classname}}.class); + if (cls != null) { + // When the OAS schema includes a discriminator, use the discriminator value to + // discriminate the anyOf schemas. + // Get the discriminator mapping value to get the class. + deserialized = tree.traverse(jp.getCodec()).readValueAs(cls); + {{classname}} ret = new {{classname}}(); + ret.setActualInstance(deserialized); + return ret; + } + {{/discriminator}} + {{#anyOf}} + // deserialize {{{.}}} + try { + deserialized = tree.traverse(jp.getCodec()).readValueAs({{{.}}}.class); + {{classname}} ret = new {{classname}}(); + ret.setActualInstance(deserialized); + return ret; + } catch (Exception e) { + // deserialization failed, continue, log to help debugging + log.log(Level.FINER, "Input data does not match '{{classname}}'", e); + } + + {{/anyOf}} + throw new IOException(String.format("Failed deserialization for {{classname}}: no match found")); + } + + /** + * Handle deserialization of the 'null' value. + */ + @Override + public {{classname}} getNullValue(DeserializationContext ctxt) throws JsonMappingException { + {{#isNullable}} + return null; + {{/isNullable}} + {{^isNullable}} + throw new JsonMappingException(ctxt.getParser(), "{{classname}} cannot be null"); + {{/isNullable}} + } + } + + // store a list of schema names defined in anyOf + public static final Map schemas = new HashMap(); + + public {{classname}}() { + super("anyOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); + } +{{> libraries/jersey2/additional_properties }} + {{#additionalPropertiesType}} + /** + * Return true if this {{name}} object is equal to o. + */ + @Override + public boolean equals(Object o) { + return super.equals(o) && Objects.equals(this.additionalProperties, (({{classname}})o).additionalProperties); + } + + @Override + public int hashCode() { + return Objects.hash(getActualInstance(), isNullable(), getSchemaType(), additionalProperties); + } + {{/additionalPropertiesType}} + {{#anyOf}} + public {{classname}}({{{.}}} o) { + super("anyOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); + setActualInstance(o); + } + + {{/anyOf}} + static { + {{#anyOf}} + schemas.put("{{{.}}}", new GenericType<{{{.}}}>() { + }); + {{/anyOf}} + JSON.registerDescendants({{classname}}.class, Collections.unmodifiableMap(schemas)); + {{#discriminator}} + // Initialize and register the discriminator mappings. + Map> mappings = new HashMap>(); + {{#mappedModels}} + mappings.put("{{mappingName}}", {{modelName}}.class); + {{/mappedModels}} + mappings.put("{{name}}", {{classname}}.class); + JSON.registerDiscriminator({{classname}}.class, "{{propertyBaseName}}", mappings); + {{/discriminator}} + } + + @Override + public Map getSchemas() { + return {{classname}}.schemas; + } + + /** + * Set the instance that matches the anyOf child schema, check + * the instance parameter is valid against the anyOf child schemas: + * {{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}} + * + * It could be an instance of the 'anyOf' schemas. + * The anyOf child schemas may themselves be a composed schema (allOf, anyOf, anyOf). + */ + @Override + public void setActualInstance(Object instance) { + {{#isNullable}} + if (instance == null) { + super.setActualInstance(instance); + return; + } + + {{/isNullable}} + {{#anyOf}} + if (JSON.isInstanceOf({{{.}}}.class, instance, new HashSet>())) { + super.setActualInstance(instance); + return; + } + + {{/anyOf}} + throw new RuntimeException("Invalid instance type. Must be {{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}}"); + } + + /** + * Get the actual instance, which can be the following: + * {{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}} + * + * @return The actual instance ({{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}}) + */ + @Override + public Object getActualInstance() { + return super.getActualInstance(); + } + + {{#anyOf}} + /** + * Get the actual instance of `{{{.}}}`. If the actual instance is not `{{{.}}}`, + * the ClassCastException will be thrown. + * + * @return The actual instance of `{{{.}}}` + * @throws ClassCastException if the instance is not `{{{.}}}` + */ + public {{{.}}} get{{{.}}}() throws ClassCastException { + return ({{{.}}})super.getActualInstance(); + } + + {{/anyOf}} +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/api.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/api.mustache index 4a2e61afe..756f0c129 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/api.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/api.mustache @@ -16,8 +16,8 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -{{/fullJavaUtil}} +{{/fullJavaUtil}} {{>generatedAnnotation}} {{#operations}} public class {{classname}} { @@ -31,13 +31,24 @@ public class {{classname}} { this.apiClient = apiClient; } + /** + * Get the API client + * + * @return API client + */ public ApiClient getApiClient() { return apiClient; } + /** + * Set the API client + * + * @param apiClient an instance of API client + */ public void setApiClient(ApiClient apiClient) { this.apiClient = apiClient; } + {{#operation}} {{^vendorExtensions.x-group-parameters}} /** @@ -47,7 +58,7 @@ public class {{classname}} { * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} {{/allParams}} {{#returnType}} - * @return {{returnType}} + * @return {{.}} {{/returnType}} * @throws ApiException if fails to make API call {{#responses.0}} @@ -70,8 +81,8 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { - {{#returnType}}return {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}){{#returnType}}.getData(){{/returnType}}; + public {{#returnType}}{{{.}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { + {{#returnType}}return {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}){{#returnType}}.getData(){{/returnType}}; } {{/vendorExtensions.x-group-parameters}} @@ -82,7 +93,7 @@ public class {{classname}} { {{#allParams}} * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} {{/allParams}} - * @return ApiResponse<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + * @return ApiResponse<{{returnType}}{{^returnType}}Void{{/returnType}}> * @throws ApiException if fails to make API call {{#responses.0}} * @http.response.details @@ -104,7 +115,7 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}} ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { + public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}} ApiResponse<{{{returnType}}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { Object localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; {{#allParams}}{{#required}} // verify the required parameter '{{paramName}}' is set @@ -123,7 +134,7 @@ public class {{classname}} { {{javaUtilPrefix}}Map localVarFormParams = new {{javaUtilPrefix}}HashMap(); {{#queryParams}} - localVarQueryParams.addAll(apiClient.parameterToPairs("{{#collectionFormat}}{{{collectionFormat}}}{{/collectionFormat}}", "{{baseName}}", {{paramName}})); + localVarQueryParams.addAll(apiClient.parameterToPairs("{{{collectionFormat}}}", "{{baseName}}", {{paramName}})); {{/queryParams}} {{#headerParams}}if ({{paramName}} != null) @@ -139,33 +150,39 @@ public class {{classname}} { {{/formParams}} final String[] localVarAccepts = { - {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} + {{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}} }; final String localVarAccept = apiClient.selectHeaderAccept(localVarAccepts); final String[] localVarContentTypes = { - {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} + {{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}} }; final String localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes); - String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{^-last}}, {{/-last}}{{/authMethods}} }; + + {{#returnType}} + GenericType<{{{returnType}}}> localVarReturnType = new GenericType<{{{returnType}}}>() {}; - {{#returnType}}GenericType<{{{returnType}}}> localVarReturnType = new GenericType<{{{returnType}}}>() {};{{/returnType}} - return apiClient.invokeAPI("{{classname}}.{{operationId}}", localVarPath, "{{httpMethod}}", localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, {{#returnType}}localVarReturnType{{/returnType}}{{^returnType}}null{{/returnType}}); + {{/returnType}} + return apiClient.invokeAPI("{{classname}}.{{operationId}}", localVarPath, "{{httpMethod}}", localVarQueryParams, localVarPostBody, + localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, + localVarAuthNames, {{#returnType}}localVarReturnType{{/returnType}}{{^returnType}}null{{/returnType}}, {{#bodyParam}}{{#isNullable}}true{{/isNullable}}{{^isNullable}}false{{/isNullable}}{{/bodyParam}}{{^bodyParam}}false{{/bodyParam}}); } {{#vendorExtensions.x-group-parameters}} public class API{{operationId}}Request { {{#allParams}} - private {{#isRequired}}final {{/isRequired}}{{{dataType}}} {{localVariablePrefix}}{{paramName}}; + private {{{dataType}}} {{paramName}}; {{/allParams}} - private API{{operationId}}Request({{#pathParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}) { + private API{{operationId}}Request({{#pathParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/pathParams}}) { {{#pathParams}} - this.{{localVariablePrefix}}{{paramName}} = {{paramName}}; + this.{{paramName}} = {{paramName}}; {{/pathParams}} } - {{#allParams}}{{^isPathParam}} + {{#allParams}} + {{^isPathParam}} /** * Set {{paramName}} @@ -173,10 +190,11 @@ public class {{classname}} { * @return API{{operationId}}Request */ public API{{operationId}}Request {{paramName}}({{{dataType}}} {{paramName}}) { - this.{{localVariablePrefix}}{{paramName}} = {{paramName}}; + this.{{paramName}} = {{paramName}}; return this; } - {{/isPathParam}}{{/allParams}} + {{/isPathParam}} + {{/allParams}} /** * Execute {{operationId}} request @@ -194,13 +212,13 @@ public class {{classname}} { {{#isDeprecated}}* @deprecated{{/isDeprecated}} */ {{#isDeprecated}}@Deprecated{{/isDeprecated}} - public {{#returnType}}{{{.}}}{{/returnType}}{{^returnType}}void{{/returnType}} execute() throws ApiException { + public {{{returnType}}}{{^returnType}}void{{/returnType}} execute() throws ApiException { {{#returnType}}return {{/returnType}}this.executeWithHttpInfo().getData(); } /** * Execute {{operationId}} request with HTTP info returned - * @return ApiResponse<{{#returnType}}{{.}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + * @return ApiResponse<{{returnType}}{{^returnType}}Void{{/returnType}}> * @throws ApiException if fails to make API call {{#responses.0}} * @http.response.details @@ -211,11 +229,14 @@ public class {{classname}} { {{/responses}} {{/responses.0}} - {{#isDeprecated}}* @deprecated{{/isDeprecated}} + {{#isDeprecated}} + * @deprecated{{/isDeprecated}} */ - {{#isDeprecated}}@Deprecated{{/isDeprecated}} - public ApiResponse<{{#returnType}}{{{.}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> executeWithHttpInfo() throws ApiException { - return {{operationId}}WithHttpInfo({{#allParams}}{{localVariablePrefix}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public ApiResponse<{{{returnType}}}{{^returnType}}Void{{/returnType}}> executeWithHttpInfo() throws ApiException { + return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); } } @@ -229,9 +250,11 @@ public class {{classname}} { {{#externalDocs}}* {{description}} * @see {{summary}} Documentation{{/externalDocs}} */ - {{#isDeprecated}}@Deprecated{{/isDeprecated}} - public API{{operationId}}Request {{operationId}}({{#pathParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}) throws ApiException { - return new API{{operationId}}Request({{#pathParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}); + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public API{{operationId}}Request {{operationId}}({{#pathParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/pathParams}}) throws ApiException { + return new API{{operationId}}Request({{#pathParams}}{{paramName}}{{^-last}}, {{/-last}}{{/pathParams}}); } {{/vendorExtensions.x-group-parameters}} {{/operation}} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/apiException.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/apiException.mustache index e89524565..74a419aac 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/apiException.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/apiException.mustache @@ -5,10 +5,13 @@ package {{invokerPackage}}; import java.util.Map; import java.util.List; {{#caseInsensitiveResponseHeaders}} -import java.util.Map.Entry; +import java.util.Map.Entry; import java.util.TreeMap; {{/caseInsensitiveResponseHeaders}} +/** + * API Exception + */ {{>generatedAnnotation}} public class ApiException extends{{#useRuntimeException}} RuntimeException {{/useRuntimeException}}{{^useRuntimeException}} Exception {{/useRuntimeException}}{ private int code = 0; @@ -31,7 +34,7 @@ public class ApiException extends{{#useRuntimeException}} RuntimeException {{/us {{#caseInsensitiveResponseHeaders}} Map> headers = new TreeMap>(String.CASE_INSENSITIVE_ORDER); for(Entry> entry : responseHeaders.entrySet()){ - headers.put(entry.getKey().toLowerCase(), entry.getValue()); + headers.put(entry.getKey().toLowerCase(), entry.getValue()); } {{/caseInsensitiveResponseHeaders}} this.responseHeaders = {{#caseInsensitiveResponseHeaders}}headers{{/caseInsensitiveResponseHeaders}}{{^caseInsensitiveResponseHeaders}}responseHeaders{{/caseInsensitiveResponseHeaders}}; @@ -60,7 +63,7 @@ public class ApiException extends{{#useRuntimeException}} RuntimeException {{/us {{#caseInsensitiveResponseHeaders}} Map> headers = new TreeMap>(String.CASE_INSENSITIVE_ORDER); for(Entry> entry : responseHeaders.entrySet()){ - headers.put(entry.getKey().toLowerCase(), entry.getValue()); + headers.put(entry.getKey().toLowerCase(), entry.getValue()); } {{/caseInsensitiveResponseHeaders}} this.responseHeaders = {{#caseInsensitiveResponseHeaders}}headers{{/caseInsensitiveResponseHeaders}}{{^caseInsensitiveResponseHeaders}}responseHeaders{{/caseInsensitiveResponseHeaders}}; diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/api_doc.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/api_doc.mustache index f162d1cc9..26c98508e 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/api_doc.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/api_doc.mustache @@ -1,12 +1,12 @@ # {{classname}}{{#description}} -{{description}}{{/description}} +{{.}}{{/description}} All URIs are relative to *{{basePath}}* -Method | HTTP request | Description -------------- | ------------- | ------------- -{{#operations}}{{#operation}}[**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +| Method | HTTP request | Description | +|------------- | ------------- | -------------| +{{#operations}}{{#operation}}| [**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{summary}} | {{/operation}}{{/operations}} {{#operations}} @@ -15,10 +15,10 @@ Method | HTTP request | Description ## {{operationId}} {{^vendorExtensions.x-group-parameters}} -> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) +> {{#returnType}}{{.}} {{/returnType}}{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) {{/vendorExtensions.x-group-parameters}} {{#vendorExtensions.x-group-parameters}} -> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#pathParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}){{#allParams}}{{^isPathParam}}.{{paramName}}({{paramName}}){{/isPathParam}}{{/allParams}}.execute(); +> {{#returnType}}{{.}} {{/returnType}}{{operationId}}({{#pathParams}}{{paramName}}{{^-last}}, {{/-last}}{{/pathParams}}){{#allParams}}{{^isPathParam}}.{{paramName}}({{paramName}}){{/isPathParam}}{{/allParams}}.execute(); {{/vendorExtensions.x-group-parameters}} {{summary}}{{#notes}} @@ -28,12 +28,15 @@ Method | HTTP request | Description ### Example ```java +{{#vendorExtensions.x-java-import}} +import {{.}}; +{{/vendorExtensions.x-java-import}} // Import classes: import {{{invokerPackage}}}.ApiClient; import {{{invokerPackage}}}.ApiException; import {{{invokerPackage}}}.Configuration;{{#hasAuthMethods}} import {{{invokerPackage}}}.auth.*;{{/hasAuthMethods}} -import {{{invokerPackage}}}.models.*; +import {{{invokerPackage}}}.model.*; import {{{package}}}.{{{classname}}}; public class Example { @@ -66,10 +69,10 @@ public class Example { {{/allParams}} try { {{^vendorExtensions.x-group-parameters}} - {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{#returnType}}{{{.}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}}); {{/vendorExtensions.x-group-parameters}} {{#vendorExtensions.x-group-parameters}} - {{#returnType}}{{{returnType}}} result = {{/returnType}}api.{{operationId}}({{#pathParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}){{#allParams}}{{^isPathParam}} + {{#returnType}}{{{.}}} result = {{/returnType}}api.{{operationId}}({{#pathParams}}{{paramName}}{{^-last}}, {{/-last}}{{/pathParams}}){{#allParams}}{{^isPathParam}} .{{paramName}}({{paramName}}){{/isPathParam}}{{/allParams}} .execute(); {{/vendorExtensions.x-group-parameters}} @@ -90,9 +93,9 @@ public class Example { ### Parameters {{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{#allParams}}{{#-last}} -Name | Type | Description | Notes -------------- | ------------- | ------------- | -------------{{/-last}}{{/allParams}} -{{#allParams}} **{{paramName}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}[**{{dataType}}**]({{baseType}}.md){{/isFile}}{{/isPrimitiveType}}| {{description}} |{{^required}} [optional]{{/required}}{{^isContainer}}{{#defaultValue}} [default to {{defaultValue}}]{{/defaultValue}}{{/isContainer}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}} +| Name | Type | Description | Notes | +|------------- | ------------- | ------------- | -------------|{{/-last}}{{/allParams}} +{{#allParams}}| **{{paramName}}** | {{#isContainer}}{{#isArray}}{{#items}}{{#isModel}}{{^isFile}}[{{/isFile}}{{/isModel}}**List<{{dataType}}>**{{#isModel}}{{^isFile}}]({{^baseType}}{{dataType}}{{/baseType}}{{baseType}}.md){{/isFile}}{{/isModel}}{{/items}}{{/isArray}}{{#isMap}}{{#items}}{{#isModel}}{{^isFile}}[{{/isFile}}{{/isModel}}**Map<String,{{dataType}}>**{{#isModel}}{{^isFile}}]({{^baseType}}{{dataType}}{{/baseType}}{{baseType}}.md){{/isFile}}{{/isModel}}{{/items}}{{/isMap}}{{/isContainer}}{{^isContainer}}{{#isModel}}{{^isFile}}[{{/isFile}}{{/isModel}}**{{dataType}}**{{#isModel}}{{^isFile}}]({{^baseType}}{{dataType}}{{/baseType}}{{baseType}}.md){{/isFile}}{{/isModel}}{{/isContainer}}| {{description}} |{{^required}} [optional]{{/required}}{{^isContainer}}{{#defaultValue}} [default to {{.}}]{{/defaultValue}}{{/isContainer}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}} | {{/allParams}} ### Return type @@ -105,8 +108,8 @@ Name | Type | Description | Notes ### HTTP request headers -- **Content-Type**: {{#consumes}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} -- **Accept**: {{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}{{^produces}}Not defined{{/produces}} +- **Content-Type**: {{#consumes}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} +- **Accept**: {{#produces}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/produces}}{{^produces}}Not defined{{/produces}} {{#responses.0}} ### HTTP response details diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/api_test.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/api_test.mustache index 21e0f97d6..eb5101b1a 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/api_test.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/api_test.mustache @@ -2,50 +2,58 @@ package {{package}}; -import {{invokerPackage}}.ApiException; +import {{invokerPackage}}.*; +import {{invokerPackage}}.auth.*; {{#imports}}import {{import}}; {{/imports}} -import org.junit.Test; -import org.junit.Ignore; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; {{^fullJavaUtil}} import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -{{/fullJavaUtil}} +{{/fullJavaUtil}} /** * API tests for {{classname}} */ -@Ignore public class {{classname}}Test { private final {{classname}} api = new {{classname}}(); - {{#operations}}{{#operation}} + {{#operations}} + {{#operation}} /** + {{#summary}} * {{summary}} * + {{/summary}} + {{#notes}} * {{notes}} * - * @throws ApiException - * if the Api call fails + {{/notes}} + * @throws ApiException if the Api call fails */ @Test public void {{operationId}}Test() throws ApiException { {{#allParams}} - {{{dataType}}} {{paramName}} = null; + //{{{dataType}}} {{paramName}} = null; {{/allParams}} {{^vendorExtensions.x-group-parameters}} - {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + //{{#returnType}}{{{.}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); {{/vendorExtensions.x-group-parameters}} {{#vendorExtensions.x-group-parameters}} - {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#pathParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}){{#allParams}}{{^isPathParam}} - .{{paramName}}({{paramName}}){{/isPathParam}}{{/allParams}} - .execute(); + //{{#returnType}}{{{.}}} response = {{/returnType}}api.{{operationId}}({{#pathParams}}{{paramName}}{{^-last}}, {{/-last}}{{/pathParams}}){{#allParams}}{{^isPathParam}} + // .{{paramName}}({{paramName}}){{/isPathParam}}{{/allParams}} + // .execute(); {{/vendorExtensions.x-group-parameters}} // TODO: test validations } - {{/operation}}{{/operations}} + + {{/operation}} + {{/operations}} } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/auth/ApiKeyAuth.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/auth/ApiKeyAuth.mustache similarity index 100% rename from boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/auth/ApiKeyAuth.mustache rename to boat-scaffold/src/main/templates/boat-java/libraries/jersey2/auth/ApiKeyAuth.mustache diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/auth/Authentication.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/auth/Authentication.mustache similarity index 100% rename from boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/auth/Authentication.mustache rename to boat-scaffold/src/main/templates/boat-java/libraries/jersey2/auth/Authentication.mustache diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/auth/HttpBasicAuth.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/auth/HttpBasicAuth.mustache similarity index 74% rename from boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/auth/HttpBasicAuth.mustache rename to boat-scaffold/src/main/templates/boat-java/libraries/jersey2/auth/HttpBasicAuth.mustache index 898bb97ee..13cecfa90 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/auth/HttpBasicAuth.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/auth/HttpBasicAuth.mustache @@ -5,22 +5,13 @@ package {{invokerPackage}}.auth; import {{invokerPackage}}.Pair; import {{invokerPackage}}.ApiException; -{{^java8}} -import com.migcomponents.migbase64.Base64; -{{/java8}} -{{#java8}} import java.util.Base64; import java.nio.charset.StandardCharsets; -{{/java8}} import java.net.URI; import java.util.Map; import java.util.List; -{{^java8}} -import java.io.UnsupportedEncodingException; -{{/java8}} - {{>generatedAnnotation}} public class HttpBasicAuth implements Authentication { private String username; @@ -48,15 +39,6 @@ public class HttpBasicAuth implements Authentication { return; } String str = (username == null ? "" : username) + ":" + (password == null ? "" : password); -{{^java8}} - try { - headerParams.put("Authorization", "Basic " + Base64.encodeToString(str.getBytes("UTF-8"), false)); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); - } -{{/java8}} -{{#java8}} headerParams.put("Authorization", "Basic " + Base64.getEncoder().encodeToString(str.getBytes(StandardCharsets.UTF_8))); -{{/java8}} } } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/auth/HttpBearerAuth.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/auth/HttpBearerAuth.mustache similarity index 100% rename from boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/auth/HttpBearerAuth.mustache rename to boat-scaffold/src/main/templates/boat-java/libraries/jersey2/auth/HttpBearerAuth.mustache diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/auth/HttpSignatureAuth.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/auth/HttpSignatureAuth.mustache similarity index 56% rename from boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/auth/HttpSignatureAuth.mustache rename to boat-scaffold/src/main/templates/boat-java/libraries/jersey2/auth/HttpSignatureAuth.mustache index e56e0d229..ac0a77db8 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/auth/HttpSignatureAuth.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/auth/HttpSignatureAuth.mustache @@ -1,5 +1,5 @@ {{>licenseInfo}} - + package {{invokerPackage}}.auth; import {{invokerPackage}}.Pair; @@ -12,12 +12,19 @@ import java.security.Key; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Base64; +import java.util.Calendar; import java.util.Date; import java.util.Locale; import java.util.Map; import java.util.List; +import java.util.TimeZone; +import java.security.spec.AlgorithmParameterSpec; +import java.security.InvalidKeyException; -import org.tomitribe.auth.signatures.*; +import org.tomitribe.auth.signatures.Algorithm; +import org.tomitribe.auth.signatures.Signer; +import org.tomitribe.auth.signatures.Signature; +import org.tomitribe.auth.signatures.SigningAlgorithm; /** * A Configuration object for the HTTP message signature security scheme. @@ -30,26 +37,48 @@ public class HttpSignatureAuth implements Authentication { private String keyId; // The HTTP signature algorithm. + private SigningAlgorithm signingAlgorithm; + + // The HTTP cryptographic algorithm. private Algorithm algorithm; + // The cryptographic parameters. + private AlgorithmParameterSpec parameterSpec; + // The list of HTTP headers that should be included in the HTTP signature. private List headers; // The digest algorithm which is used to calculate a cryptographic digest of the HTTP request body. private String digestAlgorithm; + // The maximum validity duration of the HTTP signature. + private Long maxSignatureValidity; + /** * Construct a new HTTP signature auth configuration object. * * @param keyId An opaque string that the server can use to look up the component they need to validate the signature. - * @param algorithm The signature algorithm. + * @param signingAlgorithm The signature algorithm. + * @param algorithm The cryptographic algorithm. + * @param digestAlgorithm The digest algorithm. * @param headers The list of HTTP headers that should be included in the HTTP signature. + * @param maxSignatureValidity The maximum validity duration of the HTTP signature. + * Used to set the '(expires)' field in the HTTP signature. */ - public HttpSignatureAuth(String keyId, Algorithm algorithm, List headers) { + public HttpSignatureAuth(String keyId, + SigningAlgorithm signingAlgorithm, + Algorithm algorithm, + String digestAlgorithm, + AlgorithmParameterSpec parameterSpec, + List headers, + Long maxSignatureValidity) { this.keyId = keyId; + this.signingAlgorithm = signingAlgorithm; this.algorithm = algorithm; + this.parameterSpec = parameterSpec; + this.digestAlgorithm = digestAlgorithm; this.headers = headers; - this.digestAlgorithm = "SHA-256"; + this.maxSignatureValidity = maxSignatureValidity; } /** @@ -73,12 +102,28 @@ public class HttpSignatureAuth implements Authentication { /** * Returns the HTTP signature algorithm which is used to sign HTTP requests. */ + public SigningAlgorithm getSigningAlgorithm() { + return signingAlgorithm; + } + + /** + * Sets the HTTP signature algorithm which is used to sign HTTP requests. + * + * @param signingAlgorithm The HTTP signature algorithm. + */ + public void setSigningAlgorithm(SigningAlgorithm signingAlgorithm) { + this.signingAlgorithm = signingAlgorithm; + } + + /** + * Returns the HTTP cryptographic algorithm which is used to sign HTTP requests. + */ public Algorithm getAlgorithm() { return algorithm; } /** - * Sets the HTTP signature algorithm which is used to sign HTTP requests. + * Sets the HTTP cryptographic algorithm which is used to sign HTTP requests. * * @param algorithm The HTTP signature algorithm. */ @@ -86,6 +131,22 @@ public class HttpSignatureAuth implements Authentication { this.algorithm = algorithm; } + /** + * Returns the cryptographic parameters which are used to sign HTTP requests. + */ + public AlgorithmParameterSpec getAlgorithmParameterSpec() { + return parameterSpec; + } + + /** + * Sets the cryptographic parameters which are used to sign HTTP requests. + * + * @param parameterSpec The cryptographic parameters. + */ + public void setAlgorithmParameterSpec(AlgorithmParameterSpec parameterSpec) { + this.parameterSpec = parameterSpec; + } + /** * Returns the digest algorithm which is used to calculate a cryptographic digest of the HTTP request body. * @@ -127,10 +188,28 @@ public class HttpSignatureAuth implements Authentication { this.headers = headers; } + /** + * Returns the maximum validity duration of the HTTP signature. + * @return The maximum validity duration of the HTTP signature. + */ + public Long getMaxSignatureValidity() { + return maxSignatureValidity; + } + + /** + * Returns the signer instance used to sign HTTP messages. + * + * @return the signer instance. + */ public Signer getSigner() { return signer; } + /** + * Sets the signer instance used to sign HTTP messages. + * + * @param signer The signer instance to set. + */ public void setSigner(Signer signer) { this.signer = signer; } @@ -139,13 +218,15 @@ public class HttpSignatureAuth implements Authentication { * Set the private key used to sign HTTP requests using the HTTP signature scheme. * * @param key The private key. + * + * @throws InvalidKeyException Unable to parse the key, or the security provider for this key + * is not installed. */ - public void setPrivateKey(Key key) throws ApiException { + public void setPrivateKey(Key key) throws InvalidKeyException, ApiException { if (key == null) { throw new ApiException("Private key (java.security.Key) cannot be null"); } - - signer = new Signer(key, new Signature(keyId, algorithm, null, headers)); + signer = new Signer(key, new Signature(keyId, signingAlgorithm, algorithm, parameterSpec, null, headers, maxSignatureValidity)); } @Override @@ -157,7 +238,9 @@ public class HttpSignatureAuth implements Authentication { } if (headers.contains("date")) { - headerParams.put("date", new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US).format(new Date())); + SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US); + dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); + headerParams.put("date", dateFormat.format(Calendar.getInstance().getTime())); } if (headers.contains("digest")) { @@ -170,16 +253,12 @@ public class HttpSignatureAuth implements Authentication { throw new ApiException("Signer cannot be null. Please call the method `setPrivateKey` to set it up correctly"); } - // construct the path with the URL query string - String path = uri.getPath(); - - List urlQueries = new ArrayList(); - for (Pair queryParam : queryParams) { - urlQueries.add(queryParam.getName() + "=" + URLEncoder.encode(queryParam.getValue(), "utf8").replaceAll("\\+", "%20")); - } - - if (!urlQueries.isEmpty()) { - path = path + "?" + String.join("&", urlQueries); + // construct the path with the URL-encoded path and query. + // Calling getRawPath and getRawQuery ensures the path is URL-encoded as it will be serialized + // on the wire. The HTTP signature must use the encode URL as it is sent on the wire. + String path = uri.getRawPath(); + if (uri.getRawQuery() != null && !"".equals(uri.getRawQuery())) { + path += "?" + uri.getRawQuery(); } headerParams.put("Authorization", signer.sign(method, path, headerParams).toString()); diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/auth/OAuth.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/auth/OAuth.mustache new file mode 100644 index 000000000..8908aa543 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/auth/OAuth.mustache @@ -0,0 +1,195 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; +import {{invokerPackage}}.ApiException; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.exceptions.OAuthException; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.oauth.OAuth20Service; + +import javax.ws.rs.core.UriBuilder; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.logging.Level; +import java.util.logging.Logger; + +{{>generatedAnnotation}} +public class OAuth implements Authentication { + private static final Logger log = Logger.getLogger(OAuth.class.getName()); + + private String tokenUrl; + private String absoluteTokenUrl; + private OAuthFlow flow = OAuthFlow.APPLICATION; + private OAuth20Service service; + private DefaultApi20 authApi; + private String scope; + private String username; + private String password; + private String code; + private volatile OAuth2AccessToken accessToken; + + public OAuth(String basePath, String tokenUrl) { + this.tokenUrl = tokenUrl; + this.absoluteTokenUrl = createAbsoluteTokenUrl(basePath, tokenUrl); + authApi = new DefaultApi20() { + @Override + public String getAccessTokenEndpoint() { + return absoluteTokenUrl; + } + + @Override + protected String getAuthorizationBaseUrl() { + throw new UnsupportedOperationException("Shouldn't get there !"); + } + }; + } + + private static String createAbsoluteTokenUrl(String basePath, String tokenUrl) { + if (!URI.create(tokenUrl).isAbsolute()) { + try { + return UriBuilder.fromPath(basePath).path(tokenUrl).build().toURL().toString(); + } catch (MalformedURLException e) { + log.log(Level.SEVERE, "Couldn't create absolute token URL", e); + } + } + return tokenUrl; + } + + @Override + public void applyToParams( + List queryParams, + Map headerParams, + Map cookieParams, + String payload, + String method, + URI uri) + throws ApiException { + + if (accessToken == null) { + obtainAccessToken(null); + } + if (accessToken != null) { + headerParams.put("Authorization", "Bearer " + accessToken.getAccessToken()); + } + } + + public OAuth2AccessToken renewAccessToken() throws ApiException { + String refreshToken = null; + if (accessToken != null) { + refreshToken = accessToken.getRefreshToken(); + accessToken = null; + } + return obtainAccessToken(refreshToken); + } + + public synchronized OAuth2AccessToken obtainAccessToken(String refreshToken) throws ApiException { + if (service == null) { + log.log(Level.FINE, "service is null in obtainAccessToken."); + return null; + } + try { + if (refreshToken != null) { + return service.refreshAccessToken(refreshToken); + } + } catch (OAuthException | InterruptedException | ExecutionException | IOException e) { + throw new ApiException("Refreshing the access token using the refresh token failed: " + e.toString()); + } + try { + switch (flow) { + case PASSWORD: + if (username != null && password != null) { + accessToken = service.getAccessTokenPasswordGrant(username, password, scope); + } + break; + case ACCESS_CODE: + if (code != null) { + accessToken = service.getAccessToken(code); + code = null; + } + break; + case APPLICATION: + accessToken = service.getAccessTokenClientCredentialsGrant(scope); + break; + default: + log.log(Level.SEVERE, "Invalid flow in obtainAccessToken: " + flow); + } + } catch (OAuthException | InterruptedException | ExecutionException | IOException e) { + throw new ApiException(e); + } + return accessToken; + } + + public OAuth2AccessToken getAccessToken() { + return accessToken; + } + + public OAuth setAccessToken(OAuth2AccessToken accessToken) { + this.accessToken = accessToken; + return this; + } + + public OAuth setAccessToken(String accessToken) { + this.accessToken = new OAuth2AccessToken(accessToken); + return this; + } + + public OAuth setScope(String scope) { + this.scope = scope; + return this; + } + + public OAuth setCredentials(String clientId, String clientSecret, Boolean debug) { + if (Boolean.TRUE.equals(debug)) { + service = new ServiceBuilder(clientId) + .apiSecret(clientSecret).debug() + .build(authApi); + } else { + service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .build(authApi); + } + return this; + } + + public OAuth setCredentialsForPublicClient(String clientId, Boolean debug) { + if (Boolean.TRUE.equals(debug)) { + service = new ServiceBuilder(clientId) + .apiSecretIsEmptyStringUnsafe().debug() + .build(authApi); + } else { + service = new ServiceBuilder(clientId) + .apiSecretIsEmptyStringUnsafe() + .build(authApi); + } + return this; + } + + public OAuth usePasswordFlow(String username, String password) { + this.flow = OAuthFlow.PASSWORD; + this.username = username; + this.password = password; + return this; + } + + public OAuth useAuthorizationCodeFlow(String code) { + this.flow = OAuthFlow.ACCESS_CODE; + this.code = code; + return this; + } + + public OAuth setFlow(OAuthFlow flow) { + this.flow = flow; + return this; + } + + public void setBasePath(String basePath) { + this.absoluteTokenUrl = createAbsoluteTokenUrl(basePath, tokenUrl); + } +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/auth/OAuthFlow.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/auth/OAuthFlow.mustache new file mode 100644 index 000000000..190781fb1 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/auth/OAuthFlow.mustache @@ -0,0 +1,13 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +/** + * OAuth flows that are supported by this client + */ +public enum OAuthFlow { + ACCESS_CODE, + IMPLICIT, + PASSWORD, + APPLICATION +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/build.gradle.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/build.gradle.mustache index cdb451adb..b11d0add3 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/build.gradle.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/build.gradle.mustache @@ -1,25 +1,25 @@ apply plugin: 'idea' apply plugin: 'eclipse' +apply plugin: 'com.diffplug.spotless' group = '{{groupId}}' version = '{{artifactVersion}}' buildscript { repositories { - maven { url "https://repo1.maven.org/maven2" } - jcenter() + mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:2.3.+' - classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' + classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1' + classpath 'com.diffplug.spotless:spotless-plugin-gradle:6.3.0' } } repositories { - jcenter() + mavenCentral() } - if(hasProperty('target') && target == 'android') { apply plugin: 'com.android.library' @@ -33,20 +33,8 @@ if(hasProperty('target') && target == 'android') { targetSdkVersion 25 } compileOptions { - {{#supportJava6}} - sourceCompatibility JavaVersion.VERSION_1_6 - targetCompatibility JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} - {{#java8}} sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 - {{/java8}} - {{^java8}} - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 - {{/java8}} - {{/supportJava6}} } // Rename the aar correctly @@ -61,7 +49,7 @@ if(hasProperty('target') && target == 'android') { } dependencies { - provided 'javax.annotation:jsr250-api:1.0' + provided "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version" } } @@ -89,25 +77,17 @@ if(hasProperty('target') && target == 'android') { } else { apply plugin: 'java' - apply plugin: 'maven' - {{#supportJava6}} - sourceCompatibility = JavaVersion.VERSION_1_6 - targetCompatibility = JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} - {{#java8}} + apply plugin: 'maven-publish' sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 - {{/java8}} - {{^java8}} - sourceCompatibility = JavaVersion.VERSION_1_7 - targetCompatibility = JavaVersion.VERSION_1_7 - {{/java8}} - {{/supportJava6}} - - install { - repositories.mavenInstaller { - pom.artifactId = '{{artifactId}}' + + publishing { + publications { + maven(MavenPublication) { + artifactId = '{{artifactId}}' + + from components.java + } } } @@ -118,53 +98,80 @@ if(hasProperty('target') && target == 'android') { } ext { - swagger_annotations_version = "1.5.22" - jackson_version = "2.10.3" - jackson_databind_version = "2.10.3" - jackson_databind_nullable_version = "0.2.1" - {{#supportJava6}} - jersey_version = "2.6" - commons_io_version=2.5 - commons_lang3_version=3.6 - {{/supportJava6}} - {{^supportJava6}} - jersey_version = "2.27" - {{/supportJava6}} - junit_version = "4.13" - {{#threetenbp}} - threetenbp_version = "2.9.10" - {{/threetenbp}} + swagger_annotations_version = "1.6.5" + jackson_version = "2.13.4" + jackson_databind_version = "2.13.4.2" + {{#openApiNullable}} + jackson_databind_nullable_version = "0.2.4" + {{/openApiNullable}} + jakarta_annotation_version = "1.3.5" + jersey_version = "2.35" + junit_version = "5.8.2" + {{#hasOAuthMethods}} + scribejava_apis_version = "8.3.1" + {{/hasOAuthMethods}} + {{#hasHttpSignatureMethods}} + tomitribe_http_signatures_version = "1.7" + {{/hasHttpSignatureMethods}} } dependencies { - compile "io.swagger:swagger-annotations:$swagger_annotations_version" - compile "com.google.code.findbugs:jsr305:3.0.2" - compile "org.glassfish.jersey.core:jersey-client:$jersey_version" - compile "org.glassfish.jersey.media:jersey-media-multipart:$jersey_version" - compile "org.glassfish.jersey.media:jersey-media-json-jackson:$jersey_version" - compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" - compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation "org.glassfish.jersey.core:jersey-client:$jersey_version" + implementation "org.glassfish.jersey.inject:jersey-hk2:$jersey_version" + implementation "org.glassfish.jersey.media:jersey-media-multipart:$jersey_version" + implementation "org.glassfish.jersey.media:jersey-media-json-jackson:$jersey_version" + implementation "org.glassfish.jersey.connectors:jersey-apache-connector:$jersey_version" + implementation "com.fasterxml.jackson.core:jackson-core:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" + {{#openApiNullable}} + implementation "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + {{/openApiNullable}} {{#joda}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + implementation "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" {{/joda}} - {{#java8}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" - {{/java8}} - {{#supportJava6}} - compile "commons-io:commons-io:$commons_io_version" - compile "org.apache.commons:commons-lang3:$commons_lang3_version" - {{/supportJava6}} - {{#threetenbp}} - compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$threetenbp_version" - {{/threetenbp}} - {{^java8}} - compile "com.brsanthu:migbase64:2.2" - {{/java8}} - testCompile "junit:junit:$junit_version" + implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + {{#hasOAuthMethods}} + implementation "com.github.scribejava:scribejava-apis:$scribejava_apis_version" + {{/hasOAuthMethods}} + {{#hasHttpSignatureMethods}} + implementation "org.tomitribe:tomitribe-http-signatures:$tomitribe_http_signatures_version" + {{/hasHttpSignatureMethods}} + implementation "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version" + testImplementation "org.junit.jupiter:junit-jupiter-api:$junit_version" + testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junit_version" +} + +test { + useJUnitPlatform() } javadoc { options.tags = [ "http.response.details:a:Http Response Details" ] } + +// Use spotless plugin to automatically format code, remove unused import, etc +// To apply changes directly to the file, run `gradlew spotlessApply` +// Ref: https://github.com/diffplug/spotless/tree/main/plugin-gradle +spotless { + // comment out below to run spotless as part of the `check` task + enforceCheck false + + format 'misc', { + // define the files (e.g. '*.gradle', '*.md') to apply `misc` to + target '.gitignore' + // define the steps to apply to those files + trimTrailingWhitespace() + indentWithSpaces() // Takes an integer argument if you don't like 4 + endWithNewline() + } + java { + // don't need to set target, it is inferred from java + // apply a specific flavor of google-java-format + googleJavaFormat('1.8').aosp().reflowLongStrings() + removeUnusedImports() + importOrder() + } +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/build.sbt.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/build.sbt.mustache index abb91ecdc..dc65e1b49 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/build.sbt.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/build.sbt.mustache @@ -5,34 +5,34 @@ lazy val root = (project in file(".")). version := "{{artifactVersion}}", scalaVersion := "2.11.4", scalacOptions ++= Seq("-feature"), - javacOptions in compile ++= Seq("-Xlint:deprecation"), - publishArtifact in (Compile, packageDoc) := false, + Compile / javacOptions ++= Seq("-Xlint:deprecation"), + Compile / packageDoc / publishArtifact := false, resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( - "io.swagger" % "swagger-annotations" % "1.5.22", - "org.glassfish.jersey.core" % "jersey-client" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, - "org.glassfish.jersey.media" % "jersey-media-multipart" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, - "org.glassfish.jersey.media" % "jersey-media-json-jackson" % {{#supportJava6}}"2.6"{{/supportJava6}}{{^supportJava6}}"2.25.1"{{/supportJava6}}, - "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.3" % "compile", + "com.google.code.findbugs" % "jsr305" % "3.0.0", + "io.swagger" % "swagger-annotations" % "1.6.5", + "org.glassfish.jersey.core" % "jersey-client" % "2.35", + "org.glassfish.jersey.inject" % "jersey-hk2" % "2.35", + "org.glassfish.jersey.media" % "jersey-media-multipart" % "2.35", + "org.glassfish.jersey.media" % "jersey-media-json-jackson" % "2.35", + "org.glassfish.jersey.connectors" % "jersey-apache-connector" % "2.35", + "com.fasterxml.jackson.core" % "jackson-core" % "2.13.2" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.13.2" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.13.4.1" % "compile", {{#joda}} - "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.9.10" % "compile", + "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.13.2" % "compile", {{/joda}} - {{#java8}} - "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.10" % "compile", - {{/java8}} - {{#threetenbp}} - "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile", - {{/threetenbp}} - {{^java8}} - "com.brsanthu" % "migbase64" % "2.2", - {{/java8}} - {{#supportJava6}} - "org.apache.commons" % "commons-lang3" % "3.6", - "commons-io" % "commons-io" % "2.5", - {{/supportJava6}} - "junit" % "junit" % "4.13" % "test", - "com.novocode" % "junit-interface" % "0.10" % "test" + "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.13.2" % "compile", + {{#openApiNullable}} + "org.openapitools" % "jackson-databind-nullable" % "0.2.4" % "compile", + {{/openApiNullable}} + {{#hasOAuthMethods}} + "com.github.scribejava" % "scribejava-apis" % "8.3.1" % "compile", + {{/hasOAuthMethods}} + {{#hasHttpSignatureMethods}} + "org.tomitribe" % "tomitribe-http-signatures" % "1.7" % "compile", + {{/hasHttpSignatureMethods}} + "jakarta.annotation" % "jakarta.annotation-api" % "1.3.5" % "compile", + "org.junit.jupiter" % "junit-jupiter-api" % "5.8.2" % "test" ) ) diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/model.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/model.mustache new file mode 100644 index 000000000..914e1eb1e --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/model.mustache @@ -0,0 +1,64 @@ +{{>licenseInfo}} + +package {{package}}; + +{{#useReflectionEqualsHashCode}} +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +{{/useReflectionEqualsHashCode}} +{{#models}} +{{#model}} +{{#additionalPropertiesType}} +import java.util.Map; +import java.util.HashMap; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +{{/additionalPropertiesType}} +{{/model}} +{{/models}} +import java.util.Objects; +import java.util.Arrays; +import java.util.Map; +import java.util.HashMap; +{{#imports}} +import {{import}}; +{{/imports}} +{{#serializableModel}} +import java.io.Serializable; +{{/serializableModel}} +{{#jackson}} +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +{{#withXml}} +import com.fasterxml.jackson.dataformat.xml.annotation.*; +{{/withXml}} +{{#vendorExtensions.x-has-readonly-properties}} +import com.fasterxml.jackson.annotation.JsonCreator; +{{/vendorExtensions.x-has-readonly-properties}} +{{/jackson}} +{{#withXml}} +import javax.xml.bind.annotation.*; +{{/withXml}} +{{#parcelableModel}} +import android.os.Parcelable; +import android.os.Parcel; +{{/parcelableModel}} +{{#useBeanValidation}} +import javax.validation.constraints.*; +import javax.validation.Valid; +{{/useBeanValidation}} +{{#performBeanValidation}} +import org.hibernate.validator.constraints.*; +{{/performBeanValidation}} +import {{invokerPackage}}.JSON; + +{{#models}} +{{#model}} +{{#oneOf}} +{{#-first}} +import com.fasterxml.jackson.core.type.TypeReference; +{{/-first}} +{{/oneOf}} + +{{#isEnum}}{{>modelEnum}}{{/isEnum}}{{^isEnum}}{{#oneOf}}{{#-first}}{{>oneof_model}}{{/-first}}{{/oneOf}}{{^oneOf}}{{#anyOf}}{{#-first}}{{>anyof_model}}{{/-first}}{{/anyOf}}{{^anyOf}}{{>pojo}}{{/anyOf}}{{/oneOf}}{{/isEnum}} +{{/model}} +{{/models}} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/model_anyof_doc.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/model_anyof_doc.mustache new file mode 100644 index 000000000..e360aa56e --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/model_anyof_doc.mustache @@ -0,0 +1,38 @@ +# {{classname}} + +{{#description}} +{{&description}} + +{{/description}} +## anyOf schemas +{{#anyOf}} +* [{{{.}}}]({{{.}}}.md) +{{/anyOf}} + +{{#isNullable}} +NOTE: this class is nullable. + +{{/isNullable}} +## Example +```java +// Import classes: +import {{{package}}}.{{{classname}}}; +{{#anyOf}} +import {{{package}}}.{{{.}}}; +{{/anyOf}} + +public class Example { + public static void main(String[] args) { + {{classname}} example{{classname}} = new {{classname}}(); + {{#anyOf}} + + // create a new {{{.}}} + {{{.}}} example{{{.}}} = new {{{.}}}(); + // set {{{classname}}} to {{{.}}} + example{{classname}}.setActualInstance(example{{{.}}}); + // to get back the {{{.}}} set earlier + {{{.}}} test{{{.}}} = ({{{.}}}) example{{classname}}.getActualInstance(); + {{/anyOf}} + } +} +``` diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/model_doc.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/model_doc.mustache new file mode 100644 index 000000000..be1aedcf2 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/model_doc.mustache @@ -0,0 +1,19 @@ +{{#models}}{{#model}} + +{{#isEnum}} +{{>enum_outer_doc}} +{{/isEnum}} +{{^isEnum}} +{{^oneOf.isEmpty}} +{{>model_oneof_doc}} +{{/oneOf.isEmpty}} +{{^anyOf.isEmpty}} +{{>model_anyof_doc}} +{{/anyOf.isEmpty}} +{{^anyOf}} +{{^oneOf}} +{{>pojo_doc}} +{{/oneOf}} +{{/anyOf}} +{{/isEnum}} +{{/model}}{{/models}} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/model_oneof_doc.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/model_oneof_doc.mustache new file mode 100644 index 000000000..5fff76c9e --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/model_oneof_doc.mustache @@ -0,0 +1,38 @@ +# {{classname}} + +{{#description}} +{{&description}} + +{{/description}} +## oneOf schemas +{{#oneOf}} +* [{{{.}}}]({{{.}}}.md) +{{/oneOf}} + +{{#isNullable}} +NOTE: this class is nullable. + +{{/isNullable}} +## Example +```java +// Import classes: +import {{{package}}}.{{{classname}}}; +{{#oneOf}} +import {{{package}}}.{{{.}}}; +{{/oneOf}} + +public class Example { + public static void main(String[] args) { + {{classname}} example{{classname}} = new {{classname}}(); + {{#oneOf}} + + // create a new {{{.}}} + {{{.}}} example{{{.}}} = new {{{.}}}(); + // set {{{classname}}} to {{{.}}} + example{{classname}}.setActualInstance(example{{{.}}}); + // to get back the {{{.}}} set earlier + {{{.}}} test{{{.}}} = ({{{.}}}) example{{classname}}.getActualInstance(); + {{/oneOf}} + } +} +``` diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/model_test.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/model_test.mustache new file mode 100644 index 000000000..2d4ccdd1a --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/model_test.mustache @@ -0,0 +1,51 @@ +{{>licenseInfo}} + +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +{{#fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +{{/fullJavaUtil}} +/** + * Model tests for {{classname}} + */ +public class {{classname}}Test { + {{#models}} + {{#model}} + {{^vendorExtensions.x-is-one-of-interface}} + {{^isEnum}} + private final {{classname}} model = new {{classname}}(); + + {{/isEnum}} + /** + * Model tests for {{classname}} + */ + @Test + public void test{{classname}}() { + // TODO: test {{classname}} + } + + {{#allVars}} + /** + * Test the property '{{name}}' + */ + @Test + public void {{name}}Test() { + // TODO: test {{name}} + } + + {{/allVars}} + {{/vendorExtensions.x-is-one-of-interface}} + {{/model}} + {{/models}} +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/oneof_model.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/oneof_model.mustache new file mode 100644 index 000000000..18bcbc5e1 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/oneof_model.mustache @@ -0,0 +1,235 @@ +import javax.ws.rs.core.GenericType; +import javax.ws.rs.core.Response; +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.MapperFeature; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import {{invokerPackage}}.JSON; + +{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>xmlAnnotation}} +@JsonDeserialize(using = {{classname}}.{{classname}}Deserializer.class) +@JsonSerialize(using = {{classname}}.{{classname}}Serializer.class) +public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-implements}}, {{{.}}}{{/vendorExtensions.x-implements}} { + private static final Logger log = Logger.getLogger({{classname}}.class.getName()); + + public static class {{classname}}Serializer extends StdSerializer<{{classname}}> { + public {{classname}}Serializer(Class<{{classname}}> t) { + super(t); + } + + public {{classname}}Serializer() { + this(null); + } + + @Override + public void serialize({{classname}} value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { + jgen.writeObject(value.getActualInstance()); + } + } + + public static class {{classname}}Deserializer extends StdDeserializer<{{classname}}> { + public {{classname}}Deserializer() { + this({{classname}}.class); + } + + public {{classname}}Deserializer(Class vc) { + super(vc); + } + + @Override + public {{classname}} deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { + JsonNode tree = jp.readValueAsTree(); + Object deserialized = null; + {{#useOneOfDiscriminatorLookup}} + {{#discriminator}} + {{classname}} new{{classname}} = new {{classname}}(); + Map result2 = tree.traverse(jp.getCodec()).readValueAs(new TypeReference>() {}); + String discriminatorValue = (String)result2.get("{{{propertyBaseName}}}"); + switch (discriminatorValue) { + {{#mappedModels}} + case "{{{mappingName}}}": + deserialized = tree.traverse(jp.getCodec()).readValueAs({{{modelName}}}.class); + new{{classname}}.setActualInstance(deserialized); + return new{{classname}}; + {{/mappedModels}} + default: + log.log(Level.WARNING, String.format("Failed to lookup discriminator value `%s` for {{classname}}. Possible values:{{#mappedModels}} {{{mappingName}}}{{/mappedModels}}", discriminatorValue)); + } + + {{/discriminator}} + {{/useOneOfDiscriminatorLookup}} + boolean typeCoercion = ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS); + int match = 0; + JsonToken token = tree.traverse(jp.getCodec()).nextToken(); + {{#oneOf}} + // deserialize {{{.}}} + try { + boolean attemptParsing = true; + // ensure that we respect type coercion as set on the client ObjectMapper + if ({{{.}}}.class.equals(Integer.class) || {{{.}}}.class.equals(Long.class) || {{{.}}}.class.equals(Float.class) || {{{.}}}.class.equals(Double.class) || {{{.}}}.class.equals(Boolean.class) || {{{.}}}.class.equals(String.class)) { + attemptParsing = typeCoercion; + if (!attemptParsing) { + attemptParsing |= (({{{.}}}.class.equals(Integer.class) || {{{.}}}.class.equals(Long.class)) && token == JsonToken.VALUE_NUMBER_INT); + attemptParsing |= (({{{.}}}.class.equals(Float.class) || {{{.}}}.class.equals(Double.class)) && token == JsonToken.VALUE_NUMBER_FLOAT); + attemptParsing |= ({{{.}}}.class.equals(Boolean.class) && (token == JsonToken.VALUE_FALSE || token == JsonToken.VALUE_TRUE)); + attemptParsing |= ({{{.}}}.class.equals(String.class) && token == JsonToken.VALUE_STRING); + {{#isNullable}} + attemptParsing |= (token == JsonToken.VALUE_NULL); + {{/isNullable}} + } + } + if (attemptParsing) { + deserialized = tree.traverse(jp.getCodec()).readValueAs({{{.}}}.class); + // TODO: there is no validation against JSON schema constraints + // (min, max, enum, pattern...), this does not perform a strict JSON + // validation, which means the 'match' count may be higher than it should be. + match++; + log.log(Level.FINER, "Input data matches schema '{{{.}}}'"); + } + } catch (Exception e) { + // deserialization failed, continue + log.log(Level.FINER, "Input data does not match schema '{{{.}}}'", e); + } + + {{/oneOf}} + if (match == 1) { + {{classname}} ret = new {{classname}}(); + ret.setActualInstance(deserialized); + return ret; + } + throw new IOException(String.format("Failed deserialization for {{classname}}: %d classes match result, expected 1", match)); + } + + /** + * Handle deserialization of the 'null' value. + */ + @Override + public {{classname}} getNullValue(DeserializationContext ctxt) throws JsonMappingException { + {{#isNullable}} + return null; + {{/isNullable}} + {{^isNullable}} + throw new JsonMappingException(ctxt.getParser(), "{{classname}} cannot be null"); + {{/isNullable}} + } + } + + // store a list of schema names defined in oneOf + public static final Map schemas = new HashMap(); + + public {{classname}}() { + super("oneOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); + } +{{> libraries/jersey2/additional_properties }} + {{#additionalPropertiesType}} + /** + * Return true if this {{name}} object is equal to o. + */ + @Override + public boolean equals(Object o) { + return super.equals(o) && Objects.equals(this.additionalProperties, (({{classname}})o).additionalProperties); + } + + @Override + public int hashCode() { + return Objects.hash(getActualInstance(), isNullable(), getSchemaType(), additionalProperties); + } + {{/additionalPropertiesType}} + {{#oneOf}} + public {{classname}}({{{.}}} o) { + super("oneOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); + setActualInstance(o); + } + + {{/oneOf}} + static { + {{#oneOf}} + schemas.put("{{{.}}}", new GenericType<{{{.}}}>() { + }); + {{/oneOf}} + JSON.registerDescendants({{classname}}.class, Collections.unmodifiableMap(schemas)); + {{#discriminator}} + // Initialize and register the discriminator mappings. + Map> mappings = new HashMap>(); + {{#mappedModels}} + mappings.put("{{mappingName}}", {{modelName}}.class); + {{/mappedModels}} + mappings.put("{{name}}", {{classname}}.class); + JSON.registerDiscriminator({{classname}}.class, "{{propertyBaseName}}", mappings); + {{/discriminator}} + } + + @Override + public Map getSchemas() { + return {{classname}}.schemas; + } + + /** + * Set the instance that matches the oneOf child schema, check + * the instance parameter is valid against the oneOf child schemas: + * {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}} + * + * It could be an instance of the 'oneOf' schemas. + * The oneOf child schemas may themselves be a composed schema (allOf, anyOf, oneOf). + */ + @Override + public void setActualInstance(Object instance) { + {{#isNullable}} + if (instance == null) { + super.setActualInstance(instance); + return; + } + + {{/isNullable}} + {{#oneOf}} + if (JSON.isInstanceOf({{{.}}}.class, instance, new HashSet>())) { + super.setActualInstance(instance); + return; + } + + {{/oneOf}} + throw new RuntimeException("Invalid instance type. Must be {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}"); + } + + /** + * Get the actual instance, which can be the following: + * {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}} + * + * @return The actual instance ({{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}) + */ + @Override + public Object getActualInstance() { + return super.getActualInstance(); + } + + {{#oneOf}} + /** + * Get the actual instance of `{{{.}}}`. If the actual instance is not `{{{.}}}`, + * the ClassCastException will be thrown. + * + * @return The actual instance of `{{{.}}}` + * @throws ClassCastException if the instance is not `{{{.}}}` + */ + public {{{.}}} get{{{.}}}() throws ClassCastException { + return ({{{.}}})super.getActualInstance(); + } + + {{/oneOf}} +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/pojo.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/pojo.mustache new file mode 100644 index 000000000..4eb9cc2f1 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/pojo.mustache @@ -0,0 +1,422 @@ +/** + * {{description}}{{^description}}{{classname}}{{/description}}{{#isDeprecated}} + * @deprecated{{/isDeprecated}} + */{{#isDeprecated}} +@Deprecated{{/isDeprecated}} +{{#swagger1AnnotationLibrary}} +{{#description}} +@ApiModel(description = "{{{.}}}") +{{/description}} +{{/swagger1AnnotationLibrary}} +{{#jackson}} +@JsonPropertyOrder({ +{{#vars}} + {{classname}}.JSON_PROPERTY_{{nameInSnakeCase}}{{^-last}},{{/-last}} +{{/vars}} +}) +{{#isClassnameSanitized}} +@JsonTypeName("{{name}}") +{{/isClassnameSanitized}} +{{/jackson}} +{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}} +{{#vendorExtensions.x-class-extra-annotation}} +{{{vendorExtensions.x-class-extra-annotation}}} +{{/vendorExtensions.x-class-extra-annotation}} +public class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{{#vendorExtensions.x-implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{#-last}} {{/-last}}{{/vendorExtensions.x-implements}}{ +{{#serializableModel}} + private static final long serialVersionUID = 1L; + +{{/serializableModel}} + {{#vars}} + {{#isEnum}} + {{^isContainer}} + {{^vendorExtensions.x-enum-as-string}} +{{>modelInnerEnum}} + {{/vendorExtensions.x-enum-as-string}} + {{/isContainer}} + {{#isContainer}} + {{#mostInnerItems}} +{{>modelInnerEnum}} + {{/mostInnerItems}} + {{/isContainer}} + {{/isEnum}} + {{#gson}} + public static final String SERIALIZED_NAME_{{nameInSnakeCase}} = "{{baseName}}"; + {{/gson}} + {{#jackson}} + public static final String JSON_PROPERTY_{{nameInSnakeCase}} = "{{baseName}}"; + {{/jackson}} + {{#withXml}} + {{#isXmlAttribute}} + @XmlAttribute(name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isXmlAttribute}} + {{^isXmlAttribute}} + {{^isContainer}} + @XmlElement({{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isContainer}} + {{#isContainer}} + // Is a container wrapped={{isXmlWrapped}} + {{#items}} + // items.name={{name}} items.baseName={{baseName}} items.xmlName={{xmlName}} items.xmlNamespace={{xmlNamespace}} + // items.example={{example}} items.type={{dataType}} + @XmlElement({{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/items}} + {{#isXmlWrapped}} + @XmlElementWrapper({{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isXmlWrapped}} + {{/isContainer}} + {{/isXmlAttribute}} + {{/withXml}} + {{#gson}} + @SerializedName(SERIALIZED_NAME_{{nameInSnakeCase}}) + {{/gson}} + {{#vendorExtensions.x-field-extra-annotation}} + {{{vendorExtensions.x-field-extra-annotation}}} + {{/vendorExtensions.x-field-extra-annotation}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} + {{#isContainer}} + private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>undefined(); + {{/isContainer}} + {{^isContainer}} + private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}}; + {{/isContainer}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + {{#isContainer}} + private {{{datatypeWithEnum}}} {{name}}{{#required}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/required}}{{^required}} = null{{/required}}; + {{/isContainer}} + {{^isContainer}} + private {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}; + {{/isContainer}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} + + {{/vars}} + public {{classname}}() { {{#parent}}{{#parcelableModel}} + super();{{/parcelableModel}}{{/parent}}{{#gson}}{{#discriminator}} + this.{{{discriminatorName}}} = this.getClass().getSimpleName();{{/discriminator}}{{/gson}} + }{{#vendorExtensions.x-has-readonly-properties}}{{^withXml}}{{#jackson}} + + @JsonCreator + public {{classname}}( + {{#readOnlyVars}} + {{#jackson}}@JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}}){{/jackson}} {{{datatypeWithEnum}}} {{name}}{{^-last}}, {{/-last}} + {{/readOnlyVars}} + ) { + this(); + {{#readOnlyVars}} + this.{{name}} = {{#vendorExtensions.x-is-jackson-optional-nullable}}{{name}} == null ? JsonNullable.<{{{datatypeWithEnum}}}>undefined() : JsonNullable.of({{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{name}}{{/vendorExtensions.x-is-jackson-optional-nullable}}; + {{/readOnlyVars}} + }{{/jackson}}{{/withXml}}{{/vendorExtensions.x-has-readonly-properties}} + {{#vars}} + + {{^isReadOnly}} + {{#vendorExtensions.x-enum-as-string}} + public static final Set {{{nameInSnakeCase}}}_VALUES = new HashSet<>(Arrays.asList( + {{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}} + )); + + {{/vendorExtensions.x-enum-as-string}} + public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) { + {{#vendorExtensions.x-enum-as-string}} + if (!{{{nameInSnakeCase}}}_VALUES.contains({{name}})) { + throw new IllegalArgumentException({{name}} + " is invalid. Possible values for {{name}}: " + String.join(", ", {{{nameInSnakeCase}}}_VALUES)); + } + + {{/vendorExtensions.x-enum-as-string}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}}); + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = {{name}}; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + return this; + } + {{#isArray}} + + public {{classname}} add{{nameInCamelCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + if (this.{{name}} == null || !this.{{name}}.isPresent()) { + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}); + } + try { + this.{{name}}.get().add({{name}}Item); + } catch (java.util.NoSuchElementException e) { + // this can never happen, as we make sure above that the value is present + } + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + {{^required}} + if (this.{{name}} == null) { + this.{{name}} = {{{defaultValue}}}; + } + {{/required}} + this.{{name}}.add({{name}}Item); + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + {{/isArray}} + {{#isMap}} + + public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + if (this.{{name}} == null || !this.{{name}}.isPresent()) { + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}); + } + try { + this.{{name}}.get().put(key, {{name}}Item); + } catch (java.util.NoSuchElementException e) { + // this can never happen, as we make sure above that the value is present + } + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + {{^required}} + if (this.{{name}} == null) { + this.{{name}} = {{{defaultValue}}}; + } + {{/required}} + this.{{name}}.put(key, {{name}}Item); + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + {{/isMap}} + + {{/isReadOnly}} + /** + {{#description}} + * {{.}} + {{/description}} + {{^description}} + * Get {{name}} + {{/description}} + {{#minimum}} + * minimum: {{.}} + {{/minimum}} + {{#maximum}} + * maximum: {{.}} + {{/maximum}} + * @return {{name}} + {{#deprecated}} + * @deprecated + {{/deprecated}} + **/ +{{#deprecated}} + @Deprecated +{{/deprecated}} +{{#required}} +{{#isNullable}} + @javax.annotation.Nullable +{{/isNullable}} +{{^isNullable}} + @javax.annotation.Nonnull +{{/isNullable}} +{{/required}} +{{^required}} + @javax.annotation.Nullable +{{/required}} +{{#useBeanValidation}} +{{>beanValidation}} +{{/useBeanValidation}} +{{#swagger1AnnotationLibrary}} + @ApiModelProperty({{#example}}example = "{{{.}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}") +{{/swagger1AnnotationLibrary}} +{{#vendorExtensions.x-extra-annotation}} + {{{vendorExtensions.x-extra-annotation}}} +{{/vendorExtensions.x-extra-annotation}} +{{#vendorExtensions.x-is-jackson-optional-nullable}} + {{!unannotated, Jackson would pick this up automatically and add it *in addition* to the _JsonNullable getter field}} + @JsonIgnore +{{/vendorExtensions.x-is-jackson-optional-nullable}} +{{^vendorExtensions.x-is-jackson-optional-nullable}}{{#jackson}}{{> jackson_annotations}}{{/jackson}}{{/vendorExtensions.x-is-jackson-optional-nullable}} + public {{{datatypeWithEnum}}} {{getter}}() { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + {{#isReadOnly}}{{! A readonly attribute doesn't have setter => jackson will set null directly if explicitly returned by API, so make sure we have an empty JsonNullable}} + if ({{name}} == null) { + {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}}; + } + {{/isReadOnly}} + return {{name}}.orElse(null); + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + return {{name}}; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + + {{#vendorExtensions.x-is-jackson-optional-nullable}} +{{> jackson_annotations}} + public JsonNullable<{{{datatypeWithEnum}}}> {{getter}}_JsonNullable() { + return {{name}}; + } + {{/vendorExtensions.x-is-jackson-optional-nullable}}{{#vendorExtensions.x-is-jackson-optional-nullable}} + @JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}}) + {{#isReadOnly}}private{{/isReadOnly}}{{^isReadOnly}}public{{/isReadOnly}} void {{setter}}_JsonNullable(JsonNullable<{{{datatypeWithEnum}}}> {{name}}) { + {{! For getters/setters that have name differing from attribute name, we must include setter (albeit private) for jackson to be able to set the attribute}} + this.{{name}} = {{name}}; + } + {{/vendorExtensions.x-is-jackson-optional-nullable}} + + {{^isReadOnly}} +{{#vendorExtensions.x-setter-extra-annotation}} {{{vendorExtensions.x-setter-extra-annotation}}} +{{/vendorExtensions.x-setter-extra-annotation}}{{#jackson}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{> jackson_annotations}}{{/vendorExtensions.x-is-jackson-optional-nullable}}{{/jackson}} public void {{setter}}({{{datatypeWithEnum}}} {{name}}) { + {{#vendorExtensions.x-enum-as-string}} + if (!{{{nameInSnakeCase}}}_VALUES.contains({{name}})) { + throw new IllegalArgumentException({{name}} + " is invalid. Possible values for {{name}}: " + String.join(", ", {{{nameInSnakeCase}}}_VALUES)); + } + + {{/vendorExtensions.x-enum-as-string}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}}); + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = {{name}}; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + {{/isReadOnly}} + + {{/vars}} +{{>libraries/jersey2/additional_properties}} + /** + * Return true if this {{name}} object is equal to o. + */ + @Override + public boolean equals(Object o) { + {{#useReflectionEqualsHashCode}} + return EqualsBuilder.reflectionEquals(this, o, false, null, true); + {{/useReflectionEqualsHashCode}} + {{^useReflectionEqualsHashCode}} + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + }{{#hasVars}} + {{classname}} {{classVarName}} = ({{classname}}) o; + return {{#vars}}{{#vendorExtensions.x-is-jackson-optional-nullable}}equalsNullable(this.{{name}}, {{classVarName}}.{{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{#isByteArray}}Arrays{{/isByteArray}}{{^isByteArray}}Objects{{/isByteArray}}.equals(this.{{name}}, {{classVarName}}.{{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^-last}} && + {{/-last}}{{/vars}}{{#additionalPropertiesType}}&& + Objects.equals(this.additionalProperties, {{classVarName}}.additionalProperties){{/additionalPropertiesType}}{{#parent}} && + super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}} + return {{#parent}}super.equals(o){{/parent}}{{^parent}}true{{/parent}};{{/hasVars}} + {{/useReflectionEqualsHashCode}} + }{{#vendorExtensions.x-jackson-optional-nullable-helpers}} + + private static boolean equalsNullable(JsonNullable a, JsonNullable b) { + return a == b || (a != null && b != null && a.isPresent() && b.isPresent() && Objects.deepEquals(a.get(), b.get())); + }{{/vendorExtensions.x-jackson-optional-nullable-helpers}} + + @Override + public int hashCode() { + {{#useReflectionEqualsHashCode}} + return HashCodeBuilder.reflectionHashCode(this); + {{/useReflectionEqualsHashCode}} + {{^useReflectionEqualsHashCode}} + return Objects.hash({{#vars}}{{#vendorExtensions.x-is-jackson-optional-nullable}}hashCodeNullable({{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{^isByteArray}}{{name}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{/vendorExtensions.x-is-jackson-optional-nullable}}{{^-last}}, {{/-last}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}{{#additionalPropertiesType}}{{#hasVars}}, {{/hasVars}}{{^hasVars}}{{#parent}}, {{/parent}}{{/hasVars}}additionalProperties{{/additionalPropertiesType}}); + {{/useReflectionEqualsHashCode}} + }{{#vendorExtensions.x-jackson-optional-nullable-helpers}} + + private static int hashCodeNullable(JsonNullable a) { + if (a == null) { + return 1; + } + return a.isPresent() ? Arrays.deepHashCode(new Object[]{a.get()}) : 31; + }{{/vendorExtensions.x-jackson-optional-nullable-helpers}} + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class {{classname}} {\n"); + {{#parent}} + sb.append(" ").append(toIndentedString(super.toString())).append("\n"); + {{/parent}} + {{#vars}} + sb.append(" {{name}}: ").append(toIndentedString({{name}})).append("\n"); + {{/vars}} + {{#additionalPropertiesType}} + sb.append(" additionalProperties: ").append(toIndentedString(additionalProperties)).append("\n"); + {{/additionalPropertiesType}} + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + +{{#parcelableModel}} + + public void writeToParcel(Parcel out, int flags) { +{{#model}} +{{#isArray}} + out.writeList(this); +{{/isArray}} +{{^isArray}} +{{#parent}} + super.writeToParcel(out, flags); +{{/parent}} +{{#vars}} + out.writeValue({{name}}); +{{/vars}} +{{/isArray}} +{{/model}} + } + + {{classname}}(Parcel in) { +{{#isArray}} + in.readTypedList(this, {{arrayModelType}}.CREATOR); +{{/isArray}} +{{^isArray}} +{{#parent}} + super(in); +{{/parent}} +{{#vars}} +{{#isPrimitiveType}} + {{name}} = ({{{datatypeWithEnum}}})in.readValue(null); +{{/isPrimitiveType}} +{{^isPrimitiveType}} + {{name}} = ({{{datatypeWithEnum}}})in.readValue({{complexType}}.class.getClassLoader()); +{{/isPrimitiveType}} +{{/vars}} +{{/isArray}} + } + + public int describeContents() { + return 0; + } + + public static final Parcelable.Creator<{{classname}}> CREATOR = new Parcelable.Creator<{{classname}}>() { + public {{classname}} createFromParcel(Parcel in) { +{{#model}} +{{#isArray}} + {{classname}} result = new {{classname}}(); + result.addAll(in.readArrayList({{arrayModelType}}.class.getClassLoader())); + return result; +{{/isArray}} +{{^isArray}} + return new {{classname}}(in); +{{/isArray}} +{{/model}} + } + public {{classname}}[] newArray(int size) { + return new {{classname}}[size]; + } + }; +{{/parcelableModel}} +{{#discriminator}} +static { + // Initialize and register the discriminator mappings. + Map> mappings = new HashMap>(); + {{#mappedModels}} + mappings.put("{{mappingName}}", {{modelName}}.class); + {{/mappedModels}} + mappings.put("{{name}}", {{classname}}.class); + JSON.registerDiscriminator({{classname}}.class, "{{propertyBaseName}}", mappings); +} +{{/discriminator}} +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/pom.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/pom.mustache index d999ffaf0..4bfecc2c6 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/pom.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey2/pom.mustache @@ -43,7 +43,7 @@ org.apache.maven.plugins maven-enforcer-plugin - 3.0.0-M1 + 3.0.0 enforce-maven @@ -63,7 +63,7 @@ org.apache.maven.plugins maven-surefire-plugin - 2.12 + 3.0.0-M5 @@ -73,7 +73,8 @@ -Xms512m -Xmx1500m methods - pertest + 10 + false @@ -90,16 +91,14 @@ - org.apache.maven.plugins maven-jar-plugin - 2.6 + 3.2.2 - jar test-jar @@ -107,11 +106,10 @@ - org.codehaus.mojo build-helper-maven-plugin - 1.10 + 3.3.0 add_sources @@ -142,28 +140,23 @@ org.apache.maven.plugins maven-compiler-plugin - 3.6.1 + 3.10.1 - {{#supportJava6}} - 1.6 - 1.6 - {{/supportJava6}} - {{^supportJava6}} - {{#java8}} - 1.8 - 1.8 - {{/java8}} - {{^java8}} - 1.7 - 1.7 - {{/java8}} - {{/supportJava6}} + 1.8 + 1.8 + true + 128m + 512m + + -Xlint:all + -J-Xss4m + org.apache.maven.plugins maven-javadoc-plugin - 3.1.1 + 3.3.2 attach-javadocs @@ -174,6 +167,7 @@ none + 1.8 http.response.details @@ -186,7 +180,7 @@ org.apache.maven.plugins maven-source-plugin - 2.2.1 + 3.2.0 attach-sources @@ -196,6 +190,46 @@ + + + com.diffplug.spotless + spotless-maven-plugin + ${spotless.version} + + + + + + + .gitignore + + + + + + true + 4 + + + + + + + + + + 1.8 + + true + + + + + + @@ -207,7 +241,7 @@ org.apache.maven.plugins maven-gpg-plugin - 1.5 + 3.0.1 sign-artifacts @@ -224,11 +258,13 @@ + {{#swagger1AnnotationLibrary}} io.swagger swagger-annotations ${swagger-annotations-version} + {{/swagger1AnnotationLibrary}} @@ -236,20 +272,18 @@ jsr305 3.0.2 - + org.glassfish.jersey.core jersey-client ${jersey-version} - {{^supportJava6}} org.glassfish.jersey.inject jersey-hk2 ${jersey-version} - {{/supportJava6}} org.glassfish.jersey.media jersey-media-multipart @@ -277,97 +311,93 @@ jackson-databind ${jackson-databind-version} + {{#openApiNullable}} org.openapitools jackson-databind-nullable ${jackson-databind-nullable-version} + {{/openApiNullable}} {{#withXml}} - - - - org.glassfish.jersey.media - jersey-media-jaxb - ${jersey-version} - - + + + org.glassfish.jersey.media + jersey-media-jaxb + ${jersey-version} + {{/withXml}} {{#joda}} - - com.fasterxml.jackson.datatype - jackson-datatype-joda - ${jackson-version} - + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-version} + {{/joda}} - {{#java8}} - - com.fasterxml.jackson.datatype - jackson-datatype-jsr310 - ${jackson-version} - - {{/java8}} - {{#threetenbp}} - - com.github.joschi.jackson - jackson-datatype-threetenbp - ${threetenbp-version} - - {{/threetenbp}} - {{^java8}} - - - com.brsanthu - migbase64 - 2.2 - - {{/java8}} - {{#supportJava6}} - - org.apache.commons - commons-lang3 - ${commons_lang3_version} - - - commons-io - commons-io - ${commons_io_version} - - {{/supportJava6}} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + + {{#hasHttpSignatureMethods}} + + org.tomitribe + tomitribe-http-signatures + ${http-signature-version} + + {{/hasHttpSignatureMethods}} + {{#hasOAuthMethods}} + + com.github.scribejava + scribejava-apis + ${scribejava-apis-version} + + {{/hasOAuthMethods}} {{#useBeanValidation}} - - - javax.validation - validation-api - 1.1.0.Final - provided - + + + jakarta.validation + jakarta.validation-api + ${beanvalidation-version} + provided + {{/useBeanValidation}} + + jakarta.annotation + jakarta.annotation-api + ${jakarta-annotation-version} + provided + + + org.glassfish.jersey.connectors + jersey-apache-connector + ${jersey-version} + - junit - junit + org.junit.jupiter + junit-jupiter-api ${junit-version} test UTF-8 - 1.6.1 - {{^supportJava6}} - 2.27 - {{/supportJava6}} - {{#supportJava6}} - 2.6 - 2.5 - 3.6 - {{/supportJava6}} - 2.10.3 - 2.10.3 - 0.2.1 - {{#threetenbp}} - 2.9.10 - {{/threetenbp}} - 1.0.0 - 4.13 + 1.6.6 + 2.35 + 2.13.4 + 2.13.4.2 + 0.2.4 + 1.3.5 + {{#useBeanValidation}} + 2.0.2 + {{/useBeanValidation}} + 5.8.2 + {{#hasHttpSignatureMethods}} + 1.7 + {{/hasHttpSignatureMethods}} + {{#hasOAuthMethods}} + 8.3.1 + {{/hasOAuthMethods}} + 2.21.0 diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/AbstractOpenApiSchema.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/AbstractOpenApiSchema.mustache new file mode 100644 index 000000000..afbf6a9a0 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/AbstractOpenApiSchema.mustache @@ -0,0 +1,138 @@ +{{>licenseInfo}} + +package {{modelPackage}}; + +import {{invokerPackage}}.ApiException; +import java.util.Objects; +import java.lang.reflect.Type; +import java.util.Map; +import jakarta.ws.rs.core.GenericType; + +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Abstract class for oneOf,anyOf schemas defined in OpenAPI spec + */ +{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}} +public abstract class AbstractOpenApiSchema { + + // store the actual instance of the schema/object + private Object instance; + + // is nullable + private Boolean isNullable; + + // schema type (e.g. oneOf, anyOf) + private final String schemaType; + + public AbstractOpenApiSchema(String schemaType, Boolean isNullable) { + this.schemaType = schemaType; + this.isNullable = isNullable; + } + + /** + * Get the list of oneOf/anyOf composed schemas allowed to be stored in this object + * + * @return an instance of the actual schema/object + */ + public abstract Map getSchemas(); + + /** + * Get the actual instance + * + * @return an instance of the actual schema/object + */ + @JsonValue + public Object getActualInstance() {return instance;} + + /** + * Set the actual instance + * + * @param instance the actual instance of the schema/object + */ + public void setActualInstance(Object instance) {this.instance = instance;} + + /** + * Get the instant recursively when the schemas defined in oneOf/anyof happen to be oneOf/anyOf schema as well + * + * @return an instance of the actual schema/object + */ + public Object getActualInstanceRecursively() { + return getActualInstanceRecursively(this); + } + + private Object getActualInstanceRecursively(AbstractOpenApiSchema object) { + if (object.getActualInstance() == null) { + return null; + } else if (object.getActualInstance() instanceof AbstractOpenApiSchema) { + return getActualInstanceRecursively((AbstractOpenApiSchema)object.getActualInstance()); + } else { + return object.getActualInstance(); + } + } + + /** + * Get the schema type (e.g. anyOf, oneOf) + * + * @return the schema type + */ + public String getSchemaType() { + return schemaType; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ").append(getClass()).append(" {\n"); + sb.append(" instance: ").append(toIndentedString(instance)).append("\n"); + sb.append(" isNullable: ").append(toIndentedString(isNullable)).append("\n"); + sb.append(" schemaType: ").append(toIndentedString(schemaType)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AbstractOpenApiSchema a = (AbstractOpenApiSchema) o; + return Objects.equals(this.instance, a.instance) && + Objects.equals(this.isNullable, a.isNullable) && + Objects.equals(this.schemaType, a.schemaType); + } + + @Override + public int hashCode() { + return Objects.hash(instance, isNullable, schemaType); + } + + /** + * Is nullable + * + * @return true if it's nullable + */ + public Boolean isNullable() { + if (Boolean.TRUE.equals(isNullable)) { + return Boolean.TRUE; + } else { + return Boolean.FALSE; + } + } + +{{>libraries/jersey2/additional_properties}} + +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/ApiClient.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/ApiClient.mustache similarity index 61% rename from boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/ApiClient.mustache rename to boat-scaffold/src/main/templates/boat-java/libraries/jersey3/ApiClient.mustache index 10a976f6d..a89642a27 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/ApiClient.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/ApiClient.mustache @@ -1,16 +1,19 @@ package {{invokerPackage}}; -import javax.ws.rs.client.Client; -import javax.ws.rs.client.ClientBuilder; -import javax.ws.rs.client.Entity; -import javax.ws.rs.client.Invocation; -import javax.ws.rs.client.WebTarget; -import javax.ws.rs.core.Form; -import javax.ws.rs.core.GenericType; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.Status; +import jakarta.ws.rs.client.Client; +import jakarta.ws.rs.client.ClientBuilder; +import jakarta.ws.rs.client.Entity; +import jakarta.ws.rs.client.Invocation; +import jakarta.ws.rs.client.WebTarget; +import jakarta.ws.rs.core.Form; +import jakarta.ws.rs.core.GenericType; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.core.Response.Status; +{{#hasOAuthMethods}} +import com.github.scribejava.core.model.OAuth2AccessToken; +{{/hasOAuthMethods}} import org.glassfish.jersey.client.ClientConfig; import org.glassfish.jersey.client.ClientProperties; import org.glassfish.jersey.client.HttpUrlConnectorProvider; @@ -24,15 +27,19 @@ import java.io.IOException; import java.io.InputStream; import java.net.URI; -{{^supportJava6}} +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import java.security.cert.X509Certificate; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; import java.nio.file.Files; +import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import org.glassfish.jersey.logging.LoggingFeature; -{{/supportJava6}} -{{#supportJava6}} -import org.apache.commons.io.FileUtils; -import org.glassfish.jersey.filter.LoggingFilter; -{{/supportJava6}} +import java.util.logging.Level; +import java.util.logging.Logger; import java.util.Collection; import java.util.Collections; import java.util.Map; @@ -43,7 +50,9 @@ import java.util.List; import java.util.Arrays; import java.util.ArrayList; import java.util.Date; -import java.util.TimeZone; +{{#jsr310}} +import java.time.OffsetDateTime; +{{/jsr310}} import java.net.URLEncoder; @@ -57,19 +66,25 @@ import java.util.regex.Pattern; import {{invokerPackage}}.auth.Authentication; import {{invokerPackage}}.auth.HttpBasicAuth; import {{invokerPackage}}.auth.HttpBearerAuth; +{{#hasHttpSignatureMethods}} import {{invokerPackage}}.auth.HttpSignatureAuth; +{{/hasHttpSignatureMethods}} import {{invokerPackage}}.auth.ApiKeyAuth; -import {{invokerPackage}}.model.AbstractOpenApiSchema; - {{#hasOAuthMethods}} import {{invokerPackage}}.auth.OAuth; {{/hasOAuthMethods}} +/** + *

ApiClient class.

+ */ {{>generatedAnnotation}} -public class ApiClient { +public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} { protected Map defaultHeaderMap = new HashMap(); protected Map defaultCookieMap = new HashMap(); protected String basePath = "{{{basePath}}}"; + protected String userAgent; + private static final Logger log = Logger.getLogger(ApiClient.class.getName()); + protected List servers = new ArrayList({{#servers}}{{#-first}}Arrays.asList( {{/-first}} new ServerConfiguration( "{{{url}}}", @@ -139,6 +154,7 @@ public class ApiClient { protected Map operationServerIndex = new HashMap(); protected Map> operationServerVariables = new HashMap>(); protected boolean debugging = false; + protected ClientConfig clientConfig; protected int connectionTimeout = 0; private int readTimeout = 0; @@ -151,34 +167,68 @@ public class ApiClient { protected DateFormat dateFormat; + /** + * Constructs a new ApiClient with default parameters. + */ public ApiClient() { + this(null); + } + + /** + * Constructs a new ApiClient with the specified authentication parameters. + * + * @param authMap A hash map containing authentication parameters. + */ + public ApiClient(Map authMap) { json = new JSON(); - httpClient = buildHttpClient(debugging); + httpClient = buildHttpClient(); this.dateFormat = new RFC3339DateFormat(); // Set default User-Agent. - setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}"); + setUserAgent("{{{httpUserAgent}}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}"); // Setup authentications (key: authentication name, value: authentication). authentications = new HashMap(); + Authentication auth = null; {{#authMethods}} + if (authMap != null) { + auth = authMap.get("{{name}}"); + } {{#isBasic}} {{#isBasicBasic}} - authentications.put("{{name}}", new HttpBasicAuth()); + if (auth instanceof HttpBasicAuth) { + authentications.put("{{name}}", auth); + } else { + authentications.put("{{name}}", new HttpBasicAuth()); + } {{/isBasicBasic}} {{#isBasicBearer}} - authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}")); + if (auth instanceof HttpBearerAuth) { + authentications.put("{{name}}", auth); + } else { + authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}")); + } {{/isBasicBearer}} {{#isHttpSignature}} - authentications.put("{{name}}", new HttpSignatureAuth("{{name}}", null, null)); + if (auth instanceof HttpSignatureAuth) { + authentications.put("{{name}}", auth); + } {{/isHttpSignature}} {{/isBasic}} {{#isApiKey}} - authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}")); + if (auth instanceof ApiKeyAuth) { + authentications.put("{{name}}", auth); + } else { + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}")); + } {{/isApiKey}} {{#isOAuth}} - authentications.put("{{name}}", new OAuth()); + if (auth instanceof OAuth) { + authentications.put("{{name}}", auth); + } else { + authentications.put("{{name}}", new OAuth(basePath, "{{{tokenUrl}}}")); + } {{/isOAuth}} {{/authMethods}} // Prevent the authentications from being modified. @@ -191,59 +241,138 @@ public class ApiClient { /** * Gets the JSON instance to do JSON serialization and deserialization. + * * @return JSON */ public JSON getJSON() { return json; } + /** + *

Getter for the field httpClient.

+ * + * @return a {@link jakarta.ws.rs.client.Client} object. + */ public Client getHttpClient() { return httpClient; } + /** + *

Setter for the field httpClient.

+ * + * @param httpClient a {@link jakarta.ws.rs.client.Client} object. + * @return a {@link org.openapitools.client.ApiClient} object. + */ public ApiClient setHttpClient(Client httpClient) { this.httpClient = httpClient; return this; } + /** + * Returns the base URL to the location where the OpenAPI document is being served. + * + * @return The base URL to the target host. + */ public String getBasePath() { return basePath; } + /** + * Sets the base URL to the location where the OpenAPI document is being served. + * + * @param basePath The base URL to the target host. + * @return a {@link org.openapitools.client.ApiClient} object. + */ public ApiClient setBasePath(String basePath) { this.basePath = basePath; + {{#hasOAuthMethods}} + setOauthBasePath(basePath); + {{/hasOAuthMethods}} return this; } + /** + *

Getter for the field servers.

+ * + * @return a {@link java.util.List} of servers. + */ public List getServers() { return servers; } + /** + *

Setter for the field servers.

+ * + * @param servers a {@link java.util.List} of servers. + * @return a {@link org.openapitools.client.ApiClient} object. + */ public ApiClient setServers(List servers) { this.servers = servers; + updateBasePath(); return this; } + /** + *

Getter for the field serverIndex.

+ * + * @return a {@link java.lang.Integer} object. + */ public Integer getServerIndex() { return serverIndex; } + /** + *

Setter for the field serverIndex.

+ * + * @param serverIndex the server index + * @return a {@link org.openapitools.client.ApiClient} object. + */ public ApiClient setServerIndex(Integer serverIndex) { this.serverIndex = serverIndex; + updateBasePath(); return this; } + /** + *

Getter for the field serverVariables.

+ * + * @return a {@link java.util.Map} of server variables. + */ public Map getServerVariables() { return serverVariables; } + /** + *

Setter for the field serverVariables.

+ * + * @param serverVariables a {@link java.util.Map} of server variables. + * @return a {@link org.openapitools.client.ApiClient} object. + */ public ApiClient setServerVariables(Map serverVariables) { this.serverVariables = serverVariables; + updateBasePath(); return this; } + private void updateBasePath() { + if (serverIndex != null) { + setBasePath(servers.get(serverIndex).URL(serverVariables)); + } + } + + {{#hasOAuthMethods}} + private void setOauthBasePath(String basePath) { + for(Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setBasePath(basePath); + } + } + } + + {{/hasOAuthMethods}} /** * Get authentications (key: authentication name, value: authentication). + * * @return Map of authentication object */ public Map getAuthentications() { @@ -262,13 +391,15 @@ public class ApiClient { /** * Helper method to set username for the first HTTP basic authentication. + * * @param username Username + * @return a {@link org.openapitools.client.ApiClient} object. */ - public void setUsername(String username) { + public ApiClient setUsername(String username) { for (Authentication auth : authentications.values()) { if (auth instanceof HttpBasicAuth) { ((HttpBasicAuth) auth).setUsername(username); - return; + return this; } } throw new RuntimeException("No HTTP basic authentication configured!"); @@ -276,13 +407,15 @@ public class ApiClient { /** * Helper method to set password for the first HTTP basic authentication. + * * @param password Password + * @return a {@link org.openapitools.client.ApiClient} object. */ - public void setPassword(String password) { + public ApiClient setPassword(String password) { for (Authentication auth : authentications.values()) { if (auth instanceof HttpBasicAuth) { ((HttpBasicAuth) auth).setPassword(password); - return; + return this; } } throw new RuntimeException("No HTTP basic authentication configured!"); @@ -290,13 +423,15 @@ public class ApiClient { /** * Helper method to set API key value for the first API key authentication. + * * @param apiKey API key + * @return a {@link org.openapitools.client.ApiClient} object. */ - public void setApiKey(String apiKey) { + public ApiClient setApiKey(String apiKey) { for (Authentication auth : authentications.values()) { if (auth instanceof ApiKeyAuth) { ((ApiKeyAuth) auth).setApiKey(apiKey); - return; + return this; } } throw new RuntimeException("No API key authentication configured!"); @@ -306,30 +441,34 @@ public class ApiClient { * Helper method to configure authentications which respects aliases of API keys. * * @param secrets Hash map from authentication name to its secret. + * @return a {@link org.openapitools.client.ApiClient} object. */ - public void configureApiKeys(HashMap secrets) { + public ApiClient configureApiKeys(Map secrets) { for (Map.Entry authEntry : authentications.entrySet()) { Authentication auth = authEntry.getValue(); if (auth instanceof ApiKeyAuth) { String name = authEntry.getKey(); // respect x-auth-id-alias property - name = authenticationLookup.getOrDefault(name, name); + name = authenticationLookup.containsKey(name) ? authenticationLookup.get(name) : name; if (secrets.containsKey(name)) { ((ApiKeyAuth) auth).setApiKey(secrets.get(name)); } } } + return this; } /** * Helper method to set API key prefix for the first API key authentication. + * * @param apiKeyPrefix API key prefix + * @return a {@link org.openapitools.client.ApiClient} object. */ - public void setApiKeyPrefix(String apiKeyPrefix) { + public ApiClient setApiKeyPrefix(String apiKeyPrefix) { for (Authentication auth : authentications.values()) { if (auth instanceof ApiKeyAuth) { ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix); - return; + return this; } } throw new RuntimeException("No API key authentication configured!"); @@ -337,13 +476,15 @@ public class ApiClient { /** * Helper method to set bearer token for the first Bearer authentication. + * * @param bearerToken Bearer token + * @return a {@link org.openapitools.client.ApiClient} object. */ - public void setBearerToken(String bearerToken) { + public ApiClient setBearerToken(String bearerToken) { for (Authentication auth : authentications.values()) { if (auth instanceof HttpBearerAuth) { ((HttpBearerAuth) auth).setBearerToken(bearerToken); - return; + return this; } } throw new RuntimeException("No Bearer authentication configured!"); @@ -352,13 +493,97 @@ public class ApiClient { {{#hasOAuthMethods}} /** * Helper method to set access token for the first OAuth2 authentication. + * * @param accessToken Access token + * @return a {@link org.openapitools.client.ApiClient} object. */ - public void setAccessToken(String accessToken) { + public ApiClient setAccessToken(String accessToken) { for (Authentication auth : authentications.values()) { if (auth instanceof OAuth) { ((OAuth) auth).setAccessToken(accessToken); - return; + return this; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + /** + * Helper method to set the credentials for the first OAuth2 authentication. + * + * @param clientId the client ID + * @param clientSecret the client secret + * @return a {@link org.openapitools.client.ApiClient} object. + */ + public ApiClient setOauthCredentials(String clientId, String clientSecret) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setCredentials(clientId, clientSecret, isDebugging()); + return this; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + /** + * Helper method to set the credentials of a public client for the first OAuth2 authentication. + * + * @param clientId the client ID + * @return a {@link org.openapitools.client.ApiClient} object. + */ + public ApiClient setOauthCredentialsForPublicClient(String clientId) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setCredentialsForPublicClient(clientId, isDebugging()); + return this; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + /** + * Helper method to set the password flow for the first OAuth2 authentication. + * + * @param username the user name + * @param password the user password + * @return a {@link org.openapitools.client.ApiClient} object. + */ + public ApiClient setOauthPasswordFlow(String username, String password) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).usePasswordFlow(username, password); + return this; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + /** + * Helper method to set the authorization code flow for the first OAuth2 authentication. + * + * @param code the authorization code + * @return a {@link org.openapitools.client.ApiClient} object. + */ + public ApiClient setOauthAuthorizationCodeFlow(String code) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).useAuthorizationCodeFlow(code); + return this; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + + /** + * Helper method to set the scopes for the first OAuth2 authentication. + * + * @param scope the oauth scope + * @return a {@link org.openapitools.client.ApiClient} object. + */ + public ApiClient setOauthScope(String scope) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setScope(scope); + return this; } } throw new RuntimeException("No OAuth2 authentication configured!"); @@ -367,20 +592,31 @@ public class ApiClient { {{/hasOAuthMethods}} /** * Set the User-Agent header's value (by adding to the default header map). + * * @param userAgent Http user agent - * @return API client + * @return a {@link org.openapitools.client.ApiClient} object. */ public ApiClient setUserAgent(String userAgent) { + this.userAgent = userAgent; addDefaultHeader("User-Agent", userAgent); return this; } + /** + * Get the User-Agent header's value. + * + * @return User-Agent string + */ + public String getUserAgent(){ + return userAgent; + } + /** * Add a default header. * * @param key The header's key * @param value The header's value - * @return API client + * @return a {@link org.openapitools.client.ApiClient} object. */ public ApiClient addDefaultHeader(String key, String value) { defaultHeaderMap.put(key, value); @@ -392,15 +628,38 @@ public class ApiClient { * * @param key The cookie's key * @param value The cookie's value - * @return API client + * @return a {@link org.openapitools.client.ApiClient} object. */ public ApiClient addDefaultCookie(String key, String value) { defaultCookieMap.put(key, value); return this; } + /** + * Gets the client config. + * + * @return Client config + */ + public ClientConfig getClientConfig() { + return clientConfig; + } + + /** + * Set the client config. + * + * @param clientConfig Set the client config + * @return a {@link org.openapitools.client.ApiClient} object. + */ + public ApiClient setClientConfig(ClientConfig clientConfig) { + this.clientConfig = clientConfig; + // Rebuild HTTP Client according to the new "clientConfig" value. + this.httpClient = buildHttpClient(); + return this; + } + /** * Check that whether debugging is enabled for this API client. + * * @return True if debugging is switched on */ public boolean isDebugging() { @@ -411,19 +670,19 @@ public class ApiClient { * Enable/disable debugging for this API client. * * @param debugging To enable (true) or disable (false) debugging - * @return API client + * @return a {@link org.openapitools.client.ApiClient} object. */ public ApiClient setDebugging(boolean debugging) { this.debugging = debugging; // Rebuild HTTP Client according to the new "debugging" value. - this.httpClient = buildHttpClient(debugging); + this.httpClient = buildHttpClient(); return this; } /** * The path of temporary folder used to store downloaded files from endpoints * with file response. The default value is null, i.e. using - * the system's default tempopary folder. + * the system's default temporary folder. * * @return Temp folder path */ @@ -433,8 +692,9 @@ public class ApiClient { /** * Set temp folder path + * * @param tempFolderPath Temp folder path - * @return API client + * @return a {@link org.openapitools.client.ApiClient} object. */ public ApiClient setTempFolderPath(String tempFolderPath) { this.tempFolderPath = tempFolderPath; @@ -443,6 +703,7 @@ public class ApiClient { /** * Connect timeout (in milliseconds). + * * @return Connection timeout */ public int getConnectTimeout() { @@ -453,8 +714,9 @@ public class ApiClient { * Set the connect timeout (in milliseconds). * A value of 0 means no timeout, otherwise values must be between 1 and * {@link Integer#MAX_VALUE}. + * * @param connectionTimeout Connection timeout in milliseconds - * @return API client + * @return a {@link org.openapitools.client.ApiClient} object. */ public ApiClient setConnectTimeout(int connectionTimeout) { this.connectionTimeout = connectionTimeout; @@ -464,6 +726,7 @@ public class ApiClient { /** * read timeout (in milliseconds). + * * @return Read timeout */ public int getReadTimeout() { @@ -474,8 +737,9 @@ public class ApiClient { * Set the read timeout (in milliseconds). * A value of 0 means no timeout, otherwise values must be between 1 and * {@link Integer#MAX_VALUE}. + * * @param readTimeout Read timeout in milliseconds - * @return API client + * @return a {@link org.openapitools.client.ApiClient} object. */ public ApiClient setReadTimeout(int readTimeout) { this.readTimeout = readTimeout; @@ -485,6 +749,7 @@ public class ApiClient { /** * Get the date format used to parse/format date parameters. + * * @return Date format */ public DateFormat getDateFormat() { @@ -493,8 +758,9 @@ public class ApiClient { /** * Set the date format used to parse/format date parameters. + * * @param dateFormat Date format - * @return API client + * @return a {@link org.openapitools.client.ApiClient} object. */ public ApiClient setDateFormat(DateFormat dateFormat) { this.dateFormat = dateFormat; @@ -505,6 +771,7 @@ public class ApiClient { /** * Parse the given string into Date object. + * * @param str String * @return Date */ @@ -518,6 +785,7 @@ public class ApiClient { /** * Format the given Date object into string. + * * @param date Date * @return Date in string format */ @@ -527,6 +795,7 @@ public class ApiClient { /** * Format the given parameter object into string. + * * @param param Object * @return Object in string format */ @@ -535,7 +804,9 @@ public class ApiClient { return ""; } else if (param instanceof Date) { return formatDate((Date) param); - } else if (param instanceof Collection) { + } {{#jsr310}}else if (param instanceof OffsetDateTime) { + return formatOffsetDateTime((OffsetDateTime) param); + } {{/jsr310}}else if (param instanceof Collection) { StringBuilder b = new StringBuilder(); for(Object o : (Collection)param) { if(b.length() > 0) { @@ -551,6 +822,7 @@ public class ApiClient { /* * Format to {@code Pair} objects. + * * @param collectionFormat Collection format * @param name Name * @param value Value @@ -617,6 +889,7 @@ public class ApiClient { * APPLICATION/JSON * application/vnd.company+json * "* / *" is also default to JSON + * * @param mime MIME * @return True if the MIME type is JSON */ @@ -669,6 +942,7 @@ public class ApiClient { /** * Escape the given string to be used as URL query value. + * * @param str String * @return Escaped string */ @@ -683,13 +957,14 @@ public class ApiClient { /** * Serialize the given Java object into string entity according the given * Content-Type (only JSON is supported for now). + * * @param obj Object * @param formParams Form parameters * @param contentType Context type * @return Entity * @throws ApiException API exception */ - public Entity serialize(Object obj, Map formParams, String contentType) throws ApiException { + public Entity serialize(Object obj, Map formParams, String contentType, boolean isBodyNullable) throws ApiException { Entity entity; if (contentType.startsWith("multipart/form-data")) { MultiPart multiPart = new MultiPart(); @@ -713,7 +988,19 @@ public class ApiClient { entity = Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE); } else { // We let jersey handle the serialization - entity = Entity.entity(obj == null ? Entity.text("") : obj, contentType); + if (isBodyNullable) { // payload is nullable + if (obj instanceof String) { + entity = Entity.entity(obj == null ? "null" : "\"" + ((String)obj).replaceAll("\"", Matcher.quoteReplacement("\\\"")) + "\"", contentType); + } else { + entity = Entity.entity(obj == null ? "null" : obj, contentType); + } + } else { + if (obj instanceof String) { + entity = Entity.entity(obj == null ? "" : "\"" + ((String)obj).replaceAll("\"", Matcher.quoteReplacement("\\\"")) + "\"", contentType); + } else { + entity = Entity.entity(obj == null ? "" : obj, contentType); + } + } } return entity; } @@ -721,13 +1008,15 @@ public class ApiClient { /** * Serialize the given Java object into string according the given * Content-Type (only JSON, HTTP form is supported for now). + * * @param obj Object * @param formParams Form parameters * @param contentType Context type + * @param isBodyNullable True if the body is nullable * @return String * @throws ApiException API exception */ - public String serializeToString(Object obj, Map formParams, String contentType) throws ApiException { + public String serializeToString(Object obj, Map formParams, String contentType, boolean isBodyNullable) throws ApiException { try { if (contentType.startsWith("multipart/form-data")) { throw new ApiException("multipart/form-data not yet supported for serializeToString (http signature authentication)"); @@ -743,64 +1032,20 @@ public class ApiClient { return formString.substring(0, formString.length() - 1); } } else { - return json.getMapper().writeValueAsString(obj); + if (isBodyNullable) { + return obj == null ? "null" : json.getMapper().writeValueAsString(obj); + } else { + return obj == null ? "" : json.getMapper().writeValueAsString(obj); + } } } catch (Exception ex) { throw new ApiException("Failed to perform serializeToString: " + ex.toString()); } } - public AbstractOpenApiSchema deserializeSchemas(Response response, AbstractOpenApiSchema schema) throws ApiException{ - - Object result = null; - int matchCounter = 0; - ArrayList matchSchemas = new ArrayList<>(); - - for (Map.Entry entry : schema.getSchemas().entrySet()) { - String schemaName = entry.getKey(); - GenericType schemaType = entry.getValue(); - - if (schemaType instanceof GenericType) { // model - try { - Object deserializedObject = deserialize(response, schemaType); - if (deserializedObject != null) { - result = deserializedObject; - matchCounter++; - - if ("anyOf".equals(schema.getSchemaType())) { - break; - } else if ("oneOf".equals(schema.getSchemaType())) { - matchSchemas.add(schemaName); - } else { - throw new ApiException("Unknowe type found while expecting anyOf/oneOf:" + schema.getSchemaType()); - } - } else { - // failed to deserialize the response in the schema provided, proceed to the next one if any - } - } catch (Exception ex) { - // failed to deserialize, do nothing and try next one (schema) - } - } else {// unknown type - throw new ApiException(schemaType.getClass() + " is not a GenericType and cannot be handled properly in deserialization."); - } - - } - - if (matchCounter > 1 && "oneOf".equals(schema.getSchemaType())) {// more than 1 match for oneOf - throw new ApiException("Response body is invalid as it matches more than one schema (" + String.join(", ", matchSchemas) + ") defined in the oneOf model: " + schema.getClass().getName()); - } else if (matchCounter == 0) { // fail to match any in oneOf/anyOf schemas - throw new ApiException("Response body is invalid as it doens't match any schemas (" + String.join(", ", schema.getSchemas().keySet()) + ") defined in the oneOf/anyOf model: " + schema.getClass().getName()); - } else { // only one matched - schema.setActualInstance(result); - return schema; - } - - } - - - /** * Deserialize response body to Java object according to the Content-Type. + * * @param Type * @param response Response * @param returnType Return type @@ -835,6 +1080,7 @@ public class ApiClient { /** * Download file from the given response. + * * @param response Response * @return File * @throws ApiException If fail to read file content from response and write to disk @@ -842,19 +1088,20 @@ public class ApiClient { public File downloadFileFromResponse(Response response) throws ApiException { try { File file = prepareDownloadFile(response); -{{^supportJava6}} Files.copy(response.readEntity(InputStream.class), file.toPath(), StandardCopyOption.REPLACE_EXISTING); -{{/supportJava6}} -{{#supportJava6}} - // Java6 falls back to commons.io for file copying - FileUtils.copyToFile(response.readEntity(InputStream.class), file); -{{/supportJava6}} return file; } catch (IOException e) { throw new ApiException(e); } } + /** + *

Prepare the file for download from the response.

+ * + * @param response a {@link jakarta.ws.rs.core.Response} object. + * @return a {@link java.io.File} object. + * @throws java.io.IOException if any. + */ public File prepareDownloadFile(Response response) throws IOException { String filename = null; String contentDisposition = (String) response.getHeaders().getFirst("Content-Disposition"); @@ -879,15 +1126,15 @@ public class ApiClient { prefix = filename.substring(0, pos) + "-"; suffix = filename.substring(pos); } - // File.createTempFile requires the prefix to be at least three characters long + // Files.createTempFile requires the prefix to be at least three characters long if (prefix.length() < 3) prefix = "download-"; } if (tempFolderPath == null) - return File.createTempFile(prefix, suffix); + return Files.createTempFile(prefix, suffix).toFile(); else - return File.createTempFile(prefix, suffix, new File(tempFolderPath)); + return Files.createTempFile(Paths.get(tempFolderPath), prefix, suffix).toFile(); } /** @@ -906,33 +1153,39 @@ public class ApiClient { * @param contentType The request's Content-Type header * @param authNames The authentications to apply * @param returnType The return type into which to deserialize the response - * @param schema An instance of the response that uses oneOf/anyOf + * @param isBodyNullable True if the body is nullable * @return The response body in type of string * @throws ApiException API exception */ - public ApiResponse invokeAPI(String operation, String path, String method, List queryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType, AbstractOpenApiSchema schema) throws ApiException { + public ApiResponse invokeAPI( + String operation, + String path, + String method, + List queryParams, + Object body, + Map headerParams, + Map cookieParams, + Map formParams, + String accept, + String contentType, + String[] authNames, + GenericType returnType, + boolean isBodyNullable) + throws ApiException { // Not using `.target(targetURL).path(path)` below, // to support (constant) query string in `path`, e.g. "/posts?draft=1" String targetURL; - if (serverIndex != null) { - Integer index; - List serverConfigurations; - Map variables; - - if (operationServers.containsKey(operation)) { - index = operationServerIndex.getOrDefault(operation, serverIndex); - variables = operationServerVariables.getOrDefault(operation, serverVariables); - serverConfigurations = operationServers.get(operation); - } else { - index = serverIndex; - variables = serverVariables; - serverConfigurations = servers; - } + if (serverIndex != null && operationServers.containsKey(operation)) { + Integer index = operationServerIndex.containsKey(operation) ? operationServerIndex.get(operation) : serverIndex; + Map variables = operationServerVariables.containsKey(operation) ? + operationServerVariables.get(operation) : serverVariables; + List serverConfigurations = operationServers.get(operation); if (index < 0 || index >= serverConfigurations.size()) { - throw new ArrayIndexOutOfBoundsException(String.format( - "Invalid index %d when selecting the host settings. Must be less than %d", index, serverConfigurations.size() - )); + throw new ArrayIndexOutOfBoundsException( + String.format( + "Invalid index %d when selecting the host settings. Must be less than %d", + index, serverConfigurations.size())); } targetURL = serverConfigurations.get(index).URL(variables) + path; } else { @@ -948,13 +1201,11 @@ public class ApiClient { } } - Invocation.Builder invocationBuilder = target.request().accept(accept); - - for (Entry entry : headerParams.entrySet()) { - String value = entry.getValue(); - if (value != null) { - invocationBuilder = invocationBuilder.header(entry.getKey(), value); - } + Invocation.Builder invocationBuilder; + if (accept != null) { + invocationBuilder = target.request().accept(accept); + } else { + invocationBuilder = target.request(); } for (Entry entry : cookieParams.entrySet()) { @@ -971,63 +1222,63 @@ public class ApiClient { } } - for (Entry entry : defaultHeaderMap.entrySet()) { - String key = entry.getKey(); - if (!headerParams.containsKey(key)) { - String value = entry.getValue(); - if (value != null) { - invocationBuilder = invocationBuilder.header(key, value); - } - } - } - - Entity entity = serialize(body, formParams, contentType); + Entity entity = serialize(body, formParams, contentType, isBodyNullable); // put all headers in one place - Map allHeaderParams = new HashMap<>(); - allHeaderParams.putAll(defaultHeaderMap); + Map allHeaderParams = new HashMap<>(defaultHeaderMap); allHeaderParams.putAll(headerParams); - + // update different parameters (e.g. headers) for authentication - updateParamsForAuth(authNames, queryParams, allHeaderParams, cookieParams, serializeToString(body, formParams, contentType), method, target.getUri()); + updateParamsForAuth( + authNames, + queryParams, + allHeaderParams, + cookieParams, + serializeToString(body, formParams, contentType, isBodyNullable), + method, + target.getUri()); + + for (Entry entry : allHeaderParams.entrySet()) { + String value = entry.getValue(); + if (value != null) { + invocationBuilder = invocationBuilder.header(entry.getKey(), value); + } + } Response response = null; try { - if ("GET".equals(method)) { - response = invocationBuilder.get(); - } else if ("POST".equals(method)) { - response = invocationBuilder.post(entity); - } else if ("PUT".equals(method)) { - response = invocationBuilder.put(entity); - } else if ("DELETE".equals(method)) { - response = invocationBuilder.method("DELETE", entity); - } else if ("PATCH".equals(method)) { - response = invocationBuilder.method("PATCH", entity); - } else if ("HEAD".equals(method)) { - response = invocationBuilder.head(); - } else if ("OPTIONS".equals(method)) { - response = invocationBuilder.options(); - } else if ("TRACE".equals(method)) { - response = invocationBuilder.trace(); - } else { - throw new ApiException(500, "unknown method type " + method); + response = sendRequest(method, invocationBuilder, entity); + + {{#hasOAuthMethods}} + // If OAuth is used and a status 401 is received, renew the access token and retry the request + if (response.getStatusInfo() == Status.UNAUTHORIZED) { + for (String authName : authNames) { + Authentication authentication = authentications.get(authName); + if (authentication instanceof OAuth) { + OAuth2AccessToken accessToken = ((OAuth) authentication).renewAccessToken(); + if (accessToken != null) { + invocationBuilder.header("Authorization", null); + invocationBuilder.header("Authorization", "Bearer " + accessToken.getAccessToken()); + response = sendRequest(method, invocationBuilder, entity); + } + break; + } + } } + {{/hasOAuthMethods}} int statusCode = response.getStatusInfo().getStatusCode(); Map> responseHeaders = buildResponseHeaders(response); - if (response.getStatus() == Status.NO_CONTENT.getStatusCode()) { - return new ApiResponse<{{#supportJava6}}T{{/supportJava6}}>(statusCode, responseHeaders); + if (response.getStatusInfo() == Status.NO_CONTENT) { + return new ApiResponse(statusCode, responseHeaders); } else if (response.getStatusInfo().getFamily() == Status.Family.SUCCESSFUL) { - if (returnType == null) - return new ApiResponse<{{#supportJava6}}T{{/supportJava6}}>(statusCode, responseHeaders); - else - if (schema == null) { - return new ApiResponse<>(statusCode, responseHeaders, deserialize(response, returnType)); - } else { // oneOf/anyOf - return new ApiResponse<>(statusCode, responseHeaders, (T)deserializeSchemas(response, schema)); - } + if (returnType == null) { + return new ApiResponse(statusCode, responseHeaders); + } else { + return new ApiResponse(statusCode, responseHeaders, deserialize(response, returnType)); + } } else { String message = "error"; String respBody = null; @@ -1040,35 +1291,64 @@ public class ApiClient { } } throw new ApiException( - response.getStatus(), - message, - buildResponseHeaders(response), - respBody); + response.getStatus(), message, buildResponseHeaders(response), respBody); } } finally { try { response.close(); } catch (Exception e) { - // it's not critical, since the response object is local in method invokeAPI; that's fine, just continue + // it's not critical, since the response object is local in method invokeAPI; that's fine, + // just continue } } } + private Response sendRequest(String method, Invocation.Builder invocationBuilder, Entity entity) { + Response response; + if ("POST".equals(method)) { + response = invocationBuilder.post(entity); + } else if ("PUT".equals(method)) { + response = invocationBuilder.put(entity); + } else if ("DELETE".equals(method)) { + response = invocationBuilder.method("DELETE", entity); + } else if ("PATCH".equals(method)) { + response = invocationBuilder.method("PATCH", entity); + } else { + response = invocationBuilder.method(method); + } + return response; + } + /** * @deprecated Add qualified name of the operation as a first parameter. */ @Deprecated - public ApiResponse invokeAPI(String path, String method, List queryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType, AbstractOpenApiSchema schema) throws ApiException { - return invokeAPI(null, path, method, queryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames, returnType, schema); + public ApiResponse invokeAPI(String path, String method, List queryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String accept, String contentType, String[] authNames, GenericType returnType, boolean isBodyNullable) throws ApiException { + return invokeAPI(null, path, method, queryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames, returnType, isBodyNullable); } /** * Build the Client used to make HTTP requests. - * @param debugging Debug setting + * * @return Client */ - protected Client buildHttpClient(boolean debugging) { - final ClientConfig clientConfig = new ClientConfig(); + protected Client buildHttpClient() { + // recreate the client config to pickup changes + clientConfig = getDefaultClientConfig(); + + ClientBuilder clientBuilder = ClientBuilder.newBuilder(); + customizeClientBuilder(clientBuilder); + clientBuilder = clientBuilder.withConfig(clientConfig); + return clientBuilder.build(); + } + + /** + * Get the default client config. + * + * @return Client config + */ + public ClientConfig getDefaultClientConfig() { + ClientConfig clientConfig = new ClientConfig(); clientConfig.register(MultiPartFeature.class); clientConfig.register(json); clientConfig.register(JacksonFeature.class); @@ -1076,27 +1356,74 @@ public class ApiClient { // turn off compliance validation to be able to send payloads with DELETE calls clientConfig.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true); if (debugging) { -{{^supportJava6}} clientConfig.register(new LoggingFeature(java.util.logging.Logger.getLogger(LoggingFeature.DEFAULT_LOGGER_NAME), java.util.logging.Level.INFO, LoggingFeature.Verbosity.PAYLOAD_ANY, 1024*50 /* Log payloads up to 50K */)); clientConfig.property(LoggingFeature.LOGGING_FEATURE_VERBOSITY, LoggingFeature.Verbosity.PAYLOAD_ANY); // Set logger to ALL java.util.logging.Logger.getLogger(LoggingFeature.DEFAULT_LOGGER_NAME).setLevel(java.util.logging.Level.ALL); -{{/supportJava6}} -{{#supportJava6}} - clientConfig.register(new LoggingFilter(java.util.logging.Logger.getLogger(LoggingFilter.class.getName()), true)); -{{/supportJava6}} } else { // suppress warnings for payloads with DELETE calls: java.util.logging.Logger.getLogger("org.glassfish.jersey.client").setLevel(java.util.logging.Level.SEVERE); } - performAdditionalClientConfiguration(clientConfig); - return ClientBuilder.newClient(clientConfig); + + return clientConfig; } - protected void performAdditionalClientConfiguration(ClientConfig clientConfig) { + /** + * Customize the client builder. + * + * This method can be overridden to customize the API client. For example, this can be used to: + * 1. Set the hostname verifier to be used by the client to verify the endpoint's hostname + * against its identification information. + * 2. Set the client-side key store. + * 3. Set the SSL context that will be used when creating secured transport connections to + * server endpoints from web targets created by the client instance that is using this SSL context. + * 4. Set the client-side trust store. + * + * To completely disable certificate validation (at your own risk), you can + * override this method and invoke disableCertificateValidation(clientBuilder). + * + * @param clientBuilder a {@link jakarta.ws.rs.client.ClientBuilder} object. + */ + protected void customizeClientBuilder(ClientBuilder clientBuilder) { // No-op extension point } + /** + * Disable X.509 certificate validation in TLS connections. + * + * Please note that trusting all certificates is extremely risky. + * This may be useful in a development environment with self-signed certificates. + * + * @param clientBuilder a {@link jakarta.ws.rs.client.ClientBuilder} object. + * @throws java.security.KeyManagementException if any. + * @throws java.security.NoSuchAlgorithmException if any. + */ + protected void disableCertificateValidation(ClientBuilder clientBuilder) throws KeyManagementException, NoSuchAlgorithmException { + TrustManager[] trustAllCerts = new X509TrustManager[] { + new X509TrustManager() { + @Override + public X509Certificate[] getAcceptedIssuers() { + return null; + } + @Override + public void checkClientTrusted(X509Certificate[] certs, String authType) { + } + @Override + public void checkServerTrusted(X509Certificate[] certs, String authType) { + } + } + }; + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(null, trustAllCerts, new SecureRandom()); + clientBuilder.sslContext(sslContext); + } + + /** + *

Build the response headers.

+ * + * @param response a {@link jakarta.ws.rs.core.Response} object. + * @return a {@link java.util.Map} of response headers. + */ protected Map> buildResponseHeaders(Response response) { Map> responseHeaders = new HashMap>(); for (Entry> entry: response.getHeaders().entrySet()) { @@ -1125,7 +1452,7 @@ public class ApiClient { for (String authName : authNames) { Authentication auth = authentications.get(authName); if (auth == null) { - throw new RuntimeException("Authentication undefined: " + authName); + continue; } auth.applyToParams(queryParams, headerParams, cookieParams, payload, method, uri); } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/ApiResponse.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/ApiResponse.mustache similarity index 98% rename from boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/ApiResponse.mustache rename to boat-scaffold/src/main/templates/boat-java/libraries/jersey3/ApiResponse.mustache index 5dae9dc1f..86c889b0f 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/ApiResponse.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/ApiResponse.mustache @@ -5,7 +5,7 @@ package {{invokerPackage}}; import java.util.List; import java.util.Map; {{#caseInsensitiveResponseHeaders}} -import java.util.Map.Entry; +import java.util.Map.Entry; import java.util.TreeMap; {{/caseInsensitiveResponseHeaders}} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/JSON.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/JSON.mustache new file mode 100644 index 000000000..aea0628ac --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/JSON.mustache @@ -0,0 +1,261 @@ +package {{invokerPackage}}; + +import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.databind.*; +import com.fasterxml.jackson.databind.json.JsonMapper; +{{#openApiNullable}} +import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +{{#joda}} +import com.fasterxml.jackson.datatype.joda.JodaModule; +{{/joda}} +{{#models.0}} +import {{modelPackage}}.*; +{{/models.0}} + +import java.text.DateFormat; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import jakarta.ws.rs.core.GenericType; +import jakarta.ws.rs.ext.ContextResolver; + +{{>generatedAnnotation}} +public class JSON implements ContextResolver { + private ObjectMapper mapper; + + public JSON() { + mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + JsonMapper.builder().configure(MapperFeature.ALLOW_COERCION_OF_SCALARS, false); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); + mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, true); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + mapper.setDateFormat(new RFC3339DateFormat()); + mapper.registerModule(new JavaTimeModule()); + {{#joda}} + mapper.registerModule(new JodaModule()); + {{/joda}} + {{#openApiNullable}} + JsonNullableModule jnm = new JsonNullableModule(); + mapper.registerModule(jnm); + {{/openApiNullable}} + } + + /** + * Set the date format for JSON (de)serialization with Date properties. + * @param dateFormat Date format + */ + public void setDateFormat(DateFormat dateFormat) { + mapper.setDateFormat(dateFormat); + } + + @Override + public ObjectMapper getContext(Class type) { + return mapper; + } + + /** + * Get the object mapper + * + * @return object mapper + */ + public ObjectMapper getMapper() { return mapper; } + + /** + * Returns the target model class that should be used to deserialize the input data. + * The discriminator mappings are used to determine the target model class. + * + * @param node The input data. + * @param modelClass The class that contains the discriminator mappings. + */ + public static Class getClassForElement(JsonNode node, Class modelClass) { + ClassDiscriminatorMapping cdm = modelDiscriminators.get(modelClass); + if (cdm != null) { + return cdm.getClassForElement(node, new HashSet>()); + } + return null; + } + + /** + * Helper class to register the discriminator mappings. + */ + private static class ClassDiscriminatorMapping { + // The model class name. + Class modelClass; + // The name of the discriminator property. + String discriminatorName; + // The discriminator mappings for a model class. + Map> discriminatorMappings; + + // Constructs a new class discriminator. + ClassDiscriminatorMapping(Class cls, String propertyName, Map> mappings) { + modelClass = cls; + discriminatorName = propertyName; + discriminatorMappings = new HashMap>(); + if (mappings != null) { + discriminatorMappings.putAll(mappings); + } + } + + // Return the name of the discriminator property for this model class. + String getDiscriminatorPropertyName() { + return discriminatorName; + } + + // Return the discriminator value or null if the discriminator is not + // present in the payload. + String getDiscriminatorValue(JsonNode node) { + // Determine the value of the discriminator property in the input data. + if (discriminatorName != null) { + // Get the value of the discriminator property, if present in the input payload. + node = node.get(discriminatorName); + if (node != null && node.isValueNode()) { + String discrValue = node.asText(); + if (discrValue != null) { + return discrValue; + } + } + } + return null; + } + + /** + * Returns the target model class that should be used to deserialize the input data. + * This function can be invoked for anyOf/oneOf composed models with discriminator mappings. + * The discriminator mappings are used to determine the target model class. + * + * @param node The input data. + * @param visitedClasses The set of classes that have already been visited. + */ + Class getClassForElement(JsonNode node, Set> visitedClasses) { + if (visitedClasses.contains(modelClass)) { + // Class has already been visited. + return null; + } + // Determine the value of the discriminator property in the input data. + String discrValue = getDiscriminatorValue(node); + if (discrValue == null) { + return null; + } + Class cls = discriminatorMappings.get(discrValue); + // It may not be sufficient to return this cls directly because that target class + // may itself be a composed schema, possibly with its own discriminator. + visitedClasses.add(modelClass); + for (Class childClass : discriminatorMappings.values()) { + ClassDiscriminatorMapping childCdm = modelDiscriminators.get(childClass); + if (childCdm == null) { + continue; + } + if (!discriminatorName.equals(childCdm.discriminatorName)) { + discrValue = getDiscriminatorValue(node); + if (discrValue == null) { + continue; + } + } + if (childCdm != null) { + // Recursively traverse the discriminator mappings. + Class childDiscr = childCdm.getClassForElement(node, visitedClasses); + if (childDiscr != null) { + return childDiscr; + } + } + } + return cls; + } + } + + /** + * Returns true if inst is an instance of modelClass in the OpenAPI model hierarchy. + * + * The Java class hierarchy is not implemented the same way as the OpenAPI model hierarchy, + * so it's not possible to use the instanceof keyword. + * + * @param modelClass A OpenAPI model class. + * @param inst The instance object. + */ + public static boolean isInstanceOf(Class modelClass, Object inst, Set> visitedClasses) { + if (modelClass.isInstance(inst)) { + // This handles the 'allOf' use case with single parent inheritance. + return true; + } + if (visitedClasses.contains(modelClass)) { + // This is to prevent infinite recursion when the composed schemas have + // a circular dependency. + return false; + } + visitedClasses.add(modelClass); + + // Traverse the oneOf/anyOf composed schemas. + Map descendants = modelDescendants.get(modelClass); + if (descendants != null) { + for (GenericType childType : descendants.values()) { + if (isInstanceOf(childType.getRawType(), inst, visitedClasses)) { + return true; + } + } + } + return false; + } + + /** + * A map of discriminators for all model classes. + */ + private static Map, ClassDiscriminatorMapping> modelDiscriminators = new HashMap, ClassDiscriminatorMapping>(); + + /** + * A map of oneOf/anyOf descendants for each model class. + */ + private static Map, Map> modelDescendants = new HashMap, Map>(); + + /** + * Register a model class discriminator. + * + * @param modelClass the model class + * @param discriminatorPropertyName the name of the discriminator property + * @param mappings a map with the discriminator mappings. + */ + public static void registerDiscriminator(Class modelClass, String discriminatorPropertyName, Map> mappings) { + ClassDiscriminatorMapping m = new ClassDiscriminatorMapping(modelClass, discriminatorPropertyName, mappings); + modelDiscriminators.put(modelClass, m); + } + + /** + * Register the oneOf/anyOf descendants of the modelClass. + * + * @param modelClass the model class + * @param descendants a map of oneOf/anyOf descendants. + */ + public static void registerDescendants(Class modelClass, Map descendants) { + modelDescendants.put(modelClass, descendants); + } + + private static JSON json; + + static + { + json = new JSON(); + } + + /** + * Get the default JSON instance. + * + * @return the default JSON instance + */ + public static JSON getDefault() { + return json; + } + + /** + * Set the default JSON instance. + * + * @param json JSON instance to be used + */ + public static void setDefault(JSON json) { + JSON.json = json; + } +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/additional_properties.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/additional_properties.mustache new file mode 100644 index 000000000..61973dc24 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/additional_properties.mustache @@ -0,0 +1,39 @@ +{{#additionalPropertiesType}} + /** + * A container for additional, undeclared properties. + * This is a holder for any undeclared properties as specified with + * the 'additionalProperties' keyword in the OAS document. + */ + private Map additionalProperties; + + /** + * Set the additional (undeclared) property with the specified name and value. + * If the property does not already exist, create it otherwise replace it. + */ + @JsonAnySetter + public {{classname}} putAdditionalProperty(String key, {{{.}}} value) { + if (this.additionalProperties == null) { + this.additionalProperties = new HashMap(); + } + this.additionalProperties.put(key, value); + return this; + } + + /** + * Return the additional (undeclared) property. + */ + @JsonAnyGetter + public Map getAdditionalProperties() { + return additionalProperties; + } + + /** + * Return the additional (undeclared) property with the specified name. + */ + public {{{.}}} getAdditionalProperty(String key) { + if (this.additionalProperties == null) { + return null; + } + return this.additionalProperties.get(key); + } +{{/additionalPropertiesType}} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/anyof_model.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/anyof_model.mustache new file mode 100644 index 000000000..2e14233bb --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/anyof_model.mustache @@ -0,0 +1,202 @@ +import jakarta.ws.rs.core.GenericType; +import jakarta.ws.rs.core.Response; +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import {{invokerPackage}}.JSON; + +{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>xmlAnnotation}} +@JsonDeserialize(using={{classname}}.{{classname}}Deserializer.class) +@JsonSerialize(using = {{classname}}.{{classname}}Serializer.class) +public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-implements}}, {{{.}}}{{/vendorExtensions.x-implements}} { + private static final Logger log = Logger.getLogger({{classname}}.class.getName()); + + public static class {{classname}}Serializer extends StdSerializer<{{classname}}> { + public {{classname}}Serializer(Class<{{classname}}> t) { + super(t); + } + + public {{classname}}Serializer() { + this(null); + } + + @Override + public void serialize({{classname}} value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { + jgen.writeObject(value.getActualInstance()); + } + } + + public static class {{classname}}Deserializer extends StdDeserializer<{{classname}}> { + public {{classname}}Deserializer() { + this({{classname}}.class); + } + + public {{classname}}Deserializer(Class vc) { + super(vc); + } + + @Override + public {{classname}} deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { + JsonNode tree = jp.readValueAsTree(); + + Object deserialized = null; + {{#discriminator}} + Class cls = JSON.getClassForElement(tree, {{classname}}.class); + if (cls != null) { + // When the OAS schema includes a discriminator, use the discriminator value to + // discriminate the anyOf schemas. + // Get the discriminator mapping value to get the class. + deserialized = tree.traverse(jp.getCodec()).readValueAs(cls); + {{classname}} ret = new {{classname}}(); + ret.setActualInstance(deserialized); + return ret; + } + {{/discriminator}} + {{#anyOf}} + // deserialize {{{.}}} + try { + deserialized = tree.traverse(jp.getCodec()).readValueAs({{{.}}}.class); + {{classname}} ret = new {{classname}}(); + ret.setActualInstance(deserialized); + return ret; + } catch (Exception e) { + // deserialization failed, continue, log to help debugging + log.log(Level.FINER, "Input data does not match '{{classname}}'", e); + } + + {{/anyOf}} + throw new IOException(String.format("Failed deserialization for {{classname}}: no match found")); + } + + /** + * Handle deserialization of the 'null' value. + */ + @Override + public {{classname}} getNullValue(DeserializationContext ctxt) throws JsonMappingException { + {{#isNullable}} + return null; + {{/isNullable}} + {{^isNullable}} + throw new JsonMappingException(ctxt.getParser(), "{{classname}} cannot be null"); + {{/isNullable}} + } + } + + // store a list of schema names defined in anyOf + public static final Map schemas = new HashMap(); + + public {{classname}}() { + super("anyOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); + } +{{> libraries/jersey2/additional_properties }} + {{#additionalPropertiesType}} + /** + * Return true if this {{name}} object is equal to o. + */ + @Override + public boolean equals(Object o) { + return super.equals(o) && Objects.equals(this.additionalProperties, (({{classname}})o).additionalProperties); + } + + @Override + public int hashCode() { + return Objects.hash(getActualInstance(), isNullable(), getSchemaType(), additionalProperties); + } + {{/additionalPropertiesType}} + {{#anyOf}} + public {{classname}}({{{.}}} o) { + super("anyOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); + setActualInstance(o); + } + + {{/anyOf}} + static { + {{#anyOf}} + schemas.put("{{{.}}}", new GenericType<{{{.}}}>() { + }); + {{/anyOf}} + JSON.registerDescendants({{classname}}.class, Collections.unmodifiableMap(schemas)); + {{#discriminator}} + // Initialize and register the discriminator mappings. + Map> mappings = new HashMap>(); + {{#mappedModels}} + mappings.put("{{mappingName}}", {{modelName}}.class); + {{/mappedModels}} + mappings.put("{{name}}", {{classname}}.class); + JSON.registerDiscriminator({{classname}}.class, "{{propertyBaseName}}", mappings); + {{/discriminator}} + } + + @Override + public Map getSchemas() { + return {{classname}}.schemas; + } + + /** + * Set the instance that matches the anyOf child schema, check + * the instance parameter is valid against the anyOf child schemas: + * {{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}} + * + * It could be an instance of the 'anyOf' schemas. + * The anyOf child schemas may themselves be a composed schema (allOf, anyOf, anyOf). + */ + @Override + public void setActualInstance(Object instance) { + {{#isNullable}} + if (instance == null) { + super.setActualInstance(instance); + return; + } + + {{/isNullable}} + {{#anyOf}} + if (JSON.isInstanceOf({{{.}}}.class, instance, new HashSet>())) { + super.setActualInstance(instance); + return; + } + + {{/anyOf}} + throw new RuntimeException("Invalid instance type. Must be {{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}}"); + } + + /** + * Get the actual instance, which can be the following: + * {{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}} + * + * @return The actual instance ({{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}}) + */ + @Override + public Object getActualInstance() { + return super.getActualInstance(); + } + + {{#anyOf}} + /** + * Get the actual instance of `{{{.}}}`. If the actual instance is not `{{{.}}}`, + * the ClassCastException will be thrown. + * + * @return The actual instance of `{{{.}}}` + * @throws ClassCastException if the instance is not `{{{.}}}` + */ + public {{{.}}} get{{{.}}}() throws ClassCastException { + return ({{{.}}})super.getActualInstance(); + } + + {{/anyOf}} +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/api.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/api.mustache similarity index 77% rename from boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/api.mustache rename to boat-scaffold/src/main/templates/boat-java/libraries/jersey3/api.mustache index 509ae48a5..4ba6a6e95 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/api.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/api.mustache @@ -6,7 +6,7 @@ import {{invokerPackage}}.ApiResponse; import {{invokerPackage}}.Configuration; import {{invokerPackage}}.Pair; -import javax.ws.rs.core.GenericType; +import jakarta.ws.rs.core.GenericType; {{#imports}}import {{import}}; {{/imports}} @@ -32,7 +32,7 @@ public class {{classname}} { } /** - * Get the API cilent + * Get the API client * * @return API client */ @@ -41,7 +41,7 @@ public class {{classname}} { } /** - * Set the API cilent + * Set the API client * * @param apiClient an instance of API client */ @@ -58,7 +58,7 @@ public class {{classname}} { * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} {{/allParams}} {{#returnType}} - * @return {{returnType}} + * @return {{.}} {{/returnType}} * @throws ApiException if fails to make API call {{#responses.0}} @@ -81,8 +81,8 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { - {{#returnType}}return {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}){{#returnType}}.getData(){{/returnType}}; + public {{#returnType}}{{{.}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { + {{#returnType}}return {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}){{#returnType}}.getData(){{/returnType}}; } {{/vendorExtensions.x-group-parameters}} @@ -93,7 +93,7 @@ public class {{classname}} { {{#allParams}} * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} {{/allParams}} - * @return ApiResponse<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + * @return ApiResponse<{{returnType}}{{^returnType}}Void{{/returnType}}> * @throws ApiException if fails to make API call {{#responses.0}} * @http.response.details @@ -115,7 +115,7 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}} ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { + public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}} ApiResponse<{{{returnType}}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { Object localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; {{#allParams}}{{#required}} // verify the required parameter '{{paramName}}' is set @@ -134,7 +134,7 @@ public class {{classname}} { {{javaUtilPrefix}}Map localVarFormParams = new {{javaUtilPrefix}}HashMap(); {{#queryParams}} - localVarQueryParams.addAll(apiClient.parameterToPairs("{{#collectionFormat}}{{{collectionFormat}}}{{/collectionFormat}}", "{{baseName}}", {{paramName}})); + localVarQueryParams.addAll(apiClient.parameterToPairs("{{{collectionFormat}}}", "{{baseName}}", {{paramName}})); {{/queryParams}} {{#headerParams}}if ({{paramName}} != null) @@ -150,16 +150,16 @@ public class {{classname}} { {{/formParams}} final String[] localVarAccepts = { - {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} + {{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}} }; final String localVarAccept = apiClient.selectHeaderAccept(localVarAccepts); final String[] localVarContentTypes = { - {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} + {{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}} }; final String localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes); - String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{^-last}}, {{/-last}}{{/authMethods}} }; {{#returnType}} GenericType<{{{returnType}}}> localVarReturnType = new GenericType<{{{returnType}}}>() {}; @@ -167,18 +167,18 @@ public class {{classname}} { {{/returnType}} return apiClient.invokeAPI("{{classname}}.{{operationId}}", localVarPath, "{{httpMethod}}", localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, - localVarAuthNames, {{#returnType}}localVarReturnType{{/returnType}}{{^returnType}}null{{/returnType}}, {{#vendorExtensions.x-java-return-type-one-of}}new {{{returnType}}}(){{/vendorExtensions.x-java-return-type-one-of}}{{^vendorExtensions.x-java-return-type-one-of}}{{#vendorExtensions.x-java-return-type-any-of}}new {{{returnType}}}(){{/vendorExtensions.x-java-return-type-any-of}}{{^vendorExtensions.x-java-return-type-any-of}}null{{/vendorExtensions.x-java-return-type-any-of}}{{/vendorExtensions.x-java-return-type-one-of}}); + localVarAuthNames, {{#returnType}}localVarReturnType{{/returnType}}{{^returnType}}null{{/returnType}}, {{#bodyParam}}{{#isNullable}}true{{/isNullable}}{{^isNullable}}false{{/isNullable}}{{/bodyParam}}{{^bodyParam}}false{{/bodyParam}}); } {{#vendorExtensions.x-group-parameters}} public class API{{operationId}}Request { {{#allParams}} - private {{#isRequired}}final {{/isRequired}}{{{dataType}}} {{localVariablePrefix}}{{paramName}}; + private {{{dataType}}} {{paramName}}; {{/allParams}} - private API{{operationId}}Request({{#pathParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}) { + private API{{operationId}}Request({{#pathParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/pathParams}}) { {{#pathParams}} - this.{{localVariablePrefix}}{{paramName}} = {{paramName}}; + this.{{paramName}} = {{paramName}}; {{/pathParams}} } {{#allParams}} @@ -190,7 +190,7 @@ public class {{classname}} { * @return API{{operationId}}Request */ public API{{operationId}}Request {{paramName}}({{{dataType}}} {{paramName}}) { - this.{{localVariablePrefix}}{{paramName}} = {{paramName}}; + this.{{paramName}} = {{paramName}}; return this; } {{/isPathParam}} @@ -212,13 +212,13 @@ public class {{classname}} { {{#isDeprecated}}* @deprecated{{/isDeprecated}} */ {{#isDeprecated}}@Deprecated{{/isDeprecated}} - public {{#returnType}}{{{.}}}{{/returnType}}{{^returnType}}void{{/returnType}} execute() throws ApiException { + public {{{returnType}}}{{^returnType}}void{{/returnType}} execute() throws ApiException { {{#returnType}}return {{/returnType}}this.executeWithHttpInfo().getData(); } /** * Execute {{operationId}} request with HTTP info returned - * @return ApiResponse<{{#returnType}}{{.}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + * @return ApiResponse<{{returnType}}{{^returnType}}Void{{/returnType}}> * @throws ApiException if fails to make API call {{#responses.0}} * @http.response.details @@ -235,8 +235,8 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public ApiResponse<{{#returnType}}{{{.}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> executeWithHttpInfo() throws ApiException { - return {{operationId}}WithHttpInfo({{#allParams}}{{localVariablePrefix}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + public ApiResponse<{{{returnType}}}{{^returnType}}Void{{/returnType}}> executeWithHttpInfo() throws ApiException { + return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); } } @@ -253,8 +253,8 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public API{{operationId}}Request {{operationId}}({{#pathParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}) throws ApiException { - return new API{{operationId}}Request({{#pathParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}); + public API{{operationId}}Request {{operationId}}({{#pathParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/pathParams}}) throws ApiException { + return new API{{operationId}}Request({{#pathParams}}{{paramName}}{{^-last}}, {{/-last}}{{/pathParams}}); } {{/vendorExtensions.x-group-parameters}} {{/operation}} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/apiException.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/apiException.mustache similarity index 95% rename from boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/apiException.mustache rename to boat-scaffold/src/main/templates/boat-java/libraries/jersey3/apiException.mustache index f0079c7bb..74a419aac 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/apiException.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/apiException.mustache @@ -5,7 +5,7 @@ package {{invokerPackage}}; import java.util.Map; import java.util.List; {{#caseInsensitiveResponseHeaders}} -import java.util.Map.Entry; +import java.util.Map.Entry; import java.util.TreeMap; {{/caseInsensitiveResponseHeaders}} @@ -34,7 +34,7 @@ public class ApiException extends{{#useRuntimeException}} RuntimeException {{/us {{#caseInsensitiveResponseHeaders}} Map> headers = new TreeMap>(String.CASE_INSENSITIVE_ORDER); for(Entry> entry : responseHeaders.entrySet()){ - headers.put(entry.getKey().toLowerCase(), entry.getValue()); + headers.put(entry.getKey().toLowerCase(), entry.getValue()); } {{/caseInsensitiveResponseHeaders}} this.responseHeaders = {{#caseInsensitiveResponseHeaders}}headers{{/caseInsensitiveResponseHeaders}}{{^caseInsensitiveResponseHeaders}}responseHeaders{{/caseInsensitiveResponseHeaders}}; @@ -63,7 +63,7 @@ public class ApiException extends{{#useRuntimeException}} RuntimeException {{/us {{#caseInsensitiveResponseHeaders}} Map> headers = new TreeMap>(String.CASE_INSENSITIVE_ORDER); for(Entry> entry : responseHeaders.entrySet()){ - headers.put(entry.getKey().toLowerCase(), entry.getValue()); + headers.put(entry.getKey().toLowerCase(), entry.getValue()); } {{/caseInsensitiveResponseHeaders}} this.responseHeaders = {{#caseInsensitiveResponseHeaders}}headers{{/caseInsensitiveResponseHeaders}}{{^caseInsensitiveResponseHeaders}}responseHeaders{{/caseInsensitiveResponseHeaders}}; diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/api_doc.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/api_doc.mustache similarity index 63% rename from boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/api_doc.mustache rename to boat-scaffold/src/main/templates/boat-java/libraries/jersey3/api_doc.mustache index f162d1cc9..26c98508e 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/api_doc.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/api_doc.mustache @@ -1,12 +1,12 @@ # {{classname}}{{#description}} -{{description}}{{/description}} +{{.}}{{/description}} All URIs are relative to *{{basePath}}* -Method | HTTP request | Description -------------- | ------------- | ------------- -{{#operations}}{{#operation}}[**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +| Method | HTTP request | Description | +|------------- | ------------- | -------------| +{{#operations}}{{#operation}}| [**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{summary}} | {{/operation}}{{/operations}} {{#operations}} @@ -15,10 +15,10 @@ Method | HTTP request | Description ## {{operationId}} {{^vendorExtensions.x-group-parameters}} -> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) +> {{#returnType}}{{.}} {{/returnType}}{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) {{/vendorExtensions.x-group-parameters}} {{#vendorExtensions.x-group-parameters}} -> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#pathParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}){{#allParams}}{{^isPathParam}}.{{paramName}}({{paramName}}){{/isPathParam}}{{/allParams}}.execute(); +> {{#returnType}}{{.}} {{/returnType}}{{operationId}}({{#pathParams}}{{paramName}}{{^-last}}, {{/-last}}{{/pathParams}}){{#allParams}}{{^isPathParam}}.{{paramName}}({{paramName}}){{/isPathParam}}{{/allParams}}.execute(); {{/vendorExtensions.x-group-parameters}} {{summary}}{{#notes}} @@ -28,12 +28,15 @@ Method | HTTP request | Description ### Example ```java +{{#vendorExtensions.x-java-import}} +import {{.}}; +{{/vendorExtensions.x-java-import}} // Import classes: import {{{invokerPackage}}}.ApiClient; import {{{invokerPackage}}}.ApiException; import {{{invokerPackage}}}.Configuration;{{#hasAuthMethods}} import {{{invokerPackage}}}.auth.*;{{/hasAuthMethods}} -import {{{invokerPackage}}}.models.*; +import {{{invokerPackage}}}.model.*; import {{{package}}}.{{{classname}}}; public class Example { @@ -66,10 +69,10 @@ public class Example { {{/allParams}} try { {{^vendorExtensions.x-group-parameters}} - {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{#returnType}}{{{.}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}}); {{/vendorExtensions.x-group-parameters}} {{#vendorExtensions.x-group-parameters}} - {{#returnType}}{{{returnType}}} result = {{/returnType}}api.{{operationId}}({{#pathParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}){{#allParams}}{{^isPathParam}} + {{#returnType}}{{{.}}} result = {{/returnType}}api.{{operationId}}({{#pathParams}}{{paramName}}{{^-last}}, {{/-last}}{{/pathParams}}){{#allParams}}{{^isPathParam}} .{{paramName}}({{paramName}}){{/isPathParam}}{{/allParams}} .execute(); {{/vendorExtensions.x-group-parameters}} @@ -90,9 +93,9 @@ public class Example { ### Parameters {{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{#allParams}}{{#-last}} -Name | Type | Description | Notes -------------- | ------------- | ------------- | -------------{{/-last}}{{/allParams}} -{{#allParams}} **{{paramName}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}[**{{dataType}}**]({{baseType}}.md){{/isFile}}{{/isPrimitiveType}}| {{description}} |{{^required}} [optional]{{/required}}{{^isContainer}}{{#defaultValue}} [default to {{defaultValue}}]{{/defaultValue}}{{/isContainer}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}} +| Name | Type | Description | Notes | +|------------- | ------------- | ------------- | -------------|{{/-last}}{{/allParams}} +{{#allParams}}| **{{paramName}}** | {{#isContainer}}{{#isArray}}{{#items}}{{#isModel}}{{^isFile}}[{{/isFile}}{{/isModel}}**List<{{dataType}}>**{{#isModel}}{{^isFile}}]({{^baseType}}{{dataType}}{{/baseType}}{{baseType}}.md){{/isFile}}{{/isModel}}{{/items}}{{/isArray}}{{#isMap}}{{#items}}{{#isModel}}{{^isFile}}[{{/isFile}}{{/isModel}}**Map<String,{{dataType}}>**{{#isModel}}{{^isFile}}]({{^baseType}}{{dataType}}{{/baseType}}{{baseType}}.md){{/isFile}}{{/isModel}}{{/items}}{{/isMap}}{{/isContainer}}{{^isContainer}}{{#isModel}}{{^isFile}}[{{/isFile}}{{/isModel}}**{{dataType}}**{{#isModel}}{{^isFile}}]({{^baseType}}{{dataType}}{{/baseType}}{{baseType}}.md){{/isFile}}{{/isModel}}{{/isContainer}}| {{description}} |{{^required}} [optional]{{/required}}{{^isContainer}}{{#defaultValue}} [default to {{.}}]{{/defaultValue}}{{/isContainer}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}} | {{/allParams}} ### Return type @@ -105,8 +108,8 @@ Name | Type | Description | Notes ### HTTP request headers -- **Content-Type**: {{#consumes}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} -- **Accept**: {{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}{{^produces}}Not defined{{/produces}} +- **Content-Type**: {{#consumes}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} +- **Accept**: {{#produces}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/produces}}{{^produces}}Not defined{{/produces}} {{#responses.0}} ### HTTP response details diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/api_test.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/api_test.mustache similarity index 57% rename from boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/api_test.mustache rename to boat-scaffold/src/main/templates/boat-java/libraries/jersey3/api_test.mustache index 5ee6e4940..eb5101b1a 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/api_test.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/api_test.mustache @@ -2,20 +2,22 @@ package {{package}}; -import {{invokerPackage}}.ApiException; +import {{invokerPackage}}.*; +import {{invokerPackage}}.auth.*; {{#imports}}import {{import}}; {{/imports}} -import org.junit.Test; -import org.junit.Ignore; -import org.junit.Assert; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; {{^fullJavaUtil}} import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -{{/fullJavaUtil}} +{{/fullJavaUtil}} /** * API tests for {{classname}} */ @@ -23,14 +25,18 @@ public class {{classname}}Test { private final {{classname}} api = new {{classname}}(); - {{#operations}}{{#operation}} + {{#operations}} + {{#operation}} /** + {{#summary}} * {{summary}} * + {{/summary}} + {{#notes}} * {{notes}} * - * @throws ApiException - * if the Api call fails + {{/notes}} + * @throws ApiException if the Api call fails */ @Test public void {{operationId}}Test() throws ApiException { @@ -38,14 +44,16 @@ public class {{classname}}Test { //{{{dataType}}} {{paramName}} = null; {{/allParams}} {{^vendorExtensions.x-group-parameters}} - //{{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + //{{#returnType}}{{{.}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); {{/vendorExtensions.x-group-parameters}} {{#vendorExtensions.x-group-parameters}} - //{{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#pathParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}){{#allParams}}{{^isPathParam}} + //{{#returnType}}{{{.}}} response = {{/returnType}}api.{{operationId}}({{#pathParams}}{{paramName}}{{^-last}}, {{/-last}}{{/pathParams}}){{#allParams}}{{^isPathParam}} // .{{paramName}}({{paramName}}){{/isPathParam}}{{/allParams}} // .execute(); {{/vendorExtensions.x-group-parameters}} // TODO: test validations } - {{/operation}}{{/operations}} + + {{/operation}} + {{/operations}} } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/auth/ApiKeyAuth.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/auth/ApiKeyAuth.mustache new file mode 100644 index 000000000..1731f936f --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/auth/ApiKeyAuth.mustache @@ -0,0 +1,68 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; +import {{invokerPackage}}.ApiException; + +import java.net.URI; +import java.util.Map; +import java.util.List; + +{{>generatedAnnotation}} +public class ApiKeyAuth implements Authentication { + private final String location; + private final String paramName; + + private String apiKey; + private String apiKeyPrefix; + + public ApiKeyAuth(String location, String paramName) { + this.location = location; + this.paramName = paramName; + } + + public String getLocation() { + return location; + } + + public String getParamName() { + return paramName; + } + + public String getApiKey() { + return apiKey; + } + + public void setApiKey(String apiKey) { + this.apiKey = apiKey; + } + + public String getApiKeyPrefix() { + return apiKeyPrefix; + } + + public void setApiKeyPrefix(String apiKeyPrefix) { + this.apiKeyPrefix = apiKeyPrefix; + } + + @Override + public void applyToParams(List queryParams, Map headerParams, Map cookieParams, String payload, String method, URI uri) throws ApiException { + if (apiKey == null) { + return; + } + String value; + if (apiKeyPrefix != null) { + value = apiKeyPrefix + " " + apiKey; + } else { + value = apiKey; + } + if ("query".equals(location)) { + queryParams.add(new Pair(paramName, value)); + } else if ("header".equals(location)) { + headerParams.put(paramName, value); + } else if ("cookie".equals(location)) { + cookieParams.put(paramName, value); + } + } +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/auth/Authentication.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/auth/Authentication.mustache new file mode 100644 index 000000000..46d9c1ab6 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/auth/Authentication.mustache @@ -0,0 +1,22 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; +import {{invokerPackage}}.ApiException; + +import java.net.URI; +import java.util.Map; +import java.util.List; + +public interface Authentication { + /** + * Apply authentication settings to header and query params. + * + * @param queryParams List of query parameters + * @param headerParams Map of header parameters + * @param cookieParams Map of cookie parameters + */ + void applyToParams(List queryParams, Map headerParams, Map cookieParams, String payload, String method, URI uri) throws ApiException; + +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/auth/HttpBasicAuth.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/auth/HttpBasicAuth.mustache new file mode 100644 index 000000000..13cecfa90 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/auth/HttpBasicAuth.mustache @@ -0,0 +1,44 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; +import {{invokerPackage}}.ApiException; + +import java.util.Base64; +import java.nio.charset.StandardCharsets; + +import java.net.URI; +import java.util.Map; +import java.util.List; + +{{>generatedAnnotation}} +public class HttpBasicAuth implements Authentication { + private String username; + private String password; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + @Override + public void applyToParams(List queryParams, Map headerParams, Map cookieParams, String payload, String method, URI uri) throws ApiException { + if (username == null && password == null) { + return; + } + String str = (username == null ? "" : username) + ":" + (password == null ? "" : password); + headerParams.put("Authorization", "Basic " + Base64.getEncoder().encodeToString(str.getBytes(StandardCharsets.UTF_8))); + } +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/auth/HttpBearerAuth.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/auth/HttpBearerAuth.mustache new file mode 100644 index 000000000..110a11ea7 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/auth/HttpBearerAuth.mustache @@ -0,0 +1,51 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; +import {{invokerPackage}}.ApiException; + +import java.net.URI; +import java.util.Map; +import java.util.List; + +{{>generatedAnnotation}} +public class HttpBearerAuth implements Authentication { + private final String scheme; + private String bearerToken; + + public HttpBearerAuth(String scheme) { + this.scheme = scheme; + } + + /** + * Gets the token, which together with the scheme, will be sent as the value of the Authorization header. + * + * @return The bearer token + */ + public String getBearerToken() { + return bearerToken; + } + + /** + * Sets the token, which together with the scheme, will be sent as the value of the Authorization header. + * + * @param bearerToken The bearer token to send in the Authorization header + */ + public void setBearerToken(String bearerToken) { + this.bearerToken = bearerToken; + } + + @Override + public void applyToParams(List queryParams, Map headerParams, Map cookieParams, String payload, String method, URI uri) throws ApiException { + if(bearerToken == null) { + return; + } + + headerParams.put("Authorization", (scheme != null ? upperCaseBearer(scheme) + " " : "") + bearerToken); + } + + private static String upperCaseBearer(String scheme) { + return ("bearer".equalsIgnoreCase(scheme)) ? "Bearer" : scheme; + } +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/auth/HttpSignatureAuth.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/auth/HttpSignatureAuth.mustache new file mode 100644 index 000000000..ac0a77db8 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/auth/HttpSignatureAuth.mustache @@ -0,0 +1,269 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; +import {{invokerPackage}}.ApiException; + +import java.net.URI; +import java.net.URLEncoder; +import java.security.MessageDigest; +import java.security.Key; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Base64; +import java.util.Calendar; +import java.util.Date; +import java.util.Locale; +import java.util.Map; +import java.util.List; +import java.util.TimeZone; +import java.security.spec.AlgorithmParameterSpec; +import java.security.InvalidKeyException; + +import org.tomitribe.auth.signatures.Algorithm; +import org.tomitribe.auth.signatures.Signer; +import org.tomitribe.auth.signatures.Signature; +import org.tomitribe.auth.signatures.SigningAlgorithm; + +/** + * A Configuration object for the HTTP message signature security scheme. + */ +public class HttpSignatureAuth implements Authentication { + + private Signer signer; + + // An opaque string that the server can use to look up the component they need to validate the signature. + private String keyId; + + // The HTTP signature algorithm. + private SigningAlgorithm signingAlgorithm; + + // The HTTP cryptographic algorithm. + private Algorithm algorithm; + + // The cryptographic parameters. + private AlgorithmParameterSpec parameterSpec; + + // The list of HTTP headers that should be included in the HTTP signature. + private List headers; + + // The digest algorithm which is used to calculate a cryptographic digest of the HTTP request body. + private String digestAlgorithm; + + // The maximum validity duration of the HTTP signature. + private Long maxSignatureValidity; + + /** + * Construct a new HTTP signature auth configuration object. + * + * @param keyId An opaque string that the server can use to look up the component they need to validate the signature. + * @param signingAlgorithm The signature algorithm. + * @param algorithm The cryptographic algorithm. + * @param digestAlgorithm The digest algorithm. + * @param headers The list of HTTP headers that should be included in the HTTP signature. + * @param maxSignatureValidity The maximum validity duration of the HTTP signature. + * Used to set the '(expires)' field in the HTTP signature. + */ + public HttpSignatureAuth(String keyId, + SigningAlgorithm signingAlgorithm, + Algorithm algorithm, + String digestAlgorithm, + AlgorithmParameterSpec parameterSpec, + List headers, + Long maxSignatureValidity) { + this.keyId = keyId; + this.signingAlgorithm = signingAlgorithm; + this.algorithm = algorithm; + this.parameterSpec = parameterSpec; + this.digestAlgorithm = digestAlgorithm; + this.headers = headers; + this.maxSignatureValidity = maxSignatureValidity; + } + + /** + * Returns the opaque string that the server can use to look up the component they need to validate the signature. + * + * @return The keyId. + */ + public String getKeyId() { + return keyId; + } + + /** + * Set the HTTP signature key id. + * + * @param keyId An opaque string that the server can use to look up the component they need to validate the signature. + */ + public void setKeyId(String keyId) { + this.keyId = keyId; + } + + /** + * Returns the HTTP signature algorithm which is used to sign HTTP requests. + */ + public SigningAlgorithm getSigningAlgorithm() { + return signingAlgorithm; + } + + /** + * Sets the HTTP signature algorithm which is used to sign HTTP requests. + * + * @param signingAlgorithm The HTTP signature algorithm. + */ + public void setSigningAlgorithm(SigningAlgorithm signingAlgorithm) { + this.signingAlgorithm = signingAlgorithm; + } + + /** + * Returns the HTTP cryptographic algorithm which is used to sign HTTP requests. + */ + public Algorithm getAlgorithm() { + return algorithm; + } + + /** + * Sets the HTTP cryptographic algorithm which is used to sign HTTP requests. + * + * @param algorithm The HTTP signature algorithm. + */ + public void setAlgorithm(Algorithm algorithm) { + this.algorithm = algorithm; + } + + /** + * Returns the cryptographic parameters which are used to sign HTTP requests. + */ + public AlgorithmParameterSpec getAlgorithmParameterSpec() { + return parameterSpec; + } + + /** + * Sets the cryptographic parameters which are used to sign HTTP requests. + * + * @param parameterSpec The cryptographic parameters. + */ + public void setAlgorithmParameterSpec(AlgorithmParameterSpec parameterSpec) { + this.parameterSpec = parameterSpec; + } + + /** + * Returns the digest algorithm which is used to calculate a cryptographic digest of the HTTP request body. + * + * @see java.security.MessageDigest + */ + public String getDigestAlgorithm() { + return digestAlgorithm; + } + + /** + * Sets the digest algorithm which is used to calculate a cryptographic digest of the HTTP request body. + * + * The exact list of supported digest algorithms depends on the installed security providers. + * Every implementation of the Java platform is required to support "MD5", "SHA-1" and "SHA-256". + * Do not use "MD5" and "SHA-1", they are vulnerable to multiple known attacks. + * By default, "SHA-256" is used. + * + * @param digestAlgorithm The digest algorithm. + * + * @see java.security.MessageDigest + */ + public void setDigestAlgorithm(String digestAlgorithm) { + this.digestAlgorithm = digestAlgorithm; + } + + /** + * Returns the list of HTTP headers that should be included in the HTTP signature. + */ + public List getHeaders() { + return headers; + } + + /** + * Sets the list of HTTP headers that should be included in the HTTP signature. + * + * @param headers The HTTP headers. + */ + public void setHeaders(List headers) { + this.headers = headers; + } + + /** + * Returns the maximum validity duration of the HTTP signature. + * @return The maximum validity duration of the HTTP signature. + */ + public Long getMaxSignatureValidity() { + return maxSignatureValidity; + } + + /** + * Returns the signer instance used to sign HTTP messages. + * + * @return the signer instance. + */ + public Signer getSigner() { + return signer; + } + + /** + * Sets the signer instance used to sign HTTP messages. + * + * @param signer The signer instance to set. + */ + public void setSigner(Signer signer) { + this.signer = signer; + } + + /** + * Set the private key used to sign HTTP requests using the HTTP signature scheme. + * + * @param key The private key. + * + * @throws InvalidKeyException Unable to parse the key, or the security provider for this key + * is not installed. + */ + public void setPrivateKey(Key key) throws InvalidKeyException, ApiException { + if (key == null) { + throw new ApiException("Private key (java.security.Key) cannot be null"); + } + signer = new Signer(key, new Signature(keyId, signingAlgorithm, algorithm, parameterSpec, null, headers, maxSignatureValidity)); + } + + @Override + public void applyToParams(List queryParams, Map headerParams, Map cookieParams, + String payload, String method, URI uri) throws ApiException { + try { + if (headers.contains("host")) { + headerParams.put("host", uri.getHost()); + } + + if (headers.contains("date")) { + SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US); + dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); + headerParams.put("date", dateFormat.format(Calendar.getInstance().getTime())); + } + + if (headers.contains("digest")) { + headerParams.put("digest", + this.digestAlgorithm + "=" + + new String(Base64.getEncoder().encode(MessageDigest.getInstance(this.digestAlgorithm).digest(payload.getBytes())))); + } + + if (signer == null) { + throw new ApiException("Signer cannot be null. Please call the method `setPrivateKey` to set it up correctly"); + } + + // construct the path with the URL-encoded path and query. + // Calling getRawPath and getRawQuery ensures the path is URL-encoded as it will be serialized + // on the wire. The HTTP signature must use the encode URL as it is sent on the wire. + String path = uri.getRawPath(); + if (uri.getRawQuery() != null && !"".equals(uri.getRawQuery())) { + path += "?" + uri.getRawQuery(); + } + + headerParams.put("Authorization", signer.sign(method, path, headerParams).toString()); + } catch (Exception ex) { + throw new ApiException("Failed to create signature in the HTTP request header: " + ex.toString()); + } + } +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/auth/OAuth.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/auth/OAuth.mustache new file mode 100644 index 000000000..67f565976 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/auth/OAuth.mustache @@ -0,0 +1,195 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; +import {{invokerPackage}}.ApiException; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.exceptions.OAuthException; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.oauth.OAuth20Service; + +import jakarta.ws.rs.core.UriBuilder; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.logging.Level; +import java.util.logging.Logger; + +{{>generatedAnnotation}} +public class OAuth implements Authentication { + private static final Logger log = Logger.getLogger(OAuth.class.getName()); + + private String tokenUrl; + private String absoluteTokenUrl; + private OAuthFlow flow = OAuthFlow.APPLICATION; + private OAuth20Service service; + private DefaultApi20 authApi; + private String scope; + private String username; + private String password; + private String code; + private volatile OAuth2AccessToken accessToken; + + public OAuth(String basePath, String tokenUrl) { + this.tokenUrl = tokenUrl; + this.absoluteTokenUrl = createAbsoluteTokenUrl(basePath, tokenUrl); + authApi = new DefaultApi20() { + @Override + public String getAccessTokenEndpoint() { + return absoluteTokenUrl; + } + + @Override + protected String getAuthorizationBaseUrl() { + throw new UnsupportedOperationException("Shouldn't get there !"); + } + }; + } + + private static String createAbsoluteTokenUrl(String basePath, String tokenUrl) { + if (!URI.create(tokenUrl).isAbsolute()) { + try { + return UriBuilder.fromPath(basePath).path(tokenUrl).build().toURL().toString(); + } catch (MalformedURLException e) { + log.log(Level.SEVERE, "Couldn't create absolute token URL", e); + } + } + return tokenUrl; + } + + @Override + public void applyToParams( + List queryParams, + Map headerParams, + Map cookieParams, + String payload, + String method, + URI uri) + throws ApiException { + + if (accessToken == null) { + obtainAccessToken(null); + } + if (accessToken != null) { + headerParams.put("Authorization", "Bearer " + accessToken.getAccessToken()); + } + } + + public OAuth2AccessToken renewAccessToken() throws ApiException { + String refreshToken = null; + if (accessToken != null) { + refreshToken = accessToken.getRefreshToken(); + accessToken = null; + } + return obtainAccessToken(refreshToken); + } + + public synchronized OAuth2AccessToken obtainAccessToken(String refreshToken) throws ApiException { + if (service == null) { + log.log(Level.FINE, "service is null in obtainAccessToken."); + return null; + } + try { + if (refreshToken != null) { + return service.refreshAccessToken(refreshToken); + } + } catch (OAuthException | InterruptedException | ExecutionException | IOException e) { + throw new ApiException("Refreshing the access token using the refresh token failed: " + e.toString()); + } + try { + switch (flow) { + case PASSWORD: + if (username != null && password != null) { + accessToken = service.getAccessTokenPasswordGrant(username, password, scope); + } + break; + case ACCESS_CODE: + if (code != null) { + accessToken = service.getAccessToken(code); + code = null; + } + break; + case APPLICATION: + accessToken = service.getAccessTokenClientCredentialsGrant(scope); + break; + default: + log.log(Level.SEVERE, "Invalid flow in obtainAccessToken: " + flow); + } + } catch (OAuthException | InterruptedException | ExecutionException | IOException e) { + throw new ApiException(e); + } + return accessToken; + } + + public OAuth2AccessToken getAccessToken() { + return accessToken; + } + + public OAuth setAccessToken(OAuth2AccessToken accessToken) { + this.accessToken = accessToken; + return this; + } + + public OAuth setAccessToken(String accessToken) { + this.accessToken = new OAuth2AccessToken(accessToken); + return this; + } + + public OAuth setScope(String scope) { + this.scope = scope; + return this; + } + + public OAuth setCredentials(String clientId, String clientSecret, Boolean debug) { + if (Boolean.TRUE.equals(debug)) { + service = new ServiceBuilder(clientId) + .apiSecret(clientSecret).debug() + .build(authApi); + } else { + service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .build(authApi); + } + return this; + } + + public OAuth setCredentialsForPublicClient(String clientId, Boolean debug) { + if (Boolean.TRUE.equals(debug)) { + service = new ServiceBuilder(clientId) + .apiSecretIsEmptyStringUnsafe().debug() + .build(authApi); + } else { + service = new ServiceBuilder(clientId) + .apiSecretIsEmptyStringUnsafe() + .build(authApi); + } + return this; + } + + public OAuth usePasswordFlow(String username, String password) { + this.flow = OAuthFlow.PASSWORD; + this.username = username; + this.password = password; + return this; + } + + public OAuth useAuthorizationCodeFlow(String code) { + this.flow = OAuthFlow.ACCESS_CODE; + this.code = code; + return this; + } + + public OAuth setFlow(OAuthFlow flow) { + this.flow = flow; + return this; + } + + public void setBasePath(String basePath) { + this.absoluteTokenUrl = createAbsoluteTokenUrl(basePath, tokenUrl); + } +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/auth/OAuthFlow.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/auth/OAuthFlow.mustache new file mode 100644 index 000000000..190781fb1 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/auth/OAuthFlow.mustache @@ -0,0 +1,13 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +/** + * OAuth flows that are supported by this client + */ +public enum OAuthFlow { + ACCESS_CODE, + IMPLICIT, + PASSWORD, + APPLICATION +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/build.gradle.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/build.gradle.mustache new file mode 100644 index 000000000..55c2dfd81 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/build.gradle.mustache @@ -0,0 +1,177 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' +apply plugin: 'com.diffplug.spotless' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + mavenCentral() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.3.+' + classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1' + classpath 'com.diffplug.spotless:spotless-plugin-gradle:6.3.0' + } +} + +repositories { + mavenCentral() +} + +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 25 + buildToolsVersion '25.0.2' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 25 + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version" + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven-publish' + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + + publishing { + publications { + maven(MavenPublication) { + artifactId = '{{artifactId}}' + + from components.java + } + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } +} + +ext { + swagger_annotations_version = "1.6.5" + jackson_version = "2.13.4" + jackson_databind_version = "2.13.4.2" + {{#openApiNullable}} + jackson_databind_nullable_version = "0.2.4" + {{/openApiNullable}} + jakarta_annotation_version = "2.1.0" + jersey_version = "3.0.4" + junit_version = "5.8.2" + {{#hasOAuthMethods}} + scribejava_apis_version = "8.3.1" + {{/hasOAuthMethods}} + {{#hasHttpSignatureMethods}} + tomitribe_http_signatures_version = "1.7" + {{/hasHttpSignatureMethods}} +} + +dependencies { + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation "org.glassfish.jersey.core:jersey-client:$jersey_version" + implementation "org.glassfish.jersey.inject:jersey-hk2:$jersey_version" + implementation "org.glassfish.jersey.media:jersey-media-multipart:$jersey_version" + implementation "org.glassfish.jersey.media:jersey-media-json-jackson:$jersey_version" + implementation "org.glassfish.jersey.connectors:jersey-apache-connector:$jersey_version" + implementation "com.fasterxml.jackson.core:jackson-core:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" + {{#openApiNullable}} + implementation "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + {{/openApiNullable}} + {{#joda}} + implementation "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + {{/joda}} + implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + {{#hasOAuthMethods}} + implementation "com.github.scribejava:scribejava-apis:$scribejava_apis_version" + {{/hasOAuthMethods}} + {{#hasHttpSignatureMethods}} + implementation "org.tomitribe:tomitribe-http-signatures:$tomitribe_http_signatures_version" + {{/hasHttpSignatureMethods}} + implementation "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version" + testImplementation "org.junit.jupiter:junit-jupiter-api:$junit_version" + testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junit_version" +} + +test { + useJUnitPlatform() +} + +javadoc { + options.tags = [ "http.response.details:a:Http Response Details" ] +} + +// Use spotless plugin to automatically format code, remove unused import, etc +// To apply changes directly to the file, run `gradlew spotlessApply` +// Ref: https://github.com/diffplug/spotless/tree/main/plugin-gradle +spotless { + // comment out below to run spotless as part of the `check` task + enforceCheck false + + format 'misc', { + // define the files (e.g. '*.gradle', '*.md') to apply `misc` to + target '.gitignore' + // define the steps to apply to those files + trimTrailingWhitespace() + indentWithSpaces() // Takes an integer argument if you don't like 4 + endWithNewline() + } + java { + // don't need to set target, it is inferred from java + // apply a specific flavor of google-java-format + googleJavaFormat('1.8').aosp().reflowLongStrings() + removeUnusedImports() + importOrder() + } +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/build.sbt.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/build.sbt.mustache new file mode 100644 index 000000000..ee811eb8c --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/build.sbt.mustache @@ -0,0 +1,38 @@ +lazy val root = (project in file(".")). + settings( + organization := "{{groupId}}", + name := "{{artifactId}}", + version := "{{artifactVersion}}", + scalaVersion := "2.11.4", + scalacOptions ++= Seq("-feature"), + Compile / javacOptions ++= Seq("-Xlint:deprecation"), + Compile / packageDoc / publishArtifact := false, + resolvers += Resolver.mavenLocal, + libraryDependencies ++= Seq( + "com.google.code.findbugs" % "jsr305" % "3.0.0", + "io.swagger" % "swagger-annotations" % "1.6.5", + "org.glassfish.jersey.core" % "jersey-client" % "3.0.4", + "org.glassfish.jersey.inject" % "jersey-hk2" % "3.0.4", + "org.glassfish.jersey.media" % "jersey-media-multipart" % "3.0.4", + "org.glassfish.jersey.media" % "jersey-media-json-jackson" % "3.0.4", + "org.glassfish.jersey.connectors" % "jersey-apache-connector" % "3.0.4", + "com.fasterxml.jackson.core" % "jackson-core" % "2.13.4" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.13.4" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.13.4.2" % "compile", + {{#joda}} + "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.13.2" % "compile", + {{/joda}} + "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.13.2" % "compile", + {{#openApiNullable}} + "org.openapitools" % "jackson-databind-nullable" % "0.2.4" % "compile", + {{/openApiNullable}} + {{#hasOAuthMethods}} + "com.github.scribejava" % "scribejava-apis" % "8.3.1" % "compile", + {{/hasOAuthMethods}} + {{#hasHttpSignatureMethods}} + "org.tomitribe" % "tomitribe-http-signatures" % "1.7" % "compile", + {{/hasHttpSignatureMethods}} + "jakarta.annotation" % "jakarta.annotation-api" % "2.1.0" % "compile", + "org.junit.jupiter" % "junit-jupiter-api" % "5.8.2" % "test" + ) + ) diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/generatedAnnotation.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/generatedAnnotation.mustache new file mode 100644 index 000000000..e4f874954 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/generatedAnnotation.mustache @@ -0,0 +1 @@ +@jakarta.annotation.Generated(value = "{{generatorClass}}"{{^hideGenerationTimestamp}}, date = "{{generatedDate}}"{{/hideGenerationTimestamp}}) \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/model.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/model.mustache new file mode 100644 index 000000000..914e1eb1e --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/model.mustache @@ -0,0 +1,64 @@ +{{>licenseInfo}} + +package {{package}}; + +{{#useReflectionEqualsHashCode}} +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +{{/useReflectionEqualsHashCode}} +{{#models}} +{{#model}} +{{#additionalPropertiesType}} +import java.util.Map; +import java.util.HashMap; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +{{/additionalPropertiesType}} +{{/model}} +{{/models}} +import java.util.Objects; +import java.util.Arrays; +import java.util.Map; +import java.util.HashMap; +{{#imports}} +import {{import}}; +{{/imports}} +{{#serializableModel}} +import java.io.Serializable; +{{/serializableModel}} +{{#jackson}} +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +{{#withXml}} +import com.fasterxml.jackson.dataformat.xml.annotation.*; +{{/withXml}} +{{#vendorExtensions.x-has-readonly-properties}} +import com.fasterxml.jackson.annotation.JsonCreator; +{{/vendorExtensions.x-has-readonly-properties}} +{{/jackson}} +{{#withXml}} +import javax.xml.bind.annotation.*; +{{/withXml}} +{{#parcelableModel}} +import android.os.Parcelable; +import android.os.Parcel; +{{/parcelableModel}} +{{#useBeanValidation}} +import javax.validation.constraints.*; +import javax.validation.Valid; +{{/useBeanValidation}} +{{#performBeanValidation}} +import org.hibernate.validator.constraints.*; +{{/performBeanValidation}} +import {{invokerPackage}}.JSON; + +{{#models}} +{{#model}} +{{#oneOf}} +{{#-first}} +import com.fasterxml.jackson.core.type.TypeReference; +{{/-first}} +{{/oneOf}} + +{{#isEnum}}{{>modelEnum}}{{/isEnum}}{{^isEnum}}{{#oneOf}}{{#-first}}{{>oneof_model}}{{/-first}}{{/oneOf}}{{^oneOf}}{{#anyOf}}{{#-first}}{{>anyof_model}}{{/-first}}{{/anyOf}}{{^anyOf}}{{>pojo}}{{/anyOf}}{{/oneOf}}{{/isEnum}} +{{/model}} +{{/models}} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/model_anyof_doc.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/model_anyof_doc.mustache new file mode 100644 index 000000000..e360aa56e --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/model_anyof_doc.mustache @@ -0,0 +1,38 @@ +# {{classname}} + +{{#description}} +{{&description}} + +{{/description}} +## anyOf schemas +{{#anyOf}} +* [{{{.}}}]({{{.}}}.md) +{{/anyOf}} + +{{#isNullable}} +NOTE: this class is nullable. + +{{/isNullable}} +## Example +```java +// Import classes: +import {{{package}}}.{{{classname}}}; +{{#anyOf}} +import {{{package}}}.{{{.}}}; +{{/anyOf}} + +public class Example { + public static void main(String[] args) { + {{classname}} example{{classname}} = new {{classname}}(); + {{#anyOf}} + + // create a new {{{.}}} + {{{.}}} example{{{.}}} = new {{{.}}}(); + // set {{{classname}}} to {{{.}}} + example{{classname}}.setActualInstance(example{{{.}}}); + // to get back the {{{.}}} set earlier + {{{.}}} test{{{.}}} = ({{{.}}}) example{{classname}}.getActualInstance(); + {{/anyOf}} + } +} +``` diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/model_doc.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/model_doc.mustache new file mode 100644 index 000000000..be1aedcf2 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/model_doc.mustache @@ -0,0 +1,19 @@ +{{#models}}{{#model}} + +{{#isEnum}} +{{>enum_outer_doc}} +{{/isEnum}} +{{^isEnum}} +{{^oneOf.isEmpty}} +{{>model_oneof_doc}} +{{/oneOf.isEmpty}} +{{^anyOf.isEmpty}} +{{>model_anyof_doc}} +{{/anyOf.isEmpty}} +{{^anyOf}} +{{^oneOf}} +{{>pojo_doc}} +{{/oneOf}} +{{/anyOf}} +{{/isEnum}} +{{/model}}{{/models}} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/model_oneof_doc.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/model_oneof_doc.mustache new file mode 100644 index 000000000..5fff76c9e --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/model_oneof_doc.mustache @@ -0,0 +1,38 @@ +# {{classname}} + +{{#description}} +{{&description}} + +{{/description}} +## oneOf schemas +{{#oneOf}} +* [{{{.}}}]({{{.}}}.md) +{{/oneOf}} + +{{#isNullable}} +NOTE: this class is nullable. + +{{/isNullable}} +## Example +```java +// Import classes: +import {{{package}}}.{{{classname}}}; +{{#oneOf}} +import {{{package}}}.{{{.}}}; +{{/oneOf}} + +public class Example { + public static void main(String[] args) { + {{classname}} example{{classname}} = new {{classname}}(); + {{#oneOf}} + + // create a new {{{.}}} + {{{.}}} example{{{.}}} = new {{{.}}}(); + // set {{{classname}}} to {{{.}}} + example{{classname}}.setActualInstance(example{{{.}}}); + // to get back the {{{.}}} set earlier + {{{.}}} test{{{.}}} = ({{{.}}}) example{{classname}}.getActualInstance(); + {{/oneOf}} + } +} +``` diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/model_test.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/model_test.mustache new file mode 100644 index 000000000..2d4ccdd1a --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/model_test.mustache @@ -0,0 +1,51 @@ +{{>licenseInfo}} + +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +{{#fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +{{/fullJavaUtil}} +/** + * Model tests for {{classname}} + */ +public class {{classname}}Test { + {{#models}} + {{#model}} + {{^vendorExtensions.x-is-one-of-interface}} + {{^isEnum}} + private final {{classname}} model = new {{classname}}(); + + {{/isEnum}} + /** + * Model tests for {{classname}} + */ + @Test + public void test{{classname}}() { + // TODO: test {{classname}} + } + + {{#allVars}} + /** + * Test the property '{{name}}' + */ + @Test + public void {{name}}Test() { + // TODO: test {{name}} + } + + {{/allVars}} + {{/vendorExtensions.x-is-one-of-interface}} + {{/model}} + {{/models}} +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/oneof_model.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/oneof_model.mustache new file mode 100644 index 000000000..e59299829 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/oneof_model.mustache @@ -0,0 +1,235 @@ +import jakarta.ws.rs.core.GenericType; +import jakarta.ws.rs.core.Response; +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.MapperFeature; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import {{invokerPackage}}.JSON; + +{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>xmlAnnotation}} +@JsonDeserialize(using = {{classname}}.{{classname}}Deserializer.class) +@JsonSerialize(using = {{classname}}.{{classname}}Serializer.class) +public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-implements}}, {{{.}}}{{/vendorExtensions.x-implements}} { + private static final Logger log = Logger.getLogger({{classname}}.class.getName()); + + public static class {{classname}}Serializer extends StdSerializer<{{classname}}> { + public {{classname}}Serializer(Class<{{classname}}> t) { + super(t); + } + + public {{classname}}Serializer() { + this(null); + } + + @Override + public void serialize({{classname}} value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { + jgen.writeObject(value.getActualInstance()); + } + } + + public static class {{classname}}Deserializer extends StdDeserializer<{{classname}}> { + public {{classname}}Deserializer() { + this({{classname}}.class); + } + + public {{classname}}Deserializer(Class vc) { + super(vc); + } + + @Override + public {{classname}} deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { + JsonNode tree = jp.readValueAsTree(); + Object deserialized = null; + {{#useOneOfDiscriminatorLookup}} + {{#discriminator}} + {{classname}} new{{classname}} = new {{classname}}(); + Map result2 = tree.traverse(jp.getCodec()).readValueAs(new TypeReference>() {}); + String discriminatorValue = (String)result2.get("{{{propertyBaseName}}}"); + switch (discriminatorValue) { + {{#mappedModels}} + case "{{{mappingName}}}": + deserialized = tree.traverse(jp.getCodec()).readValueAs({{{modelName}}}.class); + new{{classname}}.setActualInstance(deserialized); + return new{{classname}}; + {{/mappedModels}} + default: + log.log(Level.WARNING, String.format("Failed to lookup discriminator value `%s` for {{classname}}. Possible values:{{#mappedModels}} {{{mappingName}}}{{/mappedModels}}", discriminatorValue)); + } + + {{/discriminator}} + {{/useOneOfDiscriminatorLookup}} + boolean typeCoercion = ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS); + int match = 0; + JsonToken token = tree.traverse(jp.getCodec()).nextToken(); + {{#oneOf}} + // deserialize {{{.}}} + try { + boolean attemptParsing = true; + // ensure that we respect type coercion as set on the client ObjectMapper + if ({{{.}}}.class.equals(Integer.class) || {{{.}}}.class.equals(Long.class) || {{{.}}}.class.equals(Float.class) || {{{.}}}.class.equals(Double.class) || {{{.}}}.class.equals(Boolean.class) || {{{.}}}.class.equals(String.class)) { + attemptParsing = typeCoercion; + if (!attemptParsing) { + attemptParsing |= (({{{.}}}.class.equals(Integer.class) || {{{.}}}.class.equals(Long.class)) && token == JsonToken.VALUE_NUMBER_INT); + attemptParsing |= (({{{.}}}.class.equals(Float.class) || {{{.}}}.class.equals(Double.class)) && token == JsonToken.VALUE_NUMBER_FLOAT); + attemptParsing |= ({{{.}}}.class.equals(Boolean.class) && (token == JsonToken.VALUE_FALSE || token == JsonToken.VALUE_TRUE)); + attemptParsing |= ({{{.}}}.class.equals(String.class) && token == JsonToken.VALUE_STRING); + {{#isNullable}} + attemptParsing |= (token == JsonToken.VALUE_NULL); + {{/isNullable}} + } + } + if (attemptParsing) { + deserialized = tree.traverse(jp.getCodec()).readValueAs({{{.}}}.class); + // TODO: there is no validation against JSON schema constraints + // (min, max, enum, pattern...), this does not perform a strict JSON + // validation, which means the 'match' count may be higher than it should be. + match++; + log.log(Level.FINER, "Input data matches schema '{{{.}}}'"); + } + } catch (Exception e) { + // deserialization failed, continue + log.log(Level.FINER, "Input data does not match schema '{{{.}}}'", e); + } + + {{/oneOf}} + if (match == 1) { + {{classname}} ret = new {{classname}}(); + ret.setActualInstance(deserialized); + return ret; + } + throw new IOException(String.format("Failed deserialization for {{classname}}: %d classes match result, expected 1", match)); + } + + /** + * Handle deserialization of the 'null' value. + */ + @Override + public {{classname}} getNullValue(DeserializationContext ctxt) throws JsonMappingException { + {{#isNullable}} + return null; + {{/isNullable}} + {{^isNullable}} + throw new JsonMappingException(ctxt.getParser(), "{{classname}} cannot be null"); + {{/isNullable}} + } + } + + // store a list of schema names defined in oneOf + public static final Map schemas = new HashMap(); + + public {{classname}}() { + super("oneOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); + } +{{> libraries/jersey2/additional_properties }} + {{#additionalPropertiesType}} + /** + * Return true if this {{name}} object is equal to o. + */ + @Override + public boolean equals(Object o) { + return super.equals(o) && Objects.equals(this.additionalProperties, (({{classname}})o).additionalProperties); + } + + @Override + public int hashCode() { + return Objects.hash(getActualInstance(), isNullable(), getSchemaType(), additionalProperties); + } + {{/additionalPropertiesType}} + {{#oneOf}} + public {{classname}}({{{.}}} o) { + super("oneOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); + setActualInstance(o); + } + + {{/oneOf}} + static { + {{#oneOf}} + schemas.put("{{{.}}}", new GenericType<{{{.}}}>() { + }); + {{/oneOf}} + JSON.registerDescendants({{classname}}.class, Collections.unmodifiableMap(schemas)); + {{#discriminator}} + // Initialize and register the discriminator mappings. + Map> mappings = new HashMap>(); + {{#mappedModels}} + mappings.put("{{mappingName}}", {{modelName}}.class); + {{/mappedModels}} + mappings.put("{{name}}", {{classname}}.class); + JSON.registerDiscriminator({{classname}}.class, "{{propertyBaseName}}", mappings); + {{/discriminator}} + } + + @Override + public Map getSchemas() { + return {{classname}}.schemas; + } + + /** + * Set the instance that matches the oneOf child schema, check + * the instance parameter is valid against the oneOf child schemas: + * {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}} + * + * It could be an instance of the 'oneOf' schemas. + * The oneOf child schemas may themselves be a composed schema (allOf, anyOf, oneOf). + */ + @Override + public void setActualInstance(Object instance) { + {{#isNullable}} + if (instance == null) { + super.setActualInstance(instance); + return; + } + + {{/isNullable}} + {{#oneOf}} + if (JSON.isInstanceOf({{{.}}}.class, instance, new HashSet>())) { + super.setActualInstance(instance); + return; + } + + {{/oneOf}} + throw new RuntimeException("Invalid instance type. Must be {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}"); + } + + /** + * Get the actual instance, which can be the following: + * {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}} + * + * @return The actual instance ({{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}) + */ + @Override + public Object getActualInstance() { + return super.getActualInstance(); + } + + {{#oneOf}} + /** + * Get the actual instance of `{{{.}}}`. If the actual instance is not `{{{.}}}`, + * the ClassCastException will be thrown. + * + * @return The actual instance of `{{{.}}}` + * @throws ClassCastException if the instance is not `{{{.}}}` + */ + public {{{.}}} get{{{.}}}() throws ClassCastException { + return ({{{.}}})super.getActualInstance(); + } + + {{/oneOf}} +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/pojo.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/pojo.mustache similarity index 57% rename from boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/pojo.mustache rename to boat-scaffold/src/main/templates/boat-java/libraries/jersey3/pojo.mustache index c438cd43e..b9527bdd5 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/pojo.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/pojo.mustache @@ -1,16 +1,28 @@ /** - * {{#description}}{{.}}{{/description}}{{^description}}{{classname}}{{/description}} - */{{#description}} -@ApiModel(description = "{{{description}}}"){{/description}} + * {{description}}{{^description}}{{classname}}{{/description}}{{#isDeprecated}} + * @deprecated{{/isDeprecated}} + */{{#isDeprecated}} +@Deprecated{{/isDeprecated}} +{{#swagger1AnnotationLibrary}} +{{#description}} +@ApiModel(description = "{{{.}}}") +{{/description}} +{{/swagger1AnnotationLibrary}} {{#jackson}} @JsonPropertyOrder({ {{#vars}} {{classname}}.JSON_PROPERTY_{{nameInSnakeCase}}{{^-last}},{{/-last}} {{/vars}} }) +{{#isClassnameSanitized}} +@JsonTypeName("{{name}}") +{{/isClassnameSanitized}} {{/jackson}} {{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}} -public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorExtensions.x-implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{#-last}} {{/-last}}{{/vendorExtensions.x-implements}}{ +{{#vendorExtensions.x-class-extra-annotation}} +{{{vendorExtensions.x-class-extra-annotation}}} +{{/vendorExtensions.x-class-extra-annotation}} +public class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{{#vendorExtensions.x-implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{#-last}} {{/-last}}{{/vendorExtensions.x-implements}}{ {{#serializableModel}} private static final long serialVersionUID = 1L; @@ -18,7 +30,9 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{#vars}} {{#isEnum}} {{^isContainer}} + {{^vendorExtensions.x-enum-as-string}} {{>modelInnerEnum}} + {{/vendorExtensions.x-enum-as-string}} {{/isContainer}} {{#isContainer}} {{#mostInnerItems}} @@ -34,21 +48,21 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{/jackson}} {{#withXml}} {{#isXmlAttribute}} - @XmlAttribute(name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + @XmlAttribute(name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") {{/isXmlAttribute}} {{^isXmlAttribute}} {{^isContainer}} - @XmlElement({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + @XmlElement({{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") {{/isContainer}} {{#isContainer}} // Is a container wrapped={{isXmlWrapped}} {{#items}} // items.name={{name}} items.baseName={{baseName}} items.xmlName={{xmlName}} items.xmlNamespace={{xmlNamespace}} // items.example={{example}} items.type={{dataType}} - @XmlElement({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + @XmlElement({{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") {{/items}} {{#isXmlWrapped}} - @XmlElementWrapper({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + @XmlElementWrapper({{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") {{/isXmlWrapped}} {{/isContainer}} {{/isXmlAttribute}} @@ -56,6 +70,9 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{#gson}} @SerializedName(SERIALIZED_NAME_{{nameInSnakeCase}}) {{/gson}} + {{#vendorExtensions.x-field-extra-annotation}} + {{{vendorExtensions.x-field-extra-annotation}}} + {{/vendorExtensions.x-field-extra-annotation}} {{#vendorExtensions.x-is-jackson-optional-nullable}} {{#isContainer}} private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>undefined(); @@ -74,36 +91,47 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{/vendorExtensions.x-is-jackson-optional-nullable}} {{/vars}} - {{#parcelableModel}} - public {{classname}}() { - {{#parent}} - super(); - {{/parent}} - {{#gson}} - {{#discriminator}} - this.{{{discriminatorName}}} = this.getClass().getSimpleName(); - {{/discriminator}} - {{/gson}} - } - {{/parcelableModel}} - {{^parcelableModel}} - {{#gson}} - {{#discriminator}} - public {{classname}}() { - this.{{{discriminatorName}}} = this.getClass().getSimpleName(); - } - {{/discriminator}} - {{/gson}} - {{/parcelableModel}} + public {{classname}}() { {{#parent}}{{#parcelableModel}} + super();{{/parcelableModel}}{{/parent}}{{#gson}}{{#discriminator}} + this.{{{discriminatorName}}} = this.getClass().getSimpleName();{{/discriminator}}{{/gson}} + }{{#vendorExtensions.x-has-readonly-properties}}{{^withXml}}{{#jackson}} + + @JsonCreator + public {{classname}}( + {{#readOnlyVars}} + {{#jackson}}@JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}}){{/jackson}} {{{datatypeWithEnum}}} {{name}}{{^-last}}, {{/-last}} + {{/readOnlyVars}} + ) { + this(); + {{#readOnlyVars}} + this.{{name}} = {{name}}; + {{/readOnlyVars}} + }{{/jackson}}{{/withXml}}{{/vendorExtensions.x-has-readonly-properties}} {{#vars}} {{^isReadOnly}} + {{#vendorExtensions.x-enum-as-string}} + public static final Set {{{nameInSnakeCase}}}_VALUES = new HashSet<>(Arrays.asList( + {{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}} + )); + + {{/vendorExtensions.x-enum-as-string}} public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) { - {{#vendorExtensions.x-is-jackson-optional-nullable}}this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}});{{/vendorExtensions.x-is-jackson-optional-nullable}} - {{^vendorExtensions.x-is-jackson-optional-nullable}}this.{{name}} = {{name}};{{/vendorExtensions.x-is-jackson-optional-nullable}} + {{#vendorExtensions.x-enum-as-string}} + if (!{{{nameInSnakeCase}}}_VALUES.contains({{name}})) { + throw new IllegalArgumentException({{name}} + " is invalid. Possible values for {{name}}: " + String.join(", ", {{{nameInSnakeCase}}}_VALUES)); + } + + {{/vendorExtensions.x-enum-as-string}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}}); + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = {{name}}; + {{/vendorExtensions.x-is-jackson-optional-nullable}} return this; } - {{#isListContainer}} + {{#isArray}} public {{classname}} add{{nameInCamelCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) { {{#vendorExtensions.x-is-jackson-optional-nullable}} @@ -127,8 +155,8 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE return this; {{/vendorExtensions.x-is-jackson-optional-nullable}} } - {{/isListContainer}} - {{#isMapContainer}} + {{/isArray}} + {{#isMap}} public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { {{#vendorExtensions.x-is-jackson-optional-nullable}} @@ -152,33 +180,47 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE return this; {{/vendorExtensions.x-is-jackson-optional-nullable}} } - {{/isMapContainer}} + {{/isMap}} {{/isReadOnly}} /** {{#description}} - * {{description}} + * {{.}} {{/description}} {{^description}} * Get {{name}} {{/description}} {{#minimum}} - * minimum: {{minimum}} + * minimum: {{.}} {{/minimum}} {{#maximum}} - * maximum: {{maximum}} + * maximum: {{.}} {{/maximum}} * @return {{name}} + {{#deprecated}} + * @deprecated + {{/deprecated}} **/ +{{#deprecated}} + @Deprecated +{{/deprecated}} {{#required}} {{#isNullable}} - @javax.annotation.Nullable + @jakarta.annotation.Nullable +{{/isNullable}} +{{^isNullable}} + @jakarta.annotation.Nonnull {{/isNullable}} {{/required}} {{^required}} - @javax.annotation.Nullable + @jakarta.annotation.Nullable {{/required}} -{{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} @ApiModelProperty({{#example}}example = "{{{example}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}") +{{#useBeanValidation}} +{{>beanValidation}} +{{/useBeanValidation}} +{{#swagger1AnnotationLibrary}} + @ApiModelProperty({{#example}}example = "{{{.}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}") +{{/swagger1AnnotationLibrary}} {{#vendorExtensions.x-extra-annotation}} {{{vendorExtensions.x-extra-annotation}}} {{/vendorExtensions.x-extra-annotation}} @@ -215,7 +257,14 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{/vendorExtensions.x-is-jackson-optional-nullable}} {{^isReadOnly}} - public void {{setter}}({{{datatypeWithEnum}}} {{name}}) { +{{#vendorExtensions.x-setter-extra-annotation}} {{{vendorExtensions.x-setter-extra-annotation}}} +{{/vendorExtensions.x-setter-extra-annotation}}{{#jackson}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{> jackson_annotations}}{{/vendorExtensions.x-is-jackson-optional-nullable}}{{/jackson}} public void {{setter}}({{{datatypeWithEnum}}} {{name}}) { + {{#vendorExtensions.x-enum-as-string}} + if (!{{{nameInSnakeCase}}}_VALUES.contains({{name}})) { + throw new IllegalArgumentException({{name}} + " is invalid. Possible values for {{name}}: " + String.join(", ", {{{nameInSnakeCase}}}_VALUES)); + } + + {{/vendorExtensions.x-enum-as-string}} {{#vendorExtensions.x-is-jackson-optional-nullable}} this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}}); {{/vendorExtensions.x-is-jackson-optional-nullable}} @@ -226,10 +275,12 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{/isReadOnly}} {{/vars}} - -{{^supportJava6}} +{{>libraries/jersey2/additional_properties}} + /** + * Return true if this {{name}} object is equal to o. + */ @Override - public boolean equals(java.lang.Object o) { + public boolean equals(Object o) { {{#useReflectionEqualsHashCode}} return EqualsBuilder.reflectionEquals(this, o, false, null, true); {{/useReflectionEqualsHashCode}} @@ -241,12 +292,17 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE return false; }{{#hasVars}} {{classname}} {{classVarName}} = ({{classname}}) o; - return {{#vars}}{{#isByteArray}}Arrays{{/isByteArray}}{{^isByteArray}}Objects{{/isByteArray}}.equals(this.{{name}}, {{classVarName}}.{{name}}){{#hasMore}} && - {{/hasMore}}{{/vars}}{{#parent}} && + return {{#vars}}{{#vendorExtensions.x-is-jackson-optional-nullable}}equalsNullable(this.{{name}}, {{classVarName}}.{{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{#isByteArray}}Arrays{{/isByteArray}}{{^isByteArray}}Objects{{/isByteArray}}.equals(this.{{name}}, {{classVarName}}.{{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^-last}} && + {{/-last}}{{/vars}}{{#additionalPropertiesType}}&& + Objects.equals(this.additionalProperties, {{classVarName}}.additionalProperties){{/additionalPropertiesType}}{{#parent}} && super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}} return {{#parent}}super.equals(o){{/parent}}{{^parent}}true{{/parent}};{{/hasVars}} {{/useReflectionEqualsHashCode}} - } + }{{#vendorExtensions.x-jackson-optional-nullable-helpers}} + + private static boolean equalsNullable(JsonNullable a, JsonNullable b) { + return a == b || (a != null && b != null && a.isPresent() && b.isPresent() && Objects.deepEquals(a.get(), b.get())); + }{{/vendorExtensions.x-jackson-optional-nullable-helpers}} @Override public int hashCode() { @@ -254,33 +310,16 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE return HashCodeBuilder.reflectionHashCode(this); {{/useReflectionEqualsHashCode}} {{^useReflectionEqualsHashCode}} - return Objects.hash({{#vars}}{{^isByteArray}}{{name}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{#hasMore}}, {{/hasMore}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}); + return Objects.hash({{#vars}}{{#vendorExtensions.x-is-jackson-optional-nullable}}hashCodeNullable({{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{^isByteArray}}{{name}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{/vendorExtensions.x-is-jackson-optional-nullable}}{{^-last}}, {{/-last}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}{{#additionalPropertiesType}}{{#hasVars}}, {{/hasVars}}{{^hasVars}}{{#parent}}, {{/parent}}{{/hasVars}}additionalProperties{{/additionalPropertiesType}}); {{/useReflectionEqualsHashCode}} - } - -{{/supportJava6}} -{{#supportJava6}} - @Override - public boolean equals(java.lang.Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - }{{#hasVars}} - {{classname}} {{classVarName}} = ({{classname}}) o; - return {{#vars}}ObjectUtils.equals(this.{{name}}, {{classVarName}}.{{name}}){{#hasMore}} && - {{/hasMore}}{{/vars}}{{#parent}} && - super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}} - return true;{{/hasVars}} - } + }{{#vendorExtensions.x-jackson-optional-nullable-helpers}} - @Override - public int hashCode() { - return ObjectUtils.hashCodeMulti({{#vars}}{{name}}{{#hasMore}}, {{/hasMore}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}); - } - -{{/supportJava6}} + private static int hashCodeNullable(JsonNullable a) { + if (a == null) { + return 1; + } + return a.isPresent() ? Arrays.deepHashCode(new Object[]{a.get()}) : 31; + }{{/vendorExtensions.x-jackson-optional-nullable-helpers}} @Override public String toString() { @@ -292,6 +331,9 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{#vars}} sb.append(" {{name}}: ").append(toIndentedString({{name}})).append("\n"); {{/vars}} + {{#additionalPropertiesType}} + sb.append(" additionalProperties: ").append(toIndentedString(additionalProperties)).append("\n"); + {{/additionalPropertiesType}} sb.append("}"); return sb.toString(); } @@ -300,7 +342,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ - private String toIndentedString(java.lang.Object o) { + private String toIndentedString(Object o) { if (o == null) { return "null"; } @@ -311,25 +353,25 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE public void writeToParcel(Parcel out, int flags) { {{#model}} -{{#isArrayModel}} +{{#isArray}} out.writeList(this); -{{/isArrayModel}} -{{^isArrayModel}} +{{/isArray}} +{{^isArray}} {{#parent}} super.writeToParcel(out, flags); {{/parent}} {{#vars}} out.writeValue({{name}}); {{/vars}} -{{/isArrayModel}} +{{/isArray}} {{/model}} } {{classname}}(Parcel in) { -{{#isArrayModel}} +{{#isArray}} in.readTypedList(this, {{arrayModelType}}.CREATOR); -{{/isArrayModel}} -{{^isArrayModel}} +{{/isArray}} +{{^isArray}} {{#parent}} super(in); {{/parent}} @@ -341,7 +383,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE {{name}} = ({{{datatypeWithEnum}}})in.readValue({{complexType}}.class.getClassLoader()); {{/isPrimitiveType}} {{/vars}} -{{/isArrayModel}} +{{/isArray}} } public int describeContents() { @@ -351,14 +393,14 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE public static final Parcelable.Creator<{{classname}}> CREATOR = new Parcelable.Creator<{{classname}}>() { public {{classname}} createFromParcel(Parcel in) { {{#model}} -{{#isArrayModel}} +{{#isArray}} {{classname}} result = new {{classname}}(); result.addAll(in.readArrayList({{arrayModelType}}.class.getClassLoader())); return result; -{{/isArrayModel}} -{{^isArrayModel}} +{{/isArray}} +{{^isArray}} return new {{classname}}(in); -{{/isArrayModel}} +{{/isArray}} {{/model}} } public {{classname}}[] newArray(int size) { @@ -366,4 +408,15 @@ public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorE } }; {{/parcelableModel}} +{{#discriminator}} +static { + // Initialize and register the discriminator mappings. + Map> mappings = new HashMap>(); + {{#mappedModels}} + mappings.put("{{mappingName}}", {{modelName}}.class); + {{/mappedModels}} + mappings.put("{{name}}", {{classname}}.class); + JSON.registerDiscriminator({{classname}}.class, "{{propertyBaseName}}", mappings); +} +{{/discriminator}} } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/pom.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/pom.mustache similarity index 73% rename from boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/pom.mustache rename to boat-scaffold/src/main/templates/boat-java/libraries/jersey3/pom.mustache index a71ab2638..5df86ad01 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/pom.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/jersey3/pom.mustache @@ -43,7 +43,7 @@ org.apache.maven.plugins maven-enforcer-plugin - 3.0.0-M1 + 3.0.0 enforce-maven @@ -63,7 +63,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.0.0-M4 + 3.0.0-M5 @@ -74,6 +74,7 @@ -Xms512m -Xmx1500m methods 10 + false @@ -90,16 +91,14 @@ - org.apache.maven.plugins maven-jar-plugin - 2.6 + 3.2.2 - jar test-jar @@ -107,11 +106,10 @@ - org.codehaus.mojo build-helper-maven-plugin - 1.10 + 3.3.0 add_sources @@ -142,22 +140,10 @@ org.apache.maven.plugins maven-compiler-plugin - 3.8.1 + 3.10.1 - {{#supportJava6}} - 1.6 - 1.6 - {{/supportJava6}} - {{^supportJava6}} - {{#java8}} - 1.8 - 1.8 - {{/java8}} - {{^java8}} - 1.7 - 1.7 - {{/java8}} - {{/supportJava6}} + 1.8 + 1.8 true 128m 512m @@ -170,7 +156,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.1.1 + 3.3.2 attach-javadocs @@ -181,6 +167,7 @@ none + 1.8 http.response.details @@ -193,7 +180,7 @@ org.apache.maven.plugins maven-source-plugin - 2.2.1 + 3.2.0 attach-sources @@ -203,6 +190,46 @@ + + + com.diffplug.spotless + spotless-maven-plugin + ${spotless.version} + + + + + + + .gitignore + + + + + + true + 4 + + + + + + + + + + 1.8 + + true + + + + + + @@ -214,7 +241,7 @@ org.apache.maven.plugins maven-gpg-plugin - 1.5 + 3.0.1 sign-artifacts @@ -231,11 +258,13 @@ + {{#swagger1AnnotationLibrary}} io.swagger swagger-annotations ${swagger-annotations-version} + {{/swagger1AnnotationLibrary}} @@ -243,20 +272,18 @@ jsr305 3.0.2 - + org.glassfish.jersey.core jersey-client ${jersey-version} - {{^supportJava6}} org.glassfish.jersey.inject jersey-hk2 ${jersey-version} - {{/supportJava6}} org.glassfish.jersey.media jersey-media-multipart @@ -284,11 +311,13 @@ jackson-databind ${jackson-databind-version} + {{#openApiNullable}} org.openapitools jackson-databind-nullable ${jackson-databind-nullable-version} + {{/openApiNullable}} {{#withXml}} @@ -304,80 +333,71 @@ ${jackson-version} {{/joda}} - {{#java8}} com.fasterxml.jackson.datatype jackson-datatype-jsr310 ${jackson-version} - {{/java8}} - {{#threetenbp}} - - com.github.joschi.jackson - jackson-datatype-threetenbp - ${threetenbp-version} - - {{/threetenbp}} - {{^java8}} - - - com.brsanthu - migbase64 - 2.2 - - {{/java8}} - {{#supportJava6}} - - org.apache.commons - commons-lang3 - ${commons-lang3-version} - - - commons-io - commons-io - ${commons-io-version} - - {{/supportJava6}} + {{#hasHttpSignatureMethods}} org.tomitribe tomitribe-http-signatures ${http-signature-version} + {{/hasHttpSignatureMethods}} + {{#hasOAuthMethods}} + + com.github.scribejava + scribejava-apis + ${scribejava-apis-version} + + {{/hasOAuthMethods}} {{#useBeanValidation}} - javax.validation - validation-api - 1.1.0.Final + jakarta.validation + jakarta.validation-api + ${beanvalidation-version} provided {{/useBeanValidation}} + + jakarta.annotation + jakarta.annotation-api + ${jakarta-annotation-version} + provided + + + org.glassfish.jersey.connectors + jersey-apache-connector + ${jersey-version} + - junit - junit + org.junit.jupiter + junit-jupiter-api ${junit-version} test UTF-8 - 1.6.1 - {{^supportJava6}} - 2.30.1 - {{/supportJava6}} - {{#supportJava6}} - 2.6 - 2.5 - 3.6 - {{/supportJava6}} - 2.10.3 - 2.10.3 - 0.2.1 - {{#threetenbp}} - 2.9.10 - {{/threetenbp}} - 4.13 - 1.3 + 1.6.6 + 3.0.4 + 2.13.4 + 2.13.4.2 + 0.2.4 + 2.1.0 + {{#useBeanValidation}} + 2.0.2 + {{/useBeanValidation}} + 5.8.2 + {{#hasHttpSignatureMethods}} + 1.7 + {{/hasHttpSignatureMethods}} + {{#hasOAuthMethods}} + 8.3.1 + {{/hasOAuthMethods}} + 2.21.0 diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/README.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/README.mustache index 8d126ada3..58d2d5f5c 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/README.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/README.mustache @@ -1,7 +1,7 @@ # {{appName}} - MicroProfile Rest Client {{#appDescriptionWithNewLines}} -{{{appDescriptionWithNewLines}}} +{{{.}}} {{/appDescriptionWithNewLines}} ## Overview diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/api.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/api.mustache index 1830838da..49ad40447 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/api.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/api.mustache @@ -8,13 +8,19 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.List; import java.util.Map; -import javax.ws.rs.*; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.MediaType; +import java.util.Set; +import {{rootJavaEEPackage}}.ws.rs.*; +import {{rootJavaEEPackage}}.ws.rs.core.Response; +import {{rootJavaEEPackage}}.ws.rs.core.MediaType; {{^disableMultipart}} import org.apache.cxf.jaxrs.ext.multipart.*; {{/disableMultipart}} +{{#useBeanValidation}} +import javax.validation.constraints.*; +import javax.validation.Valid; +{{/useBeanValidation}} + import org.eclipse.microprofile.rest.client.annotation.RegisterProvider; import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; @@ -23,15 +29,15 @@ import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; * {{{appName}}} * {{#appDescription}} - *

{{{appDescription}}} + *

{{{.}}} * {{/appDescription}} */ {{/appName}} -@RegisterRestClient +@RegisterRestClient{{#configKey}}(configKey="{{configKey}}"){{/configKey}} @RegisterProvider(ApiExceptionMapper.class) -@Path("{{^useAnnotatedBasePath}}/{{/useAnnotatedBasePath}}{{#useAnnotatedBasePath}}{{contextPath}}{{/useAnnotatedBasePath}}") +@Path("{{#useAnnotatedBasePath}}{{contextPath}}{{/useAnnotatedBasePath}}{{commonPath}}") public interface {{classname}} { {{#operations}} {{#operation}} @@ -41,21 +47,26 @@ public interface {{classname}} { * {{summary}} * {{#notes}} - * {{notes}} + * {{.}} * {{/notes}} + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} */ {{/summary}} + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} @{{httpMethod}} {{#subresourceOperation}}@Path("{{{path}}}"){{/subresourceOperation}} {{#hasConsumes}} - @Consumes({ {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} }) + @Consumes({ {{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}} }) {{/hasConsumes}} {{#hasProduces}} - @Produces({ {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} }) + @Produces({ {{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}} }) {{/hasProduces}} - public {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}} {{nickname}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException, ProcessingException; + public {{{returnType}}}{{^returnType}}void{{/returnType}} {{nickname}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException, ProcessingException; {{/operation}} } {{/operations}} - diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/api_exception.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/api_exception.mustache index fc5c5e500..af0ecc723 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/api_exception.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/api_exception.mustache @@ -1,7 +1,7 @@ {{>licenseInfo}} package {{apiPackage}}; -import javax.ws.rs.core.Response; +import {{rootJavaEEPackage}}.ws.rs.core.Response; public class ApiException extends Exception { diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/api_exception_mapper.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/api_exception_mapper.mustache index 9c5988414..12988f5ed 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/api_exception_mapper.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/api_exception_mapper.mustache @@ -1,9 +1,9 @@ {{>licenseInfo}} package {{apiPackage}}; -import javax.ws.rs.core.MultivaluedMap; -import javax.ws.rs.core.Response; -import javax.ws.rs.ext.Provider; +import {{rootJavaEEPackage}}.ws.rs.core.MultivaluedMap; +import {{rootJavaEEPackage}}.ws.rs.core.Response; +import {{rootJavaEEPackage}}.ws.rs.ext.Provider; import org.eclipse.microprofile.rest.client.ext.ResponseExceptionMapper; @Provider diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/api_test.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/api_test.mustache index 8177ac16d..9fce40aed 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/api_test.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/api_test.mustache @@ -17,16 +17,17 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; {{/fullJavaUtil}} /** {{#appName}} - * {{{appName}}} Test + * {{{.}}} Test * {{/appName}} - * API tests for {{classname}} + * API tests for {{classname}} */ {{#generateSpringBootApplication}} @RunWith(SpringJUnit4ClassRunner.class) @@ -38,13 +39,18 @@ public class {{classname}}Test { private {{classname}} client; private String baseUrl = "http://localhost:9080"; - + @Before public void setup() throws MalformedURLException { + {{#microprofile3}} + // TODO initialize the client + {{/microprofile3}} + {{^microprofile3}} client = RestClientBuilder.newBuilder() .baseUrl(new URL(baseUrl)) .register(ApiException.class) .build({{classname}}.class); + {{/microprofile3}} } {{#operations}}{{#operation}} @@ -53,7 +59,7 @@ public class {{classname}}Test { * {{summary}} * {{#notes}} - * {{notes}} + * {{.}} * {{/notes}} {{/summary}} @@ -62,14 +68,14 @@ public class {{classname}}Test { */ @Test public void {{operationId}}Test() { - // TODO: test validations + // TODO: test validations {{#allParams}} {{^isFile}}{{{dataType}}} {{paramName}} = null;{{/isFile}}{{#isFile}}org.apache.cxf.jaxrs.ext.multipart.Attachment {{paramName}} = null;{{/isFile}} {{/allParams}} - //{{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + //{{#returnType}}{{{.}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); //{{#returnType}}assertNotNull(response);{{/returnType}} - - + + } {{/operation}}{{/operations}} } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/beanValidation.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/beanValidation.mustache index c8c6946fe..f8724b244 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/beanValidation.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/beanValidation.mustache @@ -1,4 +1,6 @@ {{#required}} +{{^isReadOnly}} @NotNull +{{/isReadOnly}} {{/required}} {{>beanValidationCore}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/beanValidationCore.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/beanValidationCore.mustache index 8bcdce3df..b58f0a266 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/beanValidationCore.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/beanValidationCore.mustache @@ -1,20 +1,20 @@ -{{#pattern}} @Pattern(regexp="{{{pattern}}}"){{/pattern}}{{! +{{#pattern}} @Pattern(regexp="{{{.}}}"){{/pattern}}{{! minLength && maxLength set }}{{#minLength}}{{#maxLength}} @Size(min={{minLength}},max={{maxLength}}){{/maxLength}}{{/minLength}}{{! minLength set, maxLength not }}{{#minLength}}{{^maxLength}} @Size(min={{minLength}}){{/maxLength}}{{/minLength}}{{! minLength not set, maxLength set -}}{{^minLength}}{{#maxLength}} @Size(max={{maxLength}}){{/maxLength}}{{/minLength}}{{! +}}{{^minLength}}{{#maxLength}} @Size(max={{.}}){{/maxLength}}{{/minLength}}{{! @Size: minItems && maxItems set }}{{#minItems}}{{#maxItems}} @Size(min={{minItems}},max={{maxItems}}){{/maxItems}}{{/minItems}}{{! @Size: minItems set, maxItems not }}{{#minItems}}{{^maxItems}} @Size(min={{minItems}}){{/maxItems}}{{/minItems}}{{! @Size: minItems not set && maxItems set -}}{{^minItems}}{{#maxItems}} @Size(max={{maxItems}}){{/maxItems}}{{/minItems}}{{! +}}{{^minItems}}{{#maxItems}} @Size(max={{.}}){{/maxItems}}{{/minItems}}{{! check for integer or long / all others=decimal type with @Decimal* isInteger set -}}{{#isInteger}}{{#minimum}} @Min({{minimum}}){{/minimum}}{{#maximum}} @Max({{maximum}}){{/maximum}}{{/isInteger}}{{! +}}{{#isInteger}}{{#minimum}} @Min({{.}}){{/minimum}}{{#maximum}} @Max({{.}}){{/maximum}}{{/isInteger}}{{! isLong set -}}{{#isLong}}{{#minimum}} @Min({{minimum}}L){{/minimum}}{{#maximum}} @Max({{maximum}}L){{/maximum}}{{/isLong}}{{! +}}{{#isLong}}{{#minimum}} @Min({{.}}L){{/minimum}}{{#maximum}} @Max({{.}}L){{/maximum}}{{/isLong}}{{! Not Integer, not Long => we have a decimal value! -}}{{^isInteger}}{{^isLong}}{{#minimum}} @DecimalMin("{{minimum}}"){{/minimum}}{{#maximum}} @DecimalMax("{{maximum}}"){{/maximum}}{{/isLong}}{{/isInteger}} \ No newline at end of file +}}{{^isInteger}}{{^isLong}}{{#minimum}} @DecimalMin("{{.}}"){{/minimum}}{{#maximum}} @DecimalMax("{{.}}"){{/maximum}}{{/isLong}}{{/isInteger}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/beanValidationHeaderParams.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/beanValidationHeaderParams.mustache index f8eef8f94..c4ff01d7e 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/beanValidationHeaderParams.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/beanValidationHeaderParams.mustache @@ -1 +1 @@ -{{#required}} @NotNull{{/required}}{{>beanValidationCore}} \ No newline at end of file +{{#required}} @NotNull{{/required}}{{>beanValidationCore}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/beanValidationQueryParams.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/beanValidationQueryParams.mustache index f8eef8f94..c4ff01d7e 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/beanValidationQueryParams.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/beanValidationQueryParams.mustache @@ -1 +1 @@ -{{#required}} @NotNull{{/required}}{{>beanValidationCore}} \ No newline at end of file +{{#required}} @NotNull{{/required}}{{>beanValidationCore}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/enumClass.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/enumClass.mustache index 5bdcf238a..38127a637 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/enumClass.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/enumClass.mustache @@ -1,13 +1,24 @@ +{{#withXml}} @XmlType(name="{{datatypeWithEnum}}") @XmlEnum({{dataType}}.class) -public enum {{datatypeWithEnum}} { +{{/withXml}} +{{^withXml}} + @JsonbTypeSerializer({{datatypeWithEnum}}.Serializer.class) + @JsonbTypeDeserializer({{datatypeWithEnum}}.Deserializer.class) +{{/withXml}} + {{>additionalEnumTypeAnnotations}}public enum {{datatypeWithEnum}} { {{#allowableValues}} -{{#enumVars}}@XmlEnumValue({{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}{{{value}}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}) {{name}}({{dataType}}.valueOf({{{value}}})){{^-last}}, {{/-last}}{{#-last}};{{/-last}}{{/enumVars}} + {{#withXml}} + {{#enumVars}}@XmlEnumValue({{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}{{{value}}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}) {{name}}({{dataType}}.valueOf({{{value}}})){{^-last}}, {{/-last}}{{#-last}};{{/-last}}{{/enumVars}} + {{/withXml}} + {{^withXml}} + {{#enumVars}}{{name}}({{dataType}}.valueOf({{{value}}})){{^-last}}, {{/-last}}{{#-last}};{{/-last}}{{/enumVars}} + {{/withXml}} {{/allowableValues}} - private {{dataType}} value; + {{dataType}} value; {{datatypeWithEnum}} ({{dataType}} v) { value = v; @@ -22,12 +33,34 @@ public enum {{datatypeWithEnum}} { return String.valueOf(value); } + {{#withXml}} public static {{datatypeWithEnum}} fromValue(String v) { - for ({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { + for ({{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { if (String.valueOf(b.value).equals(v)) { return b; } } {{#useNullForUnknownEnumValue}}return null;{{/useNullForUnknownEnumValue}}{{^useNullForUnknownEnumValue}}throw new IllegalArgumentException("Unexpected value '" + v + "'");{{/useNullForUnknownEnumValue}} } -} + {{/withXml}} + {{^withXml}} + public static final class Deserializer implements JsonbDeserializer<{{datatypeWithEnum}}> { + @Override + public {{datatypeWithEnum}} deserialize(JsonParser parser, DeserializationContext ctx, Type rtType) { + for ({{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { + if (String.valueOf(b.value).equals(parser.getString())) { + return b; + } + } + {{#useNullForUnknownEnumValue}}return null;{{/useNullForUnknownEnumValue}}{{^useNullForUnknownEnumValue}}throw new IllegalArgumentException("Unexpected value '" + parser.getString() + "'");{{/useNullForUnknownEnumValue}} + } + } + + public static final class Serializer implements JsonbSerializer<{{datatypeWithEnum}}> { + @Override + public void serialize({{datatypeWithEnum}} obj, JsonGenerator generator, SerializationContext ctx) { + generator.write(obj.value); + } + } + {{/withXml}} + } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/enumOuterClass.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/enumOuterClass.mustache index df2c72873..894ce951f 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/enumOuterClass.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/enumOuterClass.mustache @@ -4,9 +4,9 @@ import com.fasterxml.jackson.annotation.JsonValue; {{/jackson}} /** - * {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{description}}{{/description}} + * {{description}}{{^description}}Gets or Sets {{{name}}}{{/description}} */ -public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} { +{{>additionalEnumTypeAnnotations}}public enum {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} { {{#gson}} {{#allowableValues}}{{#enumVars}} @SerializedName({{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}{{{value}}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}) @@ -21,14 +21,14 @@ public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum private {{{dataType}}} value; - {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}({{{dataType}}} value) { + {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}({{{dataType}}} value) { this.value = value; } @Override {{#jackson}} @JsonValue -{{/jackson}} +{{/jackson}} public String toString() { return String.valueOf(value); } @@ -36,13 +36,13 @@ public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum {{#jackson}} @JsonCreator {{/jackson}} - public static {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue(String text) { - for ({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { + public static {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue(String text) { + for ({{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { if (String.valueOf(b.value).equals(text)) { return b; } } {{#useNullForUnknownEnumValue}}return null;{{/useNullForUnknownEnumValue}}{{^useNullForUnknownEnumValue}}throw new IllegalArgumentException("Unexpected value '" + text + "'");{{/useNullForUnknownEnumValue}} } - + } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/generatedAnnotation.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/generatedAnnotation.mustache index 49110fc1a..356a48872 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/generatedAnnotation.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/generatedAnnotation.mustache @@ -1 +1 @@ -@javax.annotation.Generated(value = "{{generatorClass}}", date = "{{generatedDate}}") \ No newline at end of file +@{{rootJavaEEPackage}}.annotation.Generated(value = "{{generatorClass}}"{{^hideGenerationTimestamp}}, date = "{{generatedDate}}"{{/hideGenerationTimestamp}}) \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/kumuluzee.beans.xml.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/kumuluzee.beans.xml.mustache new file mode 100644 index 000000000..29549d01d --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/kumuluzee.beans.xml.mustache @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/kumuluzee.config.yaml.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/kumuluzee.config.yaml.mustache new file mode 100644 index 000000000..90f5237eb --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/kumuluzee.config.yaml.mustache @@ -0,0 +1,10 @@ +kumuluzee: + server: + http: + port: 8081 + + rest-client: + registrations: + {{#apiInfo}}{{#apis}}{{#operations}}- class: {{{invokerPackage}}}.{{{classname}}} + url: http://localhost:8080/v2 + {{/operations}}{{/apis}}{{/apiInfo}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/kumuluzee.pom.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/kumuluzee.pom.mustache new file mode 100644 index 000000000..ac235b7ed --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/kumuluzee.pom.mustache @@ -0,0 +1,98 @@ + + 4.0.0 + + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + 1.0.0-SNAPSHOT + + + 1.8 + 1.8 + UTF-8 + + 3.9.0 + 1.2.3 + 1.4.1 + 3.2.6 + 4.13 + 2.28 + + + + + + com.kumuluz.ee + kumuluzee-bom + ${kumuluzee.version} + pom + import + + + + + + + com.kumuluz.ee + kumuluzee-core + + + com.kumuluz.ee + kumuluzee-servlet-jetty + + + com.kumuluz.ee + kumuluzee-jax-rs-jersey + + + com.kumuluz.ee + kumuluzee-cdi-weld + + + com.kumuluz.ee + kumuluzee-json-p-jsonp + + + com.kumuluz.ee + kumuluzee-json-b-yasson + + + com.kumuluz.ee.rest-client + kumuluzee-rest-client + ${kumuluzee-rest-client.version} + + + org.apache.cxf + cxf-rt-rs-extension-providers + ${cxf-rt-rs-extension-providers.version} + + + junit + junit + ${junit-version} + test + + + + + + + com.kumuluz.ee + kumuluzee-maven-plugin + ${kumuluzee.version} + + + package + + repackage + + + + + + + + \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/licenseInfo.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/licenseInfo.mustache index 589e9e6a4..be193d0c4 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/licenseInfo.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/licenseInfo.mustache @@ -2,22 +2,10 @@ * {{{appName}}} * {{{appDescription}}} * - * {{#version}}The version of the OpenAPI document: {{{version}}}{{/version}} - * {{#infoEmail}}Contact: {{{infoEmail}}}{{/infoEmail}} + * {{#version}}The version of the OpenAPI document: {{{.}}}{{/version}} + * {{#infoEmail}}Contact: {{{.}}}{{/infoEmail}} * - * NOTE: This class is auto generated by OpenAPI Generator (https://github.com/Backbase/backbase-openapi-tools). - * https://github.com/Backbase/backbase-openapi-tools + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech * Do not edit the class manually. - * - * 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 - * - * https://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. */ diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/model.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/model.mustache index 5272ff094..00a3c3db1 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/model.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/model.mustache @@ -7,8 +7,8 @@ package {{package}}; import java.io.Serializable; {{/serializableModel}} {{#useBeanValidation}} -import javax.validation.constraints.*; -import javax.validation.Valid; +import {{rootJavaEEPackage}}.validation.constraints.*; +import {{rootJavaEEPackage}}.validation.Valid; {{/useBeanValidation}} {{#models}} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/pojo.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/pojo.mustache index 4ded8e94e..ddec54aae 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/pojo.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/pojo.mustache @@ -1,11 +1,27 @@ -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlType; -import javax.xml.bind.annotation.XmlEnum; -import javax.xml.bind.annotation.XmlEnumValue; -import javax.json.bind.annotation.JsonbProperty; +{{#withXml}} +import {{rootJavaEEPackage}}.xml.bind.annotation.XmlElement; +import {{rootJavaEEPackage}}.xml.bind.annotation.XmlRootElement; +import {{rootJavaEEPackage}}.xml.bind.annotation.XmlAccessType; +import {{rootJavaEEPackage}}.xml.bind.annotation.XmlAccessorType; +import {{rootJavaEEPackage}}.xml.bind.annotation.XmlType; +import {{rootJavaEEPackage}}.xml.bind.annotation.XmlEnum; +import {{rootJavaEEPackage}}.xml.bind.annotation.XmlEnumValue; +{{/withXml}} +{{^withXml}} +import java.lang.reflect.Type; +import {{rootJavaEEPackage}}.json.bind.annotation.JsonbTypeDeserializer; +import {{rootJavaEEPackage}}.json.bind.annotation.JsonbTypeSerializer; +import {{rootJavaEEPackage}}.json.bind.serializer.DeserializationContext; +import {{rootJavaEEPackage}}.json.bind.serializer.JsonbDeserializer; +import {{rootJavaEEPackage}}.json.bind.serializer.JsonbSerializer; +import {{rootJavaEEPackage}}.json.bind.serializer.SerializationContext; +import {{rootJavaEEPackage}}.json.stream.JsonGenerator; +import {{rootJavaEEPackage}}.json.stream.JsonParser; +import {{rootJavaEEPackage}}.json.bind.annotation.JsonbProperty; +{{#vendorExtensions.x-has-readonly-properties}} +import {{rootJavaEEPackage}}.json.bind.annotation.JsonbCreator; +{{/vendorExtensions.x-has-readonly-properties}} +{{/withXml}} {{#withXml}} @XmlAccessorType(XmlAccessType.FIELD) @@ -17,10 +33,14 @@ import javax.json.bind.annotation.JsonbProperty; {{/withXml}} {{#description}} /** - * {{{description}}} + * {{{.}}} **/ {{/description}} -public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}}{{#serializableModel}} implements Serializable{{/serializableModel}} { +{{>additionalModelTypeAnnotations}} +{{#vendorExtensions.x-class-extra-annotation}} +{{{vendorExtensions.x-class-extra-annotation}}} +{{/vendorExtensions.x-class-extra-annotation}} +public class {{classname}} {{#parent}}extends {{{.}}}{{/parent}}{{#vendorExtensions.x-implements}}{{#-first}} implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{/vendorExtensions.x-implements}} { {{#vars}}{{#isEnum}}{{^isContainer}} {{>enumClass}}{{/isContainer}}{{#isContainer}}{{#mostInnerItems}} {{>enumClass}}{{/mostInnerItems}}{{/isContainer}}{{/isEnum}} @@ -29,9 +49,15 @@ public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}}{{#serializ {{/withXml}} {{#description}} /** - * {{{description}}} + * {{{.}}} **/ {{/description}} + {{^withXml}} + @JsonbProperty("{{baseName}}") + {{/withXml}} +{{#vendorExtensions.x-field-extra-annotation}} +{{{vendorExtensions.x-field-extra-annotation}}} +{{/vendorExtensions.x-field-extra-annotation}} {{#isContainer}} private {{{datatypeWithEnum}}} {{name}}{{#required}} = {{{defaultValue}}}{{/required}}{{^required}} = null{{/required}}; {{/isContainer}} @@ -39,37 +65,58 @@ public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}}{{#serializ private {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}; {{/isContainer}} {{/vars}} - +{{#vendorExtensions.x-has-readonly-properties}}{{^withXml}} + public {{classname}}() { + } + + @JsonbCreator + public {{classname}}( + {{#readOnlyVars}} + @JsonbProperty(value = "{{baseName}}"{{^required}}, nillable = true{{/required}}) {{{datatypeWithEnum}}} {{name}}{{^-last}}, {{/-last}} + {{/readOnlyVars}} + ) { + {{#readOnlyVars}} + this.{{name}} = {{name}}; + {{/readOnlyVars}} + } + {{/withXml}}{{/vendorExtensions.x-has-readonly-properties}} {{#vars}} /** {{#description}} - * {{description}} + * {{.}} {{/description}} {{^description}} * Get {{name}} {{/description}} {{#minimum}} - * minimum: {{minimum}} + * minimum: {{.}} {{/minimum}} {{#maximum}} - * maximum: {{maximum}} + * maximum: {{.}} {{/maximum}} * @return {{name}} + {{#deprecated}} + * @deprecated + {{/deprecated}} **/ - @JsonbProperty("{{baseName}}") +{{#deprecated}} + @Deprecated +{{/deprecated}} {{#vendorExtensions.x-extra-annotation}} {{{vendorExtensions.x-extra-annotation}}} {{/vendorExtensions.x-extra-annotation}} -{{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} {{#isEnum}}{{^isListContainer}}{{^isMapContainer}}public {{dataType}} {{getter}}() { +{{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} {{#withXml}}{{#isEnum}}{{^isArray}}{{^isMap}}public {{dataType}} {{getter}}() { if ({{name}} == null) { return null; } return {{name}}.value(); - }{{/isMapContainer}}{{/isListContainer}}{{/isEnum}}{{#isEnum}}{{#isListContainer}}public {{{datatypeWithEnum}}} {{getter}}() { + }{{/isMap}}{{/isArray}}{{/isEnum}}{{/withXml}}{{^withXml}}{{#isEnum}}{{^isArray}}{{^isMap}}public {{datatypeWithEnum}} {{getter}}() { + return {{name}}; + }{{/isMap}}{{/isArray}}{{/isEnum}}{{/withXml}}{{#isEnum}}{{#isArray}}public {{{datatypeWithEnum}}} {{getter}}() { return {{name}}; - }{{/isListContainer}}{{/isEnum}}{{#isEnum}}{{#isMapContainer}}public {{{datatypeWithEnum}}} {{getter}}() { + }{{/isArray}}{{/isEnum}}{{#isEnum}}{{#isMap}}public {{{datatypeWithEnum}}} {{getter}}() { return {{name}}; - }{{/isMapContainer}}{{/isEnum}}{{^isEnum}}public {{{datatypeWithEnum}}} {{getter}}() { + }{{/isMap}}{{/isEnum}}{{^isEnum}}public {{{datatypeWithEnum}}} {{getter}}() { return {{name}}; }{{/isEnum}} @@ -77,7 +124,8 @@ public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}}{{#serializ /** * Set {{name}} **/ - public void {{setter}}({{{datatypeWithEnum}}} {{name}}) { + {{#vendorExtensions.x-setter-extra-annotation}} {{{vendorExtensions.x-setter-extra-annotation}}} + {{/vendorExtensions.x-setter-extra-annotation}}public void {{setter}}({{{datatypeWithEnum}}} {{name}}) { this.{{name}} = {{name}}; } @@ -85,20 +133,20 @@ public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}}{{#serializ this.{{name}} = {{name}}; return this; } - {{#isListContainer}} + {{#isArray}} public {{classname}} add{{nameInCamelCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) { this.{{name}}.add({{name}}Item); return this; } - {{/isListContainer}} - {{#isMapContainer}} + {{/isArray}} + {{#isMap}} public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { this.{{name}}.put(key, {{name}}Item); return this; } - {{/isMapContainer}} + {{/isMap}} {{/isReadOnly}} {{/vars}} @@ -120,7 +168,7 @@ public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}}{{#serializ * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ - private static String toIndentedString(java.lang.Object o) { + private static String toIndentedString(Object o) { if (o == null) { return "null"; } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/pom.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/pom.mustache index ca7d6b7a8..d4199a18b 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/pom.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/pom.mustache @@ -5,15 +5,28 @@ jar {{artifactId}} {{#appDescription}} - {{appDescription}} + {{.}} {{/appDescription}} {{artifactVersion}} src/main/java + + org.jboss.jandex + jandex-maven-plugin + ${jandex.maven.plugin.version} + + + make-index + + jandex + + + + maven-failsafe-plugin - 2.6 + ${maven.failsafe.plugin.version} @@ -26,7 +39,7 @@ org.codehaus.mojo build-helper-maven-plugin - 1.9.1 + ${build.helper.maven.plugin.version} add-source @@ -48,15 +61,15 @@ junit junit - ${junit-version} + ${junit.version} test {{#useBeanValidation}} - javax.validation - validation-api - ${beanvalidation-version} + jakarta.validation + jakarta.validation-api + ${beanvalidation.version} provided {{/useBeanValidation}} @@ -64,86 +77,85 @@ org.eclipse.microprofile.rest.client microprofile-rest-client-api - 1.2.1 + ${microprofile.rest.client.api.version} - javax.ws.rs - javax.ws.rs-api - 2.1.1 + jakarta.ws.rs + jakarta.ws.rs-api + ${jakarta.ws.rs.version} provided io.smallrye smallrye-rest-client - 1.2.1 + ${smallrye.rest.client.version} test io.smallrye smallrye-config - 1.3.5 + ${smallrye.config.version} test - {{^disableMultipart}} org.apache.cxf cxf-rt-rs-extension-providers - 3.2.6 + ${cxf.rt.rs.extension.providers.version} {{/disableMultipart}} - - javax.json.bind - javax.json.bind-api - 1.0 + jakarta.json.bind + jakarta.json.bind-api + ${jakarta.json.bind.version} - javax.xml.bind - jaxb-api - 2.2.11 + jakarta.json + jakarta.json-api + ${jakarta.json.version} + + + jakarta.xml.bind + jakarta.xml.bind-api + ${jakarta.xml.bind.version} com.sun.xml.bind jaxb-core - 2.2.11 + ${jaxb.core.version} com.sun.xml.bind jaxb-impl - 2.2.11 + ${jaxb.impl.version} - javax.activation - activation - 1.1.1 + jakarta.activation + jakarta.activation-api + ${jakarta.activation.version} - -{{#java8}} com.fasterxml.jackson.datatype jackson-datatype-jsr310 - ${jackson-jaxrs-version} - -{{/java8}} -{{^java8}} - - com.fasterxml.jackson.datatype - jackson-datatype-joda - ${jackson-jaxrs-version} + ${jackson.jaxrs.version} -{{/java8}} -{{#useBeanValidationFeature}} +{{#useBeanValidationFeature}} org.hibernate hibernate-validator - 5.2.2.Final + ${hibernate.validator.version} + +{{/useBeanValidationFeature}} + + jakarta.annotation + jakarta.annotation-api + ${jakarta.annotation.version} + provided -{{/useBeanValidationFeature}} @@ -158,16 +170,31 @@ 1.8 ${java.version} ${java.version} - 1.5.18 - 9.2.9.v20150224 - 4.13 - 1.1.7 - 2.5 + 1.5.18 + 9.2.9.v20150224 + 4.13.2 + 1.2.10 {{#useBeanValidation}} - 1.1.0.Final + 2.0.2 {{/useBeanValidation}} - 3.2.7 - 2.9.7 + 3.2.7 + 2.9.7 + 1.2.2 + 1.3.5 + 1.0.2 + 1.1.6 + 2.1.6 + 2.3.3 + {{microprofileRestClientVersion}} + 1.2.1 + 1.3.5 + 3.2.6 + 2.2.11 + 2.2.11 + 5.2.2.Final + 1.1.0 + 2.6 + 1.9.1 UTF-8 diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/pom_3.0.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/pom_3.0.mustache new file mode 100644 index 000000000..f2795bf32 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/pom_3.0.mustache @@ -0,0 +1,200 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{#appDescription}} + {{.}} + {{/appDescription}} + {{artifactVersion}} + + src/main/java + + + org.jboss.jandex + jandex-maven-plugin + ${jandex.maven.plugin.version} + + + make-index + + jandex + + + + + + maven-failsafe-plugin + ${maven.failsafe.plugin.version} + + + + integration-test + verify + + + + + + org.codehaus.mojo + build-helper-maven-plugin + ${build.helper.maven.plugin.version} + + + add-source + generate-sources + + add-source + + + + src/gen/java + + + + + + + + + + junit + junit + ${junit.version} + test + +{{#useBeanValidation}} + + + jakarta.validation + jakarta.validation-api + ${beanvalidation.version} + provided + +{{/useBeanValidation}} + + + org.eclipse.microprofile.rest.client + microprofile-rest-client-api + ${microprofile.rest.client.api.version} + + + + + jakarta.ws.rs + jakarta.ws.rs-api + ${jakarta.ws.rs.version} + provided + + + + org.glassfish.jersey.ext.microprofile + jersey-mp-rest-client + ${jersey.mp.rest.client.version} + test + + + org.apache.geronimo.config + geronimo-config-impl + ${geronimo.config.impl.version} + test + + + {{^disableMultipart}} + + org.apache.cxf + cxf-rt-rs-extension-providers + ${cxf.rt.rs.extension.providers.version} + + {{/disableMultipart}} + + jakarta.json.bind + jakarta.json.bind-api + ${jakarta.json.bind.version} + + + jakarta.json + jakarta.json-api + ${jakarta.json.version} + + + jakarta.xml.bind + jakarta.xml.bind-api + ${jakarta.xml.bind.version} + + + com.sun.xml.bind + jaxb-core + ${jaxb.core.version} + + + com.sun.xml.bind + jaxb-impl + ${jaxb.impl.version} + + + jakarta.activation + jakarta.activation-api + ${jakarta.activation.version} + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson.jaxrs.version} + +{{#useBeanValidationFeature}} + + org.hibernate + hibernate-validator + ${hibernate.validator.version} + +{{/useBeanValidationFeature}} + + jakarta.annotation + jakarta.annotation-api + ${jakarta.annotation.version} + provided + + + + + sonatype-snapshots + https://oss.sonatype.org/content/repositories/snapshots + + true + + + + + 11 + ${java.version} + ${java.version} + 1.5.18 + 9.2.9.v20150224 + 4.13.2 + 1.2.10 +{{#useBeanValidation}} + 3.0.1 +{{/useBeanValidation}} + 3.2.7 + 2.13.2 + 2.1.0 + 2.0.0 + 2.0.0 + 2.0.1 + 3.0.0 + 3.0.1 + {{microprofileRestClientVersion}} + 3.0.4 + 1.2.3 + 3.5.1 + 3.0.2 + 3.0.2 + 7.0.4.Final + 1.1.0 + 2.6 + 1.9.1 + UTF-8 + + diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/queryParams.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/queryParams.mustache index ca2c6e106..38bfb9ed0 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/queryParams.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/queryParams.mustache @@ -1 +1 @@ -{{#isQueryParam}}@QueryParam("{{baseName}}"){{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}} {{^isContainer}}{{#defaultValue}}@DefaultValue({{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}{{{defaultValue}}}{{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}) {{/defaultValue}}{{/isContainer}}{{{dataType}}} {{paramName}}{{/isQueryParam}} \ No newline at end of file +{{#isQueryParam}}@QueryParam("{{baseName}}"){{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}} {{^isContainer}}{{#defaultValue}}@DefaultValue("{{{.}}}") {{/defaultValue}}{{/isContainer}}{{{dataType}}} {{paramName}}{{/isQueryParam}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/returnTypes.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/returnTypes.mustache index 6af86ffe4..32f96a904 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/returnTypes.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/microprofile/returnTypes.mustache @@ -1,4 +1,4 @@ -{{#useGenericResponse}}Response{{/useGenericResponse}}{{! non-generic response: +{{#useGenericResponse}}Response{{/useGenericResponse}}{{! non-generic response: }}{{^useGenericResponse}}{{! }}{{{returnType}}}{{! }}{{/useGenericResponse}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/native/AbstractOpenApiSchema.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/native/AbstractOpenApiSchema.mustache new file mode 100644 index 000000000..d3b428159 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/native/AbstractOpenApiSchema.mustache @@ -0,0 +1,136 @@ +{{>licenseInfo}} + +package {{modelPackage}}; + +import java.util.Objects; +import java.lang.reflect.Type; +import java.util.Map; + +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Abstract class for oneOf,anyOf schemas defined in OpenAPI spec + */ +{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}} +public abstract class AbstractOpenApiSchema { + + // store the actual instance of the schema/object + private Object instance; + + // is nullable + private Boolean isNullable; + + // schema type (e.g. oneOf, anyOf) + private final String schemaType; + + public AbstractOpenApiSchema(String schemaType, Boolean isNullable) { + this.schemaType = schemaType; + this.isNullable = isNullable; + } + + /** + * Get the list of oneOf/anyOf composed schemas allowed to be stored in this object + * + * @return an instance of the actual schema/object + */ + public abstract Map> getSchemas(); + + /** + * Get the actual instance + * + * @return an instance of the actual schema/object + */ + @JsonValue + public Object getActualInstance() {return instance;} + + /** + * Set the actual instance + * + * @param instance the actual instance of the schema/object + */ + public void setActualInstance(Object instance) {this.instance = instance;} + + /** + * Get the instant recursively when the schemas defined in oneOf/anyof happen to be oneOf/anyOf schema as well + * + * @return an instance of the actual schema/object + */ + public Object getActualInstanceRecursively() { + return getActualInstanceRecursively(this); + } + + private Object getActualInstanceRecursively(AbstractOpenApiSchema object) { + if (object.getActualInstance() == null) { + return null; + } else if (object.getActualInstance() instanceof AbstractOpenApiSchema) { + return getActualInstanceRecursively((AbstractOpenApiSchema)object.getActualInstance()); + } else { + return object.getActualInstance(); + } + } + + /** + * Get the schema type (e.g. anyOf, oneOf) + * + * @return the schema type + */ + public String getSchemaType() { + return schemaType; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ").append(getClass()).append(" {\n"); + sb.append(" instance: ").append(toIndentedString(instance)).append("\n"); + sb.append(" isNullable: ").append(toIndentedString(isNullable)).append("\n"); + sb.append(" schemaType: ").append(toIndentedString(schemaType)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AbstractOpenApiSchema a = (AbstractOpenApiSchema) o; + return Objects.equals(this.instance, a.instance) && + Objects.equals(this.isNullable, a.isNullable) && + Objects.equals(this.schemaType, a.schemaType); + } + + @Override + public int hashCode() { + return Objects.hash(instance, isNullable, schemaType); + } + + /** + * Is nullable + * + * @return true if it's nullable + */ + public Boolean isNullable() { + if (Boolean.TRUE.equals(isNullable)) { + return Boolean.TRUE; + } else { + return Boolean.FALSE; + } + } + +{{>libraries/native/additional_properties}} + +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/native/ApiClient.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/native/ApiClient.mustache index fb83d919b..14add046a 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/native/ApiClient.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/native/ApiClient.mustache @@ -6,16 +6,20 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +{{#openApiNullable}} import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} import java.io.InputStream; import java.net.URI; import java.net.URLEncoder; import java.net.http.HttpClient; +import java.net.http.HttpConnectTimeoutException; import java.net.http.HttpRequest; import java.net.http.HttpResponse; -import java.nio.charset.Charset; import java.time.Duration; +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -23,6 +27,8 @@ import java.util.StringJoiner; import java.util.function.Consumer; import java.util.stream.Collectors; +import static java.nio.charset.StandardCharsets.UTF_8; + /** * Configuration and utility class for API clients. * @@ -39,8 +45,6 @@ import java.util.stream.Collectors; {{>generatedAnnotation}} public class ApiClient { - private static final Charset UTF_8 = Charset.forName("UTF-8"); - private HttpClient.Builder builder; private ObjectMapper mapper; private String scheme; @@ -49,12 +53,17 @@ public class ApiClient { private String basePath; private Consumer interceptor; private Consumer> responseInterceptor; + private Consumer> asyncResponseInterceptor; private Duration readTimeout; + private Duration connectTimeout; private static String valueToString(Object value) { if (value == null) { return ""; } + if (value instanceof OffsetDateTime) { + return ((OffsetDateTime) value).format(DateTimeFormatter.ISO_OFFSET_DATE_TIME); + } return value.toString(); } @@ -65,7 +74,7 @@ public class ApiClient { * @return URL-encoded representation of the input string. */ public static String urlEncode(String s) { - return URLEncoder.encode(s, UTF_8); + return URLEncoder.encode(s, UTF_8).replaceAll("\\+", "%20"); } /** @@ -85,7 +94,7 @@ public class ApiClient { if (name == null || name.isEmpty() || value == null) { return Collections.emptyList(); } - return Collections.singletonList(new Pair(urlEncode(name), urlEncode(value.toString()))); + return Collections.singletonList(new Pair(urlEncode(name), urlEncode(valueToString(value)))); } /** @@ -143,28 +152,67 @@ public class ApiClient { } /** - * Ctor. + * Create an instance of ApiClient. */ public ApiClient() { - builder = HttpClient.newBuilder(); - mapper = new ObjectMapper(); + this.builder = createDefaultHttpClientBuilder(); + this.mapper = createDefaultObjectMapper(); + updateBaseUri(getDefaultBaseUri()); + interceptor = null; + readTimeout = null; + connectTimeout = null; + responseInterceptor = null; + asyncResponseInterceptor = null; + } + + /** + * Create an instance of ApiClient. + * + * @param builder Http client builder. + * @param mapper Object mapper. + * @param baseUri Base URI + */ + public ApiClient(HttpClient.Builder builder, ObjectMapper mapper, String baseUri) { + this.builder = builder; + this.mapper = mapper; + updateBaseUri(baseUri != null ? baseUri : getDefaultBaseUri()); + interceptor = null; + readTimeout = null; + connectTimeout = null; + responseInterceptor = null; + asyncResponseInterceptor = null; + } + + protected ObjectMapper createDefaultObjectMapper() { + ObjectMapper mapper = new ObjectMapper(); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + mapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE); mapper.registerModule(new JavaTimeModule()); - JsonNullableModule jnm = new JsonNullableModule(); - mapper.registerModule(jnm); - URI baseURI = URI.create("{{{basePath}}}"); - scheme = baseURI.getScheme(); - host = baseURI.getHost(); - port = baseURI.getPort(); - basePath = baseURI.getRawPath(); - interceptor = null; - readTimeout = null; - responseInterceptor = null; + {{#openApiNullable}} + mapper.registerModule(new JsonNullableModule()); + {{/openApiNullable}} + return mapper; + } + + protected String getDefaultBaseUri() { + return "{{{basePath}}}"; + } + + protected HttpClient.Builder createDefaultHttpClientBuilder() { + return HttpClient.newBuilder(); + } + + public void updateBaseUri(String baseUri) { + URI uri = URI.create(baseUri); + scheme = uri.getScheme(); + host = uri.getHost(); + port = uri.getPort(); + basePath = uri.getRawPath(); } /** @@ -319,6 +367,29 @@ public class ApiClient { return responseInterceptor; } + /** + * Set a custom async response interceptor. Use this interceptor when asyncNative is set to 'true'. + * + *

This is useful for logging, monitoring or extraction of header variables

+ * + * @param interceptor A function invoked before creating each request. A value + * of null resets the interceptor to a no-op. + * @return This object. + */ + public ApiClient setAsyncResponseInterceptor(Consumer> interceptor) { + this.asyncResponseInterceptor = interceptor; + return this; + } + + /** + * Get the custom async response interceptor. Use this interceptor when asyncNative is set to 'true'. + * + * @return The custom interceptor that was set, or null if there isn't any. + */ + public Consumer> getAsyncResponseInterceptor() { + return asyncResponseInterceptor; + } + /** * Set the read timeout for the http client. * @@ -334,7 +405,7 @@ public class ApiClient { this.readTimeout = readTimeout; return this; } - + /** * Get the read timeout that was set. * @@ -344,4 +415,35 @@ public class ApiClient { public Duration getReadTimeout() { return readTimeout; } + /** + * Sets the connect timeout (in milliseconds) for the http client. + * + *

In the case where a new connection needs to be established, if + * the connection cannot be established within the given {@code + * duration}, then {@link HttpClient#send(HttpRequest,BodyHandler) + * HttpClient::send} throws an {@link HttpConnectTimeoutException}, or + * {@link HttpClient#sendAsync(HttpRequest,BodyHandler) + * HttpClient::sendAsync} completes exceptionally with an + * {@code HttpConnectTimeoutException}. If a new connection does not + * need to be established, for example if a connection can be reused + * from a previous request, then this timeout duration has no effect. + * + * @param connectTimeout connection timeout in milliseconds + * + * @return This object. + */ + public ApiClient setConnectTimeout(Duration connectTimeout) { + this.connectTimeout = connectTimeout; + this.builder.connectTimeout(connectTimeout); + return this; + } + + /** + * Get connection timeout (in milliseconds). + * + * @return Timeout in milliseconds + */ + public Duration getConnectTimeout() { + return connectTimeout; + } } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/native/ApiResponse.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/native/ApiResponse.mustache new file mode 100644 index 000000000..1e277319a --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/native/ApiResponse.mustache @@ -0,0 +1,58 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import java.util.List; +import java.util.Map; +{{#caseInsensitiveResponseHeaders}} +import java.util.Map.Entry; +import java.util.TreeMap; +{{/caseInsensitiveResponseHeaders}} + +/** + * API response returned by API call. + * + * @param The type of data that is deserialized from response body + */ +public class ApiResponse { + final private int statusCode; + final private Map> headers; + final private T data; + + /** + * @param statusCode The status code of HTTP response + * @param headers The headers of HTTP response + */ + public ApiResponse(int statusCode, Map> headers) { + this(statusCode, headers, null); + } + + /** + * @param statusCode The status code of HTTP response + * @param headers The headers of HTTP response + * @param data The object deserialized from response bod + */ + public ApiResponse(int statusCode, Map> headers, T data) { + this.statusCode = statusCode; + {{#caseInsensitiveResponseHeaders}} + Map> responseHeaders = new TreeMap>(String.CASE_INSENSITIVE_ORDER); + for(Entry> entry : headers.entrySet()){ + responseHeaders.put(entry.getKey().toLowerCase(), entry.getValue()); + } + {{/caseInsensitiveResponseHeaders}} + this.headers = {{#caseInsensitiveResponseHeaders}}responseHeaders{{/caseInsensitiveResponseHeaders}}{{^caseInsensitiveResponseHeaders}}headers{{/caseInsensitiveResponseHeaders}}; + this.data = data; + } + + public int getStatusCode() { + return statusCode; + } + + public Map> getHeaders() { + return headers; + } + + public T getData() { + return data; + } +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/native/JSON.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/native/JSON.mustache new file mode 100644 index 000000000..a13bf2fdf --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/native/JSON.mustache @@ -0,0 +1,260 @@ +package {{invokerPackage}}; + +import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.databind.*; +{{#openApiNullable}} +import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +{{#joda}} +import com.fasterxml.jackson.datatype.joda.JodaModule; +{{/joda}} +{{#models.0}} +import {{modelPackage}}.*; +{{/models.0}} + +import java.text.DateFormat; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +{{>generatedAnnotation}} +public class JSON { + private ObjectMapper mapper; + + public JSON() { + mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.configure(MapperFeature.ALLOW_COERCION_OF_SCALARS, false); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); + mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, true); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + mapper.setDateFormat(new RFC3339DateFormat()); + mapper.registerModule(new JavaTimeModule()); + {{#joda}} + mapper.registerModule(new JodaModule()); + {{/joda}} + {{#openApiNullable}} + JsonNullableModule jnm = new JsonNullableModule(); + mapper.registerModule(jnm); + {{/openApiNullable}} + } + + /** + * Set the date format for JSON (de)serialization with Date properties. + * + * @param dateFormat Date format + */ + public void setDateFormat(DateFormat dateFormat) { + mapper.setDateFormat(dateFormat); + } + + /** + * Get the object mapper + * + * @return object mapper + */ + public ObjectMapper getMapper() { return mapper; } + + /** + * Returns the target model class that should be used to deserialize the input data. + * The discriminator mappings are used to determine the target model class. + * + * @param node The input data. + * @param modelClass The class that contains the discriminator mappings. + * + * @return the target model class. + */ + public static Class getClassForElement(JsonNode node, Class modelClass) { + ClassDiscriminatorMapping cdm = modelDiscriminators.get(modelClass); + if (cdm != null) { + return cdm.getClassForElement(node, new HashSet>()); + } + return null; + } + + /** + * Helper class to register the discriminator mappings. + */ + private static class ClassDiscriminatorMapping { + // The model class name. + Class modelClass; + // The name of the discriminator property. + String discriminatorName; + // The discriminator mappings for a model class. + Map> discriminatorMappings; + + // Constructs a new class discriminator. + ClassDiscriminatorMapping(Class cls, String propertyName, Map> mappings) { + modelClass = cls; + discriminatorName = propertyName; + discriminatorMappings = new HashMap>(); + if (mappings != null) { + discriminatorMappings.putAll(mappings); + } + } + + // Return the name of the discriminator property for this model class. + String getDiscriminatorPropertyName() { + return discriminatorName; + } + + // Return the discriminator value or null if the discriminator is not + // present in the payload. + String getDiscriminatorValue(JsonNode node) { + // Determine the value of the discriminator property in the input data. + if (discriminatorName != null) { + // Get the value of the discriminator property, if present in the input payload. + node = node.get(discriminatorName); + if (node != null && node.isValueNode()) { + String discrValue = node.asText(); + if (discrValue != null) { + return discrValue; + } + } + } + return null; + } + + /** + * Returns the target model class that should be used to deserialize the input data. + * This function can be invoked for anyOf/oneOf composed models with discriminator mappings. + * The discriminator mappings are used to determine the target model class. + * + * @param node The input data. + * @param visitedClasses The set of classes that have already been visited. + * + * @return the target model class. + */ + Class getClassForElement(JsonNode node, Set> visitedClasses) { + if (visitedClasses.contains(modelClass)) { + // Class has already been visited. + return null; + } + // Determine the value of the discriminator property in the input data. + String discrValue = getDiscriminatorValue(node); + if (discrValue == null) { + return null; + } + Class cls = discriminatorMappings.get(discrValue); + // It may not be sufficient to return this cls directly because that target class + // may itself be a composed schema, possibly with its own discriminator. + visitedClasses.add(modelClass); + for (Class childClass : discriminatorMappings.values()) { + ClassDiscriminatorMapping childCdm = modelDiscriminators.get(childClass); + if (childCdm == null) { + continue; + } + if (!discriminatorName.equals(childCdm.discriminatorName)) { + discrValue = getDiscriminatorValue(node); + if (discrValue == null) { + continue; + } + } + if (childCdm != null) { + // Recursively traverse the discriminator mappings. + Class childDiscr = childCdm.getClassForElement(node, visitedClasses); + if (childDiscr != null) { + return childDiscr; + } + } + } + return cls; + } + } + + /** + * Returns true if inst is an instance of modelClass in the OpenAPI model hierarchy. + * + * The Java class hierarchy is not implemented the same way as the OpenAPI model hierarchy, + * so it's not possible to use the instanceof keyword. + * + * @param modelClass A OpenAPI model class. + * @param inst The instance object. + * @param visitedClasses The set of classes that have already been visited. + * + * @return true if inst is an instance of modelClass in the OpenAPI model hierarchy. + */ + public static boolean isInstanceOf(Class modelClass, Object inst, Set> visitedClasses) { + if (modelClass.isInstance(inst)) { + // This handles the 'allOf' use case with single parent inheritance. + return true; + } + if (visitedClasses.contains(modelClass)) { + // This is to prevent infinite recursion when the composed schemas have + // a circular dependency. + return false; + } + visitedClasses.add(modelClass); + + // Traverse the oneOf/anyOf composed schemas. + Map> descendants = modelDescendants.get(modelClass); + if (descendants != null) { + for (Class childType : descendants.values()) { + if (isInstanceOf(childType, inst, visitedClasses)) { + return true; + } + } + } + return false; + } + + /** + * A map of discriminators for all model classes. + */ + private static Map, ClassDiscriminatorMapping> modelDiscriminators = new HashMap<>(); + + /** + * A map of oneOf/anyOf descendants for each model class. + */ + private static Map, Map>> modelDescendants = new HashMap<>(); + + /** + * Register a model class discriminator. + * + * @param modelClass the model class + * @param discriminatorPropertyName the name of the discriminator property + * @param mappings a map with the discriminator mappings. + */ + public static void registerDiscriminator(Class modelClass, String discriminatorPropertyName, Map> mappings) { + ClassDiscriminatorMapping m = new ClassDiscriminatorMapping(modelClass, discriminatorPropertyName, mappings); + modelDiscriminators.put(modelClass, m); + } + + /** + * Register the oneOf/anyOf descendants of the modelClass. + * + * @param modelClass the model class + * @param descendants a map of oneOf/anyOf descendants. + */ + public static void registerDescendants(Class modelClass, Map> descendants) { + modelDescendants.put(modelClass, descendants); + } + + private static JSON json; + + static { + json = new JSON(); + } + + /** + * Get the default JSON instance. + * + * @return the default JSON instance + */ + public static JSON getDefault() { + return json; + } + + /** + * Set the default JSON instance. + * + * @param json JSON instance to be used + */ + public static void setDefault(JSON json) { + JSON.json = json; + } +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/native/README.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/native/README.mustache index f574b47b4..ef15f379a 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/native/README.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/native/README.mustache @@ -8,7 +8,7 @@ - Build date: {{generatedDate}} {{/hideGenerationTimestamp}} -{{#appDescriptionWithNewLines}}{{{appDescriptionWithNewLines}}}{{/appDescriptionWithNewLines}} +{{{appDescriptionWithNewLines}}} {{#infoUrl}} For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}) @@ -81,7 +81,11 @@ Please follow the [installation](#installation) instruction and execute the foll {{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}} import {{{invokerPackage}}}.*; import {{{modelPackage}}}.*; -import {{{package}}}.{{{classname}}}; +import {{{package}}}.{{{classname}}};{{#vendorExtensions.x-group-parameters}} +import {{{package}}}.{{{classname}}}.*;{{/vendorExtensions.x-group-parameters}} +{{#asyncNative}} +import java.util.concurrent.CompletableFuture; +{{/asyncNative}} public class {{{classname}}}Example { @@ -94,8 +98,20 @@ public class {{{classname}}}Example { {{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} {{/allParams}} try { - {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}} - System.out.println(result);{{/returnType}} + {{^vendorExtensions.x-group-parameters}} + {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}} result = {{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture result = {{/asyncNative}}{{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}}); + {{/vendorExtensions.x-group-parameters}} + {{#vendorExtensions.x-group-parameters}} + {{#hasParams}} + API{{operationId}}Request request = API{{operationId}}Request.newBuilder(){{#allParams}} + .{{paramName}}({{paramName}}){{/allParams}} + .build(); + {{/hasParams}} + {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}} result = {{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture result = {{/asyncNative}}{{/returnType}}apiInstance.{{operationId}}({{#hasParams}}request{{/hasParams}}); + {{/vendorExtensions.x-group-parameters}} + {{#returnType}} + System.out.println(result{{#asyncNative}}.get(){{/asyncNative}}); + {{/returnType}} } catch (ApiException e) { System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); System.err.println("Status code: " + e.getCode()); @@ -114,7 +130,8 @@ All URIs are relative to *{{basePath}}* Class | Method | HTTP request | Description ------------ | ------------- | ------------- | ------------- -{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{summary}} +*{{classname}}* | [**{{operationId}}WithHttpInfo**]({{apiDocPath}}{{classname}}.md#{{operationId}}WithHttpInfo) | **{{httpMethod}}** {{path}} | {{summary}} {{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} ## Documentation for Models @@ -157,5 +174,5 @@ However, the instances of the api clients created from the `ApiClient` are threa ## Author -{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}} -{{/hasMore}}{{/apis}}{{/apiInfo}} +{{#apiInfo}}{{#apis}}{{#-last}}{{infoEmail}} +{{/-last}}{{/apis}}{{/apiInfo}} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/native/additional_properties.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/native/additional_properties.mustache new file mode 100644 index 000000000..8e7182792 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/native/additional_properties.mustache @@ -0,0 +1,45 @@ +{{#additionalPropertiesType}} + /** + * A container for additional, undeclared properties. + * This is a holder for any undeclared properties as specified with + * the 'additionalProperties' keyword in the OAS document. + */ + private Map additionalProperties; + + /** + * Set the additional (undeclared) property with the specified name and value. + * If the property does not already exist, create it otherwise replace it. + * @param key the name of the property + * @param value the value of the property + * @return self reference + */ + @JsonAnySetter + public {{classname}} putAdditionalProperty(String key, {{{.}}} value) { + if (this.additionalProperties == null) { + this.additionalProperties = new HashMap(); + } + this.additionalProperties.put(key, value); + return this; + } + + /** + * Return the additional (undeclared) properties. + * @return the additional (undeclared) properties + */ + @JsonAnyGetter + public Map getAdditionalProperties() { + return additionalProperties; + } + + /** + * Return the additional (undeclared) property with the specified name. + * @param key the name of the property + * @return the additional (undeclared) property with the specified name + */ + public {{{.}}} getAdditionalProperty(String key) { + if (this.additionalProperties == null) { + return null; + } + return this.additionalProperties.get(key); + } +{{/additionalPropertiesType}} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/native/anyof_model.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/native/anyof_model.mustache new file mode 100644 index 000000000..c87c932fe --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/native/anyof_model.mustache @@ -0,0 +1,198 @@ +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import {{invokerPackage}}.JSON; + +{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>xmlAnnotation}} +@JsonDeserialize(using={{classname}}.{{classname}}Deserializer.class) +@JsonSerialize(using = {{classname}}.{{classname}}Serializer.class) +public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-implements}}, {{{.}}}{{/vendorExtensions.x-implements}} { + private static final Logger log = Logger.getLogger({{classname}}.class.getName()); + + public static class {{classname}}Serializer extends StdSerializer<{{classname}}> { + public {{classname}}Serializer(Class<{{classname}}> t) { + super(t); + } + + public {{classname}}Serializer() { + this(null); + } + + @Override + public void serialize({{classname}} value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { + jgen.writeObject(value.getActualInstance()); + } + } + + public static class {{classname}}Deserializer extends StdDeserializer<{{classname}}> { + public {{classname}}Deserializer() { + this({{classname}}.class); + } + + public {{classname}}Deserializer(Class vc) { + super(vc); + } + + @Override + public {{classname}} deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { + JsonNode tree = jp.readValueAsTree(); + + Object deserialized = null; + {{#discriminator}} + Class cls = JSON.getClassForElement(tree, {{classname}}.class); + if (cls != null) { + // When the OAS schema includes a discriminator, use the discriminator value to + // discriminate the anyOf schemas. + // Get the discriminator mapping value to get the class. + deserialized = tree.traverse(jp.getCodec()).readValueAs(cls); + {{classname}} ret = new {{classname}}(); + ret.setActualInstance(deserialized); + return ret; + } + {{/discriminator}} + {{#anyOf}} + // deserialize {{{.}}} + try { + deserialized = tree.traverse(jp.getCodec()).readValueAs({{{.}}}.class); + {{classname}} ret = new {{classname}}(); + ret.setActualInstance(deserialized); + return ret; + } catch (Exception e) { + // deserialization failed, continue, log to help debugging + log.log(Level.FINER, "Input data does not match '{{classname}}'", e); + } + + {{/anyOf}} + throw new IOException(String.format("Failed deserialization for {{classname}}: no match found")); + } + + /** + * Handle deserialization of the 'null' value. + */ + @Override + public {{classname}} getNullValue(DeserializationContext ctxt) throws JsonMappingException { + {{#isNullable}} + return null; + {{/isNullable}} + {{^isNullable}} + throw new JsonMappingException(ctxt.getParser(), "{{classname}} cannot be null"); + {{/isNullable}} + } + } + + // store a list of schema names defined in anyOf + public static final Map> schemas = new HashMap>(); + + public {{classname}}() { + super("anyOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); + } +{{> libraries/native/additional_properties }} + {{#additionalPropertiesType}} + /** + * Return true if this {{name}} object is equal to o. + */ + @Override + public boolean equals(Object o) { + return super.equals(o) && Objects.equals(this.additionalProperties, (({{classname}})o).additionalProperties); + } + + @Override + public int hashCode() { + return Objects.hash(getActualInstance(), isNullable(), getSchemaType(), additionalProperties); + } + {{/additionalPropertiesType}} + {{#anyOf}} + public {{classname}}({{{.}}} o) { + super("anyOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); + setActualInstance(o); + } + + {{/anyOf}} + static { + {{#anyOf}} + schemas.put("{{{.}}}", {{{.}}}.class); + {{/anyOf}} + JSON.registerDescendants({{classname}}.class, Collections.unmodifiableMap(schemas)); + {{#discriminator}} + // Initialize and register the discriminator mappings. + Map> mappings = new HashMap>(); + {{#mappedModels}} + mappings.put("{{mappingName}}", {{modelName}}.class); + {{/mappedModels}} + mappings.put("{{name}}", {{classname}}.class); + JSON.registerDiscriminator({{classname}}.class, "{{propertyBaseName}}", mappings); + {{/discriminator}} + } + + @Override + public Map> getSchemas() { + return {{classname}}.schemas; + } + + /** + * Set the instance that matches the anyOf child schema, check + * the instance parameter is valid against the anyOf child schemas: + * {{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}} + * + * It could be an instance of the 'anyOf' schemas. + * The anyOf child schemas may themselves be a composed schema (allOf, anyOf, anyOf). + */ + @Override + public void setActualInstance(Object instance) { + {{#isNullable}} + if (instance == null) { + super.setActualInstance(instance); + return; + } + + {{/isNullable}} + {{#anyOf}} + if (JSON.isInstanceOf({{{.}}}.class, instance, new HashSet>())) { + super.setActualInstance(instance); + return; + } + + {{/anyOf}} + throw new RuntimeException("Invalid instance type. Must be {{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}}"); + } + + /** + * Get the actual instance, which can be the following: + * {{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}} + * + * @return The actual instance ({{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}}) + */ + @Override + public Object getActualInstance() { + return super.getActualInstance(); + } + + {{#anyOf}} + /** + * Get the actual instance of `{{{.}}}`. If the actual instance is not `{{{.}}}`, + * the ClassCastException will be thrown. + * + * @return The actual instance of `{{{.}}}` + * @throws ClassCastException if the instance is not `{{{.}}}` + */ + public {{{.}}} get{{{.}}}() throws ClassCastException { + return ({{{.}}})super.getActualInstance(); + } + + {{/anyOf}} +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/native/api.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/native/api.mustache index 7d6ed2d4b..372ea7714 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/native/api.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/native/api.mustache @@ -3,6 +3,7 @@ package {{package}}; import {{invokerPackage}}.ApiClient; import {{invokerPackage}}.ApiException; +import {{invokerPackage}}.ApiResponse; import {{invokerPackage}}.Pair; {{#imports}} @@ -19,16 +20,17 @@ import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.time.Duration; -import java.util.function.Consumer; {{^fullJavaUtil}} import java.util.ArrayList; import java.util.StringJoiner; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.function.Consumer; {{/fullJavaUtil}} - {{#asyncNative}} + import java.util.concurrent.CompletableFuture; {{/asyncNative}} @@ -38,10 +40,11 @@ public class {{classname}} { private final HttpClient memberVarHttpClient; private final ObjectMapper memberVarObjectMapper; private final String memberVarBaseUri; - private final Consumer memberVarInterceptor; + private final {{#fullJavaUtil}}java.util.function.{{/fullJavaUtil}}Consumer memberVarInterceptor; private final Duration memberVarReadTimeout; - private final Consumer> memberVarResponseInterceptor; - + private final {{#fullJavaUtil}}java.util.function.{{/fullJavaUtil}}Consumer> memberVarResponseInterceptor; + private final {{#fullJavaUtil}}java.util.function.{{/fullJavaUtil}}Consumer> memberVarAsyncResponseInterceptor; + public {{classname}}() { this(new ApiClient()); } @@ -53,9 +56,91 @@ public class {{classname}} { memberVarInterceptor = apiClient.getRequestInterceptor(); memberVarReadTimeout = apiClient.getReadTimeout(); memberVarResponseInterceptor = apiClient.getResponseInterceptor(); + memberVarAsyncResponseInterceptor = apiClient.getAsyncResponseInterceptor(); + } + {{#asyncNative}} + + private ApiException getApiException(String operationId, HttpResponse response) { + String message = formatExceptionMessage(operationId, response.statusCode(), response.body()); + return new ApiException(response.statusCode(), message, response.headers(), response.body()); + } + {{/asyncNative}} + {{^asyncNative}} + + protected ApiException getApiException(String operationId, HttpResponse response) throws IOException { + String body = response.body() == null ? null : new String(response.body().readAllBytes()); + String message = formatExceptionMessage(operationId, response.statusCode(), body); + return new ApiException(response.statusCode(), message, response.headers(), body); + } + {{/asyncNative}} + + private String formatExceptionMessage(String operationId, int statusCode, String body) { + if (body == null || body.isEmpty()) { + body = "[no body]"; + } + return operationId + " call failed with: " + statusCode + " - " + body; } {{#operation}} + {{#vendorExtensions.x-group-parameters}} + {{#hasParams}} + /** + * {{summary}} + * {{notes}} + * @param apiRequest {@link API{{operationId}}Request} + {{#returnType}} + * @return {{#asyncNative}}CompletableFuture<{{/asyncNative}}{{returnType}}{{#asyncNative}}>{{/asyncNative}} + {{/returnType}} + {{^returnType}} + {{#asyncNative}} + * @return CompletableFuture<Void> + {{/asyncNative}} + {{/returnType}} + * @throws ApiException if fails to make API call + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}}{{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture{{/asyncNative}}{{^asyncNative}}void{{/asyncNative}}{{/returnType}} {{operationId}}(API{{operationId}}Request apiRequest) throws ApiException { + {{#allParams}} + {{{dataType}}} {{paramName}} = apiRequest.{{paramName}}(); + {{/allParams}} + {{#returnType}}return {{/returnType}}{{^returnType}}{{#asyncNative}}return {{/asyncNative}}{{/returnType}}{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + } + + /** + * {{summary}} + * {{notes}} + * @param apiRequest {@link API{{operationId}}Request} + * @return {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{returnType}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} + * @throws ApiException if fails to make API call + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{{returnType}}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} {{operationId}}WithHttpInfo(API{{operationId}}Request apiRequest) throws ApiException { + {{#allParams}} + {{{dataType}}} {{paramName}} = apiRequest.{{paramName}}(); + {{/allParams}} + return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + } + + {{/hasParams}} + {{/vendorExtensions.x-group-parameters}} /** * {{summary}} * {{notes}} @@ -63,7 +148,12 @@ public class {{classname}} { * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/isContainer}}{{/required}} {{/allParams}} {{#returnType}} - * @return {{returnType}} + * @return {{#asyncNative}}CompletableFuture<{{/asyncNative}}{{returnType}}{{#asyncNative}}>{{/asyncNative}} + {{/returnType}} + {{^returnType}} + {{#asyncNative}} + * @return CompletableFuture<Void> + {{/asyncNative}} {{/returnType}} * @throws ApiException if fails to make API call {{#isDeprecated}} @@ -77,17 +167,165 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}}{{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture{{/asyncNative}}{{^asyncNative}}void{{/asyncNative}}{{/returnType}} {{operationId}} ({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { - {{#allParams}} - {{#required}} - // verify the required parameter '{{paramName}}' is set - if ({{paramName}} == null) { + public {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}}{{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture{{/asyncNative}}{{^asyncNative}}void{{/asyncNative}}{{/returnType}} {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { + {{^asyncNative}} + {{#returnType}}ApiResponse<{{{.}}}> localVarResponse = {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + {{#returnType}} + return localVarResponse.getData(); + {{/returnType}} + {{/asyncNative}} {{#asyncNative}} - return CompletableFuture.failedFuture(new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{operationId}}")); + try { + HttpRequest.Builder localVarRequestBuilder = {{operationId}}RequestBuilder({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + return memberVarHttpClient.sendAsync( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofString()).thenComposeAsync(localVarResponse -> { + if (localVarResponse.statusCode()/ 100 != 2) { + return CompletableFuture.failedFuture(getApiException("{{operationId}}", localVarResponse)); + } + {{#returnType}} + try { + String responseBody = localVarResponse.body(); + return CompletableFuture.completedFuture( + responseBody == null || responseBody.isBlank() ? null : memberVarObjectMapper.readValue(responseBody, new TypeReference<{{{returnType}}}>() {}) + ); + } catch (IOException e) { + return CompletableFuture.failedFuture(new ApiException(e)); + } + {{/returnType}} + {{^returnType}} + return CompletableFuture.completedFuture(null); + {{/returnType}} + }); + } + catch (ApiException e) { + return CompletableFuture.failedFuture(e); + } {{/asyncNative}} + } + + /** + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/isContainer}}{{/required}} + {{/allParams}} + * @return {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{returnType}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} + * @throws ApiException if fails to make API call + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{{returnType}}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} {{operationId}}WithHttpInfo({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { {{^asyncNative}} - throw new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{operationId}}"); + HttpRequest.Builder localVarRequestBuilder = {{operationId}}RequestBuilder({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + try { + HttpResponse localVarResponse = memberVarHttpClient.send( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } + try { + if (localVarResponse.statusCode()/ 100 != 2) { + throw getApiException("{{operationId}}", localVarResponse); + } + {{#vendorExtensions.x-java-text-plain-string}} + // for plain text response + if (localVarResponse.headers().map().containsKey("Content-Type") && + "text/plain".equalsIgnoreCase(localVarResponse.headers().map().get("Content-Type").get(0))) { + java.util.Scanner s = new java.util.Scanner(localVarResponse.body()).useDelimiter("\\A"); + String responseBodyText = s.hasNext() ? s.next() : ""; + return new ApiResponse( + localVarResponse.statusCode(), + localVarResponse.headers().map(), + responseBodyText + ); + } else { + throw new RuntimeException("Error! The response Content-Type is supposed to be `text/plain` but it's not: " + localVarResponse); + } + {{/vendorExtensions.x-java-text-plain-string}} + {{^vendorExtensions.x-java-text-plain-string}} + return new ApiResponse<{{{returnType}}}{{^returnType}}Void{{/returnType}}>( + localVarResponse.statusCode(), + localVarResponse.headers().map(), + {{#returnType}} + localVarResponse.body() == null ? null : memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference<{{{returnType}}}>() {}) // closes the InputStream + {{/returnType}} + {{^returnType}} + null + {{/returnType}} + ); + {{/vendorExtensions.x-java-text-plain-string}} + } finally { + {{^returnType}} + // Drain the InputStream + while (localVarResponse.body().read() != -1) { + // Ignore + } + localVarResponse.body().close(); + {{/returnType}} + } + } catch (IOException e) { + throw new ApiException(e); + } + catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ApiException(e); + } {{/asyncNative}} + {{#asyncNative}} + try { + HttpRequest.Builder localVarRequestBuilder = {{operationId}}RequestBuilder({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + return memberVarHttpClient.sendAsync( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofString()).thenComposeAsync(localVarResponse -> { + if (memberVarAsyncResponseInterceptor != null) { + memberVarAsyncResponseInterceptor.accept(localVarResponse); + } + if (localVarResponse.statusCode()/ 100 != 2) { + return CompletableFuture.failedFuture(getApiException("{{operationId}}", localVarResponse)); + } + {{#returnType}} + try { + String responseBody = localVarResponse.body(); + return CompletableFuture.completedFuture( + new ApiResponse<{{{returnType}}}>( + localVarResponse.statusCode(), + localVarResponse.headers().map(), + responseBody == null || responseBody.isBlank() ? null : memberVarObjectMapper.readValue(responseBody, new TypeReference<{{{returnType}}}>() {})) + ); + } catch (IOException e) { + return CompletableFuture.failedFuture(new ApiException(e)); + } + {{/returnType}} + {{^returnType}} + return CompletableFuture.completedFuture( + new ApiResponse(localVarResponse.statusCode(), localVarResponse.headers().map(), null) + ); + {{/returnType}} + } + ); + } + catch (ApiException e) { + return CompletableFuture.failedFuture(e); + } + {{/asyncNative}} + } + + private HttpRequest.Builder {{operationId}}RequestBuilder({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { + {{#allParams}} + {{#required}} + // verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + throw new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{operationId}}"); } {{/required}} {{/allParams}} @@ -105,12 +343,43 @@ public class {{classname}} { localVarQueryParams.addAll(ApiClient.parameterToPairs("{{{collectionFormat}}}", "{{baseName}}", {{paramName}})); {{/collectionFormat}} {{^collectionFormat}} + {{#isDeepObject}} + if ({{paramName}} != null) { + {{#items.vars}} + {{#isArray}} + localVarQueryParams.addAll(ApiClient.parameterToPairs("csv", "{{paramName}}[{{name}}]", {{paramName}}.{{getter}}())); + {{/isArray}} + {{^isArray}} + localVarQueryParams.addAll(ApiClient.parameterToPairs("{{paramName}}[{{name}}]", {{paramName}}.{{getter}}())); + {{/isArray}} + {{/items.vars}} + } + {{/isDeepObject}} + {{^isDeepObject}} + {{#isExplode}} + {{#hasVars}} + {{#vars}} + {{#isArray}} + localVarQueryParams.addAll(ApiClient.parameterToPairs("multi", "{{baseName}}", {{paramName}}.{{getter}}())); + {{/isArray}} + {{^isArray}} + localVarQueryParams.addAll(ApiClient.parameterToPairs("{{baseName}}", {{paramName}}.{{getter}}())); + {{/isArray}} + {{/vars}} + {{/hasVars}} + {{^hasVars}} localVarQueryParams.addAll(ApiClient.parameterToPairs("{{baseName}}", {{paramName}})); + {{/hasVars}} + {{/isExplode}} + {{^isExplode}} + localVarQueryParams.addAll(ApiClient.parameterToPairs("{{baseName}}", {{paramName}})); + {{/isExplode}} + {{/isDeepObject}} {{/collectionFormat}} {{/queryParams}} if (!localVarQueryParams.isEmpty()) { - {{javaUtilPrefix}}StringJoiner queryJoiner = new StringJoiner("&"); + {{javaUtilPrefix}}StringJoiner queryJoiner = new {{javaUtilPrefix}}StringJoiner("&"); localVarQueryParams.forEach(p -> queryJoiner.add(p.getName() + '=' + p.getValue())); localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath + '?' + queryJoiner.toString())); } else { @@ -127,93 +396,84 @@ public class {{classname}} { } {{/headerParams}} {{#bodyParam}} - localVarRequestBuilder.header("Content-Type", "application/json"); + localVarRequestBuilder.header("Content-Type", "{{#hasConsumes}}{{#consumes}}{{#-first}}{{mediaType}}{{/-first}}{{/consumes}}{{/hasConsumes}}{{#hasConsumes}}{{^consumes}}application/json{{/consumes}}{{/hasConsumes}}{{^hasConsumes}}application/json{{/hasConsumes}}"); {{/bodyParam}} - localVarRequestBuilder.header("Accept", "application/json"); + localVarRequestBuilder.header("Accept", "{{#hasProduces}}{{#produces}}{{mediaType}}{{^-last}}, {{/-last}}{{/produces}}{{/hasProduces}}{{#hasProduces}}{{^produces}}application/json{{/produces}}{{/hasProduces}}{{^hasProduces}}application/json{{/hasProduces}}"); - {{^asyncNative}} - try { - {{/asyncNative}} - {{#asyncNative}} - {{#bodyParam}} + {{#bodyParam}} + {{#isString}} + localVarRequestBuilder.method("{{httpMethod}}", HttpRequest.BodyPublishers.ofString({{paramName}})); + {{/isString}} + {{^isString}} try { - {{/bodyParam}} - {{/asyncNative}} - {{#bodyParam}} byte[] localVarPostBody = memberVarObjectMapper.writeValueAsBytes({{paramName}}); localVarRequestBuilder.method("{{httpMethod}}", HttpRequest.BodyPublishers.ofByteArray(localVarPostBody)); - {{/bodyParam}} - {{^bodyParam}} - localVarRequestBuilder.method("{{httpMethod}}", HttpRequest.BodyPublishers.noBody()); - {{/bodyParam}} - if (memberVarReadTimeout != null) { - localVarRequestBuilder.timeout(memberVarReadTimeout); - } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); - } - {{^asyncNative}} - HttpResponse localVarResponse = memberVarHttpClient.send( - localVarRequestBuilder.build(), - HttpResponse.BodyHandlers.ofInputStream()); - if (memberVarResponseInterceptor != null) { - memberVarResponseInterceptor.accept(localVarResponse); - } - if (localVarResponse.statusCode()/ 100 != 2) { - throw new ApiException(localVarResponse.statusCode(), - "{{operationId}} call received non-success response", - localVarResponse.headers(), - localVarResponse.body() == null ? null : new String(localVarResponse.body().readAllBytes())); - } - {{#returnType}} - return memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference<{{{returnType}}}>() {}); - {{/returnType}} - {{/asyncNative}} - {{#asyncNative}} - return memberVarHttpClient.sendAsync( - localVarRequestBuilder.build(), - HttpResponse.BodyHandlers.ofString()).thenComposeAsync(localVarResponse -> { - if (localVarResponse.statusCode()/ 100 != 2) { - return CompletableFuture.failedFuture(new ApiException(localVarResponse.statusCode(), - "{{operationId}} call received non-success response", - localVarResponse.headers(), - localVarResponse.body()) - ); - } else { - try { - return CompletableFuture.completedFuture( - {{#returnType}} - memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference<{{{returnType}}}>() {}) - {{/returnType}} - {{^returnType}} - null - {{/returnType}} - ); - } catch (IOException e) { - return CompletableFuture.failedFuture(new ApiException(e)); - } - } - }); - {{/asyncNative}} - {{#asyncNative}} - {{#bodyParam}} } catch (IOException e) { - return CompletableFuture.failedFuture(new ApiException(e)); + throw new ApiException(e); } + {{/isString}} {{/bodyParam}} - {{/asyncNative}} - {{^asyncNative}} - } catch (IOException e) { - throw new ApiException(e); + {{^bodyParam}} + localVarRequestBuilder.method("{{httpMethod}}", HttpRequest.BodyPublishers.noBody()); + {{/bodyParam}} + if (memberVarReadTimeout != null) { + localVarRequestBuilder.timeout(memberVarReadTimeout); } - {{/asyncNative}} - {{^asyncNative}} - catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new ApiException(e); + if (memberVarInterceptor != null) { + memberVarInterceptor.accept(localVarRequestBuilder); } - {{/asyncNative}} + return localVarRequestBuilder; } + {{#vendorExtensions.x-group-parameters}} + {{#hasParams}} + + public static final class API{{operationId}}Request { + {{#requiredParams}} + private {{{dataType}}} {{paramName}}; // {{description}} (required) + {{/requiredParams}} + {{#optionalParams}} + private {{{dataType}}} {{paramName}}; // {{description}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/isContainer}} + {{/optionalParams}} + + private API{{operationId}}Request(Builder builder) { + {{#requiredParams}} + this.{{paramName}} = builder.{{paramName}}; + {{/requiredParams}} + {{#optionalParams}} + this.{{paramName}} = builder.{{paramName}}; + {{/optionalParams}} + } + {{#allParams}} + public {{{dataType}}} {{paramName}}() { + return {{paramName}}; + } + {{/allParams}} + public static Builder newBuilder() { + return new Builder(); + } + + public static class Builder { + {{#requiredParams}} + private {{{dataType}}} {{paramName}}; + {{/requiredParams}} + {{#optionalParams}} + private {{{dataType}}} {{paramName}}; + {{/optionalParams}} + + {{#allParams}} + public Builder {{paramName}}({{{dataType}}} {{paramName}}) { + this.{{paramName}} = {{paramName}}; + return this; + } + {{/allParams}} + public API{{operationId}}Request build() { + return new API{{operationId}}Request(this); + } + } + } + + {{/hasParams}} + {{/vendorExtensions.x-group-parameters}} {{/operation}} } {{/operations}} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/native/api_doc.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/native/api_doc.mustache new file mode 100644 index 000000000..474cb7954 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/native/api_doc.mustache @@ -0,0 +1,280 @@ +# {{classname}}{{#description}} + +{{.}}{{/description}} + +All URIs are relative to *{{basePath}}* + +| Method | HTTP request | Description | +|------------- | ------------- | -------------| +{{#operations}}{{#operation}}| [**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{summary}} | +| [**{{operationId}}WithHttpInfo**]({{classname}}.md#{{operationId}}WithHttpInfo) | **{{httpMethod}}** {{path}} | {{summary}} | +{{/operation}}{{/operations}} + +{{#operations}} +{{#operation}} + +## {{operationId}} + +{{^vendorExtensions.x-group-parameters}} +> {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}}{{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture{{/asyncNative}}{{^asyncNative}}void{{/asyncNative}}{{/returnType}} {{operationId}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}}) +{{/vendorExtensions.x-group-parameters}} +{{#vendorExtensions.x-group-parameters}} +> {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}}{{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture{{/asyncNative}}{{^asyncNative}}void{{/asyncNative}}{{/returnType}} {{operationId}}({{#hasParams}}{{operationId}}Request{{/hasParams}}) +{{/vendorExtensions.x-group-parameters}} + +{{summary}}{{#notes}} + +{{.}}{{/notes}} + +### Example + +```java +// Import classes: +import {{{invokerPackage}}}.ApiClient; +import {{{invokerPackage}}}.ApiException; +import {{{invokerPackage}}}.Configuration;{{#hasAuthMethods}} +import {{{invokerPackage}}}.auth.*;{{/hasAuthMethods}} +import {{{invokerPackage}}}.models.*; +import {{{package}}}.{{{classname}}};{{#vendorExtensions.x-group-parameters}} +import {{{package}}}.{{{classname}}}.*;{{/vendorExtensions.x-group-parameters}} +{{#asyncNative}} +import java.util.concurrent.CompletableFuture; +{{/asyncNative}} + +public class Example { + public static void main(String[] args) { + ApiClient defaultClient = Configuration.getDefaultApiClient(); + defaultClient.setBasePath("{{{basePath}}}"); + {{#hasAuthMethods}} + {{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + // Configure HTTP basic authorization: {{{name}}} + HttpBasicAuth {{{name}}} = (HttpBasicAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setUsername("YOUR USERNAME"); + {{{name}}}.setPassword("YOUR PASSWORD");{{/isBasicBasic}}{{#isBasicBearer}} + // Configure HTTP bearer authorization: {{{name}}} + HttpBearerAuth {{{name}}} = (HttpBearerAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setBearerToken("BEARER TOKEN");{{/isBasicBearer}}{{/isBasic}}{{#isApiKey}} + // Configure API key authorization: {{{name}}} + ApiKeyAuth {{{name}}} = (ApiKeyAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setApiKey("YOUR API KEY"); + // Uncomment the following line to set a prefix for the API key, e.g. "Token" (defaults to null) + //{{{name}}}.setApiKeyPrefix("Token");{{/isApiKey}}{{#isOAuth}} + // Configure OAuth2 access token for authorization: {{{name}}} + OAuth {{{name}}} = (OAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setAccessToken("YOUR ACCESS TOKEN");{{/isOAuth}} + {{/authMethods}} + {{/hasAuthMethods}} + + {{{classname}}} apiInstance = new {{{classname}}}(defaultClient); + {{#allParams}} + {{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} + {{/allParams}} + try { + {{^vendorExtensions.x-group-parameters}} + {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}} result = {{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture result = {{/asyncNative}}{{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}}); + {{/vendorExtensions.x-group-parameters}} + {{#vendorExtensions.x-group-parameters}} + {{#hasParams}} + API{{operationId}}Request request = API{{operationId}}Request.newBuilder(){{#allParams}} + .{{paramName}}({{paramName}}){{/allParams}} + .build(); + {{/hasParams}} + {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}} result = {{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture result = {{/asyncNative}}{{/returnType}}apiInstance.{{operationId}}({{#hasParams}}request{{/hasParams}}); + {{/vendorExtensions.x-group-parameters}} + {{#returnType}} + System.out.println(result{{#asyncNative}}.get(){{/asyncNative}}); + {{/returnType}} + } catch (ApiException e) { + System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); + System.err.println("Status code: " + e.getCode()); + System.err.println("Reason: " + e.getResponseBody()); + System.err.println("Response headers: " + e.getResponseHeaders()); + e.printStackTrace(); + } + } +} +``` + +### Parameters + +{{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{^vendorExtensions.x-group-parameters}}{{#allParams}}{{#-last}} +| Name | Type | Description | Notes | +|------------- | ------------- | ------------- | -------------|{{/-last}}{{/allParams}} +{{#allParams}}| **{{paramName}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}[**{{dataType}}**]({{baseType}}.md){{/isFile}}{{/isPrimitiveType}}| {{description}} |{{^required}} [optional]{{/required}}{{^isContainer}}{{#defaultValue}} [default to {{.}}]{{/defaultValue}}{{/isContainer}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}} | +{{/allParams}} +{{/vendorExtensions.x-group-parameters}} +{{#vendorExtensions.x-group-parameters}} +{{#hasParams}} +| Name | Type | Description | Notes | +|------------- | ------------- | ------------- | -------------| +| {{operationId}}Request | [**API{{operationId}}Request**]({{classname}}.md#API{{operationId}}Request)|-|-|{{/hasParams}} +{{/vendorExtensions.x-group-parameters}} + +### Return type + +{{#returnType}}{{#asyncNative}}CompletableFuture<{{/asyncNative}}{{#returnTypeIsPrimitive}}**{{returnType}}**{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}[**{{returnType}}**]({{returnBaseType}}.md){{/returnTypeIsPrimitive}}{{#asyncNative}}>{{/asyncNative}}{{/returnType}} +{{^returnType}}{{#asyncNative}}CompletableFuture{{/asyncNative}}{{^asyncNative}}null{{/asyncNative}} (empty response body){{/returnType}} + +### Authorization + +{{^authMethods}}No authorization required{{/authMethods}}{{#authMethods}}[{{name}}](../README.md#{{name}}){{^-last}}, {{/-last}}{{/authMethods}} + +### HTTP request headers + +- **Content-Type**: {{#consumes}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} +- **Accept**: {{#produces}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/produces}}{{^produces}}Not defined{{/produces}} + +{{#responses.0}} +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +{{#responses}} +| **{{code}}** | {{message}} | {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}} | +{{/responses}} +{{/responses.0}} + +## {{operationId}}WithHttpInfo + +{{^vendorExtensions.x-group-parameters}} +> {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{{returnType}}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} {{operationId}} {{operationId}}WithHttpInfo({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}}) +{{/vendorExtensions.x-group-parameters}} +{{#vendorExtensions.x-group-parameters}} +> {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{{returnType}}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} {{operationId}} {{operationId}}WithHttpInfo({{#hasParams}}{{operationId}}Request{{/hasParams}}) +{{/vendorExtensions.x-group-parameters}} + +{{summary}}{{#notes}} + +{{.}}{{/notes}} + +### Example + +```java +// Import classes: +import {{{invokerPackage}}}.ApiClient; +import {{{invokerPackage}}}.ApiException; +import {{{invokerPackage}}}.ApiResponse; +import {{{invokerPackage}}}.Configuration;{{#hasAuthMethods}} +import {{{invokerPackage}}}.auth.*;{{/hasAuthMethods}} +import {{{invokerPackage}}}.models.*; +import {{{package}}}.{{{classname}}};{{#vendorExtensions.x-group-parameters}} +import {{{package}}}.{{{classname}}}.*;{{/vendorExtensions.x-group-parameters}} +{{#asyncNative}} +import java.util.concurrent.CompletableFuture; +{{/asyncNative}} + +public class Example { + public static void main(String[] args) { + ApiClient defaultClient = Configuration.getDefaultApiClient(); + defaultClient.setBasePath("{{{basePath}}}"); + {{#hasAuthMethods}} + {{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + // Configure HTTP basic authorization: {{{name}}} + HttpBasicAuth {{{name}}} = (HttpBasicAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setUsername("YOUR USERNAME"); + {{{name}}}.setPassword("YOUR PASSWORD");{{/isBasicBasic}}{{#isBasicBearer}} + // Configure HTTP bearer authorization: {{{name}}} + HttpBearerAuth {{{name}}} = (HttpBearerAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setBearerToken("BEARER TOKEN");{{/isBasicBearer}}{{/isBasic}}{{#isApiKey}} + // Configure API key authorization: {{{name}}} + ApiKeyAuth {{{name}}} = (ApiKeyAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setApiKey("YOUR API KEY"); + // Uncomment the following line to set a prefix for the API key, e.g. "Token" (defaults to null) + //{{{name}}}.setApiKeyPrefix("Token");{{/isApiKey}}{{#isOAuth}} + // Configure OAuth2 access token for authorization: {{{name}}} + OAuth {{{name}}} = (OAuth) defaultClient.getAuthentication("{{{name}}}"); + {{{name}}}.setAccessToken("YOUR ACCESS TOKEN");{{/isOAuth}} + {{/authMethods}} + {{/hasAuthMethods}} + + {{{classname}}} apiInstance = new {{{classname}}}(defaultClient); + {{#allParams}} + {{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} + {{/allParams}} + try { + {{^vendorExtensions.x-group-parameters}} + {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{{returnType}}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} response = apiInstance.{{{operationId}}}WithHttpInfo({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}}); + {{/vendorExtensions.x-group-parameters}} + {{#vendorExtensions.x-group-parameters}} + {{#hasParams}} + API{{operationId}}Request request = API{{operationId}}Request.newBuilder(){{#allParams}} + .{{paramName}}({{paramName}}){{/allParams}} + .build(); + {{/hasParams}} + {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{{returnType}}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} response = apiInstance.{{{operationId}}}WithHttpInfo({{#hasParams}}request{{/hasParams}}); + {{/vendorExtensions.x-group-parameters}} + System.out.println("Status code: " + response{{#asyncNative}}.get(){{/asyncNative}}.getStatusCode()); + System.out.println("Response headers: " + response{{#asyncNative}}.get(){{/asyncNative}}.getHeaders()); + {{#returnType}} + System.out.println("Response body: " + response{{#asyncNative}}.get(){{/asyncNative}}.getData()); + {{/returnType}} + {{#asyncNative}} + } catch (InterruptedException | ExecutionException e) { + ApiException apiException = (ApiException)e.getCause(); + System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); + System.err.println("Status code: " + apiException.getCode()); + System.err.println("Response headers: " + apiException.getResponseHeaders()); + System.err.println("Reason: " + apiException.getResponseBody()); + e.printStackTrace(); + {{/asyncNative}} + } catch (ApiException e) { + System.err.println("Exception when calling {{{classname}}}#{{{operationId}}}"); + System.err.println("Status code: " + e.getCode()); + System.err.println("Response headers: " + e.getResponseHeaders()); + System.err.println("Reason: " + e.getResponseBody()); + e.printStackTrace(); + } + } +} +``` + +### Parameters + +{{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{^vendorExtensions.x-group-parameters}}{{#allParams}}{{#-last}} +| Name | Type | Description | Notes | +|------------- | ------------- | ------------- | -------------|{{/-last}}{{/allParams}} +{{#allParams}}| **{{paramName}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}[**{{dataType}}**]({{baseType}}.md){{/isFile}}{{/isPrimitiveType}}| {{description}} |{{^required}} [optional]{{/required}}{{^isContainer}}{{#defaultValue}} [default to {{.}}]{{/defaultValue}}{{/isContainer}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}} | +{{/allParams}} +{{/vendorExtensions.x-group-parameters}} +{{#vendorExtensions.x-group-parameters}} +{{#hasParams}} +| Name | Type | Description | Notes | +|------------- | ------------- | ------------- | -------------| +| {{operationId}}Request | [**API{{operationId}}Request**]({{classname}}.md#API{{operationId}}Request)|-|-|{{/hasParams}} +{{/vendorExtensions.x-group-parameters}} + +### Return type + +{{#returnType}}{{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{#returnTypeIsPrimitive}}**{{returnType}}**{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}[**{{returnType}}**]({{returnBaseType}}.md){{/returnTypeIsPrimitive}}>{{#asyncNative}}>{{/asyncNative}}{{/returnType}} +{{^returnType}}{{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse{{#asyncNative}}>{{/asyncNative}}{{/returnType}} + +### Authorization + +{{^authMethods}}No authorization required{{/authMethods}}{{#authMethods}}[{{name}}](../README.md#{{name}}){{^-last}}, {{/-last}}{{/authMethods}} + +### HTTP request headers + +- **Content-Type**: {{#consumes}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} +- **Accept**: {{#produces}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/produces}}{{^produces}}Not defined{{/produces}} + +{{#responses.0}} +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +{{#responses}} +| **{{code}}** | {{message}} | {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}} | +{{/responses}} +{{/responses.0}} +{{#vendorExtensions.x-group-parameters}}{{#hasParams}} + + +## API{{operationId}}Request +### Properties +{{#allParams}}{{#-last}} +| Name | Type | Description | Notes | +| ------------- | ------------- | ------------- | -------------|{{/-last}}{{/allParams}} +{{#allParams}}| **{{paramName}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}[**{{dataType}}**]({{baseType}}.md){{/isFile}}{{/isPrimitiveType}} | {{description}} |{{^required}} [optional]{{/required}}{{^isContainer}}{{#defaultValue}} [default to {{.}}]{{/defaultValue}}{{/isContainer}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}} | +{{/allParams}} + +{{/hasParams}}{{/vendorExtensions.x-group-parameters}} +{{/operation}} +{{/operations}} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/native/api_test.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/native/api_test.mustache new file mode 100644 index 000000000..ffcf05ec3 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/native/api_test.mustache @@ -0,0 +1,60 @@ +{{>licenseInfo}} + +package {{package}}; + +import {{invokerPackage}}.ApiException; +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.Test; +import org.junit.Ignore; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +{{/fullJavaUtil}} + +{{#asyncNative}} +import java.util.concurrent.CompletableFuture; +{{/asyncNative}} + +/** + * API tests for {{classname}} + */ +@Ignore +public class {{classname}}Test { + + private final {{classname}} api = new {{classname}}(); + + {{#operations}}{{#operation}} + /** + * {{summary}} + * + * {{notes}} + * + * @throws ApiException + * if the Api call fails + */ + @Test + public void {{operationId}}Test() throws ApiException { + {{#allParams}} + {{{dataType}}} {{paramName}} = null; + {{/allParams}} + {{^vendorExtensions.x-group-parameters}} + {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}} response = {{/returnType}} + {{^returnType}}{{#asyncNative}}CompletableFuture response = {{/asyncNative}}{{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + {{/vendorExtensions.x-group-parameters}} + {{#vendorExtensions.x-group-parameters}}{{#hasParams}} + {{classname}}.API{{operationId}}Request request = {{classname}}.API{{operationId}}Request.newBuilder(){{#allParams}} + .{{paramName}}({{paramName}}){{/allParams}} + .build();{{/hasParams}} + {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}} response = {{/returnType}} + {{^returnType}}{{#asyncNative}}CompletableFuture response = {{/asyncNative}}{{/returnType}}api.{{operationId}}({{#hasParams}}request{{/hasParams}}); + {{/vendorExtensions.x-group-parameters}} + + // TODO: test validations + } + {{/operation}}{{/operations}} +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/native/build.gradle.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/native/build.gradle.mustache index cea6681a9..a7ae19850 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/native/build.gradle.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/native/build.gradle.mustache @@ -6,25 +6,37 @@ version = '{{artifactVersion}}' buildscript { repositories { - maven { url "https://repo1.maven.org/maven2" } - jcenter() + mavenCentral() } } repositories { - maven { url "https://repo1.maven.org/maven2" } - jcenter() + mavenCentral() } apply plugin: 'java' -apply plugin: 'maven' +apply plugin: 'maven-publish' sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 -install { - repositories.mavenInstaller { - pom.artifactId = '{{artifactId}}' +// Some text from the schema is copy pasted into the source files as UTF-8 +// but the default still seems to be to use platform encoding +tasks.withType(JavaCompile) { + configure(options) { + options.encoding = 'UTF-8' + } +} +javadoc { + options.encoding = 'UTF-8' +} + +publishing { + publications { + maven(MavenPublication) { + artifactId = '{{artifactId}}' + from components.java + } } } @@ -50,17 +62,24 @@ artifacts { ext { - swagger_annotations_version = "1.5.22" - jackson_version = "2.9.9" - junit_version = "4.13" + {{#swagger1AnnotationLibrary}} + swagger_annotations_version = "1.6.9" + {{/swagger1AnnotationLibrary}} + jackson_version = "2.14.1" + jakarta_annotation_version = "1.3.5" + junit_version = "4.13.2" } dependencies { - compile "io.swagger:swagger-annotations:$swagger_annotations_version" - compile "com.google.code.findbugs:jsr305:3.0.2" - compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version" - compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" - testCompile "junit:junit:$junit_version" + {{#swagger1AnnotationLibrary}} + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + {{/swagger1AnnotationLibrary}} + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation "com.fasterxml.jackson.core:jackson-core:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-databind:$jackson_version" + implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + implementation "org.openapitools:jackson-databind-nullable:0.2.1" + implementation "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version" + testImplementation "junit:junit:$junit_version" } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/native/generatedAnnotation.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/native/generatedAnnotation.mustache index dc1f2cd40..baf5ff08b 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/native/generatedAnnotation.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/native/generatedAnnotation.mustache @@ -1 +1 @@ -{{^hideGenerationTimestamp}}@javax.annotation.processing.Generated(value = "{{generatorClass}}", date = "{{generatedDate}}"){{/hideGenerationTimestamp}} \ No newline at end of file +@javax.annotation.processing.Generated(value = "{{generatorClass}}"{{^hideGenerationTimestamp}}, date = "{{generatedDate}}"{{/hideGenerationTimestamp}}) \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/model.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/native/model.mustache similarity index 68% rename from boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/model.mustache rename to boat-scaffold/src/main/templates/boat-java/libraries/native/model.mustache index 02787f8bb..6f2436c38 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/model.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/native/model.mustache @@ -6,13 +6,20 @@ package {{package}}; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; {{/useReflectionEqualsHashCode}} -{{^supportJava6}} +{{#models}} +{{#model}} +{{#additionalPropertiesType}} +import java.util.Map; +import java.util.HashMap; +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +{{/additionalPropertiesType}} +{{/model}} +{{/models}} import java.util.Objects; import java.util.Arrays; -{{/supportJava6}} -{{#supportJava6}} -import org.apache.commons.lang3.ObjectUtils; -{{/supportJava6}} +import java.util.Map; +import java.util.HashMap; {{#imports}} import {{import}}; {{/imports}} @@ -24,6 +31,9 @@ import com.fasterxml.jackson.annotation.JsonPropertyOrder; {{#withXml}} import com.fasterxml.jackson.dataformat.xml.annotation.*; {{/withXml}} +{{#vendorExtensions.x-has-readonly-properties}} +import com.fasterxml.jackson.annotation.JsonCreator; +{{/vendorExtensions.x-has-readonly-properties}} {{/jackson}} {{#withXml}} import javax.xml.bind.annotation.*; @@ -42,6 +52,12 @@ import org.hibernate.validator.constraints.*; {{#models}} {{#model}} +{{#oneOf}} +{{#-first}} +import com.fasterxml.jackson.core.type.TypeReference; +{{/-first}} +{{/oneOf}} + {{#isEnum}}{{>modelEnum}}{{/isEnum}}{{^isEnum}}{{#oneOf}}{{#-first}}{{>oneof_model}}{{/-first}}{{/oneOf}}{{^oneOf}}{{#anyOf}}{{#-first}}{{>anyof_model}}{{/-first}}{{/anyOf}}{{^anyOf}}{{>pojo}}{{/anyOf}}{{/oneOf}}{{/isEnum}} {{/model}} {{/models}} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/native/model_anyof_doc.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/native/model_anyof_doc.mustache new file mode 100644 index 000000000..e360aa56e --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/native/model_anyof_doc.mustache @@ -0,0 +1,38 @@ +# {{classname}} + +{{#description}} +{{&description}} + +{{/description}} +## anyOf schemas +{{#anyOf}} +* [{{{.}}}]({{{.}}}.md) +{{/anyOf}} + +{{#isNullable}} +NOTE: this class is nullable. + +{{/isNullable}} +## Example +```java +// Import classes: +import {{{package}}}.{{{classname}}}; +{{#anyOf}} +import {{{package}}}.{{{.}}}; +{{/anyOf}} + +public class Example { + public static void main(String[] args) { + {{classname}} example{{classname}} = new {{classname}}(); + {{#anyOf}} + + // create a new {{{.}}} + {{{.}}} example{{{.}}} = new {{{.}}}(); + // set {{{classname}}} to {{{.}}} + example{{classname}}.setActualInstance(example{{{.}}}); + // to get back the {{{.}}} set earlier + {{{.}}} test{{{.}}} = ({{{.}}}) example{{classname}}.getActualInstance(); + {{/anyOf}} + } +} +``` diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/native/model_doc.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/native/model_doc.mustache new file mode 100644 index 000000000..be1aedcf2 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/native/model_doc.mustache @@ -0,0 +1,19 @@ +{{#models}}{{#model}} + +{{#isEnum}} +{{>enum_outer_doc}} +{{/isEnum}} +{{^isEnum}} +{{^oneOf.isEmpty}} +{{>model_oneof_doc}} +{{/oneOf.isEmpty}} +{{^anyOf.isEmpty}} +{{>model_anyof_doc}} +{{/anyOf.isEmpty}} +{{^anyOf}} +{{^oneOf}} +{{>pojo_doc}} +{{/oneOf}} +{{/anyOf}} +{{/isEnum}} +{{/model}}{{/models}} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/native/model_oneof_doc.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/native/model_oneof_doc.mustache new file mode 100644 index 000000000..5fff76c9e --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/native/model_oneof_doc.mustache @@ -0,0 +1,38 @@ +# {{classname}} + +{{#description}} +{{&description}} + +{{/description}} +## oneOf schemas +{{#oneOf}} +* [{{{.}}}]({{{.}}}.md) +{{/oneOf}} + +{{#isNullable}} +NOTE: this class is nullable. + +{{/isNullable}} +## Example +```java +// Import classes: +import {{{package}}}.{{{classname}}}; +{{#oneOf}} +import {{{package}}}.{{{.}}}; +{{/oneOf}} + +public class Example { + public static void main(String[] args) { + {{classname}} example{{classname}} = new {{classname}}(); + {{#oneOf}} + + // create a new {{{.}}} + {{{.}}} example{{{.}}} = new {{{.}}}(); + // set {{{classname}}} to {{{.}}} + example{{classname}}.setActualInstance(example{{{.}}}); + // to get back the {{{.}}} set earlier + {{{.}}} test{{{.}}} = ({{{.}}}) example{{classname}}.getActualInstance(); + {{/oneOf}} + } +} +``` diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/native/oneof_model.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/native/oneof_model.mustache new file mode 100644 index 000000000..ae48daf75 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/native/oneof_model.mustache @@ -0,0 +1,231 @@ +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.MapperFeature; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import {{invokerPackage}}.JSON; + +{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>xmlAnnotation}} +@JsonDeserialize(using = {{classname}}.{{classname}}Deserializer.class) +@JsonSerialize(using = {{classname}}.{{classname}}Serializer.class) +public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-implements}}, {{{.}}}{{/vendorExtensions.x-implements}} { + private static final Logger log = Logger.getLogger({{classname}}.class.getName()); + + public static class {{classname}}Serializer extends StdSerializer<{{classname}}> { + public {{classname}}Serializer(Class<{{classname}}> t) { + super(t); + } + + public {{classname}}Serializer() { + this(null); + } + + @Override + public void serialize({{classname}} value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { + jgen.writeObject(value.getActualInstance()); + } + } + + public static class {{classname}}Deserializer extends StdDeserializer<{{classname}}> { + public {{classname}}Deserializer() { + this({{classname}}.class); + } + + public {{classname}}Deserializer(Class vc) { + super(vc); + } + + @Override + public {{classname}} deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { + JsonNode tree = jp.readValueAsTree(); + Object deserialized = null; + {{#useOneOfDiscriminatorLookup}} + {{#discriminator}} + {{classname}} new{{classname}} = new {{classname}}(); + Map result2 = tree.traverse(jp.getCodec()).readValueAs(new TypeReference>() {}); + String discriminatorValue = (String)result2.get("{{{propertyBaseName}}}"); + switch (discriminatorValue) { + {{#mappedModels}} + case "{{{mappingName}}}": + deserialized = tree.traverse(jp.getCodec()).readValueAs({{{modelName}}}.class); + new{{classname}}.setActualInstance(deserialized); + return new{{classname}}; + {{/mappedModels}} + default: + log.log(Level.WARNING, String.format("Failed to lookup discriminator value `%s` for {{classname}}. Possible values:{{#mappedModels}} {{{mappingName}}}{{/mappedModels}}", discriminatorValue)); + } + + {{/discriminator}} + {{/useOneOfDiscriminatorLookup}} + boolean typeCoercion = ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS); + int match = 0; + JsonToken token = tree.traverse(jp.getCodec()).nextToken(); + {{#oneOf}} + // deserialize {{{.}}} + try { + boolean attemptParsing = true; + // ensure that we respect type coercion as set on the client ObjectMapper + if ({{{.}}}.class.equals(Integer.class) || {{{.}}}.class.equals(Long.class) || {{{.}}}.class.equals(Float.class) || {{{.}}}.class.equals(Double.class) || {{{.}}}.class.equals(Boolean.class) || {{{.}}}.class.equals(String.class)) { + attemptParsing = typeCoercion; + if (!attemptParsing) { + attemptParsing |= (({{{.}}}.class.equals(Integer.class) || {{{.}}}.class.equals(Long.class)) && token == JsonToken.VALUE_NUMBER_INT); + attemptParsing |= (({{{.}}}.class.equals(Float.class) || {{{.}}}.class.equals(Double.class)) && token == JsonToken.VALUE_NUMBER_FLOAT); + attemptParsing |= ({{{.}}}.class.equals(Boolean.class) && (token == JsonToken.VALUE_FALSE || token == JsonToken.VALUE_TRUE)); + attemptParsing |= ({{{.}}}.class.equals(String.class) && token == JsonToken.VALUE_STRING); + {{#isNullable}} + attemptParsing |= (token == JsonToken.VALUE_NULL); + {{/isNullable}} + } + } + if (attemptParsing) { + deserialized = tree.traverse(jp.getCodec()).readValueAs({{{.}}}.class); + // TODO: there is no validation against JSON schema constraints + // (min, max, enum, pattern...), this does not perform a strict JSON + // validation, which means the 'match' count may be higher than it should be. + match++; + log.log(Level.FINER, "Input data matches schema '{{{.}}}'"); + } + } catch (Exception e) { + // deserialization failed, continue + log.log(Level.FINER, "Input data does not match schema '{{{.}}}'", e); + } + + {{/oneOf}} + if (match == 1) { + {{classname}} ret = new {{classname}}(); + ret.setActualInstance(deserialized); + return ret; + } + throw new IOException(String.format("Failed deserialization for {{classname}}: %d classes match result, expected 1", match)); + } + + /** + * Handle deserialization of the 'null' value. + */ + @Override + public {{classname}} getNullValue(DeserializationContext ctxt) throws JsonMappingException { + {{#isNullable}} + return null; + {{/isNullable}} + {{^isNullable}} + throw new JsonMappingException(ctxt.getParser(), "{{classname}} cannot be null"); + {{/isNullable}} + } + } + + // store a list of schema names defined in oneOf + public static final Map> schemas = new HashMap<>(); + + public {{classname}}() { + super("oneOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); + } +{{> libraries/native/additional_properties }} + {{#additionalPropertiesType}} + /** + * Return true if this {{name}} object is equal to o. + */ + @Override + public boolean equals(Object o) { + return super.equals(o) && Objects.equals(this.additionalProperties, (({{classname}})o).additionalProperties); + } + + @Override + public int hashCode() { + return Objects.hash(getActualInstance(), isNullable(), getSchemaType(), additionalProperties); + } + {{/additionalPropertiesType}} + {{#oneOf}} + public {{classname}}({{{.}}} o) { + super("oneOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); + setActualInstance(o); + } + + {{/oneOf}} + static { + {{#oneOf}} + schemas.put("{{{.}}}", {{{.}}}.class); + {{/oneOf}} + JSON.registerDescendants({{classname}}.class, Collections.unmodifiableMap(schemas)); + {{#discriminator}} + // Initialize and register the discriminator mappings. + Map> mappings = new HashMap>(); + {{#mappedModels}} + mappings.put("{{mappingName}}", {{modelName}}.class); + {{/mappedModels}} + mappings.put("{{name}}", {{classname}}.class); + JSON.registerDiscriminator({{classname}}.class, "{{propertyBaseName}}", mappings); + {{/discriminator}} + } + + @Override + public Map> getSchemas() { + return {{classname}}.schemas; + } + + /** + * Set the instance that matches the oneOf child schema, check + * the instance parameter is valid against the oneOf child schemas: + * {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}} + * + * It could be an instance of the 'oneOf' schemas. + * The oneOf child schemas may themselves be a composed schema (allOf, anyOf, oneOf). + */ + @Override + public void setActualInstance(Object instance) { + {{#isNullable}} + if (instance == null) { + super.setActualInstance(instance); + return; + } + + {{/isNullable}} + {{#oneOf}} + if (JSON.isInstanceOf({{{.}}}.class, instance, new HashSet>())) { + super.setActualInstance(instance); + return; + } + + {{/oneOf}} + throw new RuntimeException("Invalid instance type. Must be {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}"); + } + + /** + * Get the actual instance, which can be the following: + * {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}} + * + * @return The actual instance ({{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}) + */ + @Override + public Object getActualInstance() { + return super.getActualInstance(); + } + + {{#oneOf}} + /** + * Get the actual instance of `{{{.}}}`. If the actual instance is not `{{{.}}}`, + * the ClassCastException will be thrown. + * + * @return The actual instance of `{{{.}}}` + * @throws ClassCastException if the instance is not `{{{.}}}` + */ + public {{{.}}} get{{{.}}}() throws ClassCastException { + return ({{{.}}})super.getActualInstance(); + } + + {{/oneOf}} +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/native/pojo.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/native/pojo.mustache new file mode 100644 index 000000000..8243f68c8 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/native/pojo.mustache @@ -0,0 +1,422 @@ +{{#discriminator}} +import {{invokerPackage}}.JSON; +{{/discriminator}} +/** + * {{description}}{{^description}}{{classname}}{{/description}}{{#isDeprecated}} + * @deprecated{{/isDeprecated}} + */{{#isDeprecated}} +@Deprecated{{/isDeprecated}} +{{#swagger1AnnotationLibrary}} +{{#description}} +@ApiModel(description = "{{{.}}}") +{{/description}} +{{/swagger1AnnotationLibrary}} +{{#jackson}} +@JsonPropertyOrder({ +{{#vars}} + {{classname}}.JSON_PROPERTY_{{nameInSnakeCase}}{{^-last}},{{/-last}} +{{/vars}} +}) +{{/jackson}} +{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}} +{{#vendorExtensions.x-class-extra-annotation}} +{{{vendorExtensions.x-class-extra-annotation}}} +{{/vendorExtensions.x-class-extra-annotation}} +public class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{{#vendorExtensions.x-implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{#-last}} {{/-last}}{{/vendorExtensions.x-implements}}{ +{{#serializableModel}} + private static final long serialVersionUID = 1L; + +{{/serializableModel}} + {{#vars}} + {{#isEnum}} + {{^isContainer}} + {{^vendorExtensions.x-enum-as-string}} +{{>modelInnerEnum}} + {{/vendorExtensions.x-enum-as-string}} + {{/isContainer}} + {{#isContainer}} + {{#mostInnerItems}} +{{>modelInnerEnum}} + {{/mostInnerItems}} + {{/isContainer}} + {{/isEnum}} + {{#gson}} + public static final String SERIALIZED_NAME_{{nameInSnakeCase}} = "{{baseName}}"; + {{/gson}} + {{#jackson}} + public static final String JSON_PROPERTY_{{nameInSnakeCase}} = "{{baseName}}"; + {{/jackson}} + {{#withXml}} + {{#isXmlAttribute}} + @XmlAttribute(name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isXmlAttribute}} + {{^isXmlAttribute}} + {{^isContainer}} + @XmlElement({{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isContainer}} + {{#isContainer}} + // Is a container wrapped={{isXmlWrapped}} + {{#items}} + // items.name={{name}} items.baseName={{baseName}} items.xmlName={{xmlName}} items.xmlNamespace={{xmlNamespace}} + // items.example={{example}} items.type={{dataType}} + @XmlElement({{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/items}} + {{#isXmlWrapped}} + @XmlElementWrapper({{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isXmlWrapped}} + {{/isContainer}} + {{/isXmlAttribute}} + {{/withXml}} + {{#gson}} + @SerializedName(SERIALIZED_NAME_{{nameInSnakeCase}}) + {{/gson}} + {{#vendorExtensions.x-field-extra-annotation}} + {{{vendorExtensions.x-field-extra-annotation}}} + {{/vendorExtensions.x-field-extra-annotation}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} + {{#isContainer}} + private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>undefined(); + {{/isContainer}} + {{^isContainer}} + private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}}; + {{/isContainer}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + {{#isContainer}} + private {{{datatypeWithEnum}}} {{name}}{{#required}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/required}}{{^required}} = null{{/required}}; + {{/isContainer}} + {{^isContainer}} + private {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}; + {{/isContainer}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} + + {{/vars}} + public {{classname}}() { {{#parent}}{{#parcelableModel}} + super();{{/parcelableModel}}{{/parent}}{{#gson}}{{#discriminator}} + this.{{{discriminatorName}}} = this.getClass().getSimpleName();{{/discriminator}}{{/gson}} + }{{#vendorExtensions.x-has-readonly-properties}}{{^withXml}} + + {{#jackson}}@JsonCreator{{/jackson}} + public {{classname}}( + {{#readOnlyVars}} + @JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}}) {{{datatypeWithEnum}}} {{name}}{{^-last}}, {{/-last}} + {{/readOnlyVars}} + ) { + this(); + {{#readOnlyVars}} + this.{{name}} = {{#vendorExtensions.x-is-jackson-optional-nullable}}{{name}} == null ? JsonNullable.<{{{datatypeWithEnum}}}>undefined() : JsonNullable.of({{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{name}}{{/vendorExtensions.x-is-jackson-optional-nullable}}; + {{/readOnlyVars}} + }{{/withXml}}{{/vendorExtensions.x-has-readonly-properties}} + {{#vars}} + + {{^isReadOnly}} + {{#vendorExtensions.x-enum-as-string}} + public static final Set {{{nameInSnakeCase}}}_VALUES = new HashSet<>(Arrays.asList( + {{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}} + )); + + {{/vendorExtensions.x-enum-as-string}} + public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) { + {{#vendorExtensions.x-enum-as-string}} + if (!{{{nameInSnakeCase}}}_VALUES.contains({{name}})) { + throw new IllegalArgumentException({{name}} + " is invalid. Possible values for {{name}}: " + String.join(", ", {{{nameInSnakeCase}}}_VALUES)); + } + + {{/vendorExtensions.x-enum-as-string}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}}); + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = {{name}}; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + return this; + } + {{#isArray}} + + public {{classname}} add{{nameInCamelCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + if (this.{{name}} == null || !this.{{name}}.isPresent()) { + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}); + } + try { + this.{{name}}.get().add({{name}}Item); + } catch (java.util.NoSuchElementException e) { + // this can never happen, as we make sure above that the value is present + } + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + {{^required}} + if (this.{{name}} == null) { + this.{{name}} = {{{defaultValue}}}; + } + {{/required}} + this.{{name}}.add({{name}}Item); + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + {{/isArray}} + {{#isMap}} + + public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + if (this.{{name}} == null || !this.{{name}}.isPresent()) { + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}); + } + try { + this.{{name}}.get().put(key, {{name}}Item); + } catch (java.util.NoSuchElementException e) { + // this can never happen, as we make sure above that the value is present + } + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + {{^required}} + if (this.{{name}} == null) { + this.{{name}} = {{{defaultValue}}}; + } + {{/required}} + this.{{name}}.put(key, {{name}}Item); + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + {{/isMap}} + + {{/isReadOnly}} + /** + {{#description}} + * {{.}} + {{/description}} + {{^description}} + * Get {{name}} + {{/description}} + {{#minimum}} + * minimum: {{.}} + {{/minimum}} + {{#maximum}} + * maximum: {{.}} + {{/maximum}} + * @return {{name}} + {{#deprecated}} + * @deprecated + {{/deprecated}} + **/ +{{#deprecated}} + @Deprecated +{{/deprecated}} +{{#required}} +{{#isNullable}} + @javax.annotation.Nullable +{{/isNullable}} +{{^isNullable}} + @javax.annotation.Nonnull +{{/isNullable}} +{{/required}} +{{^required}} + @javax.annotation.Nullable +{{/required}} +{{#useBeanValidation}} +{{>beanValidation}} +{{/useBeanValidation}} +{{#swagger1AnnotationLibrary}} + @ApiModelProperty({{#example}}example = "{{{.}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}") +{{/swagger1AnnotationLibrary}} +{{#vendorExtensions.x-extra-annotation}} + {{{vendorExtensions.x-extra-annotation}}} +{{/vendorExtensions.x-extra-annotation}} +{{#vendorExtensions.x-is-jackson-optional-nullable}} + {{!unannotated, Jackson would pick this up automatically and add it *in addition* to the _JsonNullable getter field}} + @JsonIgnore +{{/vendorExtensions.x-is-jackson-optional-nullable}} +{{^vendorExtensions.x-is-jackson-optional-nullable}}{{#jackson}}{{> jackson_annotations}}{{/jackson}}{{/vendorExtensions.x-is-jackson-optional-nullable}} + public {{{datatypeWithEnum}}} {{getter}}() { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + {{#isReadOnly}}{{! A readonly attribute doesn't have setter => jackson will set null directly if explicitly returned by API, so make sure we have an empty JsonNullable}} + if ({{name}} == null) { + {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}}; + } + {{/isReadOnly}} + return {{name}}.orElse(null); + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + return {{name}}; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + + {{#vendorExtensions.x-is-jackson-optional-nullable}} +{{> jackson_annotations}} + public JsonNullable<{{{datatypeWithEnum}}}> {{getter}}_JsonNullable() { + return {{name}}; + } + {{/vendorExtensions.x-is-jackson-optional-nullable}}{{#vendorExtensions.x-is-jackson-optional-nullable}} + @JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}}) + {{#isReadOnly}}private{{/isReadOnly}}{{^isReadOnly}}public{{/isReadOnly}} void {{setter}}_JsonNullable(JsonNullable<{{{datatypeWithEnum}}}> {{name}}) { + {{! For getters/setters that have name differing from attribute name, we must include setter (albeit private) for jackson to be able to set the attribute}} + this.{{name}} = {{name}}; + } + {{/vendorExtensions.x-is-jackson-optional-nullable}} + + {{^isReadOnly}} +{{#vendorExtensions.x-setter-extra-annotation}} {{{vendorExtensions.x-setter-extra-annotation}}} +{{/vendorExtensions.x-setter-extra-annotation}}{{#jackson}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{> jackson_annotations}}{{/vendorExtensions.x-is-jackson-optional-nullable}}{{/jackson}} public void {{setter}}({{{datatypeWithEnum}}} {{name}}) { + {{#vendorExtensions.x-enum-as-string}} + if (!{{{nameInSnakeCase}}}_VALUES.contains({{name}})) { + throw new IllegalArgumentException({{name}} + " is invalid. Possible values for {{name}}: " + String.join(", ", {{{nameInSnakeCase}}}_VALUES)); + } + + {{/vendorExtensions.x-enum-as-string}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}}); + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = {{name}}; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + {{/isReadOnly}} + + {{/vars}} +{{>libraries/native/additional_properties}} + /** + * Return true if this {{name}} object is equal to o. + */ + @Override + public boolean equals(Object o) { + {{#useReflectionEqualsHashCode}} + return EqualsBuilder.reflectionEquals(this, o, false, null, true); + {{/useReflectionEqualsHashCode}} + {{^useReflectionEqualsHashCode}} + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + }{{#hasVars}} + {{classname}} {{classVarName}} = ({{classname}}) o; + return {{#vars}}{{#vendorExtensions.x-is-jackson-optional-nullable}}equalsNullable(this.{{name}}, {{classVarName}}.{{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{#isByteArray}}Arrays{{/isByteArray}}{{^isByteArray}}Objects{{/isByteArray}}.equals(this.{{name}}, {{classVarName}}.{{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^-last}} && + {{/-last}}{{/vars}}{{#additionalPropertiesType}}&& + Objects.equals(this.additionalProperties, {{classVarName}}.additionalProperties){{/additionalPropertiesType}}{{#parent}} && + super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}} + return {{#parent}}super.equals(o){{/parent}}{{^parent}}true{{/parent}};{{/hasVars}} + {{/useReflectionEqualsHashCode}} + }{{#vendorExtensions.x-jackson-optional-nullable-helpers}} + + private static boolean equalsNullable(JsonNullable a, JsonNullable b) { + return a == b || (a != null && b != null && a.isPresent() && b.isPresent() && Objects.deepEquals(a.get(), b.get())); + }{{/vendorExtensions.x-jackson-optional-nullable-helpers}} + + @Override + public int hashCode() { + {{#useReflectionEqualsHashCode}} + return HashCodeBuilder.reflectionHashCode(this); + {{/useReflectionEqualsHashCode}} + {{^useReflectionEqualsHashCode}} + return Objects.hash({{#vars}}{{#vendorExtensions.x-is-jackson-optional-nullable}}hashCodeNullable({{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{^isByteArray}}{{name}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{/vendorExtensions.x-is-jackson-optional-nullable}}{{^-last}}, {{/-last}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}{{#additionalPropertiesType}}, additionalProperties{{/additionalPropertiesType}}); + {{/useReflectionEqualsHashCode}} + }{{#vendorExtensions.x-jackson-optional-nullable-helpers}} + + private static int hashCodeNullable(JsonNullable a) { + if (a == null) { + return 1; + } + return a.isPresent() ? Arrays.deepHashCode(new Object[]{a.get()}) : 31; + }{{/vendorExtensions.x-jackson-optional-nullable-helpers}} + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class {{classname}} {\n"); + {{#parent}} + sb.append(" ").append(toIndentedString(super.toString())).append("\n"); + {{/parent}} + {{#vars}} + sb.append(" {{name}}: ").append(toIndentedString({{name}})).append("\n"); + {{/vars}} + {{#additionalPropertiesType}} + sb.append(" additionalProperties: ").append(toIndentedString(additionalProperties)).append("\n"); + {{/additionalPropertiesType}} + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + +{{#parcelableModel}} + + public void writeToParcel(Parcel out, int flags) { +{{#model}} +{{#isArray}} + out.writeList(this); +{{/isArray}} +{{^isArray}} +{{#parent}} + super.writeToParcel(out, flags); +{{/parent}} +{{#vars}} + out.writeValue({{name}}); +{{/vars}} +{{/isArray}} +{{/model}} + } + + {{classname}}(Parcel in) { +{{#isArray}} + in.readTypedList(this, {{arrayModelType}}.CREATOR); +{{/isArray}} +{{^isArray}} +{{#parent}} + super(in); +{{/parent}} +{{#vars}} +{{#isPrimitiveType}} + {{name}} = ({{{datatypeWithEnum}}})in.readValue(null); +{{/isPrimitiveType}} +{{^isPrimitiveType}} + {{name}} = ({{{datatypeWithEnum}}})in.readValue({{complexType}}.class.getClassLoader()); +{{/isPrimitiveType}} +{{/vars}} +{{/isArray}} + } + + public int describeContents() { + return 0; + } + + public static final Parcelable.Creator<{{classname}}> CREATOR = new Parcelable.Creator<{{classname}}>() { + public {{classname}} createFromParcel(Parcel in) { +{{#model}} +{{#isArray}} + {{classname}} result = new {{classname}}(); + result.addAll(in.readArrayList({{arrayModelType}}.class.getClassLoader())); + return result; +{{/isArray}} +{{^isArray}} + return new {{classname}}(in); +{{/isArray}} +{{/model}} + } + public {{classname}}[] newArray(int size) { + return new {{classname}}[size]; + } + }; +{{/parcelableModel}} +{{#discriminator}} +static { + // Initialize and register the discriminator mappings. + Map> mappings = new HashMap>(); + {{#mappedModels}} + mappings.put("{{mappingName}}", {{modelName}}.class); + {{/mappedModels}} + mappings.put("{{name}}", {{classname}}.class); + JSON.registerDiscriminator({{classname}}.class, "{{propertyBaseName}}", mappings); +} +{{/discriminator}} +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/native/pom.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/native/pom.mustache index 7e6ebb2f9..2a40aad08 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/native/pom.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/native/pom.mustache @@ -42,7 +42,7 @@ maven-enforcer-plugin - 3.0.0-M1 + 3.1.0 enforce-maven @@ -64,7 +64,7 @@ maven-surefire-plugin - 3.0.0-M3 + 3.0.0-M7 conf/log4j.properties @@ -76,7 +76,7 @@ maven-dependency-plugin - 3.1.1 + 3.3.0 package @@ -94,7 +94,7 @@ org.apache.maven.plugins maven-jar-plugin - 3.1.2 + 3.3.0 @@ -107,12 +107,12 @@ maven-compiler-plugin - 3.8.1 + 3.10.1 org.apache.maven.plugins maven-javadoc-plugin - 3.1.0 + 3.4.1 attach-javadocs @@ -124,7 +124,7 @@ maven-source-plugin - 3.1.0 + 3.2.1 attach-sources @@ -144,7 +144,7 @@ maven-gpg-plugin - 1.6 + 3.0.1 sign-artifacts @@ -161,11 +161,13 @@ + {{#swagger1AnnotationLibrary}} io.swagger swagger-annotations ${swagger-annotations-version} + {{/swagger1AnnotationLibrary}} @@ -200,6 +202,12 @@ jsr305 3.0.2 + + jakarta.annotation + jakarta.annotation-api + ${jakarta-annotation-version} + provided + @@ -209,13 +217,17 @@ test + UTF-8 - 1.5.22 + {{#swagger1AnnotationLibrary}} + 1.6.9 + {{/swagger1AnnotationLibrary}} 11 11 - 2.9.9 - 0.2.1 - 4.13 + 2.14.1 + 0.2.4 + 1.3.5 + 4.13.2 diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/native/travis.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/native/travis.mustache index d489da682..c94647479 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/native/travis.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/native/travis.mustache @@ -12,5 +12,5 @@ script: - mvn test # uncomment below to test using gradle # - gradle test - # uncomment below to test using sbt + # uncomment below to test using sbt # - sbt test diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/AbstractOpenApiSchema.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/AbstractOpenApiSchema.mustache new file mode 100644 index 000000000..3ba02e44c --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/AbstractOpenApiSchema.mustache @@ -0,0 +1,138 @@ +{{>licenseInfo}} + +package {{modelPackage}}; + +import {{invokerPackage}}.ApiException; +import java.util.Objects; +import java.lang.reflect.Type; +import java.util.Map; +import javax.ws.rs.core.GenericType; + +//import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Abstract class for oneOf,anyOf schemas defined in OpenAPI spec + */ +{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}} +public abstract class AbstractOpenApiSchema { + + // store the actual instance of the schema/object + private Object instance; + + // is nullable + private Boolean isNullable; + + // schema type (e.g. oneOf, anyOf) + private final String schemaType; + + public AbstractOpenApiSchema(String schemaType, Boolean isNullable) { + this.schemaType = schemaType; + this.isNullable = isNullable; + } + + /** + * Get the list of oneOf/anyOf composed schemas allowed to be stored in this object + * + * @return an instance of the actual schema/object + */ + public abstract Map getSchemas(); + + /** + * Get the actual instance + * + * @return an instance of the actual schema/object + */ + //@JsonValue + public Object getActualInstance() {return instance;} + + /** + * Set the actual instance + * + * @param instance the actual instance of the schema/object + */ + public void setActualInstance(Object instance) {this.instance = instance;} + + /** + * Get the instant recursively when the schemas defined in oneOf/anyof happen to be oneOf/anyOf schema as well + * + * @return an instance of the actual schema/object + */ + public Object getActualInstanceRecursively() { + return getActualInstanceRecursively(this); + } + + private Object getActualInstanceRecursively(AbstractOpenApiSchema object) { + if (object.getActualInstance() == null) { + return null; + } else if (object.getActualInstance() instanceof AbstractOpenApiSchema) { + return getActualInstanceRecursively((AbstractOpenApiSchema)object.getActualInstance()); + } else { + return object.getActualInstance(); + } + } + + /** + * Get the schema type (e.g. anyOf, oneOf) + * + * @return the schema type + */ + public String getSchemaType() { + return schemaType; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ").append(getClass()).append(" {\n"); + sb.append(" instance: ").append(toIndentedString(instance)).append("\n"); + sb.append(" isNullable: ").append(toIndentedString(isNullable)).append("\n"); + sb.append(" schemaType: ").append(toIndentedString(schemaType)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AbstractOpenApiSchema a = (AbstractOpenApiSchema) o; + return Objects.equals(this.instance, a.instance) && + Objects.equals(this.isNullable, a.isNullable) && + Objects.equals(this.schemaType, a.schemaType); + } + + @Override + public int hashCode() { + return Objects.hash(instance, isNullable, schemaType); + } + + /** + * Is nullable + * + * @return true if it's nullable + */ + public Boolean isNullable() { + if (Boolean.TRUE.equals(isNullable)) { + return Boolean.TRUE; + } else { + return Boolean.FALSE; + } + } + +{{>libraries/jersey2/additional_properties}} + +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/ApiCallback.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/ApiCallback.mustache index 4cc99a76e..53b6a7b8e 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/ApiCallback.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/ApiCallback.mustache @@ -41,10 +41,10 @@ public interface ApiCallback { void onUploadProgress(long bytesWritten, long contentLength, boolean done); /** - * This is called when the API downlond processing. + * This is called when the API download processing. * * @param bytesRead bytes Read - * @param contentLength content lenngth of the response + * @param contentLength content length of the response * @param done Read end */ void onDownloadProgress(long bytesRead, long contentLength, boolean done); diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/ApiClient.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/ApiClient.mustache index 3969c08d3..c81b9643a 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/ApiClient.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/ApiClient.mustache @@ -2,11 +2,20 @@ package {{invokerPackage}}; +{{#dynamicOperations}} +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.PathItem; +import io.swagger.v3.oas.models.parameters.Parameter; +import io.swagger.v3.oas.models.parameters.Parameter.StyleEnum; +import io.swagger.v3.parser.OpenAPIV3Parser; +{{/dynamicOperations}} import okhttp3.*; import okhttp3.internal.http.HttpMethod; import okhttp3.internal.tls.OkHostnameVerifier; import okhttp3.logging.HttpLoggingInterceptor; import okhttp3.logging.HttpLoggingInterceptor.Level; +import okio.Buffer; import okio.BufferedSink; import okio.Okio; {{#joda}} @@ -14,11 +23,6 @@ import org.joda.time.DateTime; import org.joda.time.LocalDate; import org.joda.time.format.DateTimeFormatter; {{/joda}} -{{#threetenbp}} -import org.threeten.bp.LocalDate; -import org.threeten.bp.OffsetDateTime; -import org.threeten.bp.format.DateTimeFormatter; -{{/threetenbp}} {{#hasOAuthMethods}} import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder; import org.apache.oltu.oauth2.common.message.types.GrantType; @@ -33,6 +37,8 @@ import java.lang.reflect.Type; import java.net.URI; import java.net.URLConnection; import java.net.URLEncoder; +import java.nio.file.Files; +import java.nio.file.Paths; import java.security.GeneralSecurityException; import java.security.KeyStore; import java.security.SecureRandom; @@ -41,11 +47,9 @@ import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.text.DateFormat; -{{#java8}} import java.time.LocalDate; import java.time.OffsetDateTime; import java.time.format.DateTimeFormatter; -{{/java8}} import java.util.*; import java.util.Map.Entry; import java.util.concurrent.TimeUnit; @@ -62,6 +66,9 @@ import {{invokerPackage}}.auth.RetryingOAuth; import {{invokerPackage}}.auth.OAuthFlow; {{/hasOAuthMethods}} +/** + *

ApiClient class.

+ */ public class ApiClient { private String basePath = "{{{basePath}}}"; @@ -86,7 +93,11 @@ public class ApiClient { private HttpLoggingInterceptor loggingInterceptor; - /* + {{#dynamicOperations}} + private Map operationLookupMap = new HashMap<>(); + + {{/dynamicOperations}} + /** * Basic constructor for ApiClient */ public ApiClient() { @@ -102,32 +113,65 @@ public class ApiClient { authentications = Collections.unmodifiableMap(authentications); } + /** + * Basic constructor with custom OkHttpClient + * + * @param client a {@link okhttp3.OkHttpClient} object + */ + public ApiClient(OkHttpClient client) { + init(); + + httpClient = client; + + // Setup authentications (key: authentication name, value: authentication).{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} + authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} + // Prevent the authentications from being modified. + authentications = Collections.unmodifiableMap(authentications); + } + {{#hasOAuthMethods}} {{#oauthMethods}} {{#-first}} - /* + /** * Constructor for ApiClient to support access token retry on 401/403 configured with client ID + * + * @param clientId client ID */ public ApiClient(String clientId) { this(clientId, null, null); } - /* + /** * Constructor for ApiClient to support access token retry on 401/403 configured with client ID and additional parameters + * + * @param clientId client ID + * @param parameters a {@link java.util.Map} of parameters */ public ApiClient(String clientId, Map parameters) { this(clientId, null, parameters); } - /* + /** * Constructor for ApiClient to support access token retry on 401/403 configured with client ID, secret, and additional parameters + * + * @param clientId client ID + * @param clientSecret client secret + * @param parameters a {@link java.util.Map} of parameters */ public ApiClient(String clientId, String clientSecret, Map parameters) { this(null, clientId, clientSecret, parameters); } - /* + /** * Constructor for ApiClient to support access token retry on 401/403 configured with base path, client ID, secret, and additional parameters + * + * @param basePath base path + * @param clientId client ID + * @param clientSecret client secret + * @param parameters a {@link java.util.Map} of parameters */ public ApiClient(String basePath, String clientId, String clientSecret, Map parameters) { init(); @@ -135,8 +179,7 @@ public class ApiClient { this.basePath = basePath; } -{{#hasOAuthMethods}} - String tokenUrl = "{{tokenUrl}}"; + String tokenUrl = "{{{tokenUrl}}}"; if (!"".equals(tokenUrl) && !URI.create(tokenUrl).isAbsolute()) { URI uri = URI.create(getBasePath()); tokenUrl = uri.getScheme() + ":" + @@ -146,13 +189,12 @@ public class ApiClient { throw new IllegalArgumentException("OAuth2 token URL must be an absolute URL"); } } - RetryingOAuth retryingOAuth = new RetryingOAuth(tokenUrl, clientId, OAuthFlow.{{flow}}, clientSecret, parameters); + RetryingOAuth retryingOAuth = new RetryingOAuth(tokenUrl, clientId, OAuthFlow.{{#lambda.uppercase}}{{#lambda.snakecase}}{{flow}}{{/lambda.snakecase}}{{/lambda.uppercase}}, clientSecret, parameters); authentications.put( "{{name}}", retryingOAuth ); initHttpClient(Collections.singletonList(retryingOAuth)); -{{/hasOAuthMethods}} // Setup authentications (key: authentication name, value: authentication).{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} @@ -189,9 +231,14 @@ public class ApiClient { json = new JSON(); // Set default User-Agent. - setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}"); + setUserAgent("{{{httpUserAgent}}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}"); authentications = new HashMap(); + {{#dynamicOperations}} + + OpenAPI openAPI = new OpenAPIV3Parser().read("openapi/openapi.yaml"); + createOperationLookupMap(openAPI); + {{/dynamicOperations}} } /** @@ -228,7 +275,7 @@ public class ApiClient { * * @param newHttpClient An instance of OkHttpClient * @return Api Client - * @throws NullPointerException when newHttpClient is null + * @throws java.lang.NullPointerException when newHttpClient is null */ public ApiClient setHttpClient(OkHttpClient newHttpClient) { this.httpClient = Objects.requireNonNull(newHttpClient, "HttpClient must not be null!"); @@ -300,6 +347,11 @@ public class ApiClient { return this; } + /** + *

Getter for the field keyManagers.

+ * + * @return an array of {@link javax.net.ssl.KeyManager} objects + */ public KeyManager[] getKeyManagers() { return keyManagers; } @@ -317,46 +369,81 @@ public class ApiClient { return this; } + /** + *

Getter for the field dateFormat.

+ * + * @return a {@link java.text.DateFormat} object + */ public DateFormat getDateFormat() { return dateFormat; } + /** + *

Setter for the field dateFormat.

+ * + * @param dateFormat a {@link java.text.DateFormat} object + * @return a {@link {{invokerPackage}}.ApiClient} object + */ public ApiClient setDateFormat(DateFormat dateFormat) { - this.json.setDateFormat(dateFormat); + JSON.setDateFormat(dateFormat); return this; } + /** + *

Set SqlDateFormat.

+ * + * @param dateFormat a {@link java.text.DateFormat} object + * @return a {@link {{invokerPackage}}.ApiClient} object + */ public ApiClient setSqlDateFormat(DateFormat dateFormat) { - this.json.setSqlDateFormat(dateFormat); + JSON.setSqlDateFormat(dateFormat); return this; } {{#joda}} public ApiClient setDateTimeFormat(DateTimeFormatter dateFormat) { - this.json.setDateTimeFormat(dateFormat); + JSON.setDateTimeFormat(dateFormat); return this; } public ApiClient setLocalDateFormat(DateTimeFormatter dateFormat) { - this.json.setLocalDateFormat(dateFormat); + JSON.setLocalDateFormat(dateFormat); return this; } {{/joda}} {{#jsr310}} + /** + *

Set OffsetDateTimeFormat.

+ * + * @param dateFormat a {@link java.time.format.DateTimeFormatter} object + * @return a {@link {{invokerPackage}}.ApiClient} object + */ public ApiClient setOffsetDateTimeFormat(DateTimeFormatter dateFormat) { - this.json.setOffsetDateTimeFormat(dateFormat); + JSON.setOffsetDateTimeFormat(dateFormat); return this; } + /** + *

Set LocalDateFormat.

+ * + * @param dateFormat a {@link java.time.format.DateTimeFormatter} object + * @return a {@link {{invokerPackage}}.ApiClient} object + */ public ApiClient setLocalDateFormat(DateTimeFormatter dateFormat) { - this.json.setLocalDateFormat(dateFormat); + JSON.setLocalDateFormat(dateFormat); return this; } {{/jsr310}} + /** + *

Set LenientOnJson.

+ * + * @param lenientOnJson a boolean + * @return a {@link {{invokerPackage}}.ApiClient} object + */ public ApiClient setLenientOnJson(boolean lenientOnJson) { - this.json.setLenientOnJson(lenientOnJson); + JSON.setLenientOnJson(lenientOnJson); return this; } @@ -379,6 +466,22 @@ public class ApiClient { return authentications.get(authName); } + {{#hasHttpBearerMethods}} + /** + * Helper method to set access token for the first Bearer authentication. + * @param bearerToken Bearer token + */ + public void setBearerToken(String bearerToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBearerAuth) { + ((HttpBearerAuth) auth).setBearerToken(bearerToken); + return; + } + } + throw new RuntimeException("No Bearer authentication configured!"); + } + {{/hasHttpBearerMethods}} + /** * Helper method to set username for the first HTTP basic authentication. * @@ -513,7 +616,9 @@ public class ApiClient { loggingInterceptor.setLevel(Level.BODY); httpClient = httpClient.newBuilder().addInterceptor(loggingInterceptor).build(); } else { - httpClient.interceptors().remove(loggingInterceptor); + final OkHttpClient.Builder builder = httpClient.newBuilder(); + builder.interceptors().remove(loggingInterceptor); + httpClient = builder.build(); loggingInterceptor = null; } } @@ -524,9 +629,9 @@ public class ApiClient { /** * The path of temporary folder used to store downloaded files from endpoints * with file response. The default value is null, i.e. using - * the system's default tempopary folder. + * the system's default temporary folder. * - * @see createTempFile + * @see createTempFile * @return Temporary folder path */ public String getTempFolderPath() { @@ -556,7 +661,7 @@ public class ApiClient { /** * Sets the connect timeout (in milliseconds). * A value of 0 means no timeout, otherwise values must be between 1 and - * {@link Integer#MAX_VALUE}. + * {@link java.lang.Integer#MAX_VALUE}. * * @param connectionTimeout connection timeout in milliseconds * @return Api client @@ -578,7 +683,7 @@ public class ApiClient { /** * Sets the read timeout (in milliseconds). * A value of 0 means no timeout, otherwise values must be between 1 and - * {@link Integer#MAX_VALUE}. + * {@link java.lang.Integer#MAX_VALUE}. * * @param readTimeout read timeout in milliseconds * @return Api client @@ -600,7 +705,7 @@ public class ApiClient { /** * Sets the write timeout (in milliseconds). * A value of 0 means no timeout, otherwise values must be between 1 and - * {@link Integer#MAX_VALUE}. + * {@link java.lang.Integer#MAX_VALUE}. * * @param writeTimeout connection timeout in milliseconds * @return Api client @@ -638,7 +743,7 @@ public class ApiClient { return ""; } else if (param instanceof Date {{#joda}}|| param instanceof DateTime || param instanceof LocalDate{{/joda}}{{#jsr310}}|| param instanceof OffsetDateTime || param instanceof LocalDate{{/jsr310}}) { //Serialize to json string and remove the " enclosing characters - String jsonStr = json.serialize(param); + String jsonStr = JSON.serialize(param); return jsonStr.substring(1, jsonStr.length() - 1); } else if (param instanceof Collection) { StringBuilder b = new StringBuilder(); @@ -646,7 +751,7 @@ public class ApiClient { if (b.length() > 0) { b.append(","); } - b.append(String.valueOf(o)); + b.append(o); } return b.toString(); } else { @@ -675,6 +780,7 @@ public class ApiClient { return params; } + {{^dynamicOperations}} /** * Formats the specified collection query parameters to a list of {@code Pair} objects. * @@ -724,6 +830,46 @@ public class ApiClient { return params; } + {{/dynamicOperations}} + {{#dynamicOperations}} + public List parameterToPairs(Parameter param, Collection value) { + List params = new ArrayList(); + + // preconditions + if (param == null || param.getName() == null || param.getName().isEmpty() || value == null) { + return params; + } + + // create the params based on the collection format + if (StyleEnum.FORM.equals(param.getStyle()) && Boolean.TRUE.equals(param.getExplode())) { + for (Object item : value) { + params.add(new Pair(param.getName(), escapeString(parameterToString(item)))); + } + return params; + } + + // collectionFormat is assumed to be "csv" by default + String delimiter = ","; + + // escape all delimiters except commas, which are URI reserved + // characters + if (StyleEnum.SPACEDELIMITED.equals(param.getStyle())) { + delimiter = escapeString(" "); + } else if (StyleEnum.PIPEDELIMITED.equals(param.getStyle())) { + delimiter = escapeString("|"); + } + + StringBuilder sb = new StringBuilder(); + for (Object item : value) { + sb.append(delimiter); + sb.append(escapeString(parameterToString(item))); + } + + params.add(new Pair(param.getName(), sb.substring(delimiter.length()))); + + return params; + } + {{/dynamicOperations}} /** * Formats the specified collection path parameter to a string value. @@ -814,17 +960,23 @@ public class ApiClient { * * @param contentTypes The Content-Type array to select from * @return The Content-Type header to use. If the given array is empty, - * or matches "any", JSON will be used. + * returns null. If it matches "any", JSON will be used. */ public String selectHeaderContentType(String[] contentTypes) { - if (contentTypes.length == 0 || contentTypes[0].equals("*/*")) { + if (contentTypes.length == 0) { + return null; + } + + if (contentTypes[0].equals("*/*")) { return "application/json"; } + for (String contentType : contentTypes) { if (isJsonMime(contentType)) { return contentType; } } + return contentTypes[0]; } @@ -850,7 +1002,7 @@ public class ApiClient { * @param response HTTP response * @param returnType The type of the Java object * @return The deserialized Java object - * @throws ApiException If fail to deserialize response body, i.e. cannot read response body + * @throws {{invokerPackage}}.ApiException If fail to deserialize response body, i.e. cannot read response body * or the Content-Type of the response is not supported. */ @SuppressWarnings("unchecked") @@ -891,7 +1043,7 @@ public class ApiClient { contentType = "application/json"; } if (isJsonMime(contentType)) { - return json.deserialize(respBody, returnType); + return JSON.deserialize(respBody, returnType); } else if (returnType.equals(String.class)) { // Expecting string, return the raw response body. return (T) respBody; @@ -911,23 +1063,27 @@ public class ApiClient { * @param obj The Java object * @param contentType The request Content-Type * @return The serialized request body - * @throws ApiException If fail to serialize the given object + * @throws {{invokerPackage}}.ApiException If fail to serialize the given object */ public RequestBody serialize(Object obj, String contentType) throws ApiException { if (obj instanceof byte[]) { // Binary (byte array) body parameter support. - return RequestBody.create(MediaType.parse(contentType), (byte[]) obj); + return RequestBody.create((byte[]) obj, MediaType.parse(contentType)); } else if (obj instanceof File) { // File body parameter support. - return RequestBody.create(MediaType.parse(contentType), (File) obj); + return RequestBody.create((File) obj, MediaType.parse(contentType)); + } else if ("text/plain".equals(contentType) && obj instanceof String) { + return RequestBody.create((String) obj, MediaType.parse(contentType)); } else if (isJsonMime(contentType)) { String content; if (obj != null) { - content = json.serialize(obj); + content = JSON.serialize(obj); } else { content = null; } - return RequestBody.create(MediaType.parse(contentType), content); + return RequestBody.create(content, MediaType.parse(contentType)); + } else if (obj instanceof String) { + return RequestBody.create((String) obj, MediaType.parse(contentType)); } else { throw new ApiException("Content type \"" + contentType + "\" is not supported"); } @@ -937,7 +1093,7 @@ public class ApiClient { * Download file from the given response. * * @param response An instance of the Response object - * @throws ApiException If fail to read file content from response and write to disk + * @throws {{invokerPackage}}.ApiException If fail to read file content from response and write to disk * @return Downloaded file */ public File downloadFileFromResponse(Response response) throws ApiException { @@ -957,7 +1113,7 @@ public class ApiClient { * * @param response An instance of the Response object * @return Prepared file for the download - * @throws IOException If fail to prepare file for download + * @throws java.io.IOException If fail to prepare file for download */ public File prepareDownloadFile(Response response) throws IOException { String filename = null; @@ -984,15 +1140,15 @@ public class ApiClient { prefix = filename.substring(0, pos) + "-"; suffix = filename.substring(pos); } - // File.createTempFile requires the prefix to be at least three characters long + // Files.createTempFile requires the prefix to be at least three characters long if (prefix.length() < 3) prefix = "download-"; } if (tempFolderPath == null) - return File.createTempFile(prefix, suffix); + return Files.createTempFile(prefix, suffix).toFile(); else - return File.createTempFile(prefix, suffix, new File(tempFolderPath)); + return Files.createTempFile(Paths.get(tempFolderPath), prefix, suffix).toFile(); } /** @@ -1001,7 +1157,7 @@ public class ApiClient { * @param Type * @param call An instance of the Call object * @return ApiResponse<T> - * @throws ApiException If fail to execute the call + * @throws {{invokerPackage}}.ApiException If fail to execute the call */ public ApiResponse execute(Call call) throws ApiException { return execute(call, null); @@ -1016,7 +1172,7 @@ public class ApiClient { * @return ApiResponse object containing response status, headers and * data, which is a Java object deserialized from response body and would be null * when returnType is null. - * @throws ApiException If fail to execute the call + * @throws {{invokerPackage}}.ApiException If fail to execute the call */ public ApiResponse execute(Call call, Type returnType) throws ApiException { try { @@ -1028,6 +1184,31 @@ public class ApiClient { } } + {{#supportStreaming}} + /** + *

Execute stream.

+ * + * @param call a {@link okhttp3.Call} object + * @param returnType a {@link java.lang.reflect.Type} object + * @return a {@link java.io.InputStream} object + * @throws {{invokerPackage}}.ApiException if any. + */ + public InputStream executeStream(Call call, Type returnType) throws ApiException { + try { + Response response = call.execute(); + if (!response.isSuccessful()) { + throw new ApiException(response.code(), response.message(), response.headers().toMultimap(), null); + } + if (response.body() == null) { + return null; + } + return response.body().byteStream(); + } catch (IOException e) { + throw new ApiException(e); + } + } + + {{/supportStreaming}} /** * {@link #executeAsync(Call, Type, ApiCallback)} * @@ -1064,6 +1245,9 @@ public class ApiClient { } catch (ApiException e) { callback.onFailure(e, response.code(), response.headers().toMultimap()); return; + } catch (Exception e) { + callback.onFailure(new ApiException(e), response.code(), response.headers().toMultimap()); + return; } callback.onSuccess(result, response.code(), response.headers().toMultimap()); } @@ -1077,7 +1261,7 @@ public class ApiClient { * @param response Response * @param returnType Return type * @return Type - * @throws ApiException If the response has an unsuccessful status code or + * @throws {{invokerPackage}}.ApiException If the response has an unsuccessful status code or * fail to deserialize the response body */ public T handleResponse(Response response, Type returnType) throws ApiException { @@ -1112,6 +1296,7 @@ public class ApiClient { /** * Build HTTP call with the given options. * + * @param baseUrl The base URL * @param path The sub-path of the HTTP URL * @param method The request method, one of "GET", "HEAD", "OPTIONS", "POST", "PUT", "PATCH" and "DELETE" * @param queryParams The query parameters @@ -1123,10 +1308,10 @@ public class ApiClient { * @param authNames The authentications to apply * @param callback Callback for upload/download progress * @return The HTTP call - * @throws ApiException If fail to serialize the request body object + * @throws {{invokerPackage}}.ApiException If fail to serialize the request body object */ - public Call buildCall(String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String[] authNames, ApiCallback callback) throws ApiException { - Request request = buildRequest(path, method, queryParams, collectionQueryParams, body, headerParams, cookieParams, formParams, authNames, callback); + public Call buildCall(String baseUrl, String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String[] authNames, ApiCallback callback) throws ApiException { + Request request = buildRequest(baseUrl, path, method, queryParams, collectionQueryParams, body, headerParams, cookieParams, formParams, authNames, callback); return httpClient.newCall(request); } @@ -1134,6 +1319,7 @@ public class ApiClient { /** * Build an HTTP request with the given options. * + * @param baseUrl The base URL * @param path The sub-path of the HTTP URL * @param method The request method, one of "GET", "HEAD", "OPTIONS", "POST", "PUT", "PATCH" and "DELETE" * @param queryParams The query parameters @@ -1145,23 +1331,19 @@ public class ApiClient { * @param authNames The authentications to apply * @param callback Callback for upload/download progress * @return The HTTP request - * @throws ApiException If fail to serialize the request body object + * @throws {{invokerPackage}}.ApiException If fail to serialize the request body object */ - public Request buildRequest(String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String[] authNames, ApiCallback callback) throws ApiException { - updateParamsForAuth(authNames, queryParams, headerParams, cookieParams); - - final String url = buildUrl(path, queryParams, collectionQueryParams); - final Request.Builder reqBuilder = new Request.Builder().url(url); - processHeaderParams(headerParams, reqBuilder); - processCookieParams(cookieParams, reqBuilder); + public Request buildRequest(String baseUrl, String path, String method, List queryParams, List collectionQueryParams, Object body, Map headerParams, Map cookieParams, Map formParams, String[] authNames, ApiCallback callback) throws ApiException { + // aggregate queryParams (non-collection) and collectionQueryParams into allQueryParams + List allQueryParams = new ArrayList(queryParams); + allQueryParams.addAll(collectionQueryParams); - String contentType = (String) headerParams.get("Content-Type"); - // ensuring a default content type - if (contentType == null) { - contentType = "application/json"; - } + final String url = buildUrl(baseUrl, path, queryParams, collectionQueryParams); + // prepare HTTP request body RequestBody reqBody; + String contentType = headerParams.get("Content-Type"); + if (!HttpMethod.permitsRequestBody(method)) { reqBody = null; } else if ("application/x-www-form-urlencoded".equals(contentType)) { @@ -1174,12 +1356,19 @@ public class ApiClient { reqBody = null; } else { // use an empty request body (for POST, PUT and PATCH) - reqBody = RequestBody.create(MediaType.parse(contentType), ""); + reqBody = RequestBody.create("", contentType == null ? null : MediaType.parse(contentType)); } } else { reqBody = serialize(body, contentType); } + // update parameters with authentication settings + updateParamsForAuth(authNames, allQueryParams, headerParams, cookieParams, requestBodyToString(reqBody), method, URI.create(url)); + + final Request.Builder reqBuilder = new Request.Builder().url(url); + processHeaderParams(headerParams, reqBuilder); + processCookieParams(cookieParams, reqBuilder); + // Associate callback with request (if not null) so interceptor can // access it when creating ProgressResponseBody reqBuilder.tag(callback); @@ -1199,14 +1388,19 @@ public class ApiClient { /** * Build full URL by concatenating base path, the given sub path and query parameters. * + * @param baseUrl The base URL * @param path The sub path * @param queryParams The query parameters * @param collectionQueryParams The collection query parameters * @return The full URL */ - public String buildUrl(String path, List queryParams, List collectionQueryParams) { + public String buildUrl(String baseUrl, String path, List queryParams, List collectionQueryParams) { final StringBuilder url = new StringBuilder(); - url.append(basePath).append(path); + if (baseUrl != null) { + url.append(baseUrl).append(path); + } else { + url.append(basePath).append(path); + } if (queryParams != null && !queryParams.isEmpty()) { // support (constant) query string in `path`, e.g. "/posts?draft=1" @@ -1286,14 +1480,19 @@ public class ApiClient { * @param queryParams List of query parameters * @param headerParams Map of header parameters * @param cookieParams Map of cookie parameters + * @param payload HTTP request body + * @param method HTTP method + * @param uri URI + * @throws {{invokerPackage}}.ApiException If fails to update the parameters */ - public void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams, Map cookieParams) { + public void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams, + Map cookieParams, String payload, String method, URI uri) throws ApiException { for (String authName : authNames) { Authentication auth = authentications.get(authName); if (auth == null) { throw new RuntimeException("Authentication undefined: " + authName); } - auth.applyToParams(queryParams, headerParams, cookieParams); + auth.applyToParams(queryParams, headerParams, cookieParams, payload, method, uri); } } @@ -1323,12 +1522,18 @@ public class ApiClient { for (Entry param : formParams.entrySet()) { if (param.getValue() instanceof File) { File file = (File) param.getValue(); - Headers partHeaders = Headers.of("Content-Disposition", "form-data; name=\"" + param.getKey() + "\"; filename=\"" + file.getName() + "\""); - MediaType mediaType = MediaType.parse(guessContentTypeFromFile(file)); - mpBuilder.addPart(partHeaders, RequestBody.create(mediaType, file)); + addPartToMultiPartBuilder(mpBuilder, param.getKey(), file); + } else if (param.getValue() instanceof List) { + List list = (List) param.getValue(); + for (Object item: list) { + if (item instanceof File) { + addPartToMultiPartBuilder(mpBuilder, param.getKey(), (File) item); + } else { + addPartToMultiPartBuilder(mpBuilder, param.getKey(), param.getValue()); + } + } } else { - Headers partHeaders = Headers.of("Content-Disposition", "form-data; name=\"" + param.getKey() + "\""); - mpBuilder.addPart(partHeaders, RequestBody.create(null, parameterToString(param.getValue()))); + addPartToMultiPartBuilder(mpBuilder, param.getKey(), param.getValue()); } } return mpBuilder.build(); @@ -1349,6 +1554,44 @@ public class ApiClient { } } + /** + * Add a Content-Disposition Header for the given key and file to the MultipartBody Builder. + * + * @param mpBuilder MultipartBody.Builder + * @param key The key of the Header element + * @param file The file to add to the Header + */ + private void addPartToMultiPartBuilder(MultipartBody.Builder mpBuilder, String key, File file) { + Headers partHeaders = Headers.of("Content-Disposition", "form-data; name=\"" + key + "\"; filename=\"" + file.getName() + "\""); + MediaType mediaType = MediaType.parse(guessContentTypeFromFile(file)); + mpBuilder.addPart(partHeaders, RequestBody.create(file, mediaType)); + } + + /** + * Add a Content-Disposition Header for the given key and complex object to the MultipartBody Builder. + * + * @param mpBuilder MultipartBody.Builder + * @param key The key of the Header element + * @param obj The complex object to add to the Header + */ + private void addPartToMultiPartBuilder(MultipartBody.Builder mpBuilder, String key, Object obj) { + RequestBody requestBody; + if (obj instanceof String) { + requestBody = RequestBody.create((String) obj, MediaType.parse("text/plain")); + } else { + String content; + if (obj != null) { + content = JSON.serialize(obj); + } else { + content = null; + } + requestBody = RequestBody.create(content, MediaType.parse("application/json")); + } + + Headers partHeaders = Headers.of("Content-Disposition", "form-data; name=\"" + key + "\""); + mpBuilder.addPart(partHeaders, requestBody); + } + /** * Get network interceptor to add it to the httpClient to track download progress for * async requests. @@ -1416,7 +1659,7 @@ public class ApiClient { KeyStore caKeyStore = newEmptyKeyStore(password); int index = 0; for (Certificate certificate : certificates) { - String certificateAlias = "ca" + Integer.toString(index++); + String certificateAlias = "ca" + (index++); caKeyStore.setCertificateEntry(certificateAlias, certificate); } trustManagerFactory.init(caKeyStore); @@ -1445,4 +1688,97 @@ public class ApiClient { throw new AssertionError(e); } } + {{#dynamicOperations}} + + public ApiClient createOperationLookupMap(OpenAPI openAPI) { + operationLookupMap = new HashMap<>(); + for (Map.Entry pathItemEntry : openAPI.getPaths().entrySet()) { + String path = pathItemEntry.getKey(); + PathItem pathItem = pathItemEntry.getValue(); + addOperationLookupEntry(path, "GET", pathItem.getGet()); + addOperationLookupEntry(path, "PUT", pathItem.getPut()); + addOperationLookupEntry(path, "POST", pathItem.getPost()); + addOperationLookupEntry(path, "DELETE", pathItem.getDelete()); + addOperationLookupEntry(path, "OPTIONS", pathItem.getOptions()); + addOperationLookupEntry(path, "HEAD", pathItem.getHead()); + addOperationLookupEntry(path, "PATCH", pathItem.getPatch()); + addOperationLookupEntry(path, "TRACE", pathItem.getTrace()); + } + return this; + } + + private void addOperationLookupEntry(String path, String method, Operation operation) { + if ( operation != null && operation.getOperationId() != null) { + operationLookupMap.put( + operation.getOperationId(), + new ApiOperation(path, method, operation)); + } + } + + public Map getOperationLookupMap() { + return operationLookupMap; + } + + public String fillParametersFromOperation( + Operation operation, + Map paramMap, + String path, + List queryParams, + List collectionQueryParams, + Map headerParams, + Map cookieParams + ) { + for (Map.Entry entry : paramMap.entrySet()) { + Object value = entry.getValue(); + for (Parameter param : operation.getParameters()) { + if (entry.getKey().equals(param.getName())) { + switch (param.getIn()) { + case "path": + path = path.replace("{" + param.getName() + "}", escapeString(value.toString())); + break; + case "query": + if (value instanceof Collection) { + collectionQueryParams.addAll(parameterToPairs(param, (Collection) value)); + } else { + queryParams.addAll(parameterToPair(param.getName(), value)); + } + break; + case "header": + headerParams.put(param.getName(), parameterToString(value)); + break; + case "cookie": + cookieParams.put(param.getName(), parameterToString(value)); + break; + default: + throw new IllegalStateException("Unexpected param in: " + param.getIn()); + } + + } + } + } + return path; + } + {{/dynamicOperations}} + + /** + * Convert the HTTP request body to a string. + * + * @param requestBody The HTTP request object + * @return The string representation of the HTTP request body + * @throws {{invokerPackage}}.ApiException If fail to serialize the request body object into a string + */ + private String requestBodyToString(RequestBody requestBody) throws ApiException { + if (requestBody != null) { + try { + final Buffer buffer = new Buffer(); + requestBody.writeTo(buffer); + return buffer.readUtf8(); + } catch (final IOException e) { + throw new ApiException(e); + } + } + + // empty http request body + return ""; + } } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/ApiResponse.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/ApiResponse.mustache index 1f3f3a319..cecbaac1d 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/ApiResponse.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/ApiResponse.mustache @@ -5,14 +5,12 @@ package {{invokerPackage}}; import java.util.List; import java.util.Map; {{#caseInsensitiveResponseHeaders}} -import java.util.Map.Entry; +import java.util.Map.Entry; import java.util.TreeMap; {{/caseInsensitiveResponseHeaders}} /** * API response returned by API call. - * - * @param The type of data that is deserialized from response body */ public class ApiResponse { final private int statusCode; @@ -20,6 +18,8 @@ public class ApiResponse { final private T data; /** + *

Constructor for ApiResponse.

+ * * @param statusCode The status code of HTTP response * @param headers The headers of HTTP response */ @@ -28,6 +28,8 @@ public class ApiResponse { } /** + *

Constructor for ApiResponse.

+ * * @param statusCode The status code of HTTP response * @param headers The headers of HTTP response * @param data The object deserialized from response bod @@ -44,14 +46,29 @@ public class ApiResponse { this.data = data; } + /** + *

Get the status code.

+ * + * @return the status code + */ public int getStatusCode() { return statusCode; } + /** + *

Get the headers.

+ * + * @return a {@link java.util.Map} of headers + */ public Map> getHeaders() { return headers; } + /** + *

Get the data.

+ * + * @return the data + */ public T getData() { return data; } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/JSON.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/JSON.mustache new file mode 100644 index 000000000..d6883b982 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/JSON.mustache @@ -0,0 +1,534 @@ +{{>licenseInfo}} + +package {{invokerPackage}}; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonParseException; +import com.google.gson.TypeAdapter; +import com.google.gson.internal.bind.util.ISO8601Utils; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import com.google.gson.JsonElement; +import io.gsonfire.GsonFireBuilder; +import io.gsonfire.TypeSelector; +{{#joda}} +import org.joda.time.DateTime; +import org.joda.time.LocalDate; +import org.joda.time.format.DateTimeFormatter; +import org.joda.time.format.DateTimeFormatterBuilder; +import org.joda.time.format.ISODateTimeFormat; +{{/joda}} + +import okio.ByteString; + +import java.io.IOException; +import java.io.StringReader; +import java.lang.reflect.Type; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.ParsePosition; +import java.time.LocalDate; +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Date; +import java.util.Locale; +import java.util.Map; +import java.util.HashMap; + +/* + * A JSON utility class + * + * NOTE: in the future, this class may be converted to static, which may break + * backward-compatibility + */ +public class JSON { + private static Gson gson; + private static boolean isLenientOnJson = false; + private static DateTypeAdapter dateTypeAdapter = new DateTypeAdapter(); + private static SqlDateTypeAdapter sqlDateTypeAdapter = new SqlDateTypeAdapter(); + {{#joda}} + private static DateTimeTypeAdapter dateTimeTypeAdapter = new DateTimeTypeAdapter(); + private static LocalDateTypeAdapter localDateTypeAdapter = new LocalDateTypeAdapter(); + {{/joda}} + {{#jsr310}} + private static OffsetDateTimeTypeAdapter offsetDateTimeTypeAdapter = new OffsetDateTimeTypeAdapter(); + private static LocalDateTypeAdapter localDateTypeAdapter = new LocalDateTypeAdapter(); + {{/jsr310}} + private static ByteArrayAdapter byteArrayAdapter = new ByteArrayAdapter(); + + @SuppressWarnings("unchecked") + public static GsonBuilder createGson() { + GsonFireBuilder fireBuilder = new GsonFireBuilder() + {{#models}} + {{#model}} + {{#discriminator}} + .registerTypeSelector({{modelPackage}}.{{classname}}.class, new TypeSelector<{{modelPackage}}.{{classname}}>() { + @Override + public Class getClassForElement(JsonElement readElement) { + Map classByDiscriminatorValue = new HashMap(); + {{#mappedModels}} + classByDiscriminatorValue.put("{{mappingName}}"{{^discriminatorCaseSensitive}}.toUpperCase(Locale.ROOT){{/discriminatorCaseSensitive}}, {{modelPackage}}.{{modelName}}.class); + {{/mappedModels}} + classByDiscriminatorValue.put("{{name}}"{{^discriminatorCaseSensitive}}.toUpperCase(Locale.ROOT){{/discriminatorCaseSensitive}}, {{modelPackage}}.{{classname}}.class); + return getClassByDiscriminator(classByDiscriminatorValue, + getDiscriminatorValue(readElement, "{{{propertyBaseName}}}")); + } + }) + {{/discriminator}} + {{/model}} + {{/models}} + ; + GsonBuilder builder = fireBuilder.createGsonBuilder(); + {{#disableHtmlEscaping}} + builder.disableHtmlEscaping(); + {{/disableHtmlEscaping}} + return builder; + } + + private static String getDiscriminatorValue(JsonElement readElement, String discriminatorField) { + JsonElement element = readElement.getAsJsonObject().get(discriminatorField); + if (null == element) { + throw new IllegalArgumentException("missing discriminator field: <" + discriminatorField + ">"); + } + return element.getAsString(); + } + + /** + * Returns the Java class that implements the OpenAPI schema for the specified discriminator value. + * + * @param classByDiscriminatorValue The map of discriminator values to Java classes. + * @param discriminatorValue The value of the OpenAPI discriminator in the input data. + * @return The Java class that implements the OpenAPI schema + */ + private static Class getClassByDiscriminator(Map classByDiscriminatorValue, String discriminatorValue) { + Class clazz = (Class) classByDiscriminatorValue.get(discriminatorValue{{^discriminatorCaseSensitive}}.toUpperCase(Locale.ROOT){{/discriminatorCaseSensitive}}); + if (null == clazz) { + throw new IllegalArgumentException("cannot determine model class of name: <" + discriminatorValue + ">"); + } + return clazz; + } + + { + GsonBuilder gsonBuilder = createGson(); + gsonBuilder.registerTypeAdapter(Date.class, dateTypeAdapter); + gsonBuilder.registerTypeAdapter(java.sql.Date.class, sqlDateTypeAdapter); + {{#joda}} + gsonBuilder.registerTypeAdapter(DateTime.class, dateTimeTypeAdapter); + gsonBuilder.registerTypeAdapter(LocalDate.class, localDateTypeAdapter); + {{/joda}} + {{#jsr310}} + gsonBuilder.registerTypeAdapter(OffsetDateTime.class, offsetDateTimeTypeAdapter); + gsonBuilder.registerTypeAdapter(LocalDate.class, localDateTypeAdapter); + {{/jsr310}} + gsonBuilder.registerTypeAdapter(byte[].class, byteArrayAdapter); + {{#models}} + {{#model}} + {{^isEnum}} + {{^hasChildren}} + gsonBuilder.registerTypeAdapterFactory(new {{modelPackage}}.{{{classname}}}.CustomTypeAdapterFactory()); + {{/hasChildren}} + {{/isEnum}} + {{/model}} + {{/models}} + gson = gsonBuilder.create(); + } + + /** + * Get Gson. + * + * @return Gson + */ + public static Gson getGson() { + return gson; + } + + /** + * Set Gson. + * + * @param gson Gson + */ + public static void setGson(Gson gson) { + JSON.gson = gson; + } + + public static void setLenientOnJson(boolean lenientOnJson) { + isLenientOnJson = lenientOnJson; + } + + /** + * Serialize the given Java object into JSON string. + * + * @param obj Object + * @return String representation of the JSON + */ + public static String serialize(Object obj) { + return gson.toJson(obj); + } + + /** + * Deserialize the given JSON string to Java object. + * + * @param Type + * @param body The JSON string + * @param returnType The type to deserialize into + * @return The deserialized Java object + */ + @SuppressWarnings("unchecked") + public static T deserialize(String body, Type returnType) { + try { + if (isLenientOnJson) { + JsonReader jsonReader = new JsonReader(new StringReader(body)); + // see https://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/stream/JsonReader.html#setLenient(boolean) + jsonReader.setLenient(true); + return gson.fromJson(jsonReader, returnType); + } else { + return gson.fromJson(body, returnType); + } + } catch (JsonParseException e) { + // Fallback processing when failed to parse JSON form response body: + // return the response body string directly for the String return type; + if (returnType.equals(String.class)) { + return (T) body; + } else { + throw (e); + } + } + } + + /** + * Gson TypeAdapter for Byte Array type + */ + public static class ByteArrayAdapter extends TypeAdapter { + + @Override + public void write(JsonWriter out, byte[] value) throws IOException { + if (value == null) { + out.nullValue(); + } else { + out.value(ByteString.of(value).base64()); + } + } + + @Override + public byte[] read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String bytesAsBase64 = in.nextString(); + ByteString byteString = ByteString.decodeBase64(bytesAsBase64); + return byteString.toByteArray(); + } + } + } + + {{#joda}} + /** + * Gson TypeAdapter for Joda DateTime type + */ + public static class DateTimeTypeAdapter extends TypeAdapter { + + private DateTimeFormatter formatter; + + public DateTimeTypeAdapter() { + this(new DateTimeFormatterBuilder() + .append(ISODateTimeFormat.dateTime().getPrinter(), ISODateTimeFormat.dateOptionalTimeParser().getParser()) + .toFormatter()); + } + + public DateTimeTypeAdapter(DateTimeFormatter formatter) { + this.formatter = formatter; + } + + public void setFormat(DateTimeFormatter dateFormat) { + this.formatter = dateFormat; + } + + @Override + public void write(JsonWriter out, DateTime date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + out.value(formatter.print(date)); + } + } + + @Override + public DateTime read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + return formatter.parseDateTime(date); + } + } + } + + /** + * Gson TypeAdapter for Joda LocalDate type + */ + public static class LocalDateTypeAdapter extends TypeAdapter { + + private DateTimeFormatter formatter; + + public LocalDateTypeAdapter() { + this(ISODateTimeFormat.date()); + } + + public LocalDateTypeAdapter(DateTimeFormatter formatter) { + this.formatter = formatter; + } + + public void setFormat(DateTimeFormatter dateFormat) { + this.formatter = dateFormat; + } + + @Override + public void write(JsonWriter out, LocalDate date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + out.value(formatter.print(date)); + } + } + + @Override + public LocalDate read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + return formatter.parseLocalDate(date); + } + } + } + + public static void setDateTimeFormat(DateTimeFormatter dateFormat) { + dateTimeTypeAdapter.setFormat(dateFormat); + } + + public static void setLocalDateFormat(DateTimeFormatter dateFormat) { + localDateTypeAdapter.setFormat(dateFormat); + } + + {{/joda}} + {{#jsr310}} + /** + * Gson TypeAdapter for JSR310 OffsetDateTime type + */ + public static class OffsetDateTimeTypeAdapter extends TypeAdapter { + + private DateTimeFormatter formatter; + + public OffsetDateTimeTypeAdapter() { + this(DateTimeFormatter.ISO_OFFSET_DATE_TIME); + } + + public OffsetDateTimeTypeAdapter(DateTimeFormatter formatter) { + this.formatter = formatter; + } + + public void setFormat(DateTimeFormatter dateFormat) { + this.formatter = dateFormat; + } + + @Override + public void write(JsonWriter out, OffsetDateTime date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + out.value(formatter.format(date)); + } + } + + @Override + public OffsetDateTime read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + if (date.endsWith("+0000")) { + date = date.substring(0, date.length()-5) + "Z"; + } + return OffsetDateTime.parse(date, formatter); + } + } + } + + /** + * Gson TypeAdapter for JSR310 LocalDate type + */ + public static class LocalDateTypeAdapter extends TypeAdapter { + + private DateTimeFormatter formatter; + + public LocalDateTypeAdapter() { + this(DateTimeFormatter.ISO_LOCAL_DATE); + } + + public LocalDateTypeAdapter(DateTimeFormatter formatter) { + this.formatter = formatter; + } + + public void setFormat(DateTimeFormatter dateFormat) { + this.formatter = dateFormat; + } + + @Override + public void write(JsonWriter out, LocalDate date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + out.value(formatter.format(date)); + } + } + + @Override + public LocalDate read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + return LocalDate.parse(date, formatter); + } + } + } + + public static void setOffsetDateTimeFormat(DateTimeFormatter dateFormat) { + offsetDateTimeTypeAdapter.setFormat(dateFormat); + } + + public static void setLocalDateFormat(DateTimeFormatter dateFormat) { + localDateTypeAdapter.setFormat(dateFormat); + } + + {{/jsr310}} + /** + * Gson TypeAdapter for java.sql.Date type + * If the dateFormat is null, a simple "yyyy-MM-dd" format will be used + * (more efficient than SimpleDateFormat). + */ + public static class SqlDateTypeAdapter extends TypeAdapter { + + private DateFormat dateFormat; + + public SqlDateTypeAdapter() {} + + public SqlDateTypeAdapter(DateFormat dateFormat) { + this.dateFormat = dateFormat; + } + + public void setFormat(DateFormat dateFormat) { + this.dateFormat = dateFormat; + } + + @Override + public void write(JsonWriter out, java.sql.Date date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + String value; + if (dateFormat != null) { + value = dateFormat.format(date); + } else { + value = date.toString(); + } + out.value(value); + } + } + + @Override + public java.sql.Date read(JsonReader in) throws IOException { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + try { + if (dateFormat != null) { + return new java.sql.Date(dateFormat.parse(date).getTime()); + } + return new java.sql.Date(ISO8601Utils.parse(date, new ParsePosition(0)).getTime()); + } catch (ParseException e) { + throw new JsonParseException(e); + } + } + } + } + + /** + * Gson TypeAdapter for java.util.Date type + * If the dateFormat is null, ISO8601Utils will be used. + */ + public static class DateTypeAdapter extends TypeAdapter { + + private DateFormat dateFormat; + + public DateTypeAdapter() {} + + public DateTypeAdapter(DateFormat dateFormat) { + this.dateFormat = dateFormat; + } + + public void setFormat(DateFormat dateFormat) { + this.dateFormat = dateFormat; + } + + @Override + public void write(JsonWriter out, Date date) throws IOException { + if (date == null) { + out.nullValue(); + } else { + String value; + if (dateFormat != null) { + value = dateFormat.format(date); + } else { + value = ISO8601Utils.format(date, true); + } + out.value(value); + } + } + + @Override + public Date read(JsonReader in) throws IOException { + try { + switch (in.peek()) { + case NULL: + in.nextNull(); + return null; + default: + String date = in.nextString(); + try { + if (dateFormat != null) { + return dateFormat.parse(date); + } + return ISO8601Utils.parse(date, new ParsePosition(0)); + } catch (ParseException e) { + throw new JsonParseException(e); + } + } + } catch (IllegalArgumentException e) { + throw new JsonParseException(e); + } + } + } + + public static void setDateFormat(DateFormat dateFormat) { + dateTypeAdapter.setFormat(dateFormat); + } + + public static void setSqlDateFormat(DateFormat dateFormat) { + sqlDateTypeAdapter.setFormat(dateFormat); + } +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/ProgressResponseBody.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/ProgressResponseBody.mustache index 50f2eba39..45115940b 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/ProgressResponseBody.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/ProgressResponseBody.mustache @@ -57,5 +57,3 @@ public class ProgressResponseBody extends ResponseBody { }; } } - - diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/README.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/README.mustache index e9be868f5..b4b5d2cdd 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/README.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/README.mustache @@ -6,7 +6,7 @@ - Build date: {{generatedDate}} {{/hideGenerationTimestamp}} -{{#appDescriptionWithNewLines}}{{{appDescriptionWithNewLines}}}{{/appDescriptionWithNewLines}} +{{{appDescriptionWithNewLines}}} {{#infoUrl}} For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}) @@ -18,8 +18,8 @@ ## Requirements Building the API client library requires: -1. Java {{#supportJava6}}1.6{{/supportJava6}}{{^supportJava6}}{{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}}{{/supportJava6}}+ -2. Maven/Gradle +1. Java 1.8+ +2. Maven (3.8.3+)/Gradle (7.2+) ## Installation @@ -55,7 +55,14 @@ Add this dependency to your project's POM: Add this dependency to your project's build file: ```groovy -compile "{{{groupId}}}:{{{artifactId}}}:{{{artifactVersion}}}" + repositories { + mavenCentral() // Needed if the '{{{artifactId}}}' jar has been published to maven central. + mavenLocal() // Needed if the '{{{artifactId}}}' jar has been published to the local maven repo. + } + + dependencies { + implementation "{{{groupId}}}:{{{artifactId}}}:{{{artifactVersion}}}" + } ``` ### Others @@ -114,7 +121,7 @@ public class Example { {{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} {{/allParams}} try { - {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}{{^vendorExtensions.x-group-parameters}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}({{#requiredParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}){{#optionalParams}} + {{#returnType}}{{{.}}} result = {{/returnType}}apiInstance.{{{operationId}}}{{^vendorExtensions.x-group-parameters}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}});{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}({{#requiredParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/requiredParams}}){{#optionalParams}} .{{{paramName}}}({{{paramName}}}){{/optionalParams}} .execute();{{/vendorExtensions.x-group-parameters}}{{#returnType}} System.out.println(result);{{/returnType}} @@ -136,7 +143,7 @@ All URIs are relative to *{{basePath}}* Class | Method | HTTP request | Description ------------ | ------------- | ------------- | ------------- -{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{summary}} {{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} ## Documentation for Models @@ -172,5 +179,5 @@ It's recommended to create an instance of `ApiClient` per thread in a multithrea ## Author -{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}} -{{/hasMore}}{{/apis}}{{/apiInfo}} +{{#apiInfo}}{{#apis}}{{#-last}}{{infoEmail}} +{{/-last}}{{/apis}}{{/apiInfo}} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/additional_properties.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/additional_properties.mustache new file mode 100644 index 000000000..bca54f84d --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/additional_properties.mustache @@ -0,0 +1,46 @@ +{{#isAdditionalPropertiesTrue}} + /** + * A container for additional, undeclared properties. + * This is a holder for any undeclared properties as specified with + * the 'additionalProperties' keyword in the OAS document. + */ + private Map additionalProperties; + + /** + * Set the additional (undeclared) property with the specified name and value. + * If the property does not already exist, create it otherwise replace it. + * + * @param key name of the property + * @param value value of the property + * @return the {{classname}} instance itself + */ + public {{classname}} putAdditionalProperty(String key, Object value) { + if (this.additionalProperties == null) { + this.additionalProperties = new HashMap(); + } + this.additionalProperties.put(key, value); + return this; + } + + /** + * Return the additional (undeclared) property. + * + * @return a map of objects + */ + public Map getAdditionalProperties() { + return additionalProperties; + } + + /** + * Return the additional (undeclared) property with the specified name. + * + * @param key name of the property + * @return an object + */ + public Object getAdditionalProperty(String key) { + if (this.additionalProperties == null) { + return null; + } + return this.additionalProperties.get(key); + } +{{/isAdditionalPropertiesTrue}} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/anyof_model.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/anyof_model.mustache new file mode 100644 index 000000000..bdaddadae --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/anyof_model.mustache @@ -0,0 +1,236 @@ +import javax.ws.rs.core.GenericType; + +import java.io.IOException; +import java.lang.reflect.Type; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.HashMap; +import java.util.Map; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonParseException; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.reflect.TypeToken; +import com.google.gson.JsonPrimitive; +import com.google.gson.annotations.JsonAdapter; +import com.google.gson.annotations.SerializedName; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; + +import {{invokerPackage}}.JSON; + +{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>xmlAnnotation}} +public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-implements}}, {{{.}}}{{/vendorExtensions.x-implements}} { + private static final Logger log = Logger.getLogger({{classname}}.class.getName()); + + public static class CustomTypeAdapterFactory implements TypeAdapterFactory { + @SuppressWarnings("unchecked") + @Override + public TypeAdapter create(Gson gson, TypeToken type) { + if (!{{classname}}.class.isAssignableFrom(type.getRawType())) { + return null; // this class only serializes '{{classname}}' and its subtypes + } + final TypeAdapter elementAdapter = gson.getAdapter(JsonElement.class); + {{#anyOf}} + final TypeAdapter<{{.}}> adapter{{.}} = gson.getDelegateAdapter(this, TypeToken.get({{.}}.class)); + {{/anyOf}} + + return (TypeAdapter) new TypeAdapter<{{classname}}>() { + @Override + public void write(JsonWriter out, {{classname}} value) throws IOException { + if (value == null || value.getActualInstance() == null) { + elementAdapter.write(out, null); + return; + } + + {{#anyOf}} + // check if the actual instance is of the type `{{.}}` + if (value.getActualInstance() instanceof {{.}}) { + JsonObject obj = adapter{{.}}.toJsonTree(({{.}})value.getActualInstance()).getAsJsonObject(); + elementAdapter.write(out, obj); + return; + } + + {{/anyOf}} + throw new IOException("Failed to serialize as the type doesn't match anyOf schemas: {{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}}"); + } + + @Override + public {{classname}} read(JsonReader in) throws IOException { + Object deserialized = null; + JsonObject jsonObject = elementAdapter.read(in).getAsJsonObject(); + + {{#useOneOfDiscriminatorLookup}} + {{#discriminator}} + // use discriminator value for faster anyOf lookup + {{classname}} new{{classname}} = new {{classname}}(); + String discriminatorValue = elementAdapter.read(in).getAsJsonObject().get("{{{propertyBaseName}}}").getAsString(); + switch (discriminatorValue) { + {{#mappedModels}} + case "{{{mappingName}}}": + deserialized = adapter{{modelName}}.fromJsonTree(jsonObject); + new{{classname}}.setActualInstance(deserialized); + return new{{classname}}; + {{/mappedModels}} + default: + log.log(Level.WARNING, String.format("Failed to lookup discriminator value `%s` for {{classname}}. Possible values:{{#mappedModels}} {{{mappingName}}}{{/mappedModels}}", discriminatorValue)); + } + + {{/discriminator}} + {{/useOneOfDiscriminatorLookup}} + {{#anyOf}} + // deserialize {{{.}}} + try { + // validate the JSON object to see if any exception is thrown + {{.}}.validateJsonObject(jsonObject); + log.log(Level.FINER, "Input data matches schema '{{{.}}}'"); + {{classname}} ret = new {{classname}}(); + ret.setActualInstance(adapter{{.}}.fromJsonTree(jsonObject)); + return ret; + } catch (Exception e) { + // deserialization failed, continue + log.log(Level.FINER, "Input data does not match schema '{{{.}}}'", e); + } + + {{/anyOf}} + + throw new IOException(String.format("Failed deserialization for {{classname}}: no class matched. JSON: %s", jsonObject.toString())); + } + }.nullSafe(); + } + } + + // store a list of schema names defined in anyOf + public static final Map schemas = new HashMap(); + + public {{classname}}() { + super("anyOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); + } + + {{#anyOf}} + public {{classname}}({{{.}}} o) { + super("anyOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); + setActualInstance(o); + } + + {{/anyOf}} + static { + {{#anyOf}} + schemas.put("{{{.}}}", new GenericType<{{{.}}}>() { + }); + {{/anyOf}} + } + + @Override + public Map getSchemas() { + return {{classname}}.schemas; + } + + /** + * Set the instance that matches the anyOf child schema, check + * the instance parameter is valid against the anyOf child schemas: + * {{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}} + * + * It could be an instance of the 'anyOf' schemas. + * The anyOf child schemas may themselves be a composed schema (allOf, anyOf, anyOf). + */ + @Override + public void setActualInstance(Object instance) { + {{#isNullable}} + if (instance == null) { + super.setActualInstance(instance); + return; + } + + {{/isNullable}} + {{#anyOf}} + if (instance instanceof {{{.}}}) { + super.setActualInstance(instance); + return; + } + + {{/anyOf}} + throw new RuntimeException("Invalid instance type. Must be {{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}}"); + } + + /** + * Get the actual instance, which can be the following: + * {{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}} + * + * @return The actual instance ({{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}}) + */ + @Override + public Object getActualInstance() { + return super.getActualInstance(); + } + + {{#anyOf}} + /** + * Get the actual instance of `{{{.}}}`. If the actual instance is not `{{{.}}}`, + * the ClassCastException will be thrown. + * + * @return The actual instance of `{{{.}}}` + * @throws ClassCastException if the instance is not `{{{.}}}` + */ + public {{{.}}} get{{{.}}}() throws ClassCastException { + return ({{{.}}})super.getActualInstance(); + } + + {{/anyOf}} + + /** + * Validates the JSON Object and throws an exception if issues found + * + * @param jsonObj JSON Object + * @throws IOException if the JSON Object is invalid with respect to {{classname}} + */ + public static void validateJsonObject(JsonObject jsonObj) throws IOException { + // validate anyOf schemas one by one + int validCount = 0; + {{#anyOf}} + // validate the json string with {{{.}}} + try { + {{{.}}}.validateJsonObject(jsonObj); + return; // return earlier as at least one schema is valid with respect to the Json object + //validCount++; + } catch (Exception e) { + // continue to the next one + } + {{/anyOf}} + if (validCount == 0) { + throw new IOException(String.format("The JSON string is invalid for {{classname}} with anyOf schemas: {{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}}. JSON: %s", jsonObj.toString())); + } + } + + /** + * Create an instance of {{classname}} given an JSON string + * + * @param jsonString JSON string + * @return An instance of {{classname}} + * @throws IOException if the JSON string is invalid with respect to {{classname}} + */ + public static {{{classname}}} fromJson(String jsonString) throws IOException { + return JSON.getGson().fromJson(jsonString, {{{classname}}}.class); + } + + /** + * Convert an instance of {{classname}} to an JSON string + * + * @return JSON string + */ + public String toJson() { + return JSON.getGson().toJson(this); + } +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/api.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/api.mustache index 98bcd3d46..d39478dec 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/api.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/api.mustache @@ -5,6 +5,9 @@ package {{package}}; import {{invokerPackage}}.ApiCallback; import {{invokerPackage}}.ApiClient; import {{invokerPackage}}.ApiException; +{{#dynamicOperations}} +import {{invokerPackage}}.ApiOperation; +{{/dynamicOperations}} import {{invokerPackage}}.ApiResponse; import {{invokerPackage}}.Configuration; import {{invokerPackage}}.Pair; @@ -15,6 +18,10 @@ import {{invokerPackage}}.BeanValidationException; {{/performBeanValidation}} import com.google.gson.reflect.TypeToken; +{{#dynamicOperations}} +import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.parameters.Parameter; +{{/dynamicOperations}} import java.io.IOException; @@ -40,11 +47,17 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +{{#supportStreaming}} +import java.io.InputStream; +{{/supportStreaming}} {{/fullJavaUtil}} +import javax.ws.rs.core.GenericType; {{#operations}} public class {{classname}} { private ApiClient localVarApiClient; + private int localHostIndex; + private String localCustomBaseUrl; public {{classname}}() { this(Configuration.getDefaultApiClient()); @@ -62,6 +75,22 @@ public class {{classname}} { this.localVarApiClient = apiClient; } + public int getHostIndex() { + return localHostIndex; + } + + public void setHostIndex(int hostIndex) { + this.localHostIndex = hostIndex; + } + + public String getCustomBaseUrl() { + return localCustomBaseUrl; + } + + public void setCustomBaseUrl(String customBaseUrl) { + this.localCustomBaseUrl = customBaseUrl; + } + {{#operation}} {{^vendorExtensions.x-group-parameters}}/** * Build call for {{operationId}}{{#allParams}} @@ -90,43 +119,83 @@ public class {{classname}} { @Deprecated {{/isDeprecated}} public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}} okhttp3.Call {{operationId}}Call({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ApiCallback _callback) throws ApiException { + String basePath = null; + // Operation Servers + String[] localBasePaths = new String[] { {{#servers}}"{{{url}}}"{{^-last}}, {{/-last}}{{/servers}} }; + + // Determine Base Path to Use + if (localCustomBaseUrl != null){ + basePath = localCustomBaseUrl; + } else if ( localBasePaths.length > 0 ) { + basePath = localBasePaths[localHostIndex]; + } else { + basePath = null; + } + Object localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; // create path and map variables + {{^dynamicOperations}} String localVarPath = "{{{path}}}"{{#pathParams}} - .replaceAll("\\{" + "{{baseName}}" + "\\}", localVarApiClient.escapeString({{#collectionFormat}}localVarApiClient.collectionPathParameterToString("{{{collectionFormat}}}", {{{paramName}}}){{/collectionFormat}}{{^collectionFormat}}{{{paramName}}}.toString(){{/collectionFormat}})){{/pathParams}}; + .replace("{" + "{{baseName}}" + "}", localVarApiClient.escapeString({{#collectionFormat}}localVarApiClient.collectionPathParameterToString("{{{collectionFormat}}}", {{{paramName}}}){{/collectionFormat}}{{^collectionFormat}}{{{paramName}}}.toString(){{/collectionFormat}})){{/pathParams}}; + {{/dynamicOperations}} + {{#dynamicOperations}} + ApiOperation apiOperation = localVarApiClient.getOperationLookupMap().get("{{{operationId}}}"); + if (apiOperation == null) { + throw new ApiException("Operation not found in OAS"); + } + Operation operation = apiOperation.getOperation(); + String localVarPath = apiOperation.getPath(); + Map paramMap = new HashMap<>(); + {{#allParams}} + {{^isFormParam}} + {{^isBodyParam}} + paramMap.put("{{baseName}}", {{paramName}}); + {{/isBodyParam}} + {{/isFormParam}} + {{/allParams}} + {{/dynamicOperations}} {{javaUtilPrefix}}List localVarQueryParams = new {{javaUtilPrefix}}ArrayList(); {{javaUtilPrefix}}List localVarCollectionQueryParams = new {{javaUtilPrefix}}ArrayList(); + {{javaUtilPrefix}}Map localVarHeaderParams = new {{javaUtilPrefix}}HashMap(); + {{javaUtilPrefix}}Map localVarCookieParams = new {{javaUtilPrefix}}HashMap(); + {{javaUtilPrefix}}Map localVarFormParams = new {{javaUtilPrefix}}HashMap(); + + {{#formParams}} + if ({{paramName}} != null) { + localVarFormParams.put("{{baseName}}", {{paramName}}); + } + + {{/formParams}} + {{^dynamicOperations}} {{#queryParams}} if ({{paramName}} != null) { - {{#collectionFormat}}localVarCollectionQueryParams.addAll(localVarApiClient.parameterToPairs("{{{collectionFormat}}}", {{/collectionFormat}}{{^collectionFormat}}localVarQueryParams.addAll(localVarApiClient.parameterToPair({{/collectionFormat}}"{{baseName}}", {{paramName}})); + {{#collectionFormat}}localVarCollectionQueryParams.addAll(localVarApiClient.parameterToPairs("{{{.}}}", {{/collectionFormat}}{{^collectionFormat}}localVarQueryParams.addAll(localVarApiClient.parameterToPair({{/collectionFormat}}"{{baseName}}", {{paramName}})); } {{/queryParams}} - {{javaUtilPrefix}}Map localVarHeaderParams = new {{javaUtilPrefix}}HashMap(); {{#headerParams}} if ({{paramName}} != null) { localVarHeaderParams.put("{{baseName}}", localVarApiClient.parameterToString({{paramName}})); } {{/headerParams}} - {{javaUtilPrefix}}Map localVarCookieParams = new {{javaUtilPrefix}}HashMap(); {{#cookieParams}} if ({{paramName}} != null) { localVarCookieParams.put("{{baseName}}", localVarApiClient.parameterToString({{paramName}})); } {{/cookieParams}} - {{javaUtilPrefix}}Map localVarFormParams = new {{javaUtilPrefix}}HashMap(); - {{#formParams}} - if ({{paramName}} != null) { - localVarFormParams.put("{{baseName}}", {{paramName}}); - } + {{/dynamicOperations}} + {{#dynamicOperations}} + localVarPath = localVarApiClient.fillParametersFromOperation(operation, paramMap, localVarPath, localVarQueryParams, localVarCollectionQueryParams, localVarHeaderParams, localVarCookieParams); - {{/formParams}} + {{/dynamicOperations}} final String[] localVarAccepts = { - {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} + {{#produces}} + "{{{mediaType}}}"{{^-last}},{{/-last}} + {{/produces}} }; final String localVarAccept = localVarApiClient.selectHeaderAccept(localVarAccepts); if (localVarAccept != null) { @@ -134,13 +203,17 @@ public class {{classname}} { } final String[] localVarContentTypes = { - {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} + {{#consumes}} + "{{{mediaType}}}"{{^-last}},{{/-last}} + {{/consumes}} }; final String localVarContentType = localVarApiClient.selectHeaderContentType(localVarContentTypes); - localVarHeaderParams.put("Content-Type", localVarContentType); + if (localVarContentType != null) { + localVarHeaderParams.put("Content-Type", localVarContentType); + } - String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; - return localVarApiClient.buildCall(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); + String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{^-last}}, {{/-last}}{{/authMethods}} }; + return localVarApiClient.buildCall(basePath, localVarPath, {{^dynamicOperations}}"{{httpMethod}}"{{/dynamicOperations}}{{#dynamicOperations}}apiOperation.getMethod(){{/dynamicOperations}}, localVarQueryParams, localVarCollectionQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAuthNames, _callback); } {{#isDeprecated}} @@ -149,15 +222,16 @@ public class {{classname}} { @SuppressWarnings("rawtypes") private okhttp3.Call {{operationId}}ValidateBeforeCall({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ApiCallback _callback) throws ApiException { {{^performBeanValidation}} - {{#allParams}}{{#required}} + {{#allParams}} + {{#required}} // verify the required parameter '{{paramName}}' is set if ({{paramName}} == null) { throw new ApiException("Missing the required parameter '{{paramName}}' when calling {{operationId}}(Async)"); } - {{/required}}{{/allParams}} - okhttp3.Call localVarCall = {{operationId}}Call({{#allParams}}{{paramName}}, {{/allParams}}_callback); - return localVarCall; + {{/required}} + {{/allParams}} + return {{operationId}}Call({{#allParams}}{{paramName}}, {{/allParams}}_callback); {{/performBeanValidation}} {{#performBeanValidation}} @@ -165,15 +239,13 @@ public class {{classname}} { ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); ExecutableValidator executableValidator = factory.getValidator().forExecutables(); - Object[] parameterValues = { {{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}} }; - Method method = this.getClass().getMethod("{{operationId}}WithHttpInfo"{{#allParams}}, {{#isListContainer}}java.util.List{{/isListContainer}}{{#isMapContainer}}java.util.Map{{/isMapContainer}}{{^isListContainer}}{{^isMapContainer}}{{{dataType}}}{{/isMapContainer}}{{/isListContainer}}.class{{/allParams}}); + Object[] parameterValues = { {{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}} }; + Method method = this.getClass().getMethod("{{operationId}}WithHttpInfo"{{#allParams}}, {{#isArray}}java.util.List{{/isArray}}{{#isMap}}java.util.Map{{/isMap}}{{^isArray}}{{^isMap}}{{{dataType}}}{{/isMap}}{{/isArray}}.class{{/allParams}}); Set> violations = executableValidator.validateParameters(this, method, parameterValues); if (violations.size() == 0) { - okhttp3.Call localVarCall = {{operationId}}Call({{#allParams}}{{paramName}}, {{/allParams}}_callback); - return localVarCall; - + return {{operationId}}Call({{#allParams}}{{paramName}}, {{/allParams}}_callback); } else { throw new BeanValidationException((Set) violations); } @@ -184,7 +256,6 @@ public class {{classname}} { e.printStackTrace(); throw new ApiException(e.getMessage()); } - {{/performBeanValidation}} } @@ -193,7 +264,7 @@ public class {{classname}} { * {{summary}} * {{notes}}{{#allParams}} * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}}{{/allParams}}{{#returnType}} - * @return {{returnType}}{{/returnType}} + * @return {{.}}{{/returnType}} * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body {{#responses.0}} * @http.response.details @@ -215,17 +286,25 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { - {{#returnType}}ApiResponse<{{{returnType}}}> localVarResp = {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}} + {{#vendorExtensions.x-streaming}} + public {{#returnType}}InputStream {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { + {{#returnType}}InputStream localVarResp = {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});{{#returnType}} + return localVarResp;{{/returnType}} + } + {{/vendorExtensions.x-streaming}} + {{^vendorExtensions.x-streaming}} + public {{#returnType}}{{{.}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { + {{#returnType}}ApiResponse<{{{.}}}> localVarResp = {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});{{#returnType}} return localVarResp.getData();{{/returnType}} } + {{/vendorExtensions.x-streaming}} {{/vendorExtensions.x-group-parameters}} {{^vendorExtensions.x-group-parameters}}/** * {{summary}} * {{notes}}{{#allParams}} * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}{{/isContainer}}){{/required}}{{/allParams}} - * @return ApiResponse<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + * @return ApiResponse<{{returnType}}{{^returnType}}Void{{/returnType}}> * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body {{#responses.0}} * @http.response.details @@ -247,11 +326,46 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}} ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { + public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-streaming}} InputStream {{operationId}}WithHttpInfo({{#allParams}}{{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { okhttp3.Call localVarCall = {{operationId}}ValidateBeforeCall({{#allParams}}{{paramName}}, {{/allParams}}null); - {{#returnType}}Type localVarReturnType = new TypeToken<{{{returnType}}}>(){}.getType(); - return localVarApiClient.execute(localVarCall, localVarReturnType);{{/returnType}}{{^returnType}}return localVarApiClient.execute(localVarCall);{{/returnType}} + {{#returnType}} + {{#errorObjectType}} + try { + Type localVarReturnType = new TypeToken<{{{returnType}}}>(){}.getType(); + return localVarApiClient.executeStream(localVarCall, localVarReturnType); + } catch (ApiException e) { + e.setErrorObject(localVarApiClient.getJSON().getGson().fromJson(e.getResponseBody(), new TypeToken<{{{errorObjectType}}}>(){}.getType())); + throw e; + } + {{/errorObjectType}} + {{^errorObjectType}} + Type localVarReturnType = new TypeToken<{{{returnType}}}>(){}.getType(); + return localVarApiClient.executeStream(localVarCall, localVarReturnType); + {{/errorObjectType}} + {{/returnType}} + } + {{/vendorExtensions.x-streaming}}{{^vendorExtensions.x-streaming}} ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { + okhttp3.Call localVarCall = {{operationId}}ValidateBeforeCall({{#allParams}}{{paramName}}, {{/allParams}}null); + {{^returnType}} + return localVarApiClient.execute(localVarCall); + {{/returnType}} + {{#returnType}} + {{#errorObjectType}} + try { + Type localVarReturnType = new TypeToken<{{{returnType}}}>(){}.getType(); + return localVarApiClient.execute(localVarCall, localVarReturnType); + } catch (ApiException e) { + e.setErrorObject(localVarApiClient.getJSON().getGson().fromJson(e.getResponseBody(), new TypeToken<{{{errorObjectType}}}>(){}.getType())); + throw e; + } + {{/errorObjectType}} + {{^errorObjectType}} + Type localVarReturnType = new TypeToken<{{{returnType}}}>(){}.getType(); + return localVarApiClient.execute(localVarCall, localVarReturnType); + {{/errorObjectType}} + {{/returnType}} } + {{/vendorExtensions.x-streaming}} {{^vendorExtensions.x-group-parameters}}/** * {{summary}} (asynchronously) @@ -280,7 +394,7 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}} okhttp3.Call {{operationId}}Async({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ApiCallback<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> _callback) throws ApiException { + public{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}private{{/vendorExtensions.x-group-parameters}} okhttp3.Call {{operationId}}Async({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}final ApiCallback<{{{returnType}}}{{^returnType}}Void{{/returnType}}> _callback) throws ApiException { okhttp3.Call localVarCall = {{operationId}}ValidateBeforeCall({{#allParams}}{{paramName}}, {{/allParams}}_callback); {{#returnType}}Type localVarReturnType = new TypeToken<{{{returnType}}}>(){}.getType(); @@ -297,7 +411,7 @@ public class {{classname}} { private {{{dataType}}} {{paramName}}; {{/optionalParams}} - private API{{operationId}}Request({{#requiredParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}) { + private API{{operationId}}Request({{#requiredParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/requiredParams}}) { {{#requiredParams}} this.{{paramName}} = {{paramName}}; {{/requiredParams}} @@ -342,7 +456,7 @@ public class {{classname}} { /** * Execute {{operationId}} request{{#returnType}} - * @return {{returnType}}{{/returnType}} + * @return {{.}}{{/returnType}} * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body {{#responses.0}} * @http.response.details @@ -360,14 +474,21 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}} execute() throws ApiException { - {{#returnType}}ApiResponse<{{{returnType}}}> localVarResp = {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{#returnType}} + {{^vendorExtensions.x-streaming}} + public {{{returnType}}}{{^returnType}}void{{/returnType}} execute() throws ApiException { + {{#returnType}}ApiResponse<{{{.}}}> localVarResp = {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});{{#returnType}} return localVarResp.getData();{{/returnType}} } + {{/vendorExtensions.x-streaming}} + {{#vendorExtensions.x-streaming}} + public InputStream execute() throws ApiException { + return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + } + {{/vendorExtensions.x-streaming}} /** * Execute {{operationId}} request with HTTP info returned - * @return ApiResponse<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + * @return ApiResponse<{{returnType}}{{^returnType}}Void{{/returnType}}> * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body {{#responses.0}} * @http.response.details @@ -385,9 +506,16 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public ApiResponse<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> executeWithHttpInfo() throws ApiException { - return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{^vendorExtensions.x-streaming}} + public ApiResponse<{{{returnType}}}{{^returnType}}Void{{/returnType}}> executeWithHttpInfo() throws ApiException { + return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + } + {{/vendorExtensions.x-streaming}} + {{#vendorExtensions.x-streaming}} + public InputStream executeWithHttpInfo() throws ApiException { + return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); } + {{/vendorExtensions.x-streaming}} /** * Execute {{operationId}} request (asynchronously) @@ -410,7 +538,7 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public okhttp3.Call executeAsync(final ApiCallback<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> _callback) throws ApiException { + public okhttp3.Call executeAsync(final ApiCallback<{{{returnType}}}{{^returnType}}Void{{/returnType}}> _callback) throws ApiException { return {{operationId}}Async({{#allParams}}{{paramName}}, {{/allParams}}_callback); } } @@ -440,8 +568,8 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public API{{operationId}}Request {{operationId}}({{#requiredParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}) { - return new API{{operationId}}Request({{#requiredParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}); + public API{{operationId}}Request {{operationId}}({{#requiredParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/requiredParams}}) { + return new API{{operationId}}Request({{#requiredParams}}{{paramName}}{{^-last}}, {{/-last}}{{/requiredParams}}); } {{/vendorExtensions.x-group-parameters}} {{/operation}} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/apiException.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/apiException.mustache index e89524565..dd224d582 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/apiException.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/apiException.mustache @@ -5,62 +5,130 @@ package {{invokerPackage}}; import java.util.Map; import java.util.List; {{#caseInsensitiveResponseHeaders}} -import java.util.Map.Entry; +import java.util.Map.Entry; import java.util.TreeMap; {{/caseInsensitiveResponseHeaders}} +import javax.ws.rs.core.GenericType; + +/** + *

ApiException class.

+ */ +@SuppressWarnings("serial") {{>generatedAnnotation}} public class ApiException extends{{#useRuntimeException}} RuntimeException {{/useRuntimeException}}{{^useRuntimeException}} Exception {{/useRuntimeException}}{ private int code = 0; private Map> responseHeaders = null; private String responseBody = null; - + {{#errorObjectType}} + private {{{errorObjectType}}} errorObject = null; + {{/errorObjectType}} + + /** + *

Constructor for ApiException.

+ */ public ApiException() {} + /** + *

Constructor for ApiException.

+ * + * @param throwable a {@link java.lang.Throwable} object + */ public ApiException(Throwable throwable) { super(throwable); } + /** + *

Constructor for ApiException.

+ * + * @param message the error message + */ public ApiException(String message) { super(message); } + /** + *

Constructor for ApiException.

+ * + * @param message the error message + * @param throwable a {@link java.lang.Throwable} object + * @param code HTTP status code + * @param responseHeaders a {@link java.util.Map} of HTTP response headers + * @param responseBody the response body + */ public ApiException(String message, Throwable throwable, int code, Map> responseHeaders, String responseBody) { super(message, throwable); this.code = code; {{#caseInsensitiveResponseHeaders}} Map> headers = new TreeMap>(String.CASE_INSENSITIVE_ORDER); for(Entry> entry : responseHeaders.entrySet()){ - headers.put(entry.getKey().toLowerCase(), entry.getValue()); + headers.put(entry.getKey().toLowerCase(), entry.getValue()); } {{/caseInsensitiveResponseHeaders}} this.responseHeaders = {{#caseInsensitiveResponseHeaders}}headers{{/caseInsensitiveResponseHeaders}}{{^caseInsensitiveResponseHeaders}}responseHeaders{{/caseInsensitiveResponseHeaders}}; this.responseBody = responseBody; } + /** + *

Constructor for ApiException.

+ * + * @param message the error message + * @param code HTTP status code + * @param responseHeaders a {@link java.util.Map} of HTTP response headers + * @param responseBody the response body + */ public ApiException(String message, int code, Map> responseHeaders, String responseBody) { this(message, (Throwable) null, code, responseHeaders, responseBody); } + /** + *

Constructor for ApiException.

+ * + * @param message the error message + * @param throwable a {@link java.lang.Throwable} object + * @param code HTTP status code + * @param responseHeaders a {@link java.util.Map} of HTTP response headers + */ public ApiException(String message, Throwable throwable, int code, Map> responseHeaders) { this(message, throwable, code, responseHeaders, null); } + /** + *

Constructor for ApiException.

+ * + * @param code HTTP status code + * @param responseHeaders a {@link java.util.Map} of HTTP response headers + * @param responseBody the response body + */ public ApiException(int code, Map> responseHeaders, String responseBody) { - this((String) null, (Throwable) null, code, responseHeaders, responseBody); + this("Response Code: " + code + " Response Body: " + responseBody, (Throwable) null, code, responseHeaders, responseBody); } + /** + *

Constructor for ApiException.

+ * + * @param code HTTP status code + * @param message a {@link java.lang.String} object + */ public ApiException(int code, String message) { super(message); this.code = code; } + /** + *

Constructor for ApiException.

+ * + * @param code HTTP status code + * @param message the error message + * @param responseHeaders a {@link java.util.Map} of HTTP response headers + * @param responseBody the response body + */ public ApiException(int code, String message, Map> responseHeaders, String responseBody) { this(code, message); {{#caseInsensitiveResponseHeaders}} Map> headers = new TreeMap>(String.CASE_INSENSITIVE_ORDER); for(Entry> entry : responseHeaders.entrySet()){ - headers.put(entry.getKey().toLowerCase(), entry.getValue()); + headers.put(entry.getKey().toLowerCase(), entry.getValue()); } {{/caseInsensitiveResponseHeaders}} this.responseHeaders = {{#caseInsensitiveResponseHeaders}}headers{{/caseInsensitiveResponseHeaders}}{{^caseInsensitiveResponseHeaders}}responseHeaders{{/caseInsensitiveResponseHeaders}}; @@ -93,4 +161,34 @@ public class ApiException extends{{#useRuntimeException}} RuntimeException {{/us public String getResponseBody() { return responseBody; } + + /** + * Get the exception message including HTTP response data. + * + * @return The exception message + */ + public String getMessage() { + return String.format("Message: %s%nHTTP response code: %s%nHTTP response body: %s%nHTTP response headers: %s", + super.getMessage(), this.getCode(), this.getResponseBody(), this.getResponseHeaders()); + } + {{#errorObjectType}} + + /** + * Get the error object. + * + * @return Error object + */ + public {{{errorObjectType}}} getErrorObject() { + return errorObject; + } + + /** + * Get the error object. + * + * @param errorObject Error object + */ + public void setErrorObject({{{errorObjectType}}} errorObject) { + this.errorObject = errorObject; + } + {{/errorObjectType}} } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/api_doc.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/api_doc.mustache index c7ce067ce..f97eab5c7 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/api_doc.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/api_doc.mustache @@ -1,23 +1,23 @@ # {{classname}}{{#description}} -{{description}}{{/description}} +{{.}}{{/description}} All URIs are relative to *{{basePath}}* -Method | HTTP request | Description -------------- | ------------- | ------------- -{{#operations}}{{#operation}}[**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +| Method | HTTP request | Description | +|------------- | ------------- | -------------| +{{#operations}}{{#operation}}| [**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{summary}} | {{/operation}}{{/operations}} {{#operations}} {{#operation}} # **{{operationId}}**{{^vendorExtensions.x-group-parameters}} -> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}){{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}} -> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#requiredParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}){{#optionalParams}}.{{paramName}}({{paramName}}){{/optionalParams}}.execute();{{/vendorExtensions.x-group-parameters}} +> {{#returnType}}{{.}} {{/returnType}}{{operationId}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}}){{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}} +> {{#returnType}}{{.}} {{/returnType}}{{operationId}}({{#requiredParams}}{{paramName}}{{^-last}}, {{/-last}}{{/requiredParams}}){{#optionalParams}}.{{paramName}}({{paramName}}){{/optionalParams}}.execute();{{/vendorExtensions.x-group-parameters}} {{summary}}{{#notes}} -{{notes}}{{/notes}} +{{.}}{{/notes}} ### Example ```java @@ -58,7 +58,7 @@ public class Example { {{{dataType}}} {{{paramName}}} = {{{example}}}; // {{{dataType}}} | {{{description}}} {{/allParams}} try { - {{#returnType}}{{{returnType}}} result = {{/returnType}}apiInstance.{{{operationId}}}{{^vendorExtensions.x-group-parameters}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}({{#requiredParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}){{#optionalParams}} + {{#returnType}}{{{.}}} result = {{/returnType}}apiInstance.{{{operationId}}}{{^vendorExtensions.x-group-parameters}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}});{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}({{#requiredParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/requiredParams}}){{#optionalParams}} .{{{paramName}}}({{{paramName}}}){{/optionalParams}} .execute();{{/vendorExtensions.x-group-parameters}}{{#returnType}} System.out.println(result);{{/returnType}} @@ -75,9 +75,9 @@ public class Example { ### Parameters {{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{#allParams}}{{#-last}} -Name | Type | Description | Notes -------------- | ------------- | ------------- | -------------{{/-last}}{{/allParams}} -{{#allParams}} **{{paramName}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}[**{{dataType}}**]({{baseType}}.md){{/isFile}}{{/isPrimitiveType}}| {{description}} |{{^required}} [optional]{{/required}}{{^isContainer}}{{#defaultValue}} [default to {{defaultValue}}]{{/defaultValue}}{{/isContainer}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}} +| Name | Type | Description | Notes | +|------------- | ------------- | ------------- | -------------|{{/-last}}{{/allParams}} +{{#allParams}}| **{{paramName}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}[**{{dataType}}**]({{baseType}}.md){{/isFile}}{{/isPrimitiveType}}| {{description}} |{{^required}} [optional]{{/required}}{{^isContainer}}{{#defaultValue}} [default to {{.}}]{{/defaultValue}}{{/isContainer}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}} | {{/allParams}} ### Return type @@ -90,15 +90,15 @@ Name | Type | Description | Notes ### HTTP request headers - - **Content-Type**: {{#consumes}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} - - **Accept**: {{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}{{^produces}}Not defined{{/produces}} + - **Content-Type**: {{#consumes}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} + - **Accept**: {{#produces}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/produces}}{{^produces}}Not defined{{/produces}} {{#responses.0}} ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| {{#responses}} -**{{code}}** | {{message}} | {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}} | +| **{{code}}** | {{message}} | {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}} | {{/responses}} {{/responses.0}} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/api_test.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/api_test.mustache index b5693776b..f14f2cbc1 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/api_test.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/api_test.mustache @@ -5,43 +5,58 @@ package {{package}}; import {{invokerPackage}}.ApiException; {{#imports}}import {{import}}; {{/imports}} -import org.junit.Test; -import org.junit.Ignore; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; {{^fullJavaUtil}} import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +{{#supportStreaming}} +import java.io.InputStream; +{{/supportStreaming}} {{/fullJavaUtil}} /** * API tests for {{classname}} */ -@Ignore +@Disabled public class {{classname}}Test { private final {{classname}} api = new {{classname}}(); - {{#operations}}{{#operation}} + {{#operations}} + {{#operation}} /** + {{#summary}} * {{summary}} * + {{/summary}} + {{#notes}} * {{notes}} * - * @throws ApiException - * if the Api call fails + {{/notes}} + * @throws ApiException if the Api call fails */ @Test public void {{operationId}}Test() throws ApiException { {{#allParams}} {{{dataType}}} {{paramName}} = null; {{/allParams}} - {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}{{^vendorExtensions.x-group-parameters}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}({{#requiredParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/requiredParams}}){{#optionalParams}} + {{#vendorExtensions.x-streaming}} + InputStream response = api.{{operationId}}{{^vendorExtensions.x-group-parameters}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}({{#requiredParams}}{{paramName}}{{^-last}}, {{/-last}}{{/requiredParams}}){{#optionalParams}} .{{paramName}}({{paramName}}){{/optionalParams}} .execute();{{/vendorExtensions.x-group-parameters}} - + {{/vendorExtensions.x-streaming}} + {{^vendorExtensions.x-streaming}} + {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}{{^vendorExtensions.x-group-parameters}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});{{/vendorExtensions.x-group-parameters}}{{#vendorExtensions.x-group-parameters}}({{#requiredParams}}{{paramName}}{{^-last}}, {{/-last}}{{/requiredParams}}){{#optionalParams}} + .{{paramName}}({{paramName}}){{/optionalParams}} + .execute();{{/vendorExtensions.x-group-parameters}} + {{/vendorExtensions.x-streaming}} // TODO: test validations } - {{/operation}}{{/operations}} + + {{/operation}} + {{/operations}} } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/auth/ApiKeyAuth.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/auth/ApiKeyAuth.mustache new file mode 100644 index 000000000..a0dda669a --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/auth/ApiKeyAuth.mustache @@ -0,0 +1,69 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.ApiException; +import {{invokerPackage}}.Pair; + +import java.net.URI; +import java.util.Map; +import java.util.List; + +{{>generatedAnnotation}} +public class ApiKeyAuth implements Authentication { + private final String location; + private final String paramName; + + private String apiKey; + private String apiKeyPrefix; + + public ApiKeyAuth(String location, String paramName) { + this.location = location; + this.paramName = paramName; + } + + public String getLocation() { + return location; + } + + public String getParamName() { + return paramName; + } + + public String getApiKey() { + return apiKey; + } + + public void setApiKey(String apiKey) { + this.apiKey = apiKey; + } + + public String getApiKeyPrefix() { + return apiKeyPrefix; + } + + public void setApiKeyPrefix(String apiKeyPrefix) { + this.apiKeyPrefix = apiKeyPrefix; + } + + @Override + public void applyToParams(List queryParams, Map headerParams, Map cookieParams, + String payload, String method, URI uri) throws ApiException { + if (apiKey == null) { + return; + } + String value; + if (apiKeyPrefix != null) { + value = apiKeyPrefix + " " + apiKey; + } else { + value = apiKey; + } + if ("query".equals(location)) { + queryParams.add(new Pair(paramName, value)); + } else if ("header".equals(location)) { + headerParams.put(paramName, value); + } else if ("cookie".equals(location)) { + cookieParams.put(paramName, value); + } + } +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/auth/Authentication.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/auth/Authentication.mustache new file mode 100644 index 000000000..c4ad338c7 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/auth/Authentication.mustache @@ -0,0 +1,25 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.Pair; +import {{invokerPackage}}.ApiException; + +import java.net.URI; +import java.util.Map; +import java.util.List; + +public interface Authentication { + /** + * Apply authentication settings to header and query params. + * + * @param queryParams List of query parameters + * @param headerParams Map of header parameters + * @param cookieParams Map of cookie parameters + * @param payload HTTP request body + * @param method HTTP method + * @param uri URI + * @throws ApiException if failed to update the parameters + */ + void applyToParams(List queryParams, Map headerParams, Map cookieParams, String payload, String method, URI uri) throws ApiException; +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/auth/HttpBasicAuth.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/auth/HttpBasicAuth.mustache index 9cff50a74..417a89e34 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/auth/HttpBasicAuth.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/auth/HttpBasicAuth.mustache @@ -3,9 +3,11 @@ package {{invokerPackage}}.auth; import {{invokerPackage}}.Pair; +import {{invokerPackage}}.ApiException; import okhttp3.Credentials; +import java.net.URI; import java.util.Map; import java.util.List; @@ -32,7 +34,8 @@ public class HttpBasicAuth implements Authentication { } @Override - public void applyToParams(List queryParams, Map headerParams, Map cookieParams) { + public void applyToParams(List queryParams, Map headerParams, Map cookieParams, + String payload, String method, URI uri) throws ApiException { if (username == null && password == null) { return; } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/auth/HttpBearerAuth.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/auth/HttpBearerAuth.mustache new file mode 100644 index 000000000..c8a9fce29 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/auth/HttpBearerAuth.mustache @@ -0,0 +1,52 @@ +{{>licenseInfo}} + +package {{invokerPackage}}.auth; + +import {{invokerPackage}}.ApiException; +import {{invokerPackage}}.Pair; + +import java.net.URI; +import java.util.Map; +import java.util.List; + +{{>generatedAnnotation}} +public class HttpBearerAuth implements Authentication { + private final String scheme; + private String bearerToken; + + public HttpBearerAuth(String scheme) { + this.scheme = scheme; + } + + /** + * Gets the token, which together with the scheme, will be sent as the value of the Authorization header. + * + * @return The bearer token + */ + public String getBearerToken() { + return bearerToken; + } + + /** + * Sets the token, which together with the scheme, will be sent as the value of the Authorization header. + * + * @param bearerToken The bearer token to send in the Authorization header + */ + public void setBearerToken(String bearerToken) { + this.bearerToken = bearerToken; + } + + @Override + public void applyToParams(List queryParams, Map headerParams, Map cookieParams, + String payload, String method, URI uri) throws ApiException { + if (bearerToken == null) { + return; + } + + headerParams.put("Authorization", (scheme != null ? upperCaseBearer(scheme) + " " : "") + bearerToken); + } + + private static String upperCaseBearer(String scheme) { + return ("bearer".equalsIgnoreCase(scheme)) ? "Bearer" : scheme; + } +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/auth/OAuth.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/auth/OAuth.mustache similarity index 81% rename from boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/auth/OAuth.mustache rename to boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/auth/OAuth.mustache index 8622798ad..34d359857 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/jersey2-experimental/auth/OAuth.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/auth/OAuth.mustache @@ -22,7 +22,8 @@ public class OAuth implements Authentication { } @Override - public void applyToParams(List queryParams, Map headerParams, Map cookieParams, String payload, String method, URI uri) throws ApiException { + public void applyToParams(List queryParams, Map headerParams, Map cookieParams, + String payload, String method, URI uri) throws ApiException { if (accessToken != null) { headerParams.put("Authorization", "Bearer " + accessToken); } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/auth/OAuthOkHttpClient.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/auth/OAuthOkHttpClient.mustache index 46b2021c9..f11b22c62 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/auth/OAuthOkHttpClient.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/auth/OAuthOkHttpClient.mustache @@ -47,7 +47,7 @@ public class OAuthOkHttpClient implements HttpClient { } } - RequestBody body = request.getBody() != null ? RequestBody.create(mediaType, request.getBody()) : null; + RequestBody body = request.getBody() != null ? RequestBody.create(request.getBody(), mediaType) : null; requestBuilder.method(requestMethod, body); try { @@ -56,6 +56,7 @@ public class OAuthOkHttpClient implements HttpClient { response.body().string(), response.body().contentType().toString(), response.code(), + response.headers().toMultimap(), responseClass); } catch (IOException e) { throw new OAuthSystemException(e); diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/auth/RetryingOAuth.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/auth/RetryingOAuth.mustache index 3ddacedb7..8fea0d292 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/auth/RetryingOAuth.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/auth/RetryingOAuth.mustache @@ -1,6 +1,7 @@ {{#hasOAuthMethods}} package {{invokerPackage}}.auth; +import {{invokerPackage}}.ApiException; import {{invokerPackage}}.Pair; import okhttp3.Interceptor; @@ -19,6 +20,7 @@ import org.apache.oltu.oauth2.common.message.types.GrantType; import java.io.IOException; import java.net.HttpURLConnection; +import java.net.URI; import java.util.Map; import java.util.List; @@ -27,22 +29,31 @@ public class RetryingOAuth extends OAuth implements Interceptor { private TokenRequestBuilder tokenRequestBuilder; + /** + * @param client An OkHttp client + * @param tokenRequestBuilder A token request builder + */ public RetryingOAuth(OkHttpClient client, TokenRequestBuilder tokenRequestBuilder) { this.oAuthClient = new OAuthClient(new OAuthOkHttpClient(client)); this.tokenRequestBuilder = tokenRequestBuilder; } + /** + * @param tokenRequestBuilder A token request builder + */ public RetryingOAuth(TokenRequestBuilder tokenRequestBuilder) { this(new OkHttpClient(), tokenRequestBuilder); } /** - @param tokenUrl The token URL to be used for this OAuth2 flow. - Applicable to the following OAuth2 flows: "password", "clientCredentials" and "authorizationCode". - The value must be an absolute URL. - @param clientId The OAuth2 client ID for the "clientCredentials" flow. - @param clientSecret The OAuth2 client secret for the "clientCredentials" flow. - */ + * @param tokenUrl The token URL to be used for this OAuth2 flow. + * Applicable to the following OAuth2 flows: "password", "clientCredentials" and "authorizationCode". + * The value must be an absolute URL. + * @param clientId The OAuth2 client ID for the "clientCredentials" flow. + * @param flow OAuth flow. + * @param clientSecret The OAuth2 client secret for the "clientCredentials" flow. + * @param parameters A map of string. + */ public RetryingOAuth( String tokenUrl, String clientId, @@ -55,24 +66,29 @@ public class RetryingOAuth extends OAuth implements Interceptor { .setClientSecret(clientSecret)); setFlow(flow); if (parameters != null) { - for (String paramName : parameters.keySet()) { - tokenRequestBuilder.setParameter(paramName, parameters.get(paramName)); + for (Map.Entry entry : parameters.entrySet()) { + tokenRequestBuilder.setParameter(entry.getKey(), entry.getValue()); } } } + /** + * Set the OAuth flow + * + * @param flow The OAuth flow. + */ public void setFlow(OAuthFlow flow) { switch(flow) { - case accessCode: + case ACCESS_CODE: tokenRequestBuilder.setGrantType(GrantType.AUTHORIZATION_CODE); break; - case implicit: + case IMPLICIT: tokenRequestBuilder.setGrantType(GrantType.IMPLICIT); break; - case password: + case PASSWORD: tokenRequestBuilder.setGrantType(GrantType.PASSWORD); break; - case application: + case APPLICATION: tokenRequestBuilder.setGrantType(GrantType.CLIENT_CREDENTIALS); break; default: @@ -114,8 +130,8 @@ public class RetryingOAuth extends OAuth implements Interceptor { } Map headers = oAuthRequest.getHeaders(); - for (String headerName : headers.keySet()) { - requestBuilder.addHeader(headerName, headers.get(headerName)); + for (Map.Entry entry : headers.entrySet()) { + requestBuilder.addHeader(entry.getKey(), entry.getValue()); } requestBuilder.url(oAuthRequest.getLocationUri()); @@ -146,8 +162,12 @@ public class RetryingOAuth extends OAuth implements Interceptor { } } - /* + /** * Returns true if the access token has been updated + * + * @param requestAccessToken the request access token + * @return True if the update is successful + * @throws java.io.IOException If fail to update the access token */ public synchronized boolean updateAccessToken(String requestAccessToken) throws IOException { if (getAccessToken() == null || getAccessToken().equals(requestAccessToken)) { @@ -156,27 +176,36 @@ public class RetryingOAuth extends OAuth implements Interceptor { oAuthClient.accessToken(tokenRequestBuilder.buildBodyMessage()); if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) { setAccessToken(accessTokenResponse.getAccessToken()); - return !getAccessToken().equals(requestAccessToken); } } catch (OAuthSystemException | OAuthProblemException e) { throw new IOException(e); } } - - return false; + return getAccessToken() == null || !getAccessToken().equals(requestAccessToken); } + /** + * Gets the token request builder + * + * @return A token request builder + */ public TokenRequestBuilder getTokenRequestBuilder() { return tokenRequestBuilder; } + /** + * Sets the token request builder + * + * @param tokenRequestBuilder Token request builder + */ public void setTokenRequestBuilder(TokenRequestBuilder tokenRequestBuilder) { this.tokenRequestBuilder = tokenRequestBuilder; } // Applying authorization to parameters is performed in the retryingIntercept method @Override - public void applyToParams(List queryParams, Map headerParams, Map cookieParams) { + public void applyToParams(List queryParams, Map headerParams, Map cookieParams, + String payload, String method, URI uri) throws ApiException { // No implementation necessary } } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/build.gradle.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/build.gradle.mustache index 919132767..2183fa8d7 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/build.gradle.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/build.gradle.mustache @@ -3,23 +3,24 @@ apply plugin: 'eclipse' {{#sourceFolder}} apply plugin: 'java' {{/sourceFolder}} +apply plugin: 'com.diffplug.spotless' group = '{{groupId}}' version = '{{artifactVersion}}' buildscript { repositories { - maven { url "https://repo1.maven.org/maven2" } - jcenter() + mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:2.3.+' - classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' + classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1' + classpath 'com.diffplug.spotless:spotless-plugin-gradle:6.11.0' } } repositories { - jcenter() + mavenCentral() } {{#sourceFolder}} sourceSets { @@ -40,20 +41,8 @@ if(hasProperty('target') && target == 'android') { targetSdkVersion 25 } compileOptions { - {{#supportJava6}} - sourceCompatibility JavaVersion.VERSION_1_6 - targetCompatibility JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} - {{#java8}} sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 - {{/java8}} - {{^java8}} - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 - {{/java8}} - {{/supportJava6}} } // Rename the aar correctly @@ -68,7 +57,7 @@ if(hasProperty('target') && target == 'android') { } dependencies { - provided 'javax.annotation:javax.annotation-api:1.3.2' + provided "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version" } } @@ -80,7 +69,7 @@ if(hasProperty('target') && target == 'android') { task.from variant.javaCompile.destinationDir task.destinationDir = project.file("${project.buildDir}/outputs/jar") task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" - artifacts.add('archives', task); + artifacts.add('archives', task) } } @@ -96,26 +85,17 @@ if(hasProperty('target') && target == 'android') { } else { apply plugin: 'java' - apply plugin: 'maven' - - {{#supportJava6}} - sourceCompatibility = JavaVersion.VERSION_1_6 - targetCompatibility = JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} - {{#java8}} + apply plugin: 'maven-publish' + sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 - {{/java8}} - {{^java8}} - sourceCompatibility = JavaVersion.VERSION_1_7 - targetCompatibility = JavaVersion.VERSION_1_7 - {{/java8}} - {{/supportJava6}} - - install { - repositories.mavenInstaller { - pom.artifactId = '{{artifactId}}' + + publishing { + publications { + maven(MavenPublication) { + artifactId = '{{artifactId}}' + from components.java + } } } @@ -125,26 +105,79 @@ if(hasProperty('target') && target == 'android') { } } +ext { + jakarta_annotation_version = "1.3.5" +} + dependencies { - compile 'io.swagger:swagger-annotations:1.5.24' - compile "com.google.code.findbugs:jsr305:3.0.2" - compile 'com.squareup.okhttp3:okhttp:3.14.7' - compile 'com.squareup.okhttp3:logging-interceptor:3.14.7' - compile 'com.google.code.gson:gson:2.8.6' - compile 'io.gsonfire:gson-fire:1.8.4' + implementation 'io.swagger:swagger-annotations:1.6.8' + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation 'com.squareup.okhttp3:okhttp:4.10.0' + implementation 'com.squareup.okhttp3:logging-interceptor:4.10.0' + implementation 'com.google.code.gson:gson:2.9.1' + implementation 'io.gsonfire:gson-fire:1.8.5' + implementation 'javax.ws.rs:jsr311-api:1.1.1' + implementation 'javax.ws.rs:javax.ws.rs-api:2.1.1' + {{#openApiNullable}} + implementation 'org.openapitools:jackson-databind-nullable:0.2.4' + {{/openApiNullable}} {{#hasOAuthMethods}} - compile group: 'org.apache.oltu.oauth2', name: 'org.apache.oltu.oauth2.client', version: '1.0.1' + implementation group: 'org.apache.oltu.oauth2', name: 'org.apache.oltu.oauth2.client', version: '1.0.2' {{/hasOAuthMethods}} - compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.10' + implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.12.0' {{#joda}} - compile 'joda-time:joda-time:2.9.9' + implementation 'joda-time:joda-time:2.9.9' {{/joda}} - {{#threetenbp}} - compile 'org.threeten:threetenbp:1.4.3' - {{/threetenbp}} - testCompile 'junit:junit:4.13' + {{#dynamicOperations}} + implementation 'io.swagger.parser.v3:swagger-parser-v3:2.0.30' + {{/dynamicOperations}} + implementation "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version" + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.1' + testImplementation 'org.mockito:mockito-core:3.12.4' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.1' } javadoc { options.tags = [ "http.response.details:a:Http Response Details" ] } + +// Use spotless plugin to automatically format code, remove unused import, etc +// To apply changes directly to the file, run `gradlew spotlessApply` +// Ref: https://github.com/diffplug/spotless/tree/main/plugin-gradle +spotless { + // comment out below to run spotless as part of the `check` task + enforceCheck false + + format 'misc', { + // define the files (e.g. '*.gradle', '*.md') to apply `misc` to + target '.gitignore' + + // define the steps to apply to those files + trimTrailingWhitespace() + indentWithSpaces() // Takes an integer argument if you don't like 4 + endWithNewline() + } + java { + // don't need to set target, it is inferred from java + + // apply a specific flavor of google-java-format + googleJavaFormat('1.8').aosp().reflowLongStrings() + + removeUnusedImports() + importOrder() + } +} + +test { + // Enable JUnit 5 (Gradle 4.6+). + useJUnitPlatform() + + // Always run tests, even when nothing changed. + dependsOn 'cleanTest' + + // Show test results. + testLogging { + events "passed", "skipped", "failed" + } + +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/build.sbt.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/build.sbt.mustache index 7c137589e..77d6183a9 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/build.sbt.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/build.sbt.mustache @@ -9,24 +9,31 @@ lazy val root = (project in file(".")). publishArtifact in (Compile, packageDoc) := false, resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( - "io.swagger" % "swagger-annotations" % "1.5.24", - "com.squareup.okhttp3" % "okhttp" % "3.14.7", - "com.squareup.okhttp3" % "logging-interceptor" % "3.14.7", - "com.google.code.gson" % "gson" % "2.8.6", - "org.apache.commons" % "commons-lang3" % "3.10", + "io.swagger" % "swagger-annotations" % "1.6.5", + "com.squareup.okhttp3" % "okhttp" % "4.10.0", + "com.squareup.okhttp3" % "logging-interceptor" % "4.10.0", + "com.google.code.gson" % "gson" % "2.9.1", + "org.apache.commons" % "commons-lang3" % "3.12.0", + "javax.ws.rs" % "jsr311-api" % "1.1.1", + "javax.ws.rs" % "javax.ws.rs-api" % "2.1.1", + {{#openApiNullable}} + "org.openapitools" % "jackson-databind-nullable" % "0.2.4", + {{/openApiNullable}} {{#hasOAuthMethods}} - "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1", + "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.2", {{/hasOAuthMethods}} {{#joda}} "joda-time" % "joda-time" % "2.9.9" % "compile", {{/joda}} - {{#threetenbp}} - "org.threeten" % "threetenbp" % "1.4.3" % "compile", - {{/threetenbp}} - "io.gsonfire" % "gson-fire" % "1.8.3" % "compile", - "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", + {{#dynamicOperations}} + "io.swagger.parser.v3" % "swagger-parser-v3" "2.0.30" % "compile" + {{/dynamicOperations}} + "io.gsonfire" % "gson-fire" % "1.8.5" % "compile", + "jakarta.annotation" % "jakarta.annotation-api" % "1.3.5" % "compile", "com.google.code.findbugs" % "jsr305" % "3.0.2" % "compile", - "junit" % "junit" % "4.13" % "test", - "com.novocode" % "junit-interface" % "0.10" % "test" + "jakarta.annotation" % "jakarta.annotation-api" % "1.3.5" % "compile", + "org.junit.jupiter" % "junit-jupiter-api" % "5.9.1" % "test", + "com.novocode" % "junit-interface" % "0.10" % "test", + "org.mockito" % "mockito-core" % "3.12.4" % "test" ) ) diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/model.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/model.mustache new file mode 100644 index 000000000..b6b0381a5 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/model.mustache @@ -0,0 +1,61 @@ +{{>licenseInfo}} + +package {{package}}; + +{{#useReflectionEqualsHashCode}} +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +{{/useReflectionEqualsHashCode}} +import java.util.Objects; +import java.util.Arrays; +{{#imports}} +import {{import}}; +{{/imports}} +{{#serializableModel}} +import java.io.Serializable; +{{/serializableModel}} +{{#jackson}} +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.annotation.JsonTypeName; +{{#withXml}} +import com.fasterxml.jackson.dataformat.xml.annotation.*; +{{/withXml}} +{{#vendorExtensions.x-has-readonly-properties}} +import com.fasterxml.jackson.annotation.JsonCreator; +{{/vendorExtensions.x-has-readonly-properties}} +{{/jackson}} +{{#withXml}} +import javax.xml.bind.annotation.*; +{{/withXml}} +{{#jsonb}} +import java.lang.reflect.Type; +import javax.json.bind.annotation.JsonbTypeDeserializer; +import javax.json.bind.annotation.JsonbTypeSerializer; +import javax.json.bind.serializer.DeserializationContext; +import javax.json.bind.serializer.JsonbDeserializer; +import javax.json.bind.serializer.JsonbSerializer; +import javax.json.bind.serializer.SerializationContext; +import javax.json.stream.JsonGenerator; +import javax.json.stream.JsonParser; +import javax.json.bind.annotation.JsonbProperty; +{{#vendorExtensions.x-has-readonly-properties}} +import javax.json.bind.annotation.JsonbCreator; +{{/vendorExtensions.x-has-readonly-properties}} +{{/jsonb}} +{{#parcelableModel}} +import android.os.Parcelable; +import android.os.Parcel; +{{/parcelableModel}} +{{#useBeanValidation}} +import javax.validation.constraints.*; +import javax.validation.Valid; +{{/useBeanValidation}} +{{#performBeanValidation}} +import org.hibernate.validator.constraints.*; +{{/performBeanValidation}} + +{{#models}} +{{#model}} +{{#isEnum}}{{>modelEnum}}{{/isEnum}}{{^isEnum}}{{#oneOf}}{{#-first}}{{>oneof_model}}{{/-first}}{{/oneOf}}{{^oneOf}}{{#anyOf}}{{#-first}}{{>anyof_model}}{{/-first}}{{/anyOf}}{{^anyOf}}{{>pojo}}{{/anyOf}}{{/oneOf}}{{/isEnum}} +{{/model}} +{{/models}} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/model_test.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/model_test.mustache new file mode 100644 index 000000000..ac4bf9a41 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/model_test.mustache @@ -0,0 +1,49 @@ +{{>licenseInfo}} + +package {{package}}; + +{{#imports}}import {{import}}; +{{/imports}} +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +{{#fullJavaUtil}} +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +{{/fullJavaUtil}} + +/** + * Model tests for {{classname}} + */ +public class {{classname}}Test { + {{#models}} + {{#model}} + {{^vendorExtensions.x-is-one-of-interface}} + {{^isEnum}} + private final {{classname}} model = new {{classname}}(); + + {{/isEnum}} + /** + * Model tests for {{classname}} + */ + @Test + public void test{{classname}}() { + // TODO: test {{classname}} + } + + {{#allVars}} + /** + * Test the property '{{name}}' + */ + @Test + public void {{name}}Test() { + // TODO: test {{name}} + } + + {{/allVars}} + {{/vendorExtensions.x-is-one-of-interface}} + {{/model}} + {{/models}} +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/oneof_model.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/oneof_model.mustache new file mode 100644 index 000000000..9b94b365f --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/oneof_model.mustache @@ -0,0 +1,250 @@ +import javax.ws.rs.core.GenericType; + +import java.io.IOException; +import java.lang.reflect.Type; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.HashMap; +import java.util.Map; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonParseException; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.reflect.TypeToken; +import com.google.gson.JsonPrimitive; +import com.google.gson.annotations.JsonAdapter; +import com.google.gson.annotations.SerializedName; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; + +import {{invokerPackage}}.JSON; + +{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>xmlAnnotation}} +public class {{classname}} extends AbstractOpenApiSchema{{#vendorExtensions.x-implements}}, {{{.}}}{{/vendorExtensions.x-implements}} { + private static final Logger log = Logger.getLogger({{classname}}.class.getName()); + + public static class CustomTypeAdapterFactory implements TypeAdapterFactory { + @SuppressWarnings("unchecked") + @Override + public TypeAdapter create(Gson gson, TypeToken type) { + if (!{{classname}}.class.isAssignableFrom(type.getRawType())) { + return null; // this class only serializes '{{classname}}' and its subtypes + } + final TypeAdapter elementAdapter = gson.getAdapter(JsonElement.class); + {{#oneOf}} + final TypeAdapter<{{.}}> adapter{{.}} = gson.getDelegateAdapter(this, TypeToken.get({{.}}.class)); + {{/oneOf}} + + return (TypeAdapter) new TypeAdapter<{{classname}}>() { + @Override + public void write(JsonWriter out, {{classname}} value) throws IOException { + if (value == null || value.getActualInstance() == null) { + elementAdapter.write(out, null); + return; + } + + {{#oneOf}} + // check if the actual instance is of the type `{{.}}` + if (value.getActualInstance() instanceof {{.}}) { + JsonObject obj = adapter{{.}}.toJsonTree(({{.}})value.getActualInstance()).getAsJsonObject(); + elementAdapter.write(out, obj); + return; + } + + {{/oneOf}} + throw new IOException("Failed to serialize as the type doesn't match oneOf schemas: {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}"); + } + + @Override + public {{classname}} read(JsonReader in) throws IOException { + Object deserialized = null; + JsonObject jsonObject = elementAdapter.read(in).getAsJsonObject(); + + {{#useOneOfDiscriminatorLookup}} + {{#discriminator}} + // use discriminator value for faster oneOf lookup + {{classname}} new{{classname}} = new {{classname}}(); + if (jsonObject.get("{{{propertyBaseName}}}") == null) { + log.log(Level.WARNING, "Failed to lookup discriminator value for {{classname}} as `{{{propertyBaseName}}}` was not found in the payload or the payload is empty."); + } else { + // look up the discriminator value in the field `{{{propertyBaseName}}}` + switch (jsonObject.get("{{{propertyBaseName}}}").getAsString()) { + {{#mappedModels}} + case "{{{mappingName}}}": + deserialized = adapter{{modelName}}.fromJsonTree(jsonObject); + new{{classname}}.setActualInstance(deserialized); + return new{{classname}}; + {{/mappedModels}} + default: + log.log(Level.WARNING, String.format("Failed to lookup discriminator value `%s` for {{classname}}. Possible values:{{#mappedModels}} {{{mappingName}}}{{/mappedModels}}", jsonObject.get("{{{propertyBaseName}}}").getAsString())); + } + } + + {{/discriminator}} + {{/useOneOfDiscriminatorLookup}} + int match = 0; + ArrayList errorMessages = new ArrayList<>(); + TypeAdapter actualAdapter = elementAdapter; + + {{#oneOf}} + // deserialize {{{.}}} + try { + // validate the JSON object to see if any exception is thrown + {{.}}.validateJsonObject(jsonObject); + actualAdapter = adapter{{.}}; + match++; + log.log(Level.FINER, "Input data matches schema '{{{.}}}'"); + } catch (Exception e) { + // deserialization failed, continue + errorMessages.add(String.format("Deserialization for {{{.}}} failed with `%s`.", e.getMessage())); + log.log(Level.FINER, "Input data does not match schema '{{{.}}}'", e); + } + + {{/oneOf}} + if (match == 1) { + {{classname}} ret = new {{classname}}(); + ret.setActualInstance(actualAdapter.fromJsonTree(jsonObject)); + return ret; + } + + throw new IOException(String.format("Failed deserialization for {{classname}}: %d classes match result, expected 1. Detailed failure message for oneOf schemas: %s. JSON: %s", match, errorMessages, jsonObject.toString())); + } + }.nullSafe(); + } + } + + // store a list of schema names defined in oneOf + public static final Map schemas = new HashMap(); + + public {{classname}}() { + super("oneOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); + } + + {{#oneOf}} + public {{classname}}({{{.}}} o) { + super("oneOf", {{#isNullable}}Boolean.TRUE{{/isNullable}}{{^isNullable}}Boolean.FALSE{{/isNullable}}); + setActualInstance(o); + } + + {{/oneOf}} + static { + {{#oneOf}} + schemas.put("{{{.}}}", new GenericType<{{{.}}}>() { + }); + {{/oneOf}} + } + + @Override + public Map getSchemas() { + return {{classname}}.schemas; + } + + /** + * Set the instance that matches the oneOf child schema, check + * the instance parameter is valid against the oneOf child schemas: + * {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}} + * + * It could be an instance of the 'oneOf' schemas. + * The oneOf child schemas may themselves be a composed schema (allOf, anyOf, oneOf). + */ + @Override + public void setActualInstance(Object instance) { + {{#isNullable}} + if (instance == null) { + super.setActualInstance(instance); + return; + } + + {{/isNullable}} + {{#oneOf}} + if (instance instanceof {{{.}}}) { + super.setActualInstance(instance); + return; + } + + {{/oneOf}} + throw new RuntimeException("Invalid instance type. Must be {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}"); + } + + /** + * Get the actual instance, which can be the following: + * {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}} + * + * @return The actual instance ({{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}) + */ + @Override + public Object getActualInstance() { + return super.getActualInstance(); + } + + {{#oneOf}} + /** + * Get the actual instance of `{{{.}}}`. If the actual instance is not `{{{.}}}`, + * the ClassCastException will be thrown. + * + * @return The actual instance of `{{{.}}}` + * @throws ClassCastException if the instance is not `{{{.}}}` + */ + public {{{.}}} get{{{.}}}() throws ClassCastException { + return ({{{.}}})super.getActualInstance(); + } + + {{/oneOf}} + + /** + * Validates the JSON Object and throws an exception if issues found + * + * @param jsonObj JSON Object + * @throws IOException if the JSON Object is invalid with respect to {{classname}} + */ + public static void validateJsonObject(JsonObject jsonObj) throws IOException { + // validate oneOf schemas one by one + int validCount = 0; + ArrayList errorMessages = new ArrayList<>(); + {{#oneOf}} + // validate the json string with {{{.}}} + try { + {{{.}}}.validateJsonObject(jsonObj); + validCount++; + } catch (Exception e) { + errorMessages.add(String.format("Deserialization for {{{.}}} failed with `%s`.", e.getMessage())); + // continue to the next one + } + {{/oneOf}} + if (validCount != 1) { + throw new IOException(String.format("The JSON string is invalid for {{classname}} with oneOf schemas: {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}. %d class(es) match the result, expected 1. Detailed failure message for oneOf schemas: %s. JSON: %s", validCount, errorMessages, jsonObj.toString())); + } + } + + /** + * Create an instance of {{classname}} given an JSON string + * + * @param jsonString JSON string + * @return An instance of {{classname}} + * @throws IOException if the JSON string is invalid with respect to {{classname}} + */ + public static {{{classname}}} fromJson(String jsonString) throws IOException { + return JSON.getGson().fromJson(jsonString, {{{classname}}}.class); + } + + /** + * Convert an instance of {{classname}} to an JSON string + * + * @return JSON string + */ + public String toJson() { + return JSON.getGson().toJson(this); + } +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/pojo.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/pojo.mustache new file mode 100644 index 000000000..e41ffd9d7 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/pojo.mustache @@ -0,0 +1,658 @@ +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.reflect.TypeToken; + +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import {{invokerPackage}}.JSON; + +/** + * {{description}}{{^description}}{{classname}}{{/description}}{{#isDeprecated}} + * @deprecated{{/isDeprecated}} + */{{#isDeprecated}} +@Deprecated{{/isDeprecated}} +{{#swagger1AnnotationLibrary}} +{{#description}} +@ApiModel(description = "{{{.}}}") +{{/description}} +{{/swagger1AnnotationLibrary}} +{{#jackson}} +@JsonPropertyOrder({ +{{#vars}} + {{classname}}.JSON_PROPERTY_{{nameInSnakeCase}}{{^-last}},{{/-last}} +{{/vars}} +}) +{{#isClassnameSanitized}} +@JsonTypeName("{{name}}") +{{/isClassnameSanitized}} +{{/jackson}} +{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}} +{{#vendorExtensions.x-class-extra-annotation}} +{{{vendorExtensions.x-class-extra-annotation}}} +{{/vendorExtensions.x-class-extra-annotation}} +public class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{{#vendorExtensions.x-implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{#-last}} {{/-last}}{{/vendorExtensions.x-implements}}{ +{{#serializableModel}} + private static final long serialVersionUID = 1L; + +{{/serializableModel}} + {{#vars}} + {{#isEnum}} + {{^isContainer}} +{{>modelInnerEnum}} + {{/isContainer}} + {{#isContainer}} + {{#mostInnerItems}} +{{>modelInnerEnum}} + {{/mostInnerItems}} + {{/isContainer}} + {{/isEnum}} + {{#gson}} + public static final String SERIALIZED_NAME_{{nameInSnakeCase}} = "{{baseName}}"; + {{/gson}} + {{#jackson}} + public static final String JSON_PROPERTY_{{nameInSnakeCase}} = "{{baseName}}"; + {{/jackson}} + {{#withXml}} + {{#isXmlAttribute}} + @XmlAttribute(name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isXmlAttribute}} + {{^isXmlAttribute}} + {{^isContainer}} + @XmlElement({{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isContainer}} + {{#isContainer}} + // Is a container wrapped={{isXmlWrapped}} + {{#items}} + // items.name={{name}} items.baseName={{baseName}} items.xmlName={{xmlName}} items.xmlNamespace={{xmlNamespace}} + // items.example={{example}} items.type={{dataType}} + @XmlElement({{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/items}} + {{#isXmlWrapped}} + @XmlElementWrapper({{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isXmlWrapped}} + {{/isContainer}} + {{/isXmlAttribute}} + {{/withXml}} + {{#gson}} + @SerializedName(SERIALIZED_NAME_{{nameInSnakeCase}}) + {{/gson}} + {{#vendorExtensions.x-field-extra-annotation}} + {{{vendorExtensions.x-field-extra-annotation}}} + {{/vendorExtensions.x-field-extra-annotation}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} + {{#isContainer}} + private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>undefined(); + {{/isContainer}} + {{^isContainer}} + private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}}; + {{/isContainer}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + {{#isContainer}} + private {{{datatypeWithEnum}}} {{name}}{{#required}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/required}}{{^required}} = null{{/required}}; + {{/isContainer}} + {{^isContainer}} + {{#isDiscriminator}}protected{{/isDiscriminator}}{{^isDiscriminator}}private{{/isDiscriminator}} {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}; + {{/isContainer}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} + + {{/vars}} + public {{classname}}() { + {{#parent}} + {{#parcelableModel}} + super(); + {{/parcelableModel}} + {{/parent}} + {{#gson}} + {{#discriminator}} + {{^discriminator.isEnum}} + this.{{{discriminatorName}}} = this.getClass().getSimpleName(); + {{/discriminator.isEnum}} + {{/discriminator}} + {{/gson}} + } + {{#vendorExtensions.x-has-readonly-properties}} + {{^withXml}} + + {{#jsonb}}@JsonbCreator{{/jsonb}}{{#jackson}}@JsonCreator{{/jackson}} + public {{classname}}( + {{#readOnlyVars}} + {{#jsonb}}@JsonbProperty("{{baseName}}"){{/jsonb}}{{#jackson}}@JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}}){{/jackson}} {{{datatypeWithEnum}}} {{name}}{{^-last}}, {{/-last}} + {{/readOnlyVars}} + ) { + this(); + {{#readOnlyVars}} + this.{{name}} = {{name}}; + {{/readOnlyVars}} + } + {{/withXml}} + {{/vendorExtensions.x-has-readonly-properties}} + {{#vars}} + + {{^isReadOnly}} + public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) { + {{#vendorExtensions.x-is-jackson-optional-nullable}}this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}});{{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}}this.{{name}} = {{name}};{{/vendorExtensions.x-is-jackson-optional-nullable}} + return this; + } + {{#isArray}} + + public {{classname}} add{{nameInCamelCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + if (this.{{name}} == null || !this.{{name}}.isPresent()) { + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}); + } + try { + this.{{name}}.get().add({{name}}Item); + } catch (java.util.NoSuchElementException e) { + // this can never happen, as we make sure above that the value is present + } + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + {{^required}} + if (this.{{name}} == null) { + this.{{name}} = {{{defaultValue}}}; + } + {{/required}} + this.{{name}}.add({{name}}Item); + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + {{/isArray}} + {{#isMap}} + + public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + if (this.{{name}} == null || !this.{{name}}.isPresent()) { + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}); + } + try { + this.{{name}}.get().put(key, {{name}}Item); + } catch (java.util.NoSuchElementException e) { + // this can never happen, as we make sure above that the value is present + } + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + {{^required}} + if (this.{{name}} == null) { + this.{{name}} = {{{defaultValue}}}; + } + {{/required}} + this.{{name}}.put(key, {{name}}Item); + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + {{/isMap}} + + {{/isReadOnly}} + /** + {{#description}} + * {{.}} + {{/description}} + {{^description}} + * Get {{name}} + {{/description}} + {{#minimum}} + * minimum: {{.}} + {{/minimum}} + {{#maximum}} + * maximum: {{.}} + {{/maximum}} + * @return {{name}} + {{#deprecated}} + * @deprecated + {{/deprecated}} + **/ +{{#deprecated}} + @Deprecated +{{/deprecated}} +{{#required}} +{{#isNullable}} + @javax.annotation.Nullable +{{/isNullable}} +{{^isNullable}} + @javax.annotation.Nonnull +{{/isNullable}} +{{/required}} +{{^required}} + @javax.annotation.Nullable +{{/required}} +{{#jsonb}} + @JsonbProperty("{{baseName}}") +{{/jsonb}} +{{#useBeanValidation}} +{{>beanValidation}} +{{/useBeanValidation}} +{{#swagger1AnnotationLibrary}} + @ApiModelProperty({{#example}}example = "{{{.}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}") +{{/swagger1AnnotationLibrary}} +{{#vendorExtensions.x-extra-annotation}} + {{{vendorExtensions.x-extra-annotation}}} +{{/vendorExtensions.x-extra-annotation}} +{{#vendorExtensions.x-is-jackson-optional-nullable}} + {{!unannotated, Jackson would pick this up automatically and add it *in addition* to the _JsonNullable getter field}} + @JsonIgnore +{{/vendorExtensions.x-is-jackson-optional-nullable}} +{{^vendorExtensions.x-is-jackson-optional-nullable}}{{#jackson}}{{> jackson_annotations}}{{/jackson}}{{/vendorExtensions.x-is-jackson-optional-nullable}} + public {{{datatypeWithEnum}}} {{getter}}() { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + {{#isReadOnly}}{{! A readonly attribute doesn't have setter => jackson will set null directly if explicitly returned by API, so make sure we have an empty JsonNullable}} + if ({{name}} == null) { + {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}}; + } + {{/isReadOnly}} + return {{name}}.orElse(null); + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + return {{name}}; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + + {{#vendorExtensions.x-is-jackson-optional-nullable}} +{{> jackson_annotations}} + public JsonNullable<{{{datatypeWithEnum}}}> {{getter}}_JsonNullable() { + return {{name}}; + } + {{/vendorExtensions.x-is-jackson-optional-nullable}}{{#vendorExtensions.x-is-jackson-optional-nullable}} + @JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}}) + {{#isReadOnly}}private{{/isReadOnly}}{{^isReadOnly}}public{{/isReadOnly}} void {{setter}}_JsonNullable(JsonNullable<{{{datatypeWithEnum}}}> {{name}}) { + {{! For getters/setters that have name differing from attribute name, we must include setter (albeit private) for jackson to be able to set the attribute}} + this.{{name}} = {{name}}; + } + {{/vendorExtensions.x-is-jackson-optional-nullable}} + + {{^isReadOnly}} +{{#vendorExtensions.x-setter-extra-annotation}} {{{vendorExtensions.x-setter-extra-annotation}}} +{{/vendorExtensions.x-setter-extra-annotation}}{{#jackson}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{> jackson_annotations}}{{/vendorExtensions.x-is-jackson-optional-nullable}}{{/jackson}} public void {{setter}}({{{datatypeWithEnum}}} {{name}}) { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}}); + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = {{name}}; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + {{/isReadOnly}} + + {{/vars}} +{{>libraries/okhttp-gson/additional_properties}} + + @Override + public boolean equals(Object o) { + {{#useReflectionEqualsHashCode}} + return EqualsBuilder.reflectionEquals(this, o, false, null, true); + {{/useReflectionEqualsHashCode}} + {{^useReflectionEqualsHashCode}} + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + }{{#hasVars}} + {{classname}} {{classVarName}} = ({{classname}}) o; + return {{#vars}}{{#vendorExtensions.x-is-jackson-optional-nullable}}equalsNullable(this.{{name}}, {{classVarName}}.{{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{#isByteArray}}Arrays{{/isByteArray}}{{^isByteArray}}Objects{{/isByteArray}}.equals(this.{{name}}, {{classVarName}}.{{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^-last}} && + {{/-last}}{{/vars}}{{#isAdditionalPropertiesTrue}}&& + Objects.equals(this.additionalProperties, {{classVarName}}.additionalProperties){{/isAdditionalPropertiesTrue}}{{#parent}} && + super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}} + return {{#parent}}super.equals(o){{/parent}}{{^parent}}true{{/parent}};{{/hasVars}} + {{/useReflectionEqualsHashCode}} + }{{#vendorExtensions.x-jackson-optional-nullable-helpers}} + + private static boolean equalsNullable(JsonNullable a, JsonNullable b) { + return a == b || (a != null && b != null && a.isPresent() && b.isPresent() && Objects.deepEquals(a.get(), b.get())); + }{{/vendorExtensions.x-jackson-optional-nullable-helpers}} + + @Override + public int hashCode() { + {{#useReflectionEqualsHashCode}} + return HashCodeBuilder.reflectionHashCode(this); + {{/useReflectionEqualsHashCode}} + {{^useReflectionEqualsHashCode}} + return Objects.hash({{#vars}}{{#vendorExtensions.x-is-jackson-optional-nullable}}hashCodeNullable({{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{^isByteArray}}{{name}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{/vendorExtensions.x-is-jackson-optional-nullable}}{{^-last}}, {{/-last}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}{{#isAdditionalPropertiesTrue}}{{#hasVars}}, {{/hasVars}}{{^hasVars}}{{#parent}}, {{/parent}}{{/hasVars}}additionalProperties{{/isAdditionalPropertiesTrue}}); + {{/useReflectionEqualsHashCode}} + }{{#vendorExtensions.x-jackson-optional-nullable-helpers}} + + private static int hashCodeNullable(JsonNullable a) { + if (a == null) { + return 1; + } + return a.isPresent() ? Arrays.deepHashCode(new Object[]{a.get()}) : 31; + }{{/vendorExtensions.x-jackson-optional-nullable-helpers}} + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class {{classname}} {\n"); + {{#parent}} + sb.append(" ").append(toIndentedString(super.toString())).append("\n"); + {{/parent}} + {{#vars}} + sb.append(" {{name}}: ").append(toIndentedString({{name}})).append("\n"); + {{/vars}} +{{#isAdditionalPropertiesTrue}} + sb.append(" additionalProperties: ").append(toIndentedString(additionalProperties)).append("\n"); +{{/isAdditionalPropertiesTrue}} + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private{{#jsonb}} static{{/jsonb}} String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + +{{#parcelableModel}} + + public void writeToParcel(Parcel out, int flags) { +{{#model}} +{{#isArray}} + out.writeList(this); +{{/isArray}} +{{^isArray}} +{{#parent}} + super.writeToParcel(out, flags); +{{/parent}} +{{#vars}} + out.writeValue({{name}}); +{{/vars}} +{{/isArray}} +{{/model}} + } + + {{classname}}(Parcel in) { +{{#isArray}} + in.readTypedList(this, {{arrayModelType}}.CREATOR); +{{/isArray}} +{{^isArray}} +{{#parent}} + super(in); +{{/parent}} +{{#vars}} +{{#isPrimitiveType}} + {{name}} = ({{{datatypeWithEnum}}})in.readValue(null); +{{/isPrimitiveType}} +{{^isPrimitiveType}} + {{name}} = ({{{datatypeWithEnum}}})in.readValue({{complexType}}.class.getClassLoader()); +{{/isPrimitiveType}} +{{/vars}} +{{/isArray}} + } + + public int describeContents() { + return 0; + } + + public static final Parcelable.Creator<{{classname}}> CREATOR = new Parcelable.Creator<{{classname}}>() { + public {{classname}} createFromParcel(Parcel in) { +{{#model}} +{{#isArray}} + {{classname}} result = new {{classname}}(); + result.addAll(in.readArrayList({{arrayModelType}}.class.getClassLoader())); + return result; +{{/isArray}} +{{^isArray}} + return new {{classname}}(in); +{{/isArray}} +{{/model}} + } + public {{classname}}[] newArray(int size) { + return new {{classname}}[size]; + } + }; +{{/parcelableModel}} + + public static HashSet openapiFields; + public static HashSet openapiRequiredFields; + + static { + // a set of all properties/fields (JSON key names) + openapiFields = new HashSet(); + {{#allVars}} + openapiFields.add("{{baseName}}"); + {{/allVars}} + + // a set of required properties/fields (JSON key names) + openapiRequiredFields = new HashSet(); + {{#requiredVars}} + openapiRequiredFields.add("{{baseName}}"); + {{/requiredVars}} + } + + /** + * Validates the JSON Object and throws an exception if issues found + * + * @param jsonObj JSON Object + * @throws IOException if the JSON Object is invalid with respect to {{classname}} + */ + public static void validateJsonObject(JsonObject jsonObj) throws IOException { + if (jsonObj == null) { + if (!{{classname}}.openapiRequiredFields.isEmpty()) { // has required fields but JSON object is null + throw new IllegalArgumentException(String.format("The required field(s) %s in {{{classname}}} is not found in the empty JSON string", {{classname}}.openapiRequiredFields.toString())); + } + } + {{^hasChildren}} + {{^isAdditionalPropertiesTrue}} + + Set> entries = jsonObj.entrySet(); + // check to see if the JSON string contains additional fields + for (Entry entry : entries) { + if (!{{classname}}.openapiFields.contains(entry.getKey())) { + throw new IllegalArgumentException(String.format("The field `%s` in the JSON string is not defined in the `{{classname}}` properties. JSON: %s", entry.getKey(), jsonObj.toString())); + } + } + {{/isAdditionalPropertiesTrue}} + {{#requiredVars}} + {{#-first}} + + // check to make sure all required properties/fields are present in the JSON string + for (String requiredField : {{classname}}.openapiRequiredFields) { + if (jsonObj.get(requiredField) == null) { + throw new IllegalArgumentException(String.format("The required field `%s` is not found in the JSON string: %s", requiredField, jsonObj.toString())); + } + } + {{/-first}} + {{/requiredVars}} + {{/hasChildren}} + {{^discriminator}} + {{#vars}} + {{#isArray}} + {{#items.isModel}} + {{#required}} + // ensure the json data is an array + if (!jsonObj.get("{{{baseName}}}").isJsonArray()) { + throw new IllegalArgumentException(String.format("Expected the field `{{{baseName}}}` to be an array in the JSON string but got `%s`", jsonObj.get("{{{baseName}}}").toString())); + } + + JsonArray jsonArray{{name}} = jsonObj.getAsJsonArray("{{{baseName}}}"); + // validate the required field `{{{baseName}}}` (array) + for (int i = 0; i < jsonArray{{name}}.size(); i++) { + {{{items.dataType}}}.validateJsonObject(jsonArray{{name}}.get(i).getAsJsonObject()); + }; + {{/required}} + {{^required}} + if (jsonObj.get("{{{baseName}}}") != null && !jsonObj.get("{{{baseName}}}").isJsonNull()) { + JsonArray jsonArray{{name}} = jsonObj.getAsJsonArray("{{{baseName}}}"); + if (jsonArray{{name}} != null) { + // ensure the json data is an array + if (!jsonObj.get("{{{baseName}}}").isJsonArray()) { + throw new IllegalArgumentException(String.format("Expected the field `{{{baseName}}}` to be an array in the JSON string but got `%s`", jsonObj.get("{{{baseName}}}").toString())); + } + + // validate the optional field `{{{baseName}}}` (array) + for (int i = 0; i < jsonArray{{name}}.size(); i++) { + {{{items.dataType}}}.validateJsonObject(jsonArray{{name}}.get(i).getAsJsonObject()); + }; + } + } + {{/required}} + {{/items.isModel}} + {{^items.isModel}} + {{^required}} + // ensure the optional json data is an array if present + if (jsonObj.get("{{{baseName}}}") != null && !jsonObj.get("{{{baseName}}}").isJsonArray()) { + throw new IllegalArgumentException(String.format("Expected the field `{{{baseName}}}` to be an array in the JSON string but got `%s`", jsonObj.get("{{{baseName}}}").toString())); + } + {{/required}} + {{#required}} + // ensure the required json array is present + if (jsonObj.get("{{{baseName}}}") == null) { + throw new IllegalArgumentException("Expected the field `linkedContent` to be an array in the JSON string but got `null`"); + } else if (!jsonObj.get("{{{baseName}}}").isJsonArray()) { + throw new IllegalArgumentException(String.format("Expected the field `{{{baseName}}}` to be an array in the JSON string but got `%s`", jsonObj.get("{{{baseName}}}").toString())); + } + {{/required}} + {{/items.isModel}} + {{/isArray}} + {{^isContainer}} + {{#isString}} + if ({{^required}}(jsonObj.get("{{{baseName}}}") != null && !jsonObj.get("{{{baseName}}}").isJsonNull()) && {{/required}}!jsonObj.get("{{{baseName}}}").isJsonPrimitive()) { + throw new IllegalArgumentException(String.format("Expected the field `{{{baseName}}}` to be a primitive type in the JSON string but got `%s`", jsonObj.get("{{{baseName}}}").toString())); + } + {{/isString}} + {{#isModel}} + {{#required}} + // validate the required field `{{{baseName}}}` + {{{dataType}}}.validateJsonObject(jsonObj.getAsJsonObject("{{{baseName}}}")); + {{/required}} + {{^required}} + // validate the optional field `{{{baseName}}}` + if (jsonObj.get("{{{baseName}}}") != null && !jsonObj.get("{{{baseName}}}").isJsonNull()) { + {{{dataType}}}.validateJsonObject(jsonObj.getAsJsonObject("{{{baseName}}}")); + } + {{/required}} + {{/isModel}} + {{/isContainer}} + {{/vars}} + {{/discriminator}} + {{#hasChildren}} + {{#discriminator}} + + String discriminatorValue = jsonObj.get("{{{propertyBaseName}}}").getAsString(); + switch (discriminatorValue) { + {{#mappedModels}} + case "{{mappingName}}": + {{modelName}}.validateJsonObject(jsonObj); + break; + {{/mappedModels}} + default: + throw new IllegalArgumentException(String.format("The value of the `{{{propertyBaseName}}}` field `%s` does not match any key defined in the discriminator's mapping.", discriminatorValue)); + } + {{/discriminator}} + {{/hasChildren}} + } + +{{^hasChildren}} + public static class CustomTypeAdapterFactory implements TypeAdapterFactory { + @SuppressWarnings("unchecked") + @Override + public TypeAdapter create(Gson gson, TypeToken type) { + if (!{{classname}}.class.isAssignableFrom(type.getRawType())) { + return null; // this class only serializes '{{classname}}' and its subtypes + } + final TypeAdapter elementAdapter = gson.getAdapter(JsonElement.class); + final TypeAdapter<{{classname}}> thisAdapter + = gson.getDelegateAdapter(this, TypeToken.get({{classname}}.class)); + + return (TypeAdapter) new TypeAdapter<{{classname}}>() { + @Override + public void write(JsonWriter out, {{classname}} value) throws IOException { + JsonObject obj = thisAdapter.toJsonTree(value).getAsJsonObject(); + {{#isAdditionalPropertiesTrue}} + obj.remove("additionalProperties"); + // serialize additional properties + if (value.getAdditionalProperties() != null) { + for (Map.Entry entry : value.getAdditionalProperties().entrySet()) { + if (entry.getValue() instanceof String) + obj.addProperty(entry.getKey(), (String) entry.getValue()); + else if (entry.getValue() instanceof Number) + obj.addProperty(entry.getKey(), (Number) entry.getValue()); + else if (entry.getValue() instanceof Boolean) + obj.addProperty(entry.getKey(), (Boolean) entry.getValue()); + else if (entry.getValue() instanceof Character) + obj.addProperty(entry.getKey(), (Character) entry.getValue()); + else { + obj.add(entry.getKey(), gson.toJsonTree(entry.getValue()).getAsJsonObject()); + } + } + } + {{/isAdditionalPropertiesTrue}} + elementAdapter.write(out, obj); + } + + @Override + public {{classname}} read(JsonReader in) throws IOException { + JsonObject jsonObj = elementAdapter.read(in).getAsJsonObject(); + validateJsonObject(jsonObj); + {{#isAdditionalPropertiesTrue}} + // store additional fields in the deserialized instance + {{classname}} instance = thisAdapter.fromJsonTree(jsonObj); + for (Map.Entry entry : jsonObj.entrySet()) { + if (!openapiFields.contains(entry.getKey())) { + if (entry.getValue().isJsonPrimitive()) { // primitive type + if (entry.getValue().getAsJsonPrimitive().isString()) + instance.putAdditionalProperty(entry.getKey(), entry.getValue().getAsString()); + else if (entry.getValue().getAsJsonPrimitive().isNumber()) + instance.putAdditionalProperty(entry.getKey(), entry.getValue().getAsNumber()); + else if (entry.getValue().getAsJsonPrimitive().isBoolean()) + instance.putAdditionalProperty(entry.getKey(), entry.getValue().getAsBoolean()); + else + throw new IllegalArgumentException(String.format("The field `%s` has unknown primitive type. Value: %s", entry.getKey(), entry.getValue().toString())); + } else if (entry.getValue().isJsonArray()) { + instance.putAdditionalProperty(entry.getKey(), gson.fromJson(entry.getValue(), List.class)); + } else { // JSON object + instance.putAdditionalProperty(entry.getKey(), gson.fromJson(entry.getValue(), HashMap.class)); + } + } + } + return instance; + {{/isAdditionalPropertiesTrue}} + {{^isAdditionalPropertiesTrue}} + return thisAdapter.fromJsonTree(jsonObj); + {{/isAdditionalPropertiesTrue}} + } + + }.nullSafe(); + } + } +{{/hasChildren}} + + /** + * Create an instance of {{classname}} given an JSON string + * + * @param jsonString JSON string + * @return An instance of {{classname}} + * @throws IOException if the JSON string is invalid with respect to {{classname}} + */ + public static {{{classname}}} fromJson(String jsonString) throws IOException { + return JSON.getGson().fromJson(jsonString, {{{classname}}}.class); + } + + /** + * Convert an instance of {{classname}} to an JSON string + * + * @return JSON string + */ + public String toJson() { + return JSON.getGson().toJson(this); + } +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/pom.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/pom.mustache index b6d67f283..2f0fb09e7 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/pom.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/okhttp-gson/pom.mustache @@ -57,7 +57,7 @@ org.apache.maven.plugins maven-enforcer-plugin - 3.0.0-M1 + 3.1.0 enforce-maven @@ -77,7 +77,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.0.0-M4 + 2.22.2 @@ -89,9 +89,18 @@ methods 10 + + + + org.junit.jupiter + junit-jupiter-engine + ${junit-version} + + maven-dependency-plugin + 3.3.0 package @@ -104,16 +113,14 @@ - org.apache.maven.plugins maven-jar-plugin - 2.2 + 3.3.0 - jar test-jar @@ -121,11 +128,10 @@ - org.codehaus.mojo build-helper-maven-plugin - 1.10 + 3.3.0 add_sources @@ -156,7 +162,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.1.1 + 3.4.1 attach-javadocs @@ -179,7 +185,7 @@ org.apache.maven.plugins maven-source-plugin - 2.2.1 + 3.2.1 attach-sources @@ -189,6 +195,48 @@ + + + com.diffplug.spotless + spotless-maven-plugin + ${spotless.version} + + + + + + + .gitignore + + + + + + true + 4 + + + + + + + + + + 1.8 + + true + + + + + + + + @@ -200,7 +248,7 @@ org.apache.maven.plugins maven-gpg-plugin - 1.5 + 3.0.1 sign-artifacts @@ -217,11 +265,13 @@ + {{#swagger1AnnotationLibrary}} io.swagger swagger-annotations - ${swagger-core-version} + ${swagger-annotations-version} + {{/swagger1AnnotationLibrary}} com.google.code.findbugs @@ -252,7 +302,7 @@ org.apache.oltu.oauth2 org.apache.oltu.oauth2.client - 1.0.1 + 1.0.2 {{/hasOAuthMethods}} @@ -267,19 +317,19 @@ ${jodatime-version} {{/joda}} - {{#threetenbp}} + {{#dynamicOperations}} - org.threeten - threetenbp - ${threetenbp-version} + io.swagger.parser.v3 + swagger-parser-v3 + 2.0.30 - {{/threetenbp}} + {{/dynamicOperations}} {{#useBeanValidation}} - javax.validation - validation-api - 1.1.0.Final + jakarta.validation + jakarta.validation-api + ${beanvalidation-version} provided {{/useBeanValidation}} @@ -288,12 +338,12 @@ org.hibernate hibernate-validator - 5.4.1.Final + 5.4.3.Final - javax.el - el-api - 2.2 + jakarta.el + jakarta.el-api + ${jakarta.el-version} {{/performBeanValidation}} {{#parcelableModel}} @@ -306,35 +356,76 @@ {{/parcelableModel}} - javax.annotation - javax.annotation-api - ${javax-annotation-version} + jakarta.annotation + jakarta.annotation-api + ${jakarta-annotation-version} + provided + + {{#openApiNullable}} + + org.openapitools + jackson-databind-nullable + ${jackson-databind-nullable-version} + + {{/openApiNullable}} + + javax.ws.rs + jsr311-api + ${jsr311-api-version} + + + javax.ws.rs + javax.ws.rs-api + ${javax.ws.rs-api-version} - junit - junit + org.junit.jupiter + junit-jupiter-engine ${junit-version} test + + org.junit.platform + junit-platform-runner + ${junit-platform-runner.version} + test + + + org.mockito + mockito-core + ${mockito-core-version} + test + - {{#supportJava6}}1.6{{/supportJava6}}{{^supportJava6}}{{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}}{{/supportJava6}} + 1.8 ${java.version} ${java.version} - 1.8.4 - 1.5.24 - 3.14.7 - 2.8.6 - 3.10 + 1.8.5 + 1.6.6 + 4.10.0 + 2.9.1 + 3.12.0 + {{#openApiNullable}} + 0.2.4 + {{/openApiNullable}} {{#joda}} - 2.9.9 + 2.12.0 {{/joda}} - {{#threetenbp}} - 1.4.3 - {{/threetenbp}} - 1.3.2 - 4.13 + 1.3.5 +{{#performBeanValidation}} + 3.0.3 +{{/performBeanValidation}} +{{#useBeanValidation}} + 2.0.2 +{{/useBeanValidation}} + 5.9.1 + 1.9.1 + 3.12.4 + 2.1.1 + 1.1.1 UTF-8 + 2.27.2 diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/rest-assured/ApiClient.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/rest-assured/ApiClient.mustache index 1a691ea94..2a0f41737 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/rest-assured/ApiClient.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/rest-assured/ApiClient.mustache @@ -19,7 +19,7 @@ import static {{invokerPackage}}.{{#gson}}GsonObjectMapper.gson{{/gson}}{{#jacks public class ApiClient { {{#basePath}} - public static final String BASE_URI = "{{basePath}}"; + public static final String BASE_URI = "{{.}}"; {{/basePath}} private final Config config; diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/rest-assured/JacksonObjectMapper.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/rest-assured/JacksonObjectMapper.mustache index 9d87ce9ef..8919eda30 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/rest-assured/JacksonObjectMapper.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/rest-assured/JacksonObjectMapper.mustache @@ -2,21 +2,15 @@ package {{invokerPackage}}; -{{#threetenbp}} -import org.threeten.bp.*; -{{/threetenbp}} import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; +{{#openApiNullable}} import org.openapitools.jackson.nullable.JsonNullableModule; -{{#java8}} +{{/openApiNullable}} import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -{{/java8}} {{#joda}} import com.fasterxml.jackson.datatype.joda.JodaModule; {{/joda}} -{{#threetenbp}} -import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule; -{{/threetenbp}} import io.restassured.internal.mapping.Jackson2Mapper; import io.restassured.path.json.mapper.factory.Jackson2ObjectMapperFactory; @@ -39,21 +33,14 @@ public class JacksonObjectMapper extends Jackson2Mapper { mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); mapper.setDateFormat(new RFC3339DateFormat()); - {{#java8}} mapper.registerModule(new JavaTimeModule()); - {{/java8}} {{#joda}} mapper.registerModule(new JodaModule()); {{/joda}} - {{#threetenbp}} - ThreeTenModule module = new ThreeTenModule(); - module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT); - module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME); - module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); - mapper.registerModule(module); - {{/threetenbp}} + {{#openApiNullable}} JsonNullableModule jnm = new JsonNullableModule(); mapper.registerModule(jnm); + {{/openApiNullable}} return mapper; }; } @@ -61,4 +48,4 @@ public class JacksonObjectMapper extends Jackson2Mapper { public static JacksonObjectMapper jackson() { return new JacksonObjectMapper(); } -} \ No newline at end of file +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/rest-assured/README.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/rest-assured/README.mustache index 56560172e..c9877589b 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/rest-assured/README.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/rest-assured/README.mustache @@ -38,6 +38,5 @@ It's recommended to create an instance of `ApiClient` per thread in a multithrea ## Author -{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}} -{{/hasMore}}{{/apis}}{{/apiInfo}} - +{{#apiInfo}}{{#apis}}{{#-last}}{{infoEmail}} +{{/-last}}{{/apis}}{{/apiInfo}} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/rest-assured/api.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/rest-assured/api.mustache index 2016726a9..0c8736061 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/rest-assured/api.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/rest-assured/api.mustache @@ -22,7 +22,9 @@ import io.restassured.common.mapper.TypeRef; {{/jackson}} import io.restassured.http.Method; import io.restassured.response.Response; +{{#swagger1AnnotationLibrary}} import io.swagger.annotations.*; +{{/swagger1AnnotationLibrary}} import java.lang.reflect.Type; import java.util.function.Consumer; @@ -34,7 +36,9 @@ import {{invokerPackage}}.JSON; {{/gson}} import static io.restassured.http.Method.*; +{{#swagger1AnnotationLibrary}} @Api(value = "{{{baseName}}}") +{{/swagger1AnnotationLibrary}} public class {{classname}} { private Supplier reqSpecSupplier; @@ -68,12 +72,14 @@ public class {{classname}} { {{#operations}} {{#operation}} +{{#swagger1AnnotationLibrary}} @ApiOperation(value = "{{{summary}}}", notes = "{{{notes}}}", nickname = "{{{operationId}}}", - tags = { {{#tags}}{{#name}}"{{{name}}}"{{/name}}{{^-last}}, {{/-last}}{{/tags}} }) + tags = { {{#tags}}{{#name}}"{{{.}}}"{{/name}}{{^-last}}, {{/-last}}{{/tags}} }) @ApiResponses(value = { {{#responses}} - @ApiResponse(code = {{{code}}}, message = "{{{message}}}") {{#hasMore}},{{/hasMore}}{{/responses}} }) + @ApiResponse(code = {{{code}}}, message = "{{{message}}}") {{^-last}},{{/-last}}{{/responses}} }) +{{/swagger1AnnotationLibrary}} {{#isDeprecated}} @Deprecated {{/isDeprecated}} @@ -103,7 +109,7 @@ public class {{classname}} { * @see #{{#isPathParam}}{{paramName}}Path{{/isPathParam}}{{#isQueryParam}}{{paramName}}Query{{/isQueryParam}}{{#isFormParam}}{{^isFile}}{{paramName}}Form{{/isFile}}{{#isFile}}{{paramName}}MultiPart{{/isFile}}{{/isFormParam}}{{#isHeaderParam}}{{paramName}}Header{{/isHeaderParam}}{{#isBodyParam}}body{{/isBodyParam}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} {{/allParams}} {{#returnType}} - * return {{returnType}} + * return {{.}} {{/returnType}} {{#isDeprecated}} * @deprecated @@ -127,9 +133,9 @@ public class {{classname}} { public {{operationIdCamelCase}}Oper(RequestSpecBuilder reqSpec) { this.reqSpec = reqSpec; {{#vendorExtensions}} - {{#x-contentType}} - reqSpec.setContentType("{{x-contentType}}"); - {{/x-contentType}} + {{#x-content-type}} + reqSpec.setContentType("{{x-content-type}}"); + {{/x-content-type}} {{#x-accepts}} reqSpec.setAccept("{{x-accepts}}"); {{/x-accepts}} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/rest-assured/api_doc.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/rest-assured/api_doc.mustache index c8bf20319..b3ca8dfab 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/rest-assured/api_doc.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/rest-assured/api_doc.mustache @@ -1,22 +1,22 @@ # {{classname}}{{#description}} -{{description}}{{/description}} +{{.}}{{/description}} All URIs are relative to *{{basePath}}* -Method | HTTP request | Description -------------- | ------------- | ------------- -{{#operations}}{{#operation}}[**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +| Method | HTTP request | Description | +|------------- | ------------- | -------------| +{{#operations}}{{#operation}}| [**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{summary}} | {{/operation}}{{/operations}} {{#operations}} {{#operation}} # **{{operationId}}** -> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#allParams}}{{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) +> {{#returnType}}{{.}} {{/returnType}}{{operationId}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}}) {{summary}}{{#notes}} -{{notes}}{{/notes}} +{{.}}{{/notes}} ### Example ```java @@ -40,9 +40,9 @@ api.{{operationId}}(){{#allParams}}{{#required}}{{#isPathParam}} ### Parameters {{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{#allParams}}{{#-last}} -Name | Type | Description | Notes -------------- | ------------- | ------------- | -------------{{/-last}}{{/allParams}} -{{#allParams}} **{{paramName}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}[**{{dataType}}**]({{baseType}}.md){{/isFile}}{{/isPrimitiveType}}| {{description}} |{{^required}} [optional]{{/required}}{{#defaultValue}} [default to {{defaultValue}}]{{/defaultValue}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}} +| Name | Type | Description | Notes | +|------------- | ------------- | ------------- | -------------|{{/-last}}{{/allParams}} +{{#allParams}}| **{{paramName}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}[**{{dataType}}**]({{baseType}}.md){{/isFile}}{{/isPrimitiveType}}| {{description}} |{{^required}} [optional]{{/required}}{{#defaultValue}} [default to {{.}}]{{/defaultValue}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}} | {{/allParams}} ### Return type @@ -55,8 +55,8 @@ Name | Type | Description | Notes ### HTTP request headers - - **Content-Type**: {{#consumes}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} - - **Accept**: {{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}{{^produces}}Not defined{{/produces}} + - **Content-Type**: {{#consumes}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} + - **Accept**: {{#produces}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/produces}}{{^produces}}Not defined{{/produces}} {{/operation}} {{/operations}} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/rest-assured/api_test.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/rest-assured/api_test.mustache index 74a1c9f7e..af38dc833 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/rest-assured/api_test.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/rest-assured/api_test.mustache @@ -12,6 +12,8 @@ import org.junit.Before; import org.junit.Test; import org.junit.Ignore; +import java.time.LocalDate; +import java.time.OffsetDateTime; {{^fullJavaUtil}} import java.util.ArrayList; import java.util.HashMap; @@ -63,4 +65,4 @@ public class {{classname}}Test { {{/responses}} {{/operation}} {{/operations}} -} \ No newline at end of file +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/rest-assured/build.gradle.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/rest-assured/build.gradle.mustache index 0868a2aa7..67a9e7191 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/rest-assured/build.gradle.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/rest-assured/build.gradle.mustache @@ -6,8 +6,7 @@ version = '{{artifactVersion}}' buildscript { repositories { - maven { url "https://repo1.maven.org/maven2" } - jcenter() + mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:1.5.+' @@ -16,7 +15,7 @@ buildscript { } repositories { - jcenter() + mavenCentral() } @@ -24,7 +23,7 @@ if(hasProperty('target') && target == 'android') { apply plugin: 'com.android.library' apply plugin: 'com.github.dcendents.android-maven' - + android { compileSdkVersion 23 buildToolsVersion '23.0.2' @@ -36,7 +35,7 @@ if(hasProperty('target') && target == 'android') { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } - + // Rename the aar correctly libraryVariants.all { variant -> variant.outputs.each { output -> @@ -49,10 +48,10 @@ if(hasProperty('target') && target == 'android') { } dependencies { - provided 'javax.annotation:jsr250-api:1.0' + provided "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version" } } - + afterEvaluate { android.libraryVariants.all { variant -> def task = project.tasks.create "jar${variant.name.capitalize()}", Jar @@ -64,12 +63,12 @@ if(hasProperty('target') && target == 'android') { artifacts.add('archives', task); } } - + task sourcesJar(type: Jar) { from android.sourceSets.main.java.srcDirs classifier = 'sources' } - + artifacts { archives sourcesJar } @@ -77,17 +76,20 @@ if(hasProperty('target') && target == 'android') { } else { apply plugin: 'java' - apply plugin: 'maven' + apply plugin: 'maven-publish' sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 - install { - repositories.mavenInstaller { - pom.artifactId = '{{artifactId}}' + publishing { + publications { + maven(MavenPublication) { + artifactId = '{{artifactId}}' + from components.java + } } } - + task execute(type:JavaExec) { main = System.getProperty('mainClass') classpath = sourceSets.main.runtimeClasspath @@ -95,69 +97,61 @@ if(hasProperty('target') && target == 'android') { } ext { - swagger_annotations_version = "1.5.21" - rest_assured_version = "4.3.0" - junit_version = "4.13" + swagger_annotations_version = "1.6.6" + rest_assured_version = "4.5.1" + junit_version = "4.13.2" {{#jackson}} - jackson_version = "2.10.3" - jackson_databind_version = "2.10.3" - jackson_databind_nullable_version = "0.2.1" - {{#threetenbp}} - jackson_threetenbp_version = "2.10.0" - {{/threetenbp}} + jackson_version = "2.13.4" + jackson_databind_version = "2.13.4.2" + {{#openApiNullable}} + jackson_databind_nullable_version = "0.2.4" + {{/openApiNullable}} + jakarta_annotation_version = "1.3.5" {{/jackson}} {{#gson}} - gson_version = "2.8.6" - gson_fire_version = "1.8.4" + gson_version = "2.8.9" + gson_fire_version = "1.8.5" {{/gson}} {{#joda}} jodatime_version = "2.10.5" {{/joda}} -{{#threetenbp}} - threetenbp_version = "1.4.3" -{{/threetenbp}} okio_version = "1.17.5" } dependencies { - compile "io.swagger:swagger-annotations:$swagger_annotations_version" - compile "com.google.code.findbugs:jsr305:3.0.2" - compile "io.rest-assured:rest-assured:$rest_assured_version" + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation "io.rest-assured:rest-assured:$rest_assured_version" {{#jackson}} - compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" - compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" - compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + implementation "com.fasterxml.jackson.core:jackson-core:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" + implementation "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" + {{#openApiNullable}} + implementation "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + {{/openApiNullable}} {{#withXml}} - compile "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:$jackson_version" + implementation "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:$jackson_version" {{/withXml}} {{#joda}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + implementation "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" {{/joda}} - {{#java8}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" - {{/java8}} - {{#threetenbp}} - compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_threetenbp_version" - {{/threetenbp}} + implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" {{/jackson}} {{#gson}} - compile "io.gsonfire:gson-fire:$gson_fire_version" - compile 'com.google.code.gson:gson:$gson_version' + implementation "io.gsonfire:gson-fire:$gson_fire_version" + implementation 'com.google.code.gson:gson:$gson_version' {{/gson}} {{#joda}} - compile "joda-time:joda-time:$jodatime_version" + implementation "joda-time:joda-time:$jodatime_version" {{/joda}} -{{#threetenbp}} - compile "org.threeten:threetenbp:$threetenbp_version" -{{/threetenbp}} - compile "com.squareup.okio:okio:$okio_version" + implementation "com.squareup.okio:okio:$okio_version" {{#useBeanValidation}} - compile "javax.validation:validation-api:2.0.1.Final" + implementation "jakarta.validation:jakarta.validation-api:2.0.2" {{/useBeanValidation}} {{#performBeanValidation}} - compile "org.hibernate:hibernate-validator:6.0.19.Final" + implementation "org.hibernate:hibernate-validator:6.0.19.Final" {{/performBeanValidation}} - testCompile "junit:junit:$junit_version" + implementation "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version" + testImplementation "junit:junit:$junit_version" } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/rest-assured/build.sbt.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/rest-assured/build.sbt.mustache index 955f515fc..820edf8d6 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/rest-assured/build.sbt.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/rest-assured/build.sbt.mustache @@ -9,46 +9,41 @@ lazy val root = (project in file(".")). publishArtifact in (Compile, packageDoc) := false, resolvers += Resolver.mavenLocal, libraryDependencies ++= Seq( - "io.swagger" % "swagger-annotations" % "1.5.21", - "io.rest-assured" % "rest-assured" % "4.3.0", - "io.rest-assured" % "scala-support" % "4.3.0", + "io.swagger" % "swagger-annotations" % "1.6.6", + "io.rest-assured" % "rest-assured" % "4.5.1", + "io.rest-assured" % "scala-support" % "4.5.1", "com.google.code.findbugs" % "jsr305" % "3.0.2", {{#jackson}} - "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.3", - "org.openapitools" % "jackson-databind-nullable" % "0.2.1", + "com.fasterxml.jackson.core" % "jackson-core" % "2.13.4", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.13.4", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.13.4.2", + {{#openApiNullable}} + "org.openapitools" % "jackson-databind-nullable" % "0.2.4", + {{/openApiNullable}} {{#withXml}} - "com.fasterxml.jackson.dataformat" % "jackson-dataformat-xml" % "2.10.3", + "com.fasterxml.jackson.dataformat" % "jackson-dataformat-xml" % "2.13.4.1", {{/withXml}} {{#joda}} - "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.10.3", + "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.13.4.1", {{/joda}} - {{#java8}} - "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.10.3", - {{/java8}} - {{#threetenbp}} - "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.10.0", - {{/threetenbp}} + "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.13.4.1", {{/jackson}} {{#gson}} - "com.google.code.gson" % "gson" % "2.8.6", - "io.gsonfire" % "gson-fire" % "1.8.4" % "compile", + "com.google.code.gson" % "gson" % "2.8.9", + "io.gsonfire" % "gson-fire" % "1.8.5" % "compile", {{/gson}} {{#joda}} "joda-time" % "joda-time" % "2.10.5" % "compile", {{/joda}} -{{#threetenbp}} - "org.threeten" % "threetenbp" % "1.4.3" % "compile", -{{/threetenbp}} "com.squareup.okio" % "okio" % "1.17.5" % "compile", {{#useBeanValidation}} - "javax.validation" % "validation-api" % "2.0.1.Final" % "compile", + "jakarta.validation" % "jakarta.validation-api" % "2.0.2" % "compile", {{/useBeanValidation}} {{#performBeanValidation}} "org.hibernate" % "hibernate-validator" % "6.0.19.Final" % "compile", {{/performBeanValidation}} - "junit" % "junit" % "4.13" % "test", + "jakarta.annotation" % "jakarta.annotation-api" % "1.3.5" % "compile", + "junit" % "junit" % "4.13.2" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" ) ) diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/rest-assured/pom.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/rest-assured/pom.mustache index 2e68695d4..2fc5a394d 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/rest-assured/pom.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/rest-assured/pom.mustache @@ -150,9 +150,10 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.2.0 + 3.3.2 none + 1.8 @@ -218,25 +219,25 @@ {{/jackson}} + {{#swagger1AnnotationLibrary}} io.swagger swagger-annotations ${swagger-annotations-version} + {{/swagger1AnnotationLibrary}} com.google.code.findbugs jsr305 3.0.2 - {{^hideGenerationTimestamp}} - javax.annotation - javax.annotation-api - 1.3.2 + jakarta.annotation + jakarta.annotation-api + ${jakarta-annotation-version} provided - {{/hideGenerationTimestamp}} io.rest-assured rest-assured @@ -256,13 +257,6 @@ ${jodatime-version} {{/joda}} - {{#threetenbp}} - - org.threeten - threetenbp - ${threetenbp-version} - - {{/threetenbp}} {{#gson}} io.gsonfire @@ -301,19 +295,10 @@ jackson-datatype-joda {{/joda}} - {{#java8}} com.fasterxml.jackson.datatype jackson-datatype-jsr310 - {{/java8}} - {{#threetenbp}} - - com.github.joschi.jackson - jackson-datatype-threetenbp - ${jackson-threetenbp-version} - - {{/threetenbp}} {{/jackson}} com.squareup.okio @@ -323,9 +308,9 @@ {{#useBeanValidation}} - javax.validation - validation-api - 2.0.1.Final + jakarta.validation + jakarta.validation-api + ${beanvalidation-version} provided {{/useBeanValidation}} @@ -347,24 +332,23 @@ UTF-8 - 1.5.21 - 4.3.0 - 2.8.6 - 1.8.4 + 1.6.6 + 4.5.1 + 2.8.9 + 1.8.5 {{#joda}} 2.10.5 {{/joda}} - {{#threetenbp}} - 1.4.3 - {{/threetenbp}} {{#jackson}} - 2.10.3 - 0.2.1 - {{#threetenbp}} - 2.10.0 - {{/threetenbp}} + 2.13.4 + 2.13.4.2 + 0.2.4 {{/jackson}} + 1.3.5 +{{#useBeanValidation}} + 2.0.2 +{{/useBeanValidation}} 1.17.5 - 4.13 + 4.13.2 diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/resteasy/ApiClient.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/resteasy/ApiClient.mustache index 16ec4c450..fe7575723 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/resteasy/ApiClient.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/resteasy/ApiClient.mustache @@ -8,6 +8,7 @@ import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.nio.file.Files; +import java.nio.file.Paths; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -22,6 +23,9 @@ import java.util.Map.Entry; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; +{{#jsr310}} +import java.time.OffsetDateTime; +{{/jsr310}} import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; @@ -48,7 +52,7 @@ import {{invokerPackage}}.auth.OAuth; {{/hasOAuthMethods}} {{>generatedAnnotation}} -public class ApiClient { +public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} { private Map defaultHeaderMap = new HashMap(); private Map defaultCookieMap = new HashMap(); private String basePath = "{{{basePath}}}"; @@ -77,7 +81,7 @@ public class ApiClient { this.json.setDateFormat((DateFormat) dateFormat.clone()); // Set default User-Agent. - setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}"); + setUserAgent("{{{httpUserAgent}}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}"); // Setup authentications (key: authentication name, value: authentication). authentications = new HashMap();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} @@ -267,10 +271,10 @@ public class ApiClient { /** * The path of temporary folder used to store downloaded files from endpoints * with file response. The default value is null, i.e. using - * the system's default tempopary folder. + * the system's default temporary folder. * * @return the temporary folder path - * @see + * @see createTempFile */ public String getTempFolderPath() { return tempFolderPath; @@ -333,7 +337,9 @@ public class ApiClient { return ""; } else if (param instanceof Date) { return formatDate((Date) param); - } else if (param instanceof Collection) { + } {{#jsr310}}else if (param instanceof OffsetDateTime) { + return formatOffsetDateTime((OffsetDateTime) param); + } {{/jsr310}}else if (param instanceof Collection) { StringBuilder b = new StringBuilder(); for(Object o : (Collection)param) { if(b.length() > 0) { @@ -555,13 +561,7 @@ public class ApiClient { public File downloadFileFromResponse(Response response) throws ApiException { try { File file = prepareDownloadFile(response); -{{^supportJava6}} Files.copy(response.readEntity(InputStream.class), file.toPath()); -{{/supportJava6}} -{{#supportJava6}} - // Java6 falls back to commons.io for file copying - FileUtils.copyToFile(response.readEntity(InputStream.class), file); -{{/supportJava6}} return file; } catch (IOException e) { throw new ApiException(e); @@ -592,15 +592,15 @@ public class ApiClient { prefix = filename.substring(0, pos) + "-"; suffix = filename.substring(pos); } - // File.createTempFile requires the prefix to be at least three characters long + // Files.createTempFile requires the prefix to be at least three characters long if (prefix.length() < 3) prefix = "download-"; } if (tempFolderPath == null) - return File.createTempFile(prefix, suffix); + return Files.createTempFile(prefix, suffix).toFile(); else - return File.createTempFile(prefix, suffix, new File(tempFolderPath)); + return Files.createTempFile(Paths.get(tempFolderPath), prefix, suffix).toFile(); } /** @@ -638,18 +638,18 @@ public class ApiClient { Invocation.Builder invocationBuilder = target.request().accept(accept); - for (Entry headerParamsEnrty : headerParams.entrySet()) { - String value = headerParamsEnrty.getValue(); + for (Entry headerParamsEntry : headerParams.entrySet()) { + String value = headerParamsEntry.getValue(); if (value != null) { - invocationBuilder = invocationBuilder.header(headerParamsEnrty.getKey(), value); + invocationBuilder = invocationBuilder.header(headerParamsEntry.getKey(), value); } } - for (Entry defaultHeaderEnrty: defaultHeaderMap.entrySet()) { - if (!headerParams.containsKey(defaultHeaderEnrty.getKey())) { - String value = defaultHeaderEnrty.getValue(); + for (Entry defaultHeaderEntry: defaultHeaderMap.entrySet()) { + if (!headerParams.containsKey(defaultHeaderEntry.getKey())) { + String value = defaultHeaderEntry.getValue(); if (value != null) { - invocationBuilder = invocationBuilder.header(defaultHeaderEnrty.getKey(), value); + invocationBuilder = invocationBuilder.header(defaultHeaderEntry.getKey(), value); } } } @@ -672,6 +672,38 @@ public class ApiClient { Entity entity = serialize(body, formParams, contentType); + try (Response response = invoke(invocationBuilder, method, entity)) { + statusCode = response.getStatusInfo().getStatusCode(); + responseHeaders = buildResponseHeaders(response); + + if (response.getStatus() == Status.NO_CONTENT.getStatusCode()) { + return null; + } else if (response.getStatusInfo().getFamily().equals(Status.Family.SUCCESSFUL)) { + if (returnType == null) + return null; + else + return deserialize(response, returnType); + } else { + String message = "error"; + String respBody = null; + if (response.hasEntity()) { + try { + respBody = String.valueOf(response.readEntity(String.class)); + message = respBody; + } catch (RuntimeException e) { + // e.printStackTrace(); + } + } + throw new ApiException( + response.getStatus(), + message, + buildResponseHeaders(response), + respBody); + } + } + } + + private Response invoke(Invocation.Builder invocationBuilder, String method, Entity entity) throws ApiException { Response response = null; if ("GET".equals(method)) { @@ -694,36 +726,10 @@ public class ApiClient { throw new ApiException(500, "unknown method type " + method); } - statusCode = response.getStatusInfo().getStatusCode(); - responseHeaders = buildResponseHeaders(response); - - if (response.getStatus() == Status.NO_CONTENT.getStatusCode()) { - return null; - } else if (response.getStatusInfo().getFamily().equals(Status.Family.SUCCESSFUL)) { - if (returnType == null) - return null; - else - return deserialize(response, returnType); - } else { - String message = "error"; - String respBody = null; - if (response.hasEntity()) { - try { - respBody = String.valueOf(response.readEntity(String.class)); - message = respBody; - } catch (RuntimeException e) { - // e.printStackTrace(); - } - } - throw new ApiException( - response.getStatus(), - message, - buildResponseHeaders(response), - respBody); - } + return response; } - /** + /** * Build the Client used to make HTTP requests. */ private Client buildHttpClient(boolean debugging) { diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/resteasy/JSON.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/resteasy/JSON.mustache index 22888421d..71bd624f7 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/resteasy/JSON.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/resteasy/JSON.mustache @@ -2,13 +2,10 @@ package {{invokerPackage}}; import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; +{{#openApiNullable}} import org.openapitools.jackson.nullable.JsonNullableModule; -{{#java8}} +{{/openApiNullable}} import com.fasterxml.jackson.datatype.jsr310.*; -{{/java8}} -{{^java8}} -import com.fasterxml.jackson.datatype.joda.*; -{{/java8}} import java.text.DateFormat; @@ -27,14 +24,11 @@ public class JSON implements ContextResolver { mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); mapper.setDateFormat(new RFC3339DateFormat()); + {{#openApiNullable}} JsonNullableModule jnm = new JsonNullableModule(); mapper.registerModule(jnm); - {{#java8}} + {{/openApiNullable}} mapper.registerModule(new JavaTimeModule()); - {{/java8}} - {{^java8}} - mapper.registerModule(new JodaModule()); - {{/java8}} } /** diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/resteasy/api.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/resteasy/api.mustache index fcb2268a1..9194b7541 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/resteasy/api.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/resteasy/api.mustache @@ -56,7 +56,7 @@ public class {{classname}} { {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException { + public {{#returnType}}{{{.}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { Object localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; {{#allParams}}{{#required}} // verify the required parameter '{{paramName}}' is set @@ -75,7 +75,7 @@ public class {{classname}} { {{javaUtilPrefix}}Map localVarFormParams = new {{javaUtilPrefix}}HashMap(); {{#queryParams}} - localVarQueryParams.addAll(apiClient.parameterToPairs("{{#collectionFormat}}{{{collectionFormat}}}{{/collectionFormat}}", "{{baseName}}", {{paramName}})); + localVarQueryParams.addAll(apiClient.parameterToPairs("{{{collectionFormat}}}", "{{baseName}}", {{paramName}})); {{/queryParams}} {{#headerParams}}if ({{paramName}} != null) @@ -91,16 +91,16 @@ public class {{classname}} { {{/formParams}} final String[] localVarAccepts = { - {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} + {{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}} }; final String localVarAccept = apiClient.selectHeaderAccept(localVarAccepts); final String[] localVarContentTypes = { - {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} + {{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}} }; final String localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes); - String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{^-last}}, {{/-last}}{{/authMethods}} }; {{#returnType}} GenericType<{{{returnType}}}> localVarReturnType = new GenericType<{{{returnType}}}>() {}; diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/resteasy/build.gradle.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/resteasy/build.gradle.mustache index 89c6fb24e..93a8b84ff 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/resteasy/build.gradle.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/resteasy/build.gradle.mustache @@ -6,8 +6,7 @@ version = '{{artifactVersion}}' buildscript { repositories { - maven { url "https://repo1.maven.org/maven2" } - jcenter() + mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:1.5.+' @@ -16,7 +15,7 @@ buildscript { } repositories { - jcenter() + mavenCentral() } @@ -33,20 +32,8 @@ if(hasProperty('target') && target == 'android') { targetSdkVersion 23 } compileOptions { - {{#supportJava6}} - sourceCompatibility JavaVersion.VERSION_1_6 - targetCompatibility JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} - {{#java8}} sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 - {{/java8}} - {{^java8}} - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 - {{/java8}} - {{/supportJava6}} } // Rename the aar correctly @@ -61,7 +48,7 @@ if(hasProperty('target') && target == 'android') { } dependencies { - provided 'javax.annotation:jsr250-api:1.0' + provided "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version" } } @@ -89,25 +76,17 @@ if(hasProperty('target') && target == 'android') { } else { apply plugin: 'java' - apply plugin: 'maven' - {{#supportJava6}} - sourceCompatibility = JavaVersion.VERSION_1_6 - targetCompatibility = JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} - {{#java8}} + apply plugin: 'maven-publish' + sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 - {{/java8}} - {{^java8}} - sourceCompatibility = JavaVersion.VERSION_1_7 - targetCompatibility = JavaVersion.VERSION_1_7 - {{/java8}} - {{/supportJava6}} - - install { - repositories.mavenInstaller { - pom.artifactId = '{{artifactId}}' + + publishing { + publications { + maven(MavenPublication) { + artifactId = '{{artifactId}}' + from components.java + } } } @@ -118,44 +97,32 @@ if(hasProperty('target') && target == 'android') { } ext { - swagger_annotations_version = "1.5.22" - jackson_version = "2.10.3" - jackson_databind_version = "2.10.3" - jackson_databind_nullable_version = "0.2.1" + swagger_annotations_version = "1.6.3" + jackson_version = "2.13.4" + jackson_databind_version = "2.13.4.2" + {{#openApiNullable}} + jackson_databind_nullable_version = "0.2.4" + {{/openApiNullable}} + jakarta_annotation_version = "1.3.5" threetenbp_version = "2.9.10" - resteasy_version = "3.1.3.Final" - {{^java8}} - jodatime_version = "2.9.9" - {{/java8}} - {{#supportJava6}} - commons_io_version=2.5 - commons_lang3_version=3.5 - {{/supportJava6}} + resteasy_version = "4.5.11.Final" junit_version = "4.13" } dependencies { - compile "io.swagger:swagger-annotations:$swagger_annotations_version" - compile "com.google.code.findbugs:jsr305:3.0.2" - compile "org.jboss.resteasy:resteasy-client:$resteasy_version" - compile "org.jboss.resteasy:resteasy-multipart-provider:$resteasy_version" - compile "org.jboss.resteasy:resteasy-jackson2-provider:$resteasy_version" - compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" - compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$threetenbp_version" - compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" - {{#java8}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" - {{/java8}} - {{^java8}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" - compile "joda-time:joda-time:$jodatime_version" - compile "com.brsanthu:migbase64:2.2" - {{/java8}} - {{#supportJava6}} - compile "commons-io:commons-io:$commons_io_version" - compile "org.apache.commons:commons-lang3:$commons_lang3_version" - {{/supportJava6}} - testCompile "junit:junit:$junit_version" + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation "org.jboss.resteasy:resteasy-client:$resteasy_version" + implementation "org.jboss.resteasy:resteasy-multipart-provider:$resteasy_version" + implementation "org.jboss.resteasy:resteasy-jackson2-provider:$resteasy_version" + implementation "com.fasterxml.jackson.core:jackson-core:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" + implementation "com.github.joschi.jackson:jackson-datatype-threetenbp:$threetenbp_version" + {{#openApiNullable}} + implementation "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + {{/openApiNullable}} + implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + implementation "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version" + testImplementation "junit:junit:$junit_version" } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/resteasy/build.sbt.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/resteasy/build.sbt.mustache index 351c07261..3e1de7399 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/resteasy/build.sbt.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/resteasy/build.sbt.mustache @@ -11,24 +11,14 @@ lazy val root = (project in file(".")). libraryDependencies ++= Seq( "io.swagger" % "swagger-annotations" % "1.5.22" % "compile", "org.jboss.resteasy" % "resteasy-client" % "3.1.3.Final" % "compile", - "org.jboss.resteasy" % "resteasy-multipart-provider" % "3.1.3.Final" % "compile", - "org.jboss.resteasy" % "resteasy-jackson2-provider" % "3.1.3.Final" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.3" % "compile", + "org.jboss.resteasy" % "resteasy-multipart-provider" % "4.5.11.Final" % "compile", + "org.jboss.resteasy" % "resteasy-jackson2-provider" % "4.5.11.Final" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.13.4" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.13.4" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.13.4.2" % "compile", "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile", - {{#java8}} "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % "2.9.10" % "compile", - {{/java8}} - {{^java8}} - "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.9.10" % "compile", - "joda-time" % "joda-time" % "2.9.9" % "compile", - "com.brsanthu" % "migbase64" % "2.2" % "compile", - {{/java8}} - {{#supportJava6}} - "org.apache.commons" % "commons-lang3" % "3.5" % "compile", - "commons-io" % "commons-io" % "2.5" % "compile", - {{/supportJava6}} + "jakarta.annotation" % "jakarta.annotation-api" % "1.3.5" % "compile", "junit" % "junit" % "4.13" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" ) diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/resteasy/pom.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/resteasy/pom.mustache index 714f4299b..1fbbb1d61 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/resteasy/pom.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/resteasy/pom.mustache @@ -142,28 +142,17 @@ maven-compiler-plugin 2.5.1 - {{#supportJava6}} - 1.6 - 1.6 - {{/supportJava6}} - {{^supportJava6}} - {{#java8}} - 1.8 - 1.8 - {{/java8}} - {{^java8}} - 1.7 - 1.7 - {{/java8}} - {{/supportJava6}} + 1.8 + 1.8 org.apache.maven.plugins maven-javadoc-plugin - 3.1.1 + 3.3.2 none + 1.8 @@ -177,11 +166,13 @@ + {{#swagger1AnnotationLibrary}} io.swagger swagger-annotations ${swagger-annotations-version} + {{/swagger1AnnotationLibrary}} com.google.code.findbugs @@ -193,11 +184,31 @@ org.jboss.resteasy resteasy-client ${resteasy-version} + + + org.jboss.resteasy + resteasy-jaxrs-services + + + net.jcip + jcip-annotations + + org.jboss.resteasy resteasy-multipart-provider ${resteasy-version} + + + com.sun.xml.bind + jaxb-impl + + + com.sun.mail + javax.mail + + @@ -215,11 +226,13 @@ jackson-databind ${jackson-databind-version} + {{#openApiNullable}} org.openapitools jackson-databind-nullable ${jackson-databind-nullable-version} + {{/openApiNullable}} {{#withXml}} @@ -228,52 +241,17 @@ jackson-dataformat-xml ${jackson-version} - - {{/withXml}} - {{#java8}} - - com.fasterxml.jackson.datatype - jackson-datatype-jsr310 - ${jackson-version} - - {{/java8}} - {{^java8}} - - com.fasterxml.jackson.datatype - jackson-datatype-joda - ${jackson-version} - - joda-time - joda-time - ${jodatime-version} + io.github.threeten-jaxb + threeten-jaxb-core + 1.2 - - - com.brsanthu - migbase64 - 2.2 - - {{/java8}} - - {{#supportJava6}} - - org.apache.commons - commons-lang3 - ${commons_lang3_version} - - - - commons-io - commons-io - ${commons_io_version} - - {{/supportJava6}} + {{/withXml}} org.jboss.resteasy resteasy-jackson2-provider - 3.1.3.Final + ${resteasy-version} com.fasterxml.jackson.datatype @@ -285,6 +263,12 @@ jackson-datatype-threetenbp ${threetenbp-version} + + jakarta.annotation + jakarta.annotation-api + ${jakarta-annotation-version} + provided + junit @@ -295,19 +279,15 @@ UTF-8 - 1.5.22 - 3.1.3.Final - 2.10.3 - 2.10.3 - 0.2.1 + 1.6.6 + 4.7.6.Final + 2.13.4 + 2.13.4.2 + {{#openApiNullable}} + 0.2.4 + {{/openApiNullable}} + 1.3.5 2.9.10 - {{^java8}} - 2.9.9 - {{/java8}} - {{#supportJava6}} - 2.5 - 3.6 - {{/supportJava6}} 1.0.0 4.13 diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/resttemplate/ApiClient.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/resttemplate/ApiClient.mustache index 3142dc70d..cd4054f24 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/resttemplate/ApiClient.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/resttemplate/ApiClient.mustache @@ -1,13 +1,12 @@ package {{invokerPackage}}; -import static java.util.stream.Collectors.joining; - {{#withXml}} import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator; {{/withXml}} import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.annotation.Autowired; {{#restTemplateBeanName}} import org.springframework.beans.factory.annotation.Qualifier; {{/restTemplateBeanName}} @@ -30,33 +29,21 @@ import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter; {{/withXml}} -{{#createApiComponent}} -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -{{/createApiComponent}} +import org.springframework.util.CollectionUtils; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.util.StringUtils; import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.UriComponentsBuilder; -{{#threetenbp}} -import org.threeten.bp.*; -import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule; -import org.springframework.http.converter.HttpMessageConverter; -import org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter; -import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.web.util.DefaultUriBuilderFactory; +{{#openApiNullable}} import org.openapitools.jackson.nullable.JsonNullableModule; -{{/threetenbp}} +{{/openApiNullable}} -{{#useJacksonConversion}} -import com.fasterxml.jackson.databind.ObjectMapper; -import org.springframework.web.client.RestClientException; -import com.fasterxml.jackson.core.JsonProcessingException; -{{/useJacksonConversion}} import java.io.BufferedReader; -import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -78,26 +65,32 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.TimeZone; +{{#jsr310}} +import java.time.OffsetDateTime; +{{/jsr310}} -{{#authMethods}} import {{invokerPackage}}.auth.Authentication; +{{#hasHttpBasicMethods}} import {{invokerPackage}}.auth.HttpBasicAuth; +{{/hasHttpBasicMethods}} +{{#hasHttpBearerMethods}} import {{invokerPackage}}.auth.HttpBearerAuth; +{{/hasHttpBearerMethods}} +{{#hasApiKeyMethods}} import {{invokerPackage}}.auth.ApiKeyAuth; +{{/hasApiKeyMethods}} {{#hasOAuthMethods}} import {{invokerPackage}}.auth.OAuth; {{/hasOAuthMethods}} -{{/authMethods}} {{>generatedAnnotation}} -{{#createApiComponent}} @Component("{{invokerPackage}}.ApiClient") -{{/createApiComponent}} -public class ApiClient { +public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} { public enum CollectionFormat { CSV(","), TSV("\t"), SSV(" "), PIPES("|"), MULTI(null); private final String separator; + private CollectionFormat(String separator) { this.separator = separator; } @@ -114,68 +107,47 @@ public class ApiClient { private String basePath = "{{basePath}}"; - private final RestTemplate restTemplate; + private RestTemplate restTemplate; -{{#authMethods}} private Map authentications; -{{/authMethods}} -{{^useJacksonConversion}} private DateFormat dateFormat; -{{/useJacksonConversion}} -{{#useDefaultApiClient}} public ApiClient() { this.restTemplate = buildRestTemplate(); init(); } -{{/useDefaultApiClient}} -{{#useJacksonConversion}} -{{#createApiComponent}} - @Autowired -{{/createApiComponent}} - private ObjectMapper objectMapper; -{{/useJacksonConversion}} -{{#createApiComponent}} @Autowired -{{/createApiComponent}} public ApiClient({{#restTemplateBeanName}}@Qualifier("{{restTemplateBeanName}}") {{/restTemplateBeanName}}RestTemplate restTemplate) { this.restTemplate = restTemplate; init(); } protected void init() { -{{^useJacksonConversion}} // Use RFC3339 format for date and datetime. // See http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14 this.dateFormat = new RFC3339DateFormat(); // Use UTC as the default time zone. this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); -{{/useJacksonConversion}} // Set default User-Agent. setUserAgent("Java-SDK"); - {{#authMethods}} // Setup authentications (key: authentication name, value: authentication). - authentications = new HashMap();{{#isBasic}}{{#isBasicBasic}} + authentications = new HashMap();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} - authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} - authentications.put("{{name}}", new OAuth());{{/isOAuth}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} // Prevent the authentications from being modified. authentications = Collections.unmodifiableMap(authentications); - {{/authMethods}} - } - - public RestTemplate getRestTemplate() { - return restTemplate; } /** * Get the current base path + * * @return String the base path */ public String getBasePath() { @@ -184,6 +156,7 @@ public class ApiClient { /** * Set the base path, which should include the host + * * @param basePath the base path * @return ApiClient this client */ @@ -192,9 +165,9 @@ public class ApiClient { return this; } -{{#authMethods}} /** * Get authentications (key: authentication name, value: authentication). + * * @return Map the currently configured authentication types */ public Map getAuthentications() { @@ -211,23 +184,29 @@ public class ApiClient { return authentications.get(authName); } + {{#hasHttpBearerMethods}} /** * Helper method to set token for HTTP bearer authentication. + * * @param bearerToken the token */ public void setBearerToken(String bearerToken) { - for (Authentication auth : authentications.values()) { - if (auth instanceof HttpBearerAuth) { - ((HttpBearerAuth) auth).setBearerToken(bearerToken); - return; + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBearerAuth) { + ((HttpBearerAuth) auth).setBearerToken(bearerToken); + return; + } } - } - throw new RuntimeException("No Bearer authentication configured!"); + throw new RuntimeException("No Bearer authentication configured!"); } + {{/hasHttpBearerMethods}} + + {{#hasHttpBasicMethods}} /** * Helper method to set username for the first HTTP basic authentication. - * @param username the username + * + * @param username Username */ public void setUsername(String username) { for (Authentication auth : authentications.values()) { @@ -241,7 +220,7 @@ public class ApiClient { /** * Helper method to set password for the first HTTP basic authentication. - * @param password the password + * @param password Password */ public void setPassword(String password) { for (Authentication auth : authentications.values()) { @@ -253,8 +232,12 @@ public class ApiClient { throw new RuntimeException("No HTTP basic authentication configured!"); } + {{/hasHttpBasicMethods}} + + {{#hasApiKeyMethods}} /** * Helper method to set API key value for the first API key authentication. + * * @param apiKey the API key */ public void setApiKey(String apiKey) { @@ -269,7 +252,8 @@ public class ApiClient { /** * Helper method to set API key prefix for the first API key authentication. - * @param apiKeyPrefix the API key prefix + * + * @param apiKeyPrefix API key prefix */ public void setApiKeyPrefix(String apiKeyPrefix) { for (Authentication auth : authentications.values()) { @@ -281,10 +265,13 @@ public class ApiClient { throw new RuntimeException("No API key authentication configured!"); } + {{/hasApiKeyMethods}} + {{#hasOAuthMethods}} /** * Helper method to set access token for the first OAuth2 authentication. - * @param accessToken the access token + * + * @param accessToken Access token */ public void setAccessToken(String accessToken) { for (Authentication auth : authentications.values()) { @@ -297,9 +284,10 @@ public class ApiClient { } {{/hasOAuthMethods}} -{{/authMethods}} + /** * Set the User-Agent header's value (by adding to the default header map). + * * @param userAgent the user agent string * @return ApiClient this client */ @@ -311,7 +299,7 @@ public class ApiClient { /** * Add a default header. * - * @param name The header's name + * @param name The header's name * @param value The header's value * @return ApiClient this client */ @@ -326,7 +314,7 @@ public class ApiClient { /** * Add a default cookie. * - * @param name The cookie's name + * @param name The cookie's name * @param value The cookie's value * @return ApiClient this client */ @@ -340,7 +328,7 @@ public class ApiClient { public void setDebugging(boolean debugging) { List currentInterceptors = this.restTemplate.getInterceptors(); - if(debugging) { + if (debugging) { if (currentInterceptors == null) { currentInterceptors = new ArrayList(); } @@ -370,7 +358,6 @@ public class ApiClient { return debugging; } -{{^useJacksonConversion}} /** * Get the date format used to parse/format date parameters. * @return DateFormat format @@ -386,19 +373,12 @@ public class ApiClient { */ public ApiClient setDateFormat(DateFormat dateFormat) { this.dateFormat = dateFormat; - {{#threetenbp}} - for(HttpMessageConverter converter:restTemplate.getMessageConverters()){ - if(converter instanceof AbstractJackson2HttpMessageConverter){ - ObjectMapper mapper = ((AbstractJackson2HttpMessageConverter)converter).getObjectMapper(); - mapper.setDateFormat(dateFormat); - } - } - {{/threetenbp}} return this; } /** * Parse the given string into Date object. + * * @param str the string to parse * @return the Date parsed from the string */ @@ -412,37 +392,31 @@ public class ApiClient { /** * Format the given Date object into string. + * * @param date the date to format * @return the formatted date as string */ public String formatDate(Date date) { return dateFormat.format(date); } -{{/useJacksonConversion}} /** * Format the given parameter object into string. + * * @param param the object to convert * @return String the parameter represented as a String */ public String parameterToString(Object param) { if (param == null) { return ""; - } -{{#useJacksonConversion}} - try { - return unquote(this.objectMapper.writeValueAsString(param)); - } catch (final JsonProcessingException e) { - throw new RestClientException(String.format("Cannot convert parameter %s to string", param), e); - } -{{/useJacksonConversion}} -{{^useJacksonConversion}} - if (param instanceof Date) { + } else if (param instanceof Date) { return formatDate( (Date) param); - } else if (param instanceof Collection) { + } {{#jsr310}}else if (param instanceof OffsetDateTime) { + return formatOffsetDateTime((OffsetDateTime) param); + } {{/jsr310}}else if (param instanceof Collection) { StringBuilder b = new StringBuilder(); - for(Object o : (Collection) param) { - if(b.length() > 0) { + for (Object o : (Collection) param) { + if (b.length() > 0) { b.append(","); } b.append(String.valueOf(o)); @@ -451,14 +425,7 @@ public class ApiClient { } else { return String.valueOf(param); } -{{/useJacksonConversion}} - } - -{{#useJacksonConversion}} - private String unquote(String text) { - return text.replaceAll("\\\"", "").replace("^\"|\"$", ""); } -{{/useJacksonConversion}} /** * Formats the specified collection path parameter to a string value. @@ -475,7 +442,7 @@ public class ApiClient { } // collectionFormat is assumed to be "csv" by default - if(collectionFormat == null) { + if (collectionFormat == null) { collectionFormat = CollectionFormat.CSV; } @@ -484,6 +451,7 @@ public class ApiClient { /** * Converts a parameter to a {@link MultiValueMap} for use in REST requests + * * @param collectionFormat The format to convert to * @param name The name of the parameter * @param value The parameter's value @@ -496,15 +464,15 @@ public class ApiClient { return params; } - if(collectionFormat == null) { + if (collectionFormat == null) { collectionFormat = CollectionFormat.CSV; } if (value instanceof Map) { - Map map = (Map) value; - - for (Object key : map.keySet()) { - params.add(parameterToString(key), parameterToString(map.get(key))); + @SuppressWarnings("unchecked") + final Map valuesMap = (Map) value; + for (final Entry entry : valuesMap.entrySet()) { + params.add(entry.getKey(), parameterToString(entry.getValue())); } return params; } @@ -517,7 +485,7 @@ public class ApiClient { return params; } - if (valueCollection.isEmpty()){ + if (valueCollection.isEmpty()) { return params; } @@ -529,7 +497,7 @@ public class ApiClient { } List values = new ArrayList(); - for(Object o : valueCollection) { + for (Object o : valueCollection) { values.add(parameterToString(o)); } params.add(name, collectionFormat.collectionToString(values)); @@ -537,8 +505,9 @@ public class ApiClient { return params; } - /** + /** * Check if the given {@code String} is a JSON MIME. + * * @param mediaType the input MediaType * @return boolean true if the MediaType represents JSON, false otherwise */ @@ -561,6 +530,7 @@ public class ApiClient { * application/json * application/json; charset=UTF8 * APPLICATION/JSON + * * @param mediaType the input MediaType * @return boolean true if the MediaType represents JSON, false otherwise */ @@ -568,6 +538,16 @@ public class ApiClient { return mediaType != null && (MediaType.APPLICATION_JSON.isCompatibleWith(mediaType) || mediaType.getSubtype().matches("^.*\\+json[;]?\\s*$")); } + /** + * Check if the given {@code String} is a Problem JSON MIME (RFC-7807). + * + * @param mediaType the input MediaType + * @return boolean true if the MediaType represents Problem JSON, false otherwise + */ + public boolean isProblemJsonMime(String mediaType) { + return "application/problem+json".equalsIgnoreCase(mediaType); + } + /** * Select the Accept header's value from the given accepts array: * if JSON exists in the given array, use it; @@ -582,7 +562,7 @@ public class ApiClient { } for (String accept : accepts) { MediaType mediaType = MediaType.parseMediaType(accept); - if (isJsonMime(mediaType)) { + if (isJsonMime(mediaType) && !isProblemJsonMime(accept)) { return Collections.singletonList(mediaType); } } @@ -612,6 +592,7 @@ public class ApiClient { /** * Select the body to use for the request + * * @param obj the body object * @param formParams the form parameters * @param contentType the content type of the request @@ -624,6 +605,7 @@ public class ApiClient { /** * Expand path template with variables + * * @param pathTemplate path template with placeholders * @param variables variables to replace * @return path with placeholders replaced by variables @@ -632,12 +614,52 @@ public class ApiClient { return restTemplate.getUriTemplateHandler().expand(pathTemplate, variables).toString(); } + /** + * Include queryParams in uriParams taking into account the paramName + * + * @param queryParams The query parameters + * @param uriParams The path parameters + * return templatized query string + */ + public String generateQueryUri(MultiValueMap queryParams, Map uriParams) { + StringBuilder queryBuilder = new StringBuilder(); + queryParams.forEach((name, values) -> { + try { + final String encodedName = URLEncoder.encode(name.toString(), "UTF-8"); + if (CollectionUtils.isEmpty(values)) { + if (queryBuilder.length() != 0) { + queryBuilder.append('&'); + } + queryBuilder.append(encodedName); + } else { + int valueItemCounter = 0; + for (Object value : values) { + if (queryBuilder.length() != 0) { + queryBuilder.append('&'); + } + queryBuilder.append(encodedName); + if (value != null) { + String templatizedKey = encodedName + valueItemCounter++; + uriParams.put(templatizedKey, value.toString()); + queryBuilder.append('=').append("{").append(templatizedKey).append("}"); + } + } + } + } catch (UnsupportedEncodingException e) { + + } + }); + return queryBuilder.toString(); + + } + /** * Invoke API by sending HTTP request with the given options. * * @param the return type to use * @param path The sub-path of the HTTP URL * @param method The request method + * @param pathParams The path parameters * @param queryParams The query parameters * @param body The request body object * @param headerParams The header parameters @@ -649,40 +671,35 @@ public class ApiClient { * @param returnType The return type into which to deserialize the response * @return ResponseEntity<T> The response of the chosen type */ - public ResponseEntity invokeAPI(String path, HttpMethod method, MultiValueMap queryParams, Object body, HttpHeaders headerParams, MultiValueMap cookieParams, MultiValueMap formParams, List accept, MediaType contentType, String[] authNames, ParameterizedTypeReference returnType) throws RestClientException { -{{#authMethods}} + public ResponseEntity invokeAPI(String path, HttpMethod method, Map pathParams, MultiValueMap queryParams, Object body, HttpHeaders headerParams, MultiValueMap cookieParams, MultiValueMap formParams, List accept, MediaType contentType, String[] authNames, ParameterizedTypeReference returnType) throws RestClientException { updateParamsForAuth(authNames, queryParams, headerParams, cookieParams); -{{/authMethods}} - - final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(basePath).path(path); - if (queryParams != null) { - //encode the query parameters in case they contain unsafe characters - for (List values : queryParams.values()) { - if (values != null) { - for (int i = 0; i < values.size(); i++) { - try { - values.set(i, URLEncoder.encode(values.get(i), "utf8")); - } catch (UnsupportedEncodingException e) { - } - } - } - } - builder.queryParams(queryParams); + Map uriParams = new HashMap<>(); + uriParams.putAll(pathParams); + + String finalUri = path; + + if (queryParams != null && !queryParams.isEmpty()) { + //Include queryParams in uriParams taking into account the paramName + String queryUri = generateQueryUri(queryParams, uriParams); + //Append to finalUri the templatized query string like "?param1={param1Value}&....... + finalUri += "?" + queryUri; } + String expandedPath = this.expandPath(finalUri, uriParams); + final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(basePath).path(expandedPath); - URI uri; + URI uri; try { uri = new URI(builder.build().toUriString()); - } catch(URISyntaxException ex) { + } catch (URISyntaxException ex) { throw new RestClientException("Could not build URL: " + builder.toUriString(), ex); } final BodyBuilder requestBuilder = RequestEntity.method(method, uri); - if(accept != null) { + if (accept != null) { requestBuilder.accept(accept.toArray(new MediaType[accept.size()])); } - if(contentType != null) { + if (contentType != null) { requestBuilder.contentType(contentType); } @@ -711,7 +728,7 @@ public class ApiClient { protected void addHeadersToRequest(HttpHeaders headers, BodyBuilder requestBuilder) { for (Entry> entry : headers.entrySet()) { List values = entry.getValue(); - for(String value : values) { + for (String value : values) { if (value != null) { requestBuilder.header(entry.getKey(), value); } @@ -721,7 +738,8 @@ public class ApiClient { /** * Add cookies to the request that is being built - * @param cookies The cookies to add + * + * @param cookies The cookies to add * @param requestBuilder The current request */ protected void addCookiesToRequest(MultiValueMap cookies, BodyBuilder requestBuilder) { @@ -748,7 +766,6 @@ public class ApiClient { return cookieValue.toString(); } -{{#useDefaultApiClient}} /** * Build the RestTemplate used to make HTTP requests. * @return RestTemplate @@ -758,31 +775,23 @@ public class ApiClient { messageConverters.add(new MappingJackson2HttpMessageConverter()); XmlMapper xmlMapper = new XmlMapper(); xmlMapper.configure(ToXmlGenerator.Feature.WRITE_XML_DECLARATION, true); + {{#openApiNullable}} xmlMapper.registerModule(new JsonNullableModule()); + {{/openApiNullable}} messageConverters.add(new MappingJackson2XmlHttpMessageConverter(xmlMapper)); RestTemplate restTemplate = new RestTemplate(messageConverters); {{/withXml}}{{^withXml}}RestTemplate restTemplate = new RestTemplate();{{/withXml}} - {{#threetenbp}} - for(HttpMessageConverter converter:restTemplate.getMessageConverters()){ - if(converter instanceof AbstractJackson2HttpMessageConverter){ - ObjectMapper mapper = ((AbstractJackson2HttpMessageConverter)converter).getObjectMapper(); - ThreeTenModule module = new ThreeTenModule(); - module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT); - module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME); - module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); - mapper.registerModule(module); - mapper.registerModule(new JsonNullableModule()); - } - } - {{/threetenbp}} // This allows us to read the response more than once - Necessary for debugging. restTemplate.setRequestFactory(new BufferingClientHttpRequestFactory(restTemplate.getRequestFactory())); + + // disable default URL encoding + DefaultUriBuilderFactory uriBuilderFactory = new DefaultUriBuilderFactory(); + uriBuilderFactory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.VALUES_ONLY); + restTemplate.setUriTemplateHandler(uriBuilderFactory); return restTemplate; } -{{/useDefaultApiClient}} -{{#authMethods}} /** * Update query and header parameters based on authentication settings. * @@ -799,10 +808,9 @@ public class ApiClient { auth.applyToParams(queryParams, headerParams, cookieParams); } } -{{/authMethods}} - static private class ApiClientHttpRequestInterceptor implements ClientHttpRequestInterceptor { - private final Log log = LogFactory.getLog(ApiClient.class); + private class ApiClientHttpRequestInterceptor implements ClientHttpRequestInterceptor { + private final Log log = LogFactory.getLog(ApiClientHttpRequestInterceptor.class); @Override public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { @@ -827,10 +835,13 @@ public class ApiClient { } private String headersToString(HttpHeaders headers) { + if(headers == null || headers.isEmpty()) { + return ""; + } StringBuilder builder = new StringBuilder(); - for(Entry> entry : headers.entrySet()) { + for (Entry> entry : headers.entrySet()) { builder.append(entry.getKey()).append("=["); - for(String value : entry.getValue()) { + for (String value : entry.getValue()) { builder.append(value).append(","); } builder.setLength(builder.length() - 1); // Get rid of trailing comma diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/resttemplate/api.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/resttemplate/api.mustache index ab0b95a62..f2e8a1b2c 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/resttemplate/api.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/resttemplate/api.mustache @@ -5,21 +5,19 @@ import {{invokerPackage}}.ApiClient; {{#imports}}import {{import}}; {{/imports}} -{{^fullJavaUtil}}import java.util.ArrayList; -import java.util.Collections; +{{^fullJavaUtil}}import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Locale; -import java.util.Map;{{/fullJavaUtil}} +import java.util.Map; +import java.util.stream.Collectors;{{/fullJavaUtil}} -{{#createApiComponent}}import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -{{/createApiComponent}} import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestClientException; import org.springframework.web.client.HttpClientErrorException; -import org.springframework.web.util.UriComponentsBuilder; import org.springframework.core.ParameterizedTypeReference; import org.springframework.core.io.FileSystemResource; import org.springframework.http.HttpHeaders; @@ -27,31 +25,19 @@ import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; -{{#useBeanValidation}} -{{#useClassLevelBeanValidation}} -import org.springframework.validation.annotation.Validated; -{{/useClassLevelBeanValidation}} -{{/useBeanValidation}} {{>generatedAnnotation}} -{{#createApiComponent}}@Component("{{package}}.{{classname}}") -{{/createApiComponent}}{{! -}}{{#useBeanValidation}}{{! -}}{{#useClassLevelBeanValidation}}{{! -}}@Validated -{{/useClassLevelBeanValidation}}{{! -}}{{/useBeanValidation}} +@Component("{{package}}.{{classname}}") +{{#operations}} public class {{classname}} { - private {{#useDefaultApiClient}}final {{/useDefaultApiClient}}ApiClient apiClient; + private ApiClient apiClient; -{{^useDefaultApiClient}} public {{classname}}() { this(new ApiClient()); } -{{/useDefaultApiClient}} -{{#createApiComponent}} @Autowired -{{/createApiComponent}} public {{classname}}(ApiClient apiClient) { + @Autowired + public {{classname}}(ApiClient apiClient) { this.apiClient = apiClient; } @@ -59,41 +45,41 @@ public class {{classname}} { return apiClient; } -{{^useDefaultApiClient}} public void setApiClient(ApiClient apiClient) { this.apiClient = apiClient; } -{{/useDefaultApiClient}} -{{#operations}} {{#operation}} /** * {{summary}} * {{notes}} {{#responses}} - *

{{code}}{{#message}} - {{message}}{{/message}} + *

{{code}}{{#message}} - {{.}}{{/message}} {{/responses}} {{#allParams}} * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} {{/allParams}} {{#returnType}} - * @return {{returnType}} + * @return {{.}} {{/returnType}} * @throws RestClientException if an error occurs while attempting to invoke the API {{#externalDocs}} * {{description}} * @see {{summary}} Documentation {{/externalDocs}} + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} */ {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws RestClientException { + public {{#returnType}}{{#isResponseFile}}{{#useAbstractionForFiles}}org.springframework.core.io.Resource{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{.}}}{{/useAbstractionForFiles}}{{/isResponseFile}}{{^isResponseFile}}{{{.}}}{{/isResponseFile}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.Resource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws RestClientException { {{#returnType}} - return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}).getBody(); + return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}).getBody(); {{/returnType}} {{^returnType}} - {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); {{/returnType}} } @@ -101,22 +87,25 @@ public class {{classname}} { * {{summary}} * {{notes}} {{#responses}} - *

{{code}}{{#message}} - {{message}}{{/message}} + *

{{code}}{{#message}} - {{.}}{{/message}} {{/responses}} {{#allParams}} * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} {{/allParams}} - * @return ResponseEntity<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + * @return ResponseEntity<{{returnType}}{{^returnType}}Void{{/returnType}}> * @throws RestClientException if an error occurs while attempting to invoke the API {{#externalDocs}} * {{description}} * @see {{summary}} Documentation {{/externalDocs}} + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} */ {{#isDeprecated}} @Deprecated {{/isDeprecated}} - public ResponseEntity<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws RestClientException { + public ResponseEntity<{{#returnType}}{{#isResponseFile}}{{#useAbstractionForFiles}}org.springframework.core.io.Resource{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{.}}}{{/useAbstractionForFiles}}{{/isResponseFile}}{{^isResponseFile}}{{{.}}}{{/isResponseFile}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.Resource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws RestClientException { Object localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; {{#allParams}}{{#required}} // verify the required parameter '{{paramName}}' is set @@ -125,44 +114,43 @@ public class {{classname}} { } {{/required}}{{/allParams}}{{#hasPathParams}} // create path and map variables - final Map localVarUriVariables = new HashMap();{{#pathParams}} - localVarUriVariables.put("{{baseName}}", {{#collectionFormat}}apiClient.collectionPathParameterToString(ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase()), {{{paramName}}}){{/collectionFormat}}{{^collectionFormat}}{{{paramName}}}{{/collectionFormat}});{{/pathParams}}{{/hasPathParams}} - String localVarPath = apiClient.expandPath("{{{path}}}", {{#hasPathParams}}localVarUriVariables{{/hasPathParams}}{{^hasPathParams}}Collections.emptyMap(){{/hasPathParams}}); + final Map uriVariables = new HashMap();{{#pathParams}} + uriVariables.put("{{baseName}}", {{#collectionFormat}}apiClient.collectionPathParameterToString(ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase()), {{{paramName}}}){{/collectionFormat}}{{^collectionFormat}}{{{paramName}}}{{/collectionFormat}});{{/pathParams}}{{/hasPathParams}} final MultiValueMap localVarQueryParams = new LinkedMultiValueMap(); final HttpHeaders localVarHeaderParams = new HttpHeaders(); final MultiValueMap localVarCookieParams = new LinkedMultiValueMap(); final MultiValueMap localVarFormParams = new LinkedMultiValueMap();{{#hasQueryParams}} - {{#queryParams}}localVarQueryParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}}));{{#hasMore}} - {{/hasMore}}{{/queryParams}}{{/hasQueryParams}}{{#hasHeaderParams}} + {{#queryParams}}localVarQueryParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{.}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}}));{{^-last}} + {{/-last}}{{/queryParams}}{{/hasQueryParams}}{{#hasHeaderParams}} {{#headerParams}}if ({{paramName}} != null) - localVarHeaderParams.add("{{baseName}}", apiClient.parameterToString({{paramName}}));{{#hasMore}} - {{/hasMore}}{{/headerParams}}{{/hasHeaderParams}}{{#hasCookieParams}} + localVarHeaderParams.add("{{baseName}}", apiClient.parameterToString({{paramName}}));{{^-last}} + {{/-last}}{{/headerParams}}{{/hasHeaderParams}}{{#hasCookieParams}} {{#cookieParams}}if ({{paramName}} != null) - localVarCookieParams.add("{{baseName}}", apiClient.parameterToString({{paramName}}));{{#hasMore}} - {{/hasMore}}{{/cookieParams}}{{/hasCookieParams}}{{#hasFormParams}} + localVarCookieParams.add("{{baseName}}", apiClient.parameterToString({{paramName}}));{{^-last}} + {{/-last}}{{/cookieParams}}{{/hasCookieParams}}{{#hasFormParams}} {{#formParams}}if ({{paramName}} != null) - localVarFormParams.{{^collectionFormat}}add{{/collectionFormat}}{{#collectionFormat}}put{{/collectionFormat}}("{{baseName}}", {{#isFile}}new FileSystemResource({{paramName}}){{/isFile}}{{^isFile}}{{paramName}}{{/isFile}});{{#hasMore}} - {{/hasMore}}{{/formParams}}{{/hasFormParams}} + localVarFormParams.{{^collectionFormat}}add{{/collectionFormat}}{{#collectionFormat}}addAll{{/collectionFormat}}("{{baseName}}", {{#isFile}}{{^collectionFormat}}{{#useAbstractionForFiles}}{{paramName}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}new FileSystemResource({{paramName}}){{/useAbstractionForFiles}}{{/collectionFormat}}{{/isFile}}{{#isFile}}{{#collectionFormat}}{{paramName}}.stream(){{^useAbstractionForFiles}}.map(FileSystemResource::new){{/useAbstractionForFiles}}.collect(Collectors.toList()){{/collectionFormat}}{{/isFile}}{{^isFile}}{{paramName}}{{/isFile}});{{^-last}} + {{/-last}}{{/formParams}}{{/hasFormParams}} final String[] localVarAccepts = { {{#hasProduces}} - {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} - {{/hasProduces}}}; + {{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}} + {{/hasProduces}} }; final List localVarAccept = apiClient.selectHeaderAccept(localVarAccepts); final String[] localVarContentTypes = { {{#hasConsumes}} - {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} - {{/hasConsumes}}}; + {{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}} + {{/hasConsumes}} }; final MediaType localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes); - String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{^-last}}, {{/-last}}{{/authMethods}} }; - {{#returnType}}ParameterizedTypeReference<{{{returnType}}}> localVarReturnType = new ParameterizedTypeReference<{{{returnType}}}>() {};{{/returnType}}{{^returnType}}ParameterizedTypeReference localVarReturnType = new ParameterizedTypeReference() {};{{/returnType}} - return apiClient.invokeAPI(localVarPath, HttpMethod.{{httpMethod}}, localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, localVarReturnType); + {{#returnType}}ParameterizedTypeReference<{{#returnType}}{{#isResponseFile}}{{#useAbstractionForFiles}}org.springframework.core.io.Resource{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{.}}}{{/useAbstractionForFiles}}{{/isResponseFile}}{{^isResponseFile}}{{{.}}}{{/isResponseFile}}{{/returnType}}> localReturnType = new ParameterizedTypeReference<{{#returnType}}{{#isResponseFile}}{{#useAbstractionForFiles}}org.springframework.core.io.Resource{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{.}}}{{/useAbstractionForFiles}}{{/isResponseFile}}{{^isResponseFile}}{{{.}}}{{/isResponseFile}}{{/returnType}}>() {};{{/returnType}}{{^returnType}}ParameterizedTypeReference localReturnType = new ParameterizedTypeReference() {};{{/returnType}} + return apiClient.invokeAPI("{{{path}}}", HttpMethod.{{httpMethod}}, {{#hasPathParams}}uriVariables{{/hasPathParams}}{{^hasPathParams}}Collections.emptyMap(){{/hasPathParams}}, localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, localReturnType); } {{/operation}} -{{/operations}} } +{{/operations}} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/resttemplate/api_test.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/resttemplate/api_test.mustache index 127ac2def..c4551ca7a 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/resttemplate/api_test.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/resttemplate/api_test.mustache @@ -7,6 +7,8 @@ package {{package}}; import org.junit.Test; import org.junit.Ignore; +import java.time.LocalDate; +import java.time.OffsetDateTime; {{^fullJavaUtil}} import java.util.ArrayList; import java.util.HashMap; @@ -34,9 +36,9 @@ public class {{classname}}Test { @Test public void {{operationId}}Test() { {{#allParams}} - {{{dataType}}} {{paramName}} = null; + {{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.Resource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}} = null; {{/allParams}} - {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{#returnType}}{{{.}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); // TODO: test validations } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/resttemplate/build.gradle.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/resttemplate/build.gradle.mustache index c61825adb..19dfe6d11 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/resttemplate/build.gradle.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/resttemplate/build.gradle.mustache @@ -6,8 +6,7 @@ version = '{{artifactVersion}}' buildscript { repositories { - maven { url "https://repo1.maven.org/maven2" } - jcenter() + mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:1.5.+' @@ -16,7 +15,7 @@ buildscript { } repositories { - jcenter() + mavenCentral() } @@ -24,7 +23,7 @@ if(hasProperty('target') && target == 'android') { apply plugin: 'com.android.library' apply plugin: 'com.github.dcendents.android-maven' - + android { compileSdkVersion 23 buildToolsVersion '23.0.2' @@ -33,22 +32,10 @@ if(hasProperty('target') && target == 'android') { targetSdkVersion 22 } compileOptions { - {{#supportJava6}} - sourceCompatibility JavaVersion.VERSION_1_6 - targetCompatibility JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} - {{#java8}} sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 - {{/java8}} - {{^java8}} - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 - {{/java8}} - {{/supportJava6}} } - + // Rename the aar correctly libraryVariants.all { variant -> variant.outputs.each { output -> @@ -61,10 +48,10 @@ if(hasProperty('target') && target == 'android') { } dependencies { - provided 'javax.annotation:jsr250-api:1.0' + provided "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version" } } - + afterEvaluate { android.libraryVariants.all { variant -> def task = project.tasks.create "jar${variant.name.capitalize()}", Jar @@ -76,12 +63,12 @@ if(hasProperty('target') && target == 'android') { artifacts.add('archives', task); } } - + task sourcesJar(type: Jar) { from android.sourceSets.main.java.srcDirs classifier = 'sources' } - + artifacts { archives sourcesJar } @@ -89,29 +76,20 @@ if(hasProperty('target') && target == 'android') { } else { apply plugin: 'java' - apply plugin: 'maven' - - {{#supportJava6}} - sourceCompatibility = JavaVersion.VERSION_1_6 - targetCompatibility = JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} - {{#java8}} + apply plugin: 'maven-publish' + sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 - {{/java8}} - {{^java8}} - sourceCompatibility = JavaVersion.VERSION_1_7 - targetCompatibility = JavaVersion.VERSION_1_7 - {{/java8}} - {{/supportJava6}} - - install { - repositories.mavenInstaller { - pom.artifactId = '{{artifactId}}' + + publishing { + publications { + maven(MavenPublication) { + artifactId = '{{artifactId}}' + from components.java + } } } - + task execute(type:JavaExec) { main = System.getProperty('mainClass') classpath = sourceSets.main.runtimeClasspath @@ -119,39 +97,38 @@ if(hasProperty('target') && target == 'android') { } ext { - swagger_annotations_version = "1.5.22" - jackson_version = "2.10.3" - jackson_databind_version = "2.10.3" - jackson_databind_nullable_version = "0.2.1" - spring_web_version = "4.3.9.RELEASE" + swagger_annotations_version = "1.6.9" + jackson_version = "2.14.1" + jackson_databind_version = "2.14.1" + {{#openApiNullable}} + jackson_databind_nullable_version = "0.2.4" + {{/openApiNullable}} + jakarta_annotation_version = "1.3.5" + spring_web_version = "5.3.18" jodatime_version = "2.9.9" - junit_version = "4.13" - {{#threetenbp}} - jackson_threeten_version = "2.9.10" - {{/threetenbp}} + junit_version = "4.13.2" } dependencies { - compile "io.swagger:swagger-annotations:$swagger_annotations_version" - compile "com.google.code.findbugs:jsr305:3.0.2" - compile "org.springframework:spring-web:$spring_web_version" - compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" - compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" - compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" - {{#java8}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" - {{/java8}} + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation "org.springframework:spring-web:$spring_web_version" + implementation "org.springframework:spring-context:$spring_web_version" + implementation "com.fasterxml.jackson.core:jackson-core:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" + implementation "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" + {{#openApiNullable}} + implementation "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + {{/openApiNullable}} + implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" {{#joda}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" - compile "joda-time:joda-time:$jodatime_version" + implementation "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + implementation "joda-time:joda-time:$jodatime_version" {{/joda}} - {{#threetenbp}} - compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_threeten_version" - {{/threetenbp}} {{#withXml}} - compile "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:$jackson_version" + implementation "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:$jackson_version" {{/withXml}} - testCompile "junit:junit:$junit_version" + implementation "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version" + testImplementation "junit:junit:$junit_version" } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/resttemplate/pom.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/resttemplate/pom.mustache index c9f02fffc..3936213de 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/resttemplate/pom.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/resttemplate/pom.mustache @@ -143,27 +143,19 @@ org.apache.maven.plugins maven-compiler-plugin 3.6.1 - - {{#supportJava6}} - 1.6 - 1.6 - {{/supportJava6}} - {{^supportJava6}} - {{#java8}} - 1.8 - 1.8 - {{/java8}} - {{^java8}} - 1.7 - 1.7 - {{/java8}} - {{/supportJava6}} - + {{#useJakartaEe}} + 17 + 17 + {{/useJakartaEe}} + {{^useJakartaEe}} + 1.8 + 1.8 + {{/useJakartaEe}} org.apache.maven.plugins maven-javadoc-plugin - 3.1.1 + 3.3.2 none @@ -217,12 +209,14 @@ + {{#swagger1AnnotationLibrary}} io.swagger swagger-annotations ${swagger-annotations-version} - + {{/swagger1AnnotationLibrary}} + com.google.code.findbugs @@ -236,6 +230,11 @@ spring-web ${spring-web-version} + + org.springframework + spring-context + ${spring-web-version} + @@ -258,47 +257,50 @@ jackson-jaxrs-json-provider ${jackson-version} + {{#openApiNullable}} org.openapitools jackson-databind-nullable ${jackson-databind-nullable-version} + {{/openApiNullable}} {{#withXml}} - - - com.fasterxml.jackson.dataformat - jackson-dataformat-xml - ${jackson-version} - - + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + ${jackson-version} + + + io.github.threeten-jaxb + threeten-jaxb-core + 1.2 + {{/withXml}} - {{#java8}} - - com.fasterxml.jackson.datatype - jackson-datatype-jsr310 - ${jackson-version} - - {{/java8}} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + {{#joda}} - - com.fasterxml.jackson.datatype - jackson-datatype-joda - ${jackson-version} - - - joda-time - joda-time - ${jodatime-version} - + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-version} + + + joda-time + joda-time + ${jodatime-version} + {{/joda}} - {{#threetenbp}} - - com.github.joschi.jackson - jackson-datatype-threetenbp - ${jackson-threetenbp-version} - - {{/threetenbp}} + + jakarta.annotation + jakarta.annotation-api + ${jakarta-annotation-version} + provided + @@ -310,18 +312,28 @@ UTF-8 - 1.5.22 - 4.3.9.RELEASE - 2.10.3 - 2.10.3 - 0.2.1 - {{#joda}} + 1.6.9 + {{#useJakartaEe}} + 6.0.3 + {{/useJakartaEe}} + {{^useJakartaEe}} + 5.3.24 + {{/useJakartaEe}} + 2.14.1 + 2.14.1 + {{#openApiNullable}} + 0.2.4 + {{/openApiNullable}} + {{#useJakartaEe}} + 2.1.1 + {{/useJakartaEe}} + {{^useJakartaEe}} + 1.3.5 + {{/useJakartaEe}} + {{#joda}} 2.9.9 {{/joda}} - {{#threetenbp}} - 2.9.10 - {{/threetenbp}} 1.0.0 - 4.13 + 4.13.2 diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/ApiClient.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/ApiClient.mustache index a4a99fea9..465762a36 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/ApiClient.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/ApiClient.mustache @@ -73,7 +73,7 @@ public class ApiClient { auth = new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"); {{/isApiKey}} {{#isOAuth}} - auth = new OAuth(OAuthFlow.{{flow}}, "{{authorizationUrl}}", "{{tokenUrl}}", "{{#scopes}}{{scope}}{{#hasMore}}, {{/hasMore}}{{/scopes}}"); + auth = new OAuth(OAuthFlow.{{flow}}, "{{{authorizationUrl}}}", "{{{tokenUrl}}}", "{{#scopes}}{{scope}}{{^-last}}, {{/-last}}{{/scopes}}"); {{/isOAuth}} } else {{/authMethods}}{ throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names"); diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/CollectionFormats.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/CollectionFormats.mustache index 33331adb0..dbfa4ae76 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/CollectionFormats.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/CollectionFormats.mustache @@ -4,18 +4,18 @@ import java.util.Arrays; import java.util.List; public class CollectionFormats { - + public static class CSVParams { protected List params; - + public CSVParams() { } - + public CSVParams(List params) { this.params = params; } - + public CSVParams(String... params) { this.params = Arrays.asList(params); } @@ -27,23 +27,23 @@ public class CollectionFormats { public void setParams(List params) { this.params = params; } - + @Override public String toString() { return StringUtil.join(params.toArray(new String[0]), ","); } - + } - + public static class SPACEParams extends SSVParams { } public static class SSVParams extends CSVParams { - + public SSVParams() { } - + public SSVParams(List params) { super(params); } @@ -57,16 +57,16 @@ public class CollectionFormats { return StringUtil.join(params.toArray(new String[0]), " "); } } - + public static class TSVParams extends CSVParams { - + public TSVParams() { } - + public TSVParams(List params) { super(params); } - + public TSVParams(String... params) { super(params); } @@ -76,16 +76,16 @@ public class CollectionFormats { return StringUtil.join( params.toArray(new String[0]), "\t"); } } - + public static class PIPESParams extends CSVParams { - + public PIPESParams() { } - + public PIPESParams(List params) { super(params); } - + public PIPESParams(String... params) { super(params); } @@ -95,5 +95,5 @@ public class CollectionFormats { return StringUtil.join(params.toArray(new String[0]), "|"); } } - + } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/README.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/README.mustache index 56560172e..c9877589b 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/README.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/README.mustache @@ -38,6 +38,5 @@ It's recommended to create an instance of `ApiClient` per thread in a multithrea ## Author -{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}} -{{/hasMore}}{{/apis}}{{/apiInfo}} - +{{#apiInfo}}{{#apis}}{{#-last}}{{infoEmail}} +{{/-last}}{{/apis}}{{/apiInfo}} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/api.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/api.mustache index 9effc0560..79e4ff137 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/api.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/api.mustache @@ -26,18 +26,24 @@ public interface {{classname}} { {{#allParams}} * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} {{/allParams}} - * @return {{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}} + * @return {{returnType}}{{^returnType}}Void{{/returnType}} {{#externalDocs}} * {{description}} * @see {{summary}} Documentation {{/externalDocs}} +{{#isDeprecated}} + * @deprecated +{{/isDeprecated}} */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} {{#formParams}}{{#-first}} {{#isMultipart}}@retrofit.http.Multipart{{/isMultipart}}{{^isMultipart}}@retrofit.http.FormUrlEncoded{{/isMultipart}}{{/-first}}{{/formParams}} @{{httpMethod}}("{{{path}}}") - {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}} {{operationId}}({{^allParams}});{{/allParams}} - {{#allParams}}{{>libraries/retrofit/queryParams}}{{>libraries/retrofit/pathParams}}{{>libraries/retrofit/headerParams}}{{>libraries/retrofit/bodyParams}}{{>libraries/retrofit/formParams}}{{#hasMore}}, {{/hasMore}}{{^hasMore}} - );{{/hasMore}}{{/allParams}} + {{{returnType}}}{{^returnType}}Void{{/returnType}} {{operationId}}({{^allParams}});{{/allParams}} + {{#allParams}}{{>libraries/retrofit/queryParams}}{{>libraries/retrofit/pathParams}}{{>libraries/retrofit/headerParams}}{{>libraries/retrofit/bodyParams}}{{>libraries/retrofit/formParams}}{{^-last}}, {{/-last}}{{#-last}} + );{{/-last}}{{/allParams}} /** * {{summary}} @@ -50,12 +56,18 @@ public interface {{classname}} { * {{description}} * @see {{summary}} Documentation {{/externalDocs}} +{{#isDeprecated}} + * @deprecated +{{/isDeprecated}} */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} {{#formParams}}{{#-first}} {{#isMultipart}}@retrofit.http.Multipart{{/isMultipart}}{{^isMultipart}}@retrofit.http.FormUrlEncoded{{/isMultipart}}{{/-first}}{{/formParams}} @{{httpMethod}}("{{{path}}}") void {{operationId}}( - {{#allParams}}{{>libraries/retrofit/queryParams}}{{>libraries/retrofit/pathParams}}{{>libraries/retrofit/headerParams}}{{>libraries/retrofit/bodyParams}}{{>libraries/retrofit/formParams}}, {{/allParams}}Callback<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> cb + {{#allParams}}{{>libraries/retrofit/queryParams}}{{>libraries/retrofit/pathParams}}{{>libraries/retrofit/headerParams}}{{>libraries/retrofit/bodyParams}}{{>libraries/retrofit/formParams}}, {{/allParams}}Callback<{{{returnType}}}{{^returnType}}Void{{/returnType}}> cb ); {{/operation}} } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/api_test.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/api_test.mustache index a34cfe0e1..112d7f73a 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/api_test.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/api_test.mustache @@ -36,7 +36,7 @@ public class {{classname}}Test { {{#allParams}} {{{dataType}}} {{paramName}} = null; {{/allParams}} - // {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + // {{#returnType}}{{{.}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); // TODO: test validations } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/auth/HttpBasicAuth.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/auth/HttpBasicAuth.mustache index 394592f64..cf82b2775 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/auth/HttpBasicAuth.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/auth/HttpBasicAuth.mustache @@ -11,7 +11,7 @@ public class HttpBasicAuth implements Interceptor { private String username; private String password; - + public String getUsername() { return username; } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/auth/OAuth.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/auth/OAuth.mustache index 4c39f4e62..bc0bad711 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/auth/OAuth.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/auth/OAuth.mustache @@ -54,19 +54,19 @@ public class OAuth implements Interceptor { public void setFlow(OAuthFlow flow) { switch(flow) { - case accessCode: - case implicit: + case ACCESS_CODE: + case IMPLICIT: tokenRequestBuilder.setGrantType(GrantType.AUTHORIZATION_CODE); break; - case password: + case PASSWORD: tokenRequestBuilder.setGrantType(GrantType.PASSWORD); break; - case application: + case APPLICATION: tokenRequestBuilder.setGrantType(GrantType.CLIENT_CREDENTIALS); break; default: break; - } + } } @Override @@ -93,7 +93,7 @@ public class OAuth implements Interceptor { if (getAccessToken() != null) { // Build the request Builder rb = request.newBuilder(); - + String requestAccessToken = new String(getAccessToken()); try { oAuthRequest = new OAuthBearerClientRequest(request.urlString()) @@ -102,15 +102,15 @@ public class OAuth implements Interceptor { } catch (OAuthSystemException e) { throw new IOException(e); } - + for ( Map.Entry header : oAuthRequest.getHeaders().entrySet() ) { rb.addHeader(header.getKey(), header.getValue()); } rb.url( oAuthRequest.getLocationUri()); - + //Execute the request Response response = chain.proceed(rb.build()); - + // 401/403 most likely indicates that access token has expired. Unless it happens two times in a row. if ( response != null && (response.code() == HTTP_UNAUTHORIZED || response.code() == HTTP_FORBIDDEN) && updateTokenAndRetryOnAuthorizationFailure ) { try { @@ -133,7 +133,7 @@ public class OAuth implements Interceptor { * Returns true if the access token has been updated */ public synchronized boolean updateAccessToken(String requestAccessToken) throws IOException { - if (getAccessToken() == null || getAccessToken().equals(requestAccessToken)) { + if (getAccessToken() == null || getAccessToken().equals(requestAccessToken)) { try { OAuthJSONAccessTokenResponse accessTokenResponse = oauthClient.accessToken(this.tokenRequestBuilder.buildBodyMessage()); if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) { diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/auth/OAuthOkHttpClient.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/auth/OAuthOkHttpClient.mustache index ea195f7df..48fc7ea4c 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/auth/OAuthOkHttpClient.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/auth/OAuthOkHttpClient.mustache @@ -53,7 +53,7 @@ public class OAuthOkHttpClient implements HttpClient { try { Response response = client.newCall(requestBuilder.build()).execute(); return OAuthClientResponseFactory.createCustomResponse( - response.body().string(), + response.body().string(), response.body().contentType().toString(), response.code(), responseClass); diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/build.gradle.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/build.gradle.mustache index fab2f0d9f..f6ab2dc4a 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/build.gradle.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/build.gradle.mustache @@ -6,8 +6,7 @@ version = '{{artifactVersion}}' buildscript { repositories { - maven { url "https://repo1.maven.org/maven2" } - jcenter() + mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:2.3.+' @@ -16,7 +15,7 @@ buildscript { } repositories { - jcenter() + mavenCentral() } @@ -33,20 +32,8 @@ if(hasProperty('target') && target == 'android') { targetSdkVersion 25 } compileOptions { - {{#supportJava6}} - sourceCompatibility JavaVersion.VERSION_1_6 - targetCompatibility JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} - {{#java8}} sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 - {{/java8}} - {{^java8}} - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 - {{/java8}} - {{/supportJava6}} } // Rename the aar correctly @@ -61,7 +48,7 @@ if(hasProperty('target') && target == 'android') { } dependencies { - provided 'javax.annotation:jsr250-api:1.0' + provided "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version" } } @@ -89,14 +76,17 @@ if(hasProperty('target') && target == 'android') { } else { apply plugin: 'java' - apply plugin: 'maven' + apply plugin: 'maven-publish' sourceCompatibility = JavaVersion.VERSION_1_7 targetCompatibility = JavaVersion.VERSION_1_7 - install { - repositories.mavenInstaller { - pom.artifactId = '{{artifactId}}' + publishing { + publications { + maven(MavenPublication) { + artifactId = '{{artifactId}}' + from components.java + } } } @@ -111,22 +101,18 @@ ext { oltu_version = "1.0.1" retrofit_version = "1.9.0" swagger_annotations_version = "1.5.21" - junit_version = "4.13" + jakarta_annotation_version = "1.3.5" + junit_version = "4.13.2" jodatime_version = "2.9.3" - {{#threetenbp}} - threetenbp_version = "1.4.0" - {{/threetenbp}} } dependencies { - compile "com.squareup.okhttp:okhttp:$okhttp_version" - compile "com.google.code.findbugs:jsr305:3.0.2" - compile "com.squareup.retrofit:retrofit:$retrofit_version" - compile "io.swagger:swagger-annotations:$swagger_annotations_version" - compile "org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:$oltu_version" - compile "joda-time:joda-time:$jodatime_version" - {{#threetenbp}} - compile "org.threeten:threetenbp:$threetenbp_version" - {{/threetenbp}} - testCompile "junit:junit:$junit_version" + implementation "com.squareup.okhttp:okhttp:$okhttp_version" + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation "com.squareup.retrofit:retrofit:$retrofit_version" + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + implementation "org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:$oltu_version" + implementation "joda-time:joda-time:$jodatime_version" + implementation "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version" + testImplementation "junit:junit:$junit_version" } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/build.sbt.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/build.sbt.mustache index 360f53d1a..2cd243945 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/build.sbt.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/build.sbt.mustache @@ -14,10 +14,8 @@ lazy val root = (project in file(".")). "io.swagger" % "swagger-annotations" % "1.5.21" % "compile", "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1" % "compile", "joda-time" % "joda-time" % "2.9.3" % "compile", - {{#threetenbp}} - "org.threeten" % "threetenbp" % "1.4.0" % "compile", - {{/threetenbp}} - "junit" % "junit" % "4.13" % "test", + "jakarta.annotation" % "jakarta.annotation-api" % "1.3.5" % "compile", + "junit" % "junit" % "4.13.2" % "test", "com.novocode" % "junit-interface" % "0.10" % "test" ) ) diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/pom.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/pom.mustache index 7c689ae4b..8ee87feca 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/pom.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit/pom.mustache @@ -144,28 +144,17 @@ maven-compiler-plugin 3.6.1 - {{#supportJava6}} - 1.6 - 1.6 - {{/supportJava6}} - {{^supportJava6}} - {{#java8}} 1.8 1.8 - {{/java8}} - {{^java8}} - 1.7 - 1.7 - {{/java8}} - {{/supportJava6}} org.apache.maven.plugins maven-javadoc-plugin - 3.1.1 + 3.3.2 none + 1.8 @@ -217,11 +206,13 @@ + {{#swagger1AnnotationLibrary}} io.swagger swagger-annotations ${swagger-annotations-version} + {{/swagger1AnnotationLibrary}} com.google.code.findbugs @@ -248,13 +239,6 @@ joda-time ${jodatime-version} - {{#threetenbp}} - - org.threeten - threetenbp - ${threetenbp-version} - - {{/threetenbp}} {{#parcelableModel}} @@ -264,6 +248,12 @@ provided {{/parcelableModel}} + + jakarta.annotation + jakarta.annotation-api + ${jakarta-annotation-version} + provided + junit @@ -274,15 +264,13 @@ UTF-8 - 1.5.21 + 1.6.6 1.9.0 2.7.5 2.9.9 - {{#threetenbp}} - 1.4.0 - {{/threetenbp}} 1.0.1 + 1.3.5 1.0.0 - 4.13 + 4.13.2 diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/ApiClient.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/ApiClient.mustache index 88f0a6700..8e40fd194 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/ApiClient.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/ApiClient.mustache @@ -14,17 +14,14 @@ import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuil {{#joda}} import org.joda.time.format.DateTimeFormatter; {{/joda}} -{{#threetenbp}} -import org.threeten.bp.format.DateTimeFormatter; -{{/threetenbp}} import retrofit2.Converter; import retrofit2.Retrofit; -{{#useRxJava}} -import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory; -{{/useRxJava}} {{#useRxJava2}} import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; {{/useRxJava2}} +{{#useRxJava3}} +import hu.akarnokd.rxjava3.retrofit.RxJava3CallAdapterFactory; +{{/useRxJava3}} import retrofit2.converter.gson.GsonConverterFactory; import retrofit2.converter.scalars.ScalarsConverterFactory; import {{invokerPackage}}.auth.HttpBasicAuth; @@ -40,9 +37,7 @@ import java.io.IOException; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.text.DateFormat; -{{#java8}} import java.time.format.DateTimeFormatter; -{{/java8}} import java.util.LinkedHashMap; import java.util.Map; import java.util.HashMap; @@ -53,10 +48,18 @@ public class ApiClient { private OkHttpClient.Builder okBuilder; private Retrofit.Builder adapterBuilder; private JSON json; + private OkHttpClient okHttpClient; public ApiClient() { apiAuthorizations = new LinkedHashMap(); createDefaultAdapter(); + okBuilder = new OkHttpClient.Builder(); + } + + public ApiClient(OkHttpClient client){ + apiAuthorizations = new LinkedHashMap(); + createDefaultAdapter(); + okHttpClient = client; } public ApiClient(String[] authNames) { @@ -74,7 +77,7 @@ public class ApiClient { auth = new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"); {{/isApiKey}} {{#isOAuth}} - auth = new OAuth(OAuthFlow.{{flow}}, "{{authorizationUrl}}", "{{tokenUrl}}", "{{#scopes}}{{scope}}{{#hasMore}}, {{/hasMore}}{{/scopes}}"); + auth = new OAuth(OAuthFlow.{{#lambda.uppercase}}{{#lambda.snakecase}}{{flow}}{{/lambda.snakecase}}{{/lambda.uppercase}}, "{{{authorizationUrl}}}", "{{{tokenUrl}}}", "{{#scopes}}{{scope}}{{^-last}}, {{/-last}}{{/scopes}}"); {{/isOAuth}} } else {{/authMethods}}{ throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names"); @@ -138,7 +141,6 @@ public class ApiClient { {{/hasOAuthMethods}} public void createDefaultAdapter() { json = new JSON(); - okBuilder = new OkHttpClient.Builder(); String baseUrl = "{{{basePath}}}"; if (!baseUrl.endsWith("/")) @@ -147,20 +149,22 @@ public class ApiClient { adapterBuilder = new Retrofit .Builder() .baseUrl(baseUrl) - {{#useRxJava}} - .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) - {{/useRxJava}}{{#useRxJava2}} + {{#useRxJava2}} .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) {{/useRxJava2}} + {{#useRxJava3}} + .addCallAdapterFactory(RxJava3CallAdapterFactory.create()) + {{/useRxJava3}} .addConverterFactory(ScalarsConverterFactory.create()) .addConverterFactory(GsonCustomConverterFactory.create(json.getGson())); } public S createService(Class serviceClass) { - return adapterBuilder - .client(okBuilder.build()) - .build() - .create(serviceClass); + if (okHttpClient != null) { + return adapterBuilder.client(okHttpClient).build().create(serviceClass); + } else { + return adapterBuilder.client(okBuilder.build()).build().create(serviceClass); + } } public ApiClient setDateFormat(DateFormat dateFormat) { @@ -350,7 +354,11 @@ public class ApiClient { throw new RuntimeException("auth name \"" + authName + "\" already in api authorizations"); } apiAuthorizations.put(authName, authorization); + if(okBuilder == null){ + throw new RuntimeException("The ApiClient was created with a built OkHttpClient so it's not possible to add an authorization interceptor to it"); + } okBuilder.addInterceptor(authorization); + return this; } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/JSON.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/JSON.mustache index 9ba7567bf..2ff8b1cb7 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/JSON.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/JSON.mustache @@ -19,11 +19,6 @@ import org.joda.time.format.DateTimeFormatter; import org.joda.time.format.DateTimeFormatterBuilder; import org.joda.time.format.ISODateTimeFormat; {{/joda}} -{{#threetenbp}} -import org.threeten.bp.LocalDate; -import org.threeten.bp.OffsetDateTime; -import org.threeten.bp.format.DateTimeFormatter; -{{/threetenbp}} {{#models.0}} import {{modelPackage}}.*; @@ -35,11 +30,9 @@ import java.lang.reflect.Type; import java.text.DateFormat; import java.text.ParseException; import java.text.ParsePosition; -{{#java8}} import java.time.LocalDate; import java.time.OffsetDateTime; import java.time.format.DateTimeFormatter; -{{/java8}} import java.util.Date; import java.util.Locale; import java.util.Map; diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/README.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/README.mustache index 9d744b858..5e892a3fa 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/README.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/README.mustache @@ -34,6 +34,5 @@ After the client library is installed/deployed, you can use it in your Maven pro ## Author -{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}} -{{/hasMore}}{{/apis}}{{/apiInfo}} - +{{#apiInfo}}{{#apis}}{{#-last}}{{infoEmail}} +{{/-last}}{{/apis}}{{/apiInfo}} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/api.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/api.mustache index 44f33a514..75418b07c 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/api.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/api.mustache @@ -2,16 +2,19 @@ package {{package}}; import {{invokerPackage}}.CollectionFormats.*; -{{#useRxJava}} -import rx.Observable; -{{/useRxJava}} {{#useRxJava2}} import io.reactivex.Observable; {{/useRxJava2}} +{{#useRxJava3}} +import io.reactivex.rxjava3.core.Observable; +{{/useRxJava3}} {{^returnType}} {{#useRxJava2}} import io.reactivex.Completable; {{/useRxJava2}} +{{#useRxJava3}} +import io.reactivex.rxjava3.core.Completable; +{{/useRxJava3}} {{/returnType}} {{#doNotUseRx}} import retrofit2.Call; @@ -30,6 +33,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; {{/fullJavaUtil}} {{#operations}} @@ -41,7 +45,7 @@ public interface {{classname}} { {{#allParams}} * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} {{/allParams}} - * @return {{^doNotUseRx}}{{#useRxJava}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}{{/isResponseFile}}>{{/useRxJava}}{{#useRxJava2}}{{#returnType}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{returnType}}{{/isResponseFile}}>{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava2}}{{/doNotUseRx}}{{#doNotUseRx}}Call<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}{{/isResponseFile}}>{{/doNotUseRx}} + * @return {{^doNotUseRx}}{{#useRxJava2}}{{#returnType}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{returnType}}{{/isResponseFile}}>{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava2}}{{#useRxJava3}}{{#returnType}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{returnType}}{{/isResponseFile}}>{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava3}}{{/doNotUseRx}}{{#doNotUseRx}}Call<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{returnType}}{{^returnType}}Void{{/returnType}}{{/isResponseFile}}>{{/doNotUseRx}} {{#isDeprecated}} * @deprecated {{/isDeprecated}} @@ -68,9 +72,9 @@ public interface {{classname}} { {{/prioritizedContentTypes}} {{/formParams}} @{{httpMethod}}("{{{path}}}") - {{^doNotUseRx}}{{#useRxJava}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}{{/isResponseFile}}>{{/useRxJava}}{{#useRxJava2}}{{#returnType}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{{returnType}}}{{/isResponseFile}}>{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava2}}{{/doNotUseRx}}{{#doNotUseRx}}Call<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}{{/isResponseFile}}>{{/doNotUseRx}} {{operationId}}({{^allParams}});{{/allParams}} - {{#allParams}}{{>libraries/retrofit2/queryParams}}{{>libraries/retrofit2/pathParams}}{{>libraries/retrofit2/headerParams}}{{>libraries/retrofit2/bodyParams}}{{>libraries/retrofit2/formParams}}{{#hasMore}}, {{/hasMore}}{{^hasMore}} - );{{/hasMore}}{{/allParams}} + {{^doNotUseRx}}{{#useRxJava2}}{{#returnType}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{{returnType}}}{{/isResponseFile}}>{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava2}}{{#useRxJava3}}{{#returnType}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{{returnType}}}{{/isResponseFile}}>{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava3}}{{/doNotUseRx}}{{#doNotUseRx}}Call<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{{returnType}}}{{^returnType}}Void{{/returnType}}{{/isResponseFile}}>{{/doNotUseRx}} {{operationId}}({{^allParams}});{{/allParams}} + {{#allParams}}{{>libraries/retrofit2/queryParams}}{{>libraries/retrofit2/pathParams}}{{>libraries/retrofit2/headerParams}}{{>libraries/retrofit2/bodyParams}}{{>libraries/retrofit2/formParams}}{{^-last}}, {{/-last}}{{#-last}} + );{{/-last}}{{/allParams}} {{/operation}} } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/api_test.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/api_test.mustache index 0a85ef509..8b547d9e9 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/api_test.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/api_test.mustache @@ -6,6 +6,8 @@ import {{invokerPackage}}.ApiClient; import org.junit.Before; import org.junit.Test; +import java.time.LocalDate; +import java.time.OffsetDateTime; {{^fullJavaUtil}} import java.util.ArrayList; import java.util.HashMap; @@ -37,7 +39,7 @@ public class {{classname}}Test { {{#allParams}} {{{dataType}}} {{paramName}} = null; {{/allParams}} - // {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + // {{#returnType}}{{{.}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); // TODO: test validations } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/auth/HttpBasicAuth.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/auth/HttpBasicAuth.mustache index d45884266..9bd756eb8 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/auth/HttpBasicAuth.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/auth/HttpBasicAuth.mustache @@ -12,7 +12,7 @@ public class HttpBasicAuth implements Interceptor { private String username; private String password; - + public String getUsername() { return username; } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/auth/OAuth.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/auth/OAuth.mustache index 80ec7b394..212763dd9 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/auth/OAuth.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/auth/OAuth.mustache @@ -54,19 +54,19 @@ public class OAuth implements Interceptor { public void setFlow(OAuthFlow flow) { switch(flow) { - case accessCode: - case implicit: + case ACCESS_CODE: + case IMPLICIT: tokenRequestBuilder.setGrantType(GrantType.AUTHORIZATION_CODE); break; - case password: + case PASSWORD: tokenRequestBuilder.setGrantType(GrantType.PASSWORD); break; - case application: + case APPLICATION: tokenRequestBuilder.setGrantType(GrantType.CLIENT_CREDENTIALS); break; default: break; - } + } } @Override @@ -133,7 +133,7 @@ public class OAuth implements Interceptor { * Returns true if the access token has been updated */ public synchronized boolean updateAccessToken(String requestAccessToken) throws IOException { - if (getAccessToken() == null || getAccessToken().equals(requestAccessToken)) { + if (getAccessToken() == null || getAccessToken().equals(requestAccessToken)) { try { OAuthJSONAccessTokenResponse accessTokenResponse = oauthClient.accessToken(this.tokenRequestBuilder.buildBodyMessage()); if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) { diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/auth/OAuthOkHttpClient.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/auth/OAuthOkHttpClient.mustache index 423fa1ba0..a499c7b8b 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/auth/OAuthOkHttpClient.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/auth/OAuthOkHttpClient.mustache @@ -56,7 +56,7 @@ public class OAuthOkHttpClient implements HttpClient { try { Response response = client.newCall(requestBuilder.build()).execute(); return OAuthClientResponseFactory.createCustomResponse( - response.body().string(), + response.body().string(), response.body().contentType().toString(), response.code(), responseClass); diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/build.gradle.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/build.gradle.mustache index 82f797406..5deba46d4 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/build.gradle.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/build.gradle.mustache @@ -6,8 +6,7 @@ version = '{{artifactVersion}}' buildscript { repositories { - maven { url "https://repo1.maven.org/maven2" } - jcenter() + mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:2.3.+' @@ -16,7 +15,7 @@ buildscript { } repositories { - jcenter() + mavenCentral() } @@ -33,20 +32,8 @@ if(hasProperty('target') && target == 'android') { targetSdkVersion 25 } compileOptions { - {{#supportJava6}} - sourceCompatibility JavaVersion.VERSION_1_6 - targetCompatibility JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} - {{#java8}} sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 - {{/java8}} - {{^java8}} - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 - {{/java8}} - {{/supportJava6}} } // Rename the aar correctly @@ -61,7 +48,7 @@ if(hasProperty('target') && target == 'android') { } dependencies { - provided 'javax.annotation:jsr250-api:1.0' + provided "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version" } } @@ -89,26 +76,17 @@ if(hasProperty('target') && target == 'android') { } else { apply plugin: 'java' - apply plugin: 'maven' - - {{#supportJava6}} - sourceCompatibility = JavaVersion.VERSION_1_6 - targetCompatibility = JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} - {{#java8}} + apply plugin: 'maven-publish' + sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 - {{/java8}} - {{^java8}} - sourceCompatibility = JavaVersion.VERSION_1_7 - targetCompatibility = JavaVersion.VERSION_1_7 - {{/java8}} - {{/supportJava6}} - - install { - repositories.mavenInstaller { - pom.artifactId = '{{artifactId}}' + + publishing { + publications { + maven(MavenPublication) { + artifactId = '{{artifactId}}' + from components.java + } } } @@ -122,77 +100,61 @@ ext { oltu_version = "1.0.1" retrofit_version = "2.3.0" {{#usePlayWS}} - {{#play24}} - jackson_version = "2.6.6" - play_version = "2.4.11" - {{/play24}} - {{#play25}} - jackson_version = "2.10.1" - play_version = "2.5.14" - {{/play25}} - {{#play26}} - jackson_version = "2.10.3" - jackson_databind_version = "2.10.3" - jackson_databind_nullable_version = "0.2.1" + jackson_version = "2.13.4" + jackson_databind_version = "2.13.4.2" + {{#openApiNullable}} + jackson_databind_nullable_version = "0.2.4" + {{/openApiNullable}} play_version = "2.6.7" - {{/play26}} {{/usePlayWS}} + jakarta_annotation_version = "1.3.5" swagger_annotations_version = "1.5.22" - junit_version = "4.13" - {{#useRxJava}} - rx_java_version = "1.3.0" - {{/useRxJava}} + junit_version = "4.13.2" {{#useRxJava2}} rx_java_version = "2.1.1" {{/useRxJava2}} + {{#useRxJava3}} + rx_java_version = "3.0.4" + {{/useRxJava3}} {{#joda}} jodatime_version = "2.9.9" {{/joda}} - {{#threetenbp}} - threetenbp_version = "1.4.0" - {{/threetenbp}} json_fire_version = "1.8.0" } dependencies { - compile "com.squareup.retrofit2:retrofit:$retrofit_version" - compile "com.squareup.retrofit2:converter-scalars:$retrofit_version" - compile "com.squareup.retrofit2:converter-gson:$retrofit_version" - {{#useRxJava}} - compile "com.squareup.retrofit2:adapter-rxjava:$retrofit_version" - compile "io.reactivex:rxjava:$rx_java_version" - {{/useRxJava}} + implementation "com.squareup.retrofit2:retrofit:$retrofit_version" + implementation "com.squareup.retrofit2:converter-scalars:$retrofit_version" + implementation "com.squareup.retrofit2:converter-gson:$retrofit_version" {{#useRxJava2}} - compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0' - compile "io.reactivex.rxjava2:rxjava:$rx_java_version" + implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0' + implementation "io.reactivex.rxjava2:rxjava:$rx_java_version" {{/useRxJava2}} - compile "io.swagger:swagger-annotations:$swagger_annotations_version" - compile "com.google.code.findbugs:jsr305:3.0.2" - compile ("org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:$oltu_version"){ + {{#useRxJava3}} + implementation 'com.github.akarnokd:rxjava3-retrofit-adapter:3.0.0' + implementation "io.reactivex.rxjava3:rxjava:$rx_java_version" + {{/useRxJava3}} + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation ("org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:$oltu_version"){ exclude group:'org.apache.oltu.oauth2' , module: 'org.apache.oltu.oauth2.common' } - compile "io.gsonfire:gson-fire:$json_fire_version" + implementation "io.gsonfire:gson-fire:$json_fire_version" {{#joda}} - compile "joda-time:joda-time:$jodatime_version" + implementation "joda-time:joda-time:$jodatime_version" {{/joda}} - {{#threetenbp}} - compile "org.threeten:threetenbp:$threetenbp_version" - {{/threetenbp}} {{#usePlayWS}} - {{#play26}} - compile "com.typesafe.play:play-ahc-ws_2.12:$play_version" - compile "javax.validation:validation-api:1.1.0.Final" - {{/play26}} - {{^play26}} - compile "com.typesafe.play:play-java-ws_2.11:$play_version" - {{/play26}} - compile "com.squareup.retrofit2:converter-jackson:$retrofit_version" - compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" - compile "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" - compile "com.fasterxml.jackson.datatype:jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}}:$jackson_version" + implementation "com.typesafe.play:play-ahc-ws_2.12:$play_version" + implementation "jakarta.validation:jakarta.validation-api:2.0.2" + implementation "com.squareup.retrofit2:converter-jackson:$retrofit_version" + implementation "com.fasterxml.jackson.core:jackson-core:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" + {{#openApiNullable}} + implementation "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + {{/openApiNullable}} + implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" {{/usePlayWS}} - - testCompile "junit:junit:$junit_version" + implementation "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version" + testImplementation "junit:junit:$junit_version" } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/build.sbt.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/build.sbt.mustache index f7b7ce464..0bc66fde8 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/build.sbt.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/build.sbt.mustache @@ -15,45 +15,29 @@ lazy val root = (project in file(".")). "com.squareup.retrofit2" % "converter-gson" % "2.3.0" % "compile", {{/usePlayWS}} {{#usePlayWS}} - {{#play24}} - "com.typesafe.play" % "play-java-ws_2.11" % "2.4.11" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.6.6" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.6.6" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.6.6" % "compile", - {{/play24}} - {{#play25}} - "com.typesafe.play" % "play-java-ws_2.11" % "2.5.15" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.3" % "compile", - {{/play25}} - {{#play26}} "com.typesafe.play" % "play-ahc-ws_2.12" % "2.6.7" % "compile", - "javax.validation" % "validation-api" % "1.1.0.Final" % "compile", - "com.fasterxml.jackson.core" % "jackson-core" % "2.10.3" % "compile", - "com.fasterxml.jackson.core" % "jackson-annotations" % "2.10.3" % "compile", - "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.10.3" % "compile", - {{/play26}} + "jakarta.validation" % "jakarta.validation-api" % "2.0.2" % "compile", "com.squareup.retrofit2" % "converter-jackson" % "2.3.0" % "compile", + "com.fasterxml.jackson.core" % "jackson-core" % "2.13.4" % "compile", + "com.fasterxml.jackson.core" % "jackson-annotations" % "2.13.4" % "compile", + "com.fasterxml.jackson.core" % "jackson-databind" % "2.13.4.2" % "compile", {{/usePlayWS}} - {{#useRxJava}} - "com.squareup.retrofit2" % "adapter-rxjava" % "2.3.0" % "compile", - "io.reactivex" % "rxjava" % "1.3.0" % "compile", - {{/useRxJava}} {{#useRxJava2}} "com.squareup.retrofit2" % "adapter-rxjava2" % "2.3.0" % "compile", "io.reactivex.rxjava2" % "rxjava" % "2.1.1" % "compile", {{/useRxJava2}} + {{#useRxJava3}} + "com.github.akarnokd" % "rxjava3-retrofit-adapter" % "3.0.0" % "compile", + "io.reactivex.rxjava3" % "rxjava" % "3.0.4" % "compile", + {{/useRxJava3}} "io.swagger" % "swagger-annotations" % "1.5.21" % "compile", "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1" % "compile", {{#joda}} "joda-time" % "joda-time" % "2.9.9" % "compile", {{/joda}} - {{#threetenbp}} - "org.threeten" % "threetenbp" % "1.4.0" % "compile", - {{/threetenbp}} "io.gsonfire" % "gson-fire" % "1.8.0" % "compile", - "junit" % "junit" % "4.13" % "test", + "jakarta.annotation" % "jakarta.annotation-api" % "1.3.5" % "compile", + "junit" % "junit" % "4.13.2" % "test", "com.novocode" % "junit-interface" % "0.11" % "test" ) ) diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play24/ApiClient.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play24/ApiClient.mustache index 2c1f1f7bb..c43f800a4 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play24/ApiClient.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play24/ApiClient.mustache @@ -9,7 +9,9 @@ import retrofit2.Retrofit; import retrofit2.converter.scalars.ScalarsConverterFactory; import retrofit2.converter.jackson.JacksonConverterFactory; import com.fasterxml.jackson.databind.ObjectMapper; +{{#openApiNullable}} import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} import play.libs.Json; import play.libs.ws.WSClient; @@ -42,7 +44,7 @@ public class ApiClient { public ApiClient() { // Setup authentications (key: authentication name, value: authentication). - authentications = new HashMap<{{#supportJava6}}String, Authentication{{/supportJava6}}>();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + authentications = new HashMap<>();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} // authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} // authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} @@ -60,9 +62,9 @@ public class ApiClient { basePath = basePath + "/"; } - Map extraHeaders = new HashMap<{{#supportJava6}}String, String{{/supportJava6}}>(); - Map extraCookies = new HashMap<{{#supportJava6}}String, String{{/supportJava6}}>(); - List extraQueryParams = new ArrayList<{{#supportJava6}}Pair{{/supportJava6}}>(); + Map extraHeaders = new HashMap<>(); + Map extraCookies = new HashMap<>(); + List extraQueryParams = new ArrayList<>(); for (String authName : authentications.keySet()) { Authentication auth = authentications.get(authName); @@ -72,8 +74,10 @@ public class ApiClient { } ObjectMapper mapper = Json.mapper(); + {{#openApiNullable}} JsonNullableModule jnm = new JsonNullableModule(); mapper.registerModule(jnm); + {{/openApiNullable}} return new Retrofit.Builder() .baseUrl(basePath) diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play24/Play24CallAdapterFactory.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play24/Play24CallAdapterFactory.mustache index be7cac4a0..d9ed3330f 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play24/Play24CallAdapterFactory.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play24/Play24CallAdapterFactory.mustache @@ -48,7 +48,7 @@ public class Play24CallAdapterFactory extends CallAdapter.Factory { return new ValueAdapter(resultType, includeResponse); } - + /** * Adapter that coverts values returned by API interface into CompletionStage */ diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play24/Play24CallFactory.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play24/Play24CallFactory.mustache index 344fadd2e..b17ac6415 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play24/Play24CallFactory.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play24/Play24CallFactory.mustache @@ -1,8 +1,10 @@ package {{invokerPackage}}; import okhttp3.*; +import okio.AsyncTimeout; import okio.Buffer; import okio.BufferedSource; +import okio.Timeout; import play.libs.F; import play.libs.ws.WSClient; import play.libs.ws.WSRequest; @@ -95,10 +97,12 @@ public class Play24CallFactory implements okhttp3.Call.Factory { private WSRequest wsRequest; private final Request request; + private final AsyncTimeout timeout; public PlayWSCall(WSClient wsClient, Request request) { this.wsClient = wsClient; this.request = request; + this.timeout = new AsyncTimeout(); } @Override @@ -106,6 +110,11 @@ public class Play24CallFactory implements okhttp3.Call.Factory { return request; } + @Override + public Timeout timeout() { + return timeout; + } + @Override public void enqueue(final okhttp3.Callback responseCallback) { final Call call = this; diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play24/api.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play24/api.mustache index dd6bf23e9..2b7512d19 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play24/api.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play24/api.mustache @@ -33,8 +33,14 @@ public interface {{classname}} { {{#allParams}} * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} {{/allParams}} - * @return Call<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + * @return Call<{{returnType}}{{^returnType}}Void{{/returnType}}> +{{#isDeprecated}} + * @deprecated +{{/isDeprecated}} */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} {{#formParams}} {{#-first}} {{#isMultipart}}@retrofit2.http.Multipart{{/isMultipart}}{{^isMultipart}}@retrofit2.http.FormUrlEncoded{{/isMultipart}} @@ -50,9 +56,9 @@ public interface {{classname}} { {{/prioritizedContentTypes}} {{/formParams}} @{{httpMethod}}("{{{path}}}") - F.Promise> {{operationId}}({{^allParams}});{{/allParams}} - {{#allParams}}{{>libraries/retrofit2/queryParams}}{{>libraries/retrofit2/pathParams}}{{>libraries/retrofit2/headerParams}}{{>libraries/retrofit2/bodyParams}}{{>libraries/retrofit2/formParams}}{{#hasMore}}, {{/hasMore}}{{^hasMore}} - );{{/hasMore}}{{/allParams}} + F.Promise> {{operationId}}({{^allParams}});{{/allParams}} + {{#allParams}}{{>libraries/retrofit2/queryParams}}{{>libraries/retrofit2/pathParams}}{{>libraries/retrofit2/headerParams}}{{>libraries/retrofit2/bodyParams}}{{>libraries/retrofit2/formParams}}{{^-last}}, {{/-last}}{{#-last}} + );{{/-last}}{{/allParams}} {{/operation}} } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play25/ApiClient.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play25/ApiClient.mustache index 90f439091..849e0665e 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play25/ApiClient.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play25/ApiClient.mustache @@ -9,7 +9,9 @@ import retrofit2.Retrofit; import retrofit2.converter.scalars.ScalarsConverterFactory; import retrofit2.converter.jackson.JacksonConverterFactory; import com.fasterxml.jackson.databind.ObjectMapper; +{{#openApiNullable}} import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} import play.libs.Json; import play.libs.ws.WSClient; @@ -42,7 +44,7 @@ public class ApiClient { public ApiClient() { // Setup authentications (key: authentication name, value: authentication). - authentications = new HashMap<{{#supportJava6}}String, Authentication{{/supportJava6}}>();{{#authMethods}}{{#isBasic}} + authentications = new HashMap<>();{{#authMethods}}{{#isBasic}} // authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}} authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"query"{{/isKeyInCookie}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} // authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} @@ -59,9 +61,9 @@ public class ApiClient { basePath = basePath + "/"; } - Map extraHeaders = new HashMap<{{#supportJava6}}String, String{{/supportJava6}}>(); - Map extraCookies = new HashMap<{{#supportJava6}}String, String{{/supportJava6}}>(); - List extraQueryParams = new ArrayList<{{#supportJava6}}Pair{{/supportJava6}}>(); + Map extraHeaders = new HashMap<>(); + Map extraCookies = new HashMap<>(); + List extraQueryParams = new ArrayList<>(); for (String authName : authentications.keySet()) { Authentication auth = authentications.get(authName); @@ -71,8 +73,10 @@ public class ApiClient { } ObjectMapper mapper = Json.mapper(); + {{#openApiNullable}} JsonNullableModule jnm = new JsonNullableModule(); mapper.registerModule(jnm); + {{/openApiNullable}} return new Retrofit.Builder() .baseUrl(basePath) diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play25/Play25CallAdapterFactory.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play25/Play25CallAdapterFactory.mustache index 088c10b16..62360bf98 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play25/Play25CallAdapterFactory.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play25/Play25CallAdapterFactory.mustache @@ -114,4 +114,3 @@ public class Play25CallAdapterFactory extends CallAdapter.Factory { } } } - diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play25/api.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play25/api.mustache index b435a16c0..d4e97cc34 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play25/api.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play25/api.mustache @@ -33,8 +33,14 @@ public interface {{classname}} { {{#allParams}} * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} {{/allParams}} - * @return Call<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + * @return Call<{{returnType}}{{^returnType}}Void{{/returnType}}> +{{#isDeprecated}} + * @deprecated +{{/isDeprecated}} */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} {{#formParams}} {{#-first}} {{#isMultipart}}@retrofit2.http.Multipart{{/isMultipart}}{{^isMultipart}}@retrofit2.http.FormUrlEncoded{{/isMultipart}} @@ -50,9 +56,9 @@ public interface {{classname}} { {{/prioritizedContentTypes}} {{/formParams}} @{{httpMethod}}("{{{path}}}") - CompletionStage> {{operationId}}({{^allParams}});{{/allParams}} - {{#allParams}}{{>libraries/retrofit2/queryParams}}{{>libraries/retrofit2/pathParams}}{{>libraries/retrofit2/headerParams}}{{>libraries/retrofit2/bodyParams}}{{>libraries/retrofit2/formParams}}{{#hasMore}}, {{/hasMore}}{{^hasMore}} - );{{/hasMore}}{{/allParams}} + CompletionStage> {{operationId}}({{^allParams}});{{/allParams}} + {{#allParams}}{{>libraries/retrofit2/queryParams}}{{>libraries/retrofit2/pathParams}}{{>libraries/retrofit2/headerParams}}{{>libraries/retrofit2/bodyParams}}{{>libraries/retrofit2/formParams}}{{^-last}}, {{/-last}}{{#-last}} + );{{/-last}}{{/allParams}} {{/operation}} } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play26/ApiClient.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play26/ApiClient.mustache index 1346ae856..b752b433d 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play26/ApiClient.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play26/ApiClient.mustache @@ -5,6 +5,7 @@ import java.io.IOException; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.*; @@ -13,7 +14,9 @@ import retrofit2.Converter; import retrofit2.Retrofit; import retrofit2.converter.scalars.ScalarsConverterFactory; import retrofit2.converter.jackson.JacksonConverterFactory; +{{#openApiNullable}} import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} import play.libs.Json; import play.libs.ws.WSClient; @@ -91,8 +94,10 @@ public class ApiClient { } if (defaultMapper == null) { defaultMapper = Json.mapper(); + {{#openApiNullable}} JsonNullableModule jnm = new JsonNullableModule(); defaultMapper.registerModule(jnm); + {{/openApiNullable}} } return new Retrofit.Builder() @@ -198,9 +203,9 @@ public class ApiClient { @Override public File convert(ResponseBody value) throws IOException { - File file = File.createTempFile("retrofit-file", ".tmp"); - Files.write(Paths.get(file.getPath()), value.bytes()); - return file; + Path path = Files.createTempFile("retrofit-file", ".tmp"); + Files.write(path, value.bytes()); + return path.toFile(); } }; } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play26/Play26CallAdapterFactory.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play26/Play26CallAdapterFactory.mustache index efbc0ac29..05c725474 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play26/Play26CallAdapterFactory.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play26/Play26CallAdapterFactory.mustache @@ -64,7 +64,7 @@ public class Play26CallAdapterFactory extends CallAdapter.Factory { } /** - * Adpater that coverts values returned by API interface into CompletionStage + * Adapter that coverts values returned by API interface into CompletionStage */ private static final class ValueAdapter implements CallAdapter> { diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play26/api.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play26/api.mustache index b435a16c0..dd3339ff8 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play26/api.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/play26/api.mustache @@ -2,9 +2,12 @@ package {{package}}; import {{invokerPackage}}.CollectionFormats.*; -{{#useRxJava}}import rx.Observable;{{/useRxJava}} -{{#useRxJava2}}import io.reactivex.Observable;{{/useRxJava2}} -{{#doNotUseRx}}import retrofit2.Call;{{/doNotUseRx}} +{{#useRxJava2}} +import io.reactivex.Observable; +{{/useRxJava2}} +{{#doNotUseRx}} +import retrofit2.Call; +{{/doNotUseRx}} import retrofit2.http.*; import okhttp3.RequestBody; @@ -33,8 +36,14 @@ public interface {{classname}} { {{#allParams}} * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} {{/allParams}} - * @return Call<{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}Void{{/returnType}}> + * @return Call<{{returnType}}{{^returnType}}Void{{/returnType}}> +{{#isDeprecated}} + * @deprecated +{{/isDeprecated}} */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} {{#formParams}} {{#-first}} {{#isMultipart}}@retrofit2.http.Multipart{{/isMultipart}}{{^isMultipart}}@retrofit2.http.FormUrlEncoded{{/isMultipart}} @@ -50,9 +59,9 @@ public interface {{classname}} { {{/prioritizedContentTypes}} {{/formParams}} @{{httpMethod}}("{{{path}}}") - CompletionStage> {{operationId}}({{^allParams}});{{/allParams}} - {{#allParams}}{{>libraries/retrofit2/queryParams}}{{>libraries/retrofit2/pathParams}}{{>libraries/retrofit2/headerParams}}{{>libraries/retrofit2/bodyParams}}{{>libraries/retrofit2/formParams}}{{#hasMore}}, {{/hasMore}}{{^hasMore}} - );{{/hasMore}}{{/allParams}} + CompletionStage> {{operationId}}({{^allParams}});{{/allParams}} + {{#allParams}}{{>libraries/retrofit2/queryParams}}{{>libraries/retrofit2/pathParams}}{{>libraries/retrofit2/headerParams}}{{>libraries/retrofit2/bodyParams}}{{>libraries/retrofit2/formParams}}{{^-last}}, {{/-last}}{{#-last}} + );{{/-last}}{{/allParams}} {{/operation}} } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/pom.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/pom.mustache index 06f19bcb0..5ec0dd025 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/pom.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/retrofit2/pom.mustache @@ -139,12 +139,22 @@ + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + 1.8 + 1.8 + + org.apache.maven.plugins maven-javadoc-plugin - 3.1.1 + 3.3.2 none + 1.8 @@ -245,37 +255,30 @@ ${jodatime-version} {{/joda}} - {{#threetenbp}} - - org.threeten - threetenbp - ${threetenbp-version} - - {{/threetenbp}} - {{#useRxJava}} + {{#useRxJava2}} - io.reactivex + io.reactivex.rxjava2 rxjava ${rxjava-version} com.squareup.retrofit2 - adapter-rxjava + adapter-rxjava2 ${retrofit-version} - {{/useRxJava}} - {{#useRxJava2}} + {{/useRxJava2}} + {{#useRxJava3}} - io.reactivex.rxjava2 + io.reactivex.rxjava3 rxjava ${rxjava-version} - com.squareup.retrofit2 - adapter-rxjava2 - ${retrofit-version} + com.github.akarnokd + rxjava3-retrofit-adapter + 3.0.0 - {{/useRxJava2}} + {{/useRxJava3}} {{#usePlayWS}} @@ -298,9 +301,16 @@ jackson-databind ${jackson-databind-version} + {{#openApiNullable}} + + org.openapitools + jackson-databind-nullable + ${jackson-databind-nullable-version} + + {{/openApiNullable}} com.fasterxml.jackson.datatype - jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}} + jackson-datatype-jsr310 ${jackson-version} {{#withXml}} @@ -311,47 +321,16 @@ ${jackson-version} {{/withXml}} - {{#play24}} - - com.typesafe.play - play-java-ws_2.11 - ${play-version} - - - org.openapitools - jackson-databind-nullable - ${jackson-databind-nullable-version} - - {{/play24}} - {{#play25}} - - com.typesafe.play - play-java-ws_2.11 - ${play-version} - - - org.openapitools - jackson-databind-nullable - ${jackson-databind-nullable-version} - - {{/play25}} - {{#play26}} com.typesafe.play play-ahc-ws_2.12 ${play-version} - javax.validation - validation-api - 1.1.0.Final + jakarta.validation + jakarta.validation-api + ${beanvalidation-version} - - org.openapitools - jackson-databind-nullable - ${jackson-databind-nullable-version} - - {{/play26}} {{/usePlayWS}} {{#parcelableModel}} @@ -362,6 +341,12 @@ provided {{/parcelableModel}} + + jakarta.annotation + jakarta.annotation-api + ${jakarta-annotation-version} + provided + junit @@ -372,41 +357,34 @@ UTF-8 - {{#supportJava6}}1.6{{/supportJava6}}{{^supportJava6}}{{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}}{{/supportJava6}} + 1.8 ${java.version} ${java.version} 1.8.3 - 1.5.22 + 1.6.3 {{#usePlayWS}} - 2.10.3 - {{#play24}} - 2.6.6 - 2.4.11 - {{/play24}} - {{#play25}} - 2.10.3 - 2.5.15 - {{/play25}} - {{#play26}} - 2.10.3 + 2.13.4 + 2.13.4.2 2.6.7 - {{/play26}} - 0.2.1 + {{#openApiNullable}} + 0.2.4 + {{/openApiNullable}} {{/usePlayWS}} 2.5.0 - {{#useRxJava}} - 1.3.0 - {{/useRxJava}} {{#useRxJava2}} 2.1.1 {{/useRxJava2}} + {{#useRxJava3}} + 3.0.4 + {{/useRxJava3}} {{#joda}} 2.9.9 {{/joda}} - {{#threetenbp}} - 1.4.0 - {{/threetenbp}} + 1.3.5 +{{#useBeanValidation}} + 2.0.2 +{{/useBeanValidation}} 1.0.1 - 4.13 + 4.13.2 diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/vertx/ApiClient.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/vertx/ApiClient.mustache index bc19a9253..68253df0b 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/vertx/ApiClient.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/vertx/ApiClient.mustache @@ -9,12 +9,15 @@ import {{invokerPackage}}.auth.OAuth; {{/hasOAuthMethods}} import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +{{#openApiNullable}} import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} import io.vertx.core.*; import io.vertx.core.buffer.Buffer; import io.vertx.core.file.AsyncFile; @@ -30,6 +33,9 @@ import io.vertx.ext.web.client.HttpResponse; import io.vertx.ext.web.client.WebClient; import io.vertx.ext.web.client.WebClientOptions; +{{#jsr310}} +import java.time.OffsetDateTime; +{{/jsr310}} import java.text.DateFormat; import java.util.*; import java.util.function.Consumer; @@ -39,7 +45,7 @@ import java.util.regex.Pattern; import static java.util.stream.Collectors.toMap; {{>generatedAnnotation}} -public class ApiClient { +public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} { private static final Pattern CONTENT_DISPOSITION_PATTERN = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?"); private static final OpenOptions FILE_DOWNLOAD_OPTIONS = new OpenOptions().setCreate(true).setTruncateExisting(true); @@ -55,6 +61,7 @@ public class ApiClient { private DateFormat dateFormat; private ObjectMapper objectMapper; private String downloadsDir = ""; + private int timeout = -1; public ApiClient(Vertx vertx, JsonObject config) { Objects.requireNonNull(vertx, "Vertx must not be null"); @@ -79,8 +86,10 @@ public class ApiClient { this.objectMapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); this.objectMapper.registerModule(new JavaTimeModule()); this.objectMapper.setDateFormat(dateFormat); + {{#openApiNullable}} JsonNullableModule jnm = new JsonNullableModule(); this.objectMapper.registerModule(jnm); + {{/openApiNullable}} // Setup authentications (key: authentication name, value: authentication). this.authentications = new HashMap<>();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} @@ -96,6 +105,7 @@ public class ApiClient { this.downloadsDir = config.getString("downloadsDir", this.downloadsDir); this.config = config; this.identifier = UUID.randomUUID().toString(); + this.timeout = config.getInteger("timeout", -1); } public Vertx getVertx() { @@ -113,10 +123,10 @@ public class ApiClient { public synchronized WebClient getWebClient() { String webClientIdentifier = "web-client-" + identifier; - WebClient webClient = Vertx.currentContext().get(webClientIdentifier); + WebClient webClient = this.vertx.getOrCreateContext().get(webClientIdentifier); if (webClient == null) { webClient = buildWebClient(vertx, config); - Vertx.currentContext().put(webClientIdentifier, webClient); + this.vertx.getOrCreateContext().put(webClientIdentifier, webClient); } return webClient; } @@ -288,7 +298,9 @@ public class ApiClient { return ""; } else if (param instanceof Date) { return formatDate((Date) param); - } else if (param instanceof Collection) { + } {{#jsr310}}else if (param instanceof OffsetDateTime) { + return formatOffsetDateTime((OffsetDateTime) param); + } {{/jsr310}}else if (param instanceof Collection) { StringBuilder b = new StringBuilder(); for (Object o : (Collection) param) { if (b.length() > 0) { @@ -428,7 +440,11 @@ public class ApiClient { AsyncFile file = (AsyncFile) body; request.sendStream(file, responseHandler); } else { - request.sendJson(body, responseHandler); + try { + request.sendBuffer(Buffer.buffer(this.objectMapper.writeValueAsBytes(body)), responseHandler); + } catch (JsonProcessingException jsonProcessingException) { + responseHandler.handle(Future.failedFuture(jsonProcessingException)); + } } } @@ -446,14 +462,15 @@ public class ApiClient { * @param accepts The request's Accept headers * @param contentTypes The request's Content-Type headers * @param authNames The authentications to apply + * @param authInfo The call specific auth override * @param returnType The return type into which to deserialize the response * @param resultHandler The asynchronous response handler */ public void invokeAPI(String path, String method, List queryParams, Object body, MultiMap headerParams, - MultiMap cookieParams, Map formParams, String[] accepts, String[] contentTypes, String[] authNames, + MultiMap cookieParams, Map formParams, String[] accepts, String[] contentTypes, String[] authNames, AuthInfo authInfo, TypeReference returnType, Handler> resultHandler) { - updateParamsForAuth(authNames, queryParams, headerParams, cookieParams); + updateParamsForAuth(authNames, authInfo, queryParams, headerParams, cookieParams); if (accepts != null && accepts.length > 0) { headerParams.add(HttpHeaders.ACCEPT, selectHeaderAccept(accepts)); @@ -465,6 +482,7 @@ public class ApiClient { HttpMethod httpMethod = HttpMethod.valueOf(method); HttpRequest request = getWebClient().requestAbs(httpMethod, basePath + path); + request.timeout(this.timeout); if (httpMethod == HttpMethod.PATCH) { request.putHeader("X-HTTP-Method-Override", "PATCH"); @@ -633,7 +651,7 @@ public class ApiClient { protected WebClient buildWebClient(Vertx vertx, JsonObject config) { if (!config.containsKey("userAgent")) { - config.put("userAgent", "{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}"); + config.put("userAgent", "{{{httpUserAgent}}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}"); } return WebClient.create(vertx, new WebClientOptions(config)); @@ -645,11 +663,72 @@ public class ApiClient { * * @param authNames The authentications to apply */ - protected void updateParamsForAuth(String[] authNames, List queryParams, MultiMap headerParams, MultiMap cookieParams) { + protected void updateParamsForAuth(String[] authNames, AuthInfo authInfo, List queryParams, MultiMap headerParams, MultiMap cookieParams) { for (String authName : authNames) { - Authentication auth = authentications.get(authName); + Authentication auth; + if (authInfo != null && authInfo.authentications.containsKey(authName)) { + auth = authInfo.authentications.get(authName); + } else { + auth = authentications.get(authName); + } if (auth == null) throw new RuntimeException("Authentication undefined: " + authName); auth.applyToParams(queryParams, headerParams, cookieParams); } } + + public static class AuthInfo { + + private final Map authentications = new LinkedHashMap<>();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + + public void add{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}Authentication(String username, String password) { + HttpBasicAuth auth = new HttpBasicAuth(); + auth.setUsername(username); + auth.setPassword(password); + authentications.put("{{name}}", auth); + }{{/isBasicBasic}}{{^isBasicBasic}} + + public void add{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}Authentication(String bearerToken) { + HttpBearerAuth auth = new + HttpBearerAuth("{{scheme}}"); + auth.setBearerToken(bearerToken); + authentications.put("{{name}}", auth); + }{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} + + public void add{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}Authentication(String apikey, String apiKeyPrefix) { + ApiKeyAuth auth = new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}},"{{keyParamName}}"); + auth.setApiKey(apikey); + auth.setApiKeyPrefix(apiKeyPrefix); + authentications.put("{{name}}", auth); + }{{/isApiKey}}{{#isOAuth}} + + public void add{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}Authentication(String accessToken) { + OAuth auth = new OAuth(); + auth.setAccessToken(accessToken); + authentications.put("{{name}}", auth); + }{{/isOAuth}}{{/authMethods}}{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + + public static AuthInfo for{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}(String username, String password) { + AuthInfo authInfo = new AuthInfo(); + authInfo.add{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}Authentication(username, password); + return authInfo; + }{{/isBasicBasic}}{{^isBasicBasic}} + + public static AuthInfo for{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}Authentication(String bearerToken) { + AuthInfo authInfo = new AuthInfo(); + authInfo.add{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}Authentication(bearerToken); + return authInfo; + }{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} + + public static AuthInfo for{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}Authentication(String apikey, String apiKeyPrefix) { + AuthInfo authInfo = new AuthInfo(); + authInfo.add{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}Authentication(apikey, apiKeyPrefix); + return authInfo; + }{{/isApiKey}}{{#isOAuth}} + + public static AuthInfo for{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}Authentication(String accessToken) { + AuthInfo authInfo = new AuthInfo(); + authInfo.add{{#lambda.titlecase}}{{name}}{{/lambda.titlecase}}Authentication(accessToken); + return authInfo; + }{{/isOAuth}}{{/authMethods}} + } } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/vertx/api.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/vertx/api.mustache index dcf9df4cc..b81c06100 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/vertx/api.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/vertx/api.mustache @@ -1,5 +1,6 @@ package {{package}}; +import {{invokerPackage}}.ApiClient; {{#imports}}import {{import}}; {{/imports}} import io.vertx.core.AsyncResult; @@ -12,7 +13,15 @@ public interface {{classname}} { {{#operations}} {{#operation}} - void {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}Handler> handler); + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + void {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}Handler> handler); + + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + void {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}ApiClient.AuthInfo authInfo, Handler> handler); {{/operation}} {{/operations}} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/vertx/apiImpl.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/vertx/apiImpl.mustache index 5ea569f4a..35daaade9 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/vertx/apiImpl.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/vertx/apiImpl.mustache @@ -11,6 +11,9 @@ import io.vertx.core.json.JsonObject; import com.fasterxml.jackson.core.type.TypeReference; import java.util.*; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import {{invokerPackage}}.ApiClient; import {{invokerPackage}}.ApiException; @@ -41,14 +44,27 @@ public class {{classname}}Impl implements {{classname}} { {{#operation}} /** - * {{summary}} - * {{notes}} - {{#allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} - {{/allParams}} - * @param resultHandler Asynchronous result handler - */ - public void {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}Handler> resultHandler) { + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + * @param resultHandler Asynchronous result handler + */ + public void {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}Handler> resultHandler) { + {{operationId}}({{#allParams}}{{paramName}}, {{/allParams}}null, resultHandler); + } + + /** + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + * @param authInfo per call authentication override. + * @param resultHandler Asynchronous result handler + */ + public void {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}ApiClient.AuthInfo authInfo, Handler> resultHandler) { Object localVarBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; {{#allParams}}{{#required}} // verify the required parameter '{{paramName}}' is set @@ -58,12 +74,12 @@ public class {{classname}}Impl implements {{classname}} { } {{/required}}{{/allParams}} // create path and map variables - String localVarPath = "{{{path}}}"{{#pathParams}}.replaceAll("\\{" + "{{baseName}}" + "\\}", {{{paramName}}}.toString()){{/pathParams}}; + String localVarPath = "{{{path}}}"{{#pathParams}}.replaceAll("\\{" + "{{baseName}}" + "\\}", encodeParameter({{{paramName}}}.toString())){{/pathParams}}; // query params List localVarQueryParams = new ArrayList<>(); {{#queryParams}} - localVarQueryParams.addAll(apiClient.parameterToPairs("{{#collectionFormat}}{{{collectionFormat}}}{{/collectionFormat}}", "{{baseName}}", {{paramName}})); + localVarQueryParams.addAll(apiClient.parameterToPairs("{{{collectionFormat}}}", "{{baseName}}", {{paramName}})); {{/queryParams}} // header params @@ -84,14 +100,22 @@ public class {{classname}}Impl implements {{classname}} { {{#formParams}}if ({{paramName}} != null) localVarFormParams.put("{{baseName}}", {{paramName}}); {{/formParams}} - String[] localVarAccepts = { {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} }; - String[] localVarContentTypes = { {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} }; - String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + String[] localVarAccepts = { {{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}} }; + String[] localVarContentTypes = { {{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}} }; + String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{^-last}}, {{/-last}}{{/authMethods}} }; {{#returnType}} TypeReference<{{{returnType}}}> localVarReturnType = new TypeReference<{{{returnType}}}>() {}; - apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccepts, localVarContentTypes, localVarAuthNames, localVarReturnType, resultHandler);{{/returnType}}{{^returnType}} - apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccepts, localVarContentTypes, localVarAuthNames, null, resultHandler);{{/returnType}} + apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccepts, localVarContentTypes, localVarAuthNames, authInfo, localVarReturnType, resultHandler);{{/returnType}}{{^returnType}} + apiClient.invokeAPI(localVarPath, "{{httpMethod}}", localVarQueryParams, localVarBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccepts, localVarContentTypes, localVarAuthNames, authInfo, null, resultHandler);{{/returnType}} } {{/operation}} + + private String encodeParameter(String parameter) { + try { + return URLEncoder.encode(parameter, StandardCharsets.UTF_8.name()); + } catch (UnsupportedEncodingException e) { + return parameter; + } + } } {{/operations}} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/vertx/api_test.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/vertx/api_test.mustache index 77010f248..f4fee565f 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/vertx/api_test.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/vertx/api_test.mustache @@ -21,6 +21,8 @@ import io.vertx.ext.unit.junit.RunTestOnContext; import io.vertx.ext.unit.TestContext; import io.vertx.ext.unit.Async; +import java.time.LocalDate; +import java.time.OffsetDateTime; {{^fullJavaUtil}} import java.util.ArrayList; import java.util.HashMap; @@ -56,8 +58,8 @@ public class {{classname}}Test { * @param context Vertx test context for doing assertions */ @Test - public void {{operationId}}Test(TestContext context) { - Async async = context.async(); + public void {{operationId}}Test(TestContext testContext) { + Async async = testContext.async(); {{#allParams}} {{{dataType}}} {{paramName}} = null; {{/allParams}} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/vertx/build.gradle.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/vertx/build.gradle.mustache index 02760c591..6f9d9e6bb 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/vertx/build.gradle.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/vertx/build.gradle.mustache @@ -5,19 +5,21 @@ group = '{{groupId}}' version = '{{artifactVersion}}' repositories { - maven { url "https://repo1.maven.org/maven2" } - jcenter() + mavenCentral() } apply plugin: 'java' -apply plugin: 'maven' +apply plugin: 'maven-publish' sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 -install { - repositories.mavenInstaller { - pom.artifactId = '{{artifactId}}' +publishing { + publications { + maven(MavenPublication) { + artifactId = '{{artifactId}}' + from components.java + } } } @@ -28,29 +30,32 @@ task execute(type:JavaExec) { ext { swagger_annotations_version = "1.5.21" - jackson_version = "2.10.3" - jackson_databind_version = "2.10.3" + jackson_version = "2.13.4" + jackson_databind_version = "2.13.4.2" vertx_version = "3.4.2" - junit_version = "4.13" + junit_version = "4.13.2" + {{#openApiNullable}} + jackson_databind_nullable_version = "0.2.4" + {{/openApiNullable}} + jakarta_annotation_version = "1.3.5" } dependencies { - compile "io.swagger:swagger-annotations:$swagger_annotations_version" - compile "com.google.code.findbugs:jsr305:3.0.2" - compile "io.vertx:vertx-web-client:$vertx_version" - compile "io.vertx:vertx-rx-java:$vertx_version" - compile "com.fasterxml.jackson.core:jackson-core:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" - compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation "io.vertx:vertx-web-client:$vertx_version" + implementation "io.vertx:vertx-rx-java:$vertx_version" + implementation "com.fasterxml.jackson.core:jackson-core:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" {{#joda}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" + implementation "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version" {{/joda}} - {{#java8}} - compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" - {{/java8}} - {{#threetenbp}} - compile "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_version" - {{/threetenbp}} - testCompile "junit:junit:$junit_version" - testCompile "io.vertx:vertx-unit:$vertx_version" + implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + {{#openApiNullable}} + implementation "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + {{/openApiNullable}} + implementation "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version" + testImplementation "junit:junit:$junit_version" + testImplementation "io.vertx:vertx-unit:$vertx_version" } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/vertx/pom.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/vertx/pom.mustache index b3539c9fd..1a10de313 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/vertx/pom.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/vertx/pom.mustache @@ -151,9 +151,10 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.1.1 + 3.3.2 none + 1.8 @@ -205,11 +206,13 @@ + {{#swagger1AnnotationLibrary}} io.swagger swagger-annotations ${swagger-annotations-version} + {{/swagger1AnnotationLibrary}} @@ -217,7 +220,7 @@ jsr305 3.0.2 - + io.vertx @@ -246,11 +249,13 @@ jackson-databind ${jackson-databind} + {{#openApiNullable}} org.openapitools jackson-databind-nullable ${jackson-databind-nullable-version} + {{/openApiNullable}} {{#joda}} com.fasterxml.jackson.datatype @@ -258,20 +263,17 @@ ${jackson-version} {{/joda}} - {{#java8}} com.fasterxml.jackson.datatype jackson-datatype-jsr310 ${jackson-version} - {{/java8}} - {{#threetenbp}} - - com.github.joschi.jackson - jackson-datatype-threetenbp - ${jackson-version} - - {{/threetenbp}} + + jakarta.annotation + jakarta.annotation-api + ${jakarta-annotation-version} + provided + @@ -291,10 +293,11 @@ UTF-8 3.4.2 - 1.5.22 - 2.10.3 - 2.10.3 - 0.2.1 - 4.13 + 1.6.6 + 2.13.4 + 2.13.4.2 + 0.2.4 + 1.3.5 + 4.13.2 diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/vertx/rxApiImpl.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/vertx/rxApiImpl.mustache index be144ff3e..f01030420 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/vertx/rxApiImpl.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/vertx/rxApiImpl.mustache @@ -2,6 +2,7 @@ package {{package}}.rxjava; {{#imports}}import {{import}}; {{/imports}} +import {{invokerPackage}}.ApiClient; import java.util.*; @@ -13,41 +14,69 @@ import io.vertx.core.Handler; {{#operations}} public class {{classname}} { - private final {{package}}.{{classname}} delegate; + private final {{package}}.{{classname}} delegate; - public {{classname}}({{package}}.{{classname}} delegate) { - this.delegate = delegate; + public {{classname}}({{package}}.{{classname}} delegate) { + this.delegate = delegate; } - public {{package}}.{{classname}} getDelegate() { - return delegate; - } + public {{package}}.{{classname}} getDelegate() { + return delegate; + } {{#operation}} /** - * {{summary}} - * {{notes}} - {{#allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} - {{/allParams}} - * @param resultHandler Asynchronous result handler - */ - public void {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}Handler> resultHandler) { + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + * @param resultHandler Asynchronous result handler + */ + public void {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}Handler> resultHandler) { delegate.{{operationId}}({{#allParams}}{{paramName}}, {{/allParams}}resultHandler); } /** - * {{summary}} - * {{notes}} - {{#allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} - {{/allParams}} - * @return Asynchronous result handler (RxJava Single) - */ - public Single<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> rx{{operationIdCamelCase}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) { - return Single.create(new io.vertx.rx.java.SingleOnSubscribeAdapter<>(fut -> { - delegate.{{operationId}}({{#allParams}}{{paramName}}, {{/allParams}}fut); - })); + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + * @param authInfo call specific auth overrides + * @param resultHandler Asynchronous result handler + */ + public void {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}ApiClient.AuthInfo authInfo, Handler> resultHandler) { + delegate.{{operationId}}({{#allParams}}{{paramName}}, {{/allParams}}authInfo, resultHandler); + } + + /** + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + * @return Asynchronous result handler (RxJava Single) + */ + public Single<{{{returnType}}}{{^returnType}}Void{{/returnType}}> rx{{operationIdCamelCase}}({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) { + return Single.create(new io.vertx.rx.java.SingleOnSubscribeAdapter<>(fut -> + delegate.{{operationId}}({{#allParams}}{{paramName}}, {{/allParams}}fut) + )); + } + + /** + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + * @param authInfo call specific auth overrides + * @return Asynchronous result handler (RxJava Single) + */ + public Single<{{{returnType}}}{{^returnType}}Void{{/returnType}}> rx{{operationIdCamelCase}}({{#allParams}}{{{dataType}}} {{paramName}}, {{/allParams}}ApiClient.AuthInfo authInfo) { + return Single.create(new io.vertx.rx.java.SingleOnSubscribeAdapter<>(fut -> + delegate.{{operationId}}({{#allParams}}{{paramName}}, {{/allParams}}authInfo, fut) + )); } {{/operation}} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/webclient/ApiClient.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/webclient/ApiClient.mustache index 1b22c2427..a33430843 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/webclient/ApiClient.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/webclient/ApiClient.mustache @@ -3,7 +3,9 @@ package {{invokerPackage}}; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +{{#openApiNullable}} import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.core.ParameterizedTypeReference; @@ -22,6 +24,7 @@ import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.http.client.ClientHttpResponse; import org.springframework.http.codec.json.Jackson2JsonDecoder; import org.springframework.http.codec.json.Jackson2JsonEncoder; +import org.springframework.util.CollectionUtils; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.util.StringUtils; @@ -29,6 +32,7 @@ import org.springframework.http.client.reactive.ClientHttpRequest; import org.springframework.web.client.RestClientException; import org.springframework.web.util.UriComponentsBuilder; import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.function.client.WebClient.ResponseSpec; import org.springframework.web.reactive.function.client.ClientResponse; import org.springframework.web.reactive.function.BodyInserter; import org.springframework.web.reactive.function.BodyInserters; @@ -58,6 +62,13 @@ import java.util.Map; import java.util.Map.Entry; import java.util.TimeZone; +{{#useJakartaEe}}import jakarta.annotation.Nullable;{{/useJakartaEe}} +{{^useJakartaEe}}import javax.annotation.Nullable;{{/useJakartaEe}} + +{{#jsr310}} +import java.time.OffsetDateTime; +{{/jsr310}} + import {{invokerPackage}}.auth.Authentication; import {{invokerPackage}}.auth.HttpBasicAuth; import {{invokerPackage}}.auth.HttpBearerAuth; @@ -67,7 +78,7 @@ import {{invokerPackage}}.auth.OAuth; {{/hasOAuthMethods}} {{>generatedAnnotation}} -public class ApiClient { +public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} { public enum CollectionFormat { CSV(","), TSV("\t"), SSV(" "), PIPES("|"), MULTI(null); @@ -81,6 +92,8 @@ public class ApiClient { } } + private static final String URI_TEMPLATE_ATTRIBUTE = WebClient.class.getName() + ".uriTemplate"; + private HttpHeaders defaultHeaders = new HttpHeaders(); private MultiValueMap defaultCookies = new LinkedMultiValueMap(); @@ -88,43 +101,58 @@ public class ApiClient { private final WebClient webClient; private final DateFormat dateFormat; + private final ObjectMapper objectMapper; private Map authentications; public ApiClient() { this.dateFormat = createDefaultDateFormat(); - ObjectMapper mapper = new ObjectMapper(); - mapper.setDateFormat(dateFormat); - mapper.registerModule(new JavaTimeModule()); - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - JsonNullableModule jnm = new JsonNullableModule(); - mapper.registerModule(jnm); - - this.webClient = buildWebClient(mapper); + this.objectMapper = createDefaultObjectMapper(this.dateFormat); + this.webClient = buildWebClient(this.objectMapper); this.init(); } + public ApiClient(WebClient webClient) { + this(Optional.ofNullable(webClient).orElseGet(() -> buildWebClient()), createDefaultDateFormat()); + } + public ApiClient(ObjectMapper mapper, DateFormat format) { this(buildWebClient(mapper.copy()), format); } public ApiClient(WebClient webClient, ObjectMapper mapper, DateFormat format) { - this(Optional.ofNullable(webClient).orElseGet(() ->buildWebClient(mapper.copy())), format); + this(Optional.ofNullable(webClient).orElseGet(() -> buildWebClient(mapper.copy())), format); } private ApiClient(WebClient webClient, DateFormat format) { this.webClient = webClient; this.dateFormat = format; + this.objectMapper = createDefaultObjectMapper(format); this.init(); } - public DateFormat createDefaultDateFormat() { + public static DateFormat createDefaultDateFormat() { DateFormat dateFormat = new RFC3339DateFormat(); dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); return dateFormat; } + public static ObjectMapper createDefaultObjectMapper(@Nullable DateFormat dateFormat) { + if (null == dateFormat) { + dateFormat = createDefaultDateFormat(); + } + ObjectMapper mapper = new ObjectMapper(); + mapper.setDateFormat(dateFormat); + mapper.registerModule(new JavaTimeModule()); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + {{#openApiNullable}} + JsonNullableModule jnm = new JsonNullableModule(); + mapper.registerModule(jnm); + {{/openApiNullable}} + return mapper; + } + protected void init() { // Setup authentications (key: authentication name, value: authentication). authentications = new HashMap();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} @@ -137,20 +165,45 @@ public class ApiClient { } /** - * Build the RestTemplate used to make HTTP requests. - * @return RestTemplate + * Build the WebClientBuilder used to make WebClient. + * @param mapper ObjectMapper used for serialize/deserialize + * @return WebClient */ - public static WebClient buildWebClient(ObjectMapper mapper) { + public static WebClient.Builder buildWebClientBuilder(ObjectMapper mapper) { ExchangeStrategies strategies = ExchangeStrategies .builder() .codecs(clientDefaultCodecsConfigurer -> { clientDefaultCodecsConfigurer.defaultCodecs().jackson2JsonEncoder(new Jackson2JsonEncoder(mapper, MediaType.APPLICATION_JSON)); clientDefaultCodecsConfigurer.defaultCodecs().jackson2JsonDecoder(new Jackson2JsonDecoder(mapper, MediaType.APPLICATION_JSON)); }).build(); - WebClient.Builder webClient = WebClient.builder().exchangeStrategies(strategies); - return webClient.build(); + WebClient.Builder webClientBuilder = WebClient.builder().exchangeStrategies(strategies); + return webClientBuilder; } + /** + * Build the WebClientBuilder used to make WebClient. + * @return WebClient + */ + public static WebClient.Builder buildWebClientBuilder() { + return buildWebClientBuilder(createDefaultObjectMapper(null)); + } + + /** + * Build the WebClient used to make HTTP requests. + * @param mapper ObjectMapper used for serialize/deserialize + * @return WebClient + */ + public static WebClient buildWebClient(ObjectMapper mapper) { + return buildWebClientBuilder(mapper).build(); + } + + /** + * Build the WebClient used to make HTTP requests. + * @return WebClient + */ + public static WebClient buildWebClient() { + return buildWebClientBuilder(createDefaultObjectMapper(null)).build(); + } /** * Get the current base path @@ -340,6 +393,22 @@ public class ApiClient { return dateFormat.format(date); } + /** + * Get the ObjectMapper used to make HTTP requests. + * @return ObjectMapper objectMapper + */ + public ObjectMapper getObjectMapper() { + return objectMapper; + } + + /** + * Get the WebClient used to make HTTP requests. + * @return WebClient webClient + */ + public WebClient getWebClient() { + return webClient; + } + /** * Format the given parameter object into string. * @param param the object to convert @@ -350,7 +419,9 @@ public class ApiClient { return ""; } else if (param instanceof Date) { return formatDate( (Date) param); - } else if (param instanceof Collection) { + } {{#jsr310}}else if (param instanceof OffsetDateTime) { + return formatOffsetDateTime((OffsetDateTime) param); + } {{/jsr310}}else if (param instanceof Collection) { StringBuilder b = new StringBuilder(); for(Object o : (Collection) param) { if(b.length() > 0) { @@ -383,10 +454,10 @@ public class ApiClient { } if (value instanceof Map) { - Map map = (Map) value; - - for (Object key : map.keySet()) { - params.add(parameterToString(key), parameterToString(map.get(key))); + @SuppressWarnings("unchecked") + final Map valuesMap = (Map) value; + for (final Entry entry : valuesMap.entrySet()) { + params.add(entry.getKey(), parameterToString(entry.getValue())); } return params; } @@ -447,7 +518,16 @@ public class ApiClient { * @return boolean true if the MediaType represents JSON, false otherwise */ public boolean isJsonMime(MediaType mediaType) { - return mediaType != null && (MediaType.APPLICATION_JSON.isCompatibleWith(mediaType) || mediaType.getSubtype().matches("^.*\\+json[;]?\\s*$")); + return mediaType != null && (MediaType.APPLICATION_JSON.isCompatibleWith(mediaType) || mediaType.getSubtype().matches("^.*(\\+json|ndjson)[;]?\\s*$")); + } + + /** + * Check if the given {@code String} is a Problem JSON MIME (RFC-7807). + * @param mediaType the input MediaType + * @return boolean true if the MediaType represents Problem JSON, false otherwise + */ + public boolean isProblemJsonMime(String mediaType) { + return "application/problem+json".equalsIgnoreCase(mediaType); } /** @@ -464,7 +544,7 @@ public class ApiClient { } for (String accept : accepts) { MediaType mediaType = MediaType.parseMediaType(accept); - if (isJsonMime(mediaType)) { + if (isJsonMime(mediaType) && !isProblemJsonMime(accept)) { return Collections.singletonList(mediaType); } } @@ -477,11 +557,11 @@ public class ApiClient { * otherwise use the first one of the array. * * @param contentTypes The Content-Type array to select from - * @return MediaType The Content-Type header to use. If the given array is empty, JSON will be used. + * @return MediaType The Content-Type header to use. If the given array is empty, null will be returned. */ public MediaType selectHeaderContentType(String[] contentTypes) { if (contentTypes.length == 0) { - return MediaType.APPLICATION_JSON; + return null; } for (String contentType : contentTypes) { MediaType mediaType = MediaType.parseMediaType(contentType); @@ -501,7 +581,7 @@ public class ApiClient { */ protected BodyInserter selectBody(Object obj, MultiValueMap formParams, MediaType contentType) { if(MediaType.APPLICATION_FORM_URLENCODED.equals(contentType)) { - MultiValueMap map = new LinkedMultiValueMap(); + MultiValueMap map = new LinkedMultiValueMap<>(); formParams .toSingleValueMap() @@ -512,7 +592,7 @@ public class ApiClient { } else if(MediaType.MULTIPART_FORM_DATA.equals(contentType)) { return BodyInserters.fromMultipartData(formParams); } else { - return obj != null ? BodyInserters.fromObject(obj) : null; + return obj != null ? BodyInserters.fromValue(obj) : null; } } @@ -533,43 +613,65 @@ public class ApiClient { * @param returnType The return type into which to deserialize the response * @return The response body in chosen type */ - public Mono invokeAPI(String path, HttpMethod method, Map pathParams, MultiValueMap queryParams, Object body, HttpHeaders headerParams, MultiValueMap cookieParams, MultiValueMap formParams, List accept, MediaType contentType, String[] authNames, ParameterizedTypeReference returnType) throws RestClientException { + public ResponseSpec invokeAPI(String path, HttpMethod method, Map pathParams, MultiValueMap queryParams, Object body, HttpHeaders headerParams, MultiValueMap cookieParams, MultiValueMap formParams, List accept, MediaType contentType, String[] authNames, ParameterizedTypeReference returnType) throws RestClientException { final WebClient.RequestBodySpec requestBuilder = prepareRequest(path, method, pathParams, queryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames); - return requestBuilder.retrieve().bodyToMono(returnType); + return requestBuilder.retrieve(); } /** - * Invoke API by sending HTTP request with the given options. - * - * @param the return type to use - * @param path The sub-path of the HTTP URL - * @param method The request method - * @param pathParams The path parameters + * Include queryParams in uriParams taking into account the paramName * @param queryParams The query parameters - * @param body The request body object - * @param headerParams The header parameters - * @param formParams The form parameters - * @param accept The request's Accept header - * @param contentType The request's Content-Type header - * @param authNames The authentications to apply - * @param returnType The return type into which to deserialize the response - * @return The response body in chosen type + * @param uriParams The path parameters + * return templatized query string */ - public Flux invokeFluxAPI(String path, HttpMethod method, Map pathParams, MultiValueMap queryParams, Object body, HttpHeaders headerParams, MultiValueMap cookieParams, MultiValueMap formParams, List accept, MediaType contentType, String[] authNames, ParameterizedTypeReference returnType) throws RestClientException { - final WebClient.RequestBodySpec requestBuilder = prepareRequest(path, method, pathParams, queryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames); - return requestBuilder.retrieve().bodyToFlux(returnType); + private String generateQueryUri(MultiValueMap queryParams, Map uriParams) { + StringBuilder queryBuilder = new StringBuilder(); + queryParams.forEach((name, values) -> { + if (CollectionUtils.isEmpty(values)) { + if (queryBuilder.length() != 0) { + queryBuilder.append('&'); + } + queryBuilder.append(name); + } else { + int valueItemCounter = 0; + for (Object value : values) { + if (queryBuilder.length() != 0) { + queryBuilder.append('&'); + } + queryBuilder.append(name); + if (value != null) { + String templatizedKey = name + valueItemCounter++; + uriParams.put(templatizedKey, value.toString()); + queryBuilder.append('=').append("{").append(templatizedKey).append("}"); + } + } + } + }); + return queryBuilder.toString(); } - private WebClient.RequestBodySpec prepareRequest(String path, HttpMethod method, Map pathParams, MultiValueMap queryParams, Object body, HttpHeaders headerParams, MultiValueMap cookieParams, MultiValueMap formParams, List accept, MediaType contentType, String[] authNames) { + private WebClient.RequestBodySpec prepareRequest(String path, HttpMethod method, Map pathParams, + MultiValueMap queryParams, Object body, HttpHeaders headerParams, + MultiValueMap cookieParams, MultiValueMap formParams, List accept, + MediaType contentType, String[] authNames) { updateParamsForAuth(authNames, queryParams, headerParams, cookieParams); final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(basePath).path(path); - if (queryParams != null) { - builder.queryParams(queryParams); + + String finalUri = builder.build(false).toUriString(); + Map uriParams = new HashMap<>(); + uriParams.putAll(pathParams); + + if (queryParams != null && !queryParams.isEmpty()) { + //Include queryParams in uriParams taking into account the paramName + String queryUri = generateQueryUri(queryParams, uriParams); + //Append to finalUri the templatized query string like "?param1={param1Value}&....... + finalUri += "?" + queryUri; } - final WebClient.RequestBodySpec requestBuilder = webClient.method(method).uri(builder.build(false).toUriString(), pathParams); - if(accept != null) { + final WebClient.RequestBodySpec requestBuilder = webClient.method(method).uri(finalUri, uriParams); + + if (accept != null) { requestBuilder.accept(accept.toArray(new MediaType[accept.size()])); } if(contentType != null) { @@ -581,6 +683,8 @@ public class ApiClient { addCookiesToRequest(cookieParams, requestBuilder); addCookiesToRequest(defaultCookies, requestBuilder); + requestBuilder.attribute(URI_TEMPLATE_ATTRIBUTE, path); + requestBuilder.body(selectBody(body, formParams, contentType)); return requestBuilder; } @@ -625,7 +729,7 @@ public class ApiClient { * @param headerParams The header parameters * @param cookieParams the cookie parameters */ - private void updateParamsForAuth(String[] authNames, MultiValueMap queryParams, HttpHeaders headerParams, MultiValueMap cookieParams) { + protected void updateParamsForAuth(String[] authNames, MultiValueMap queryParams, HttpHeaders headerParams, MultiValueMap cookieParams) { for (String authName : authNames) { Authentication auth = authentications.get(authName); if (auth == null) { @@ -650,62 +754,10 @@ public class ApiClient { } // collectionFormat is assumed to be "csv" by default - if(collectionFormat == null) { - collectionFormat = CollectionFormat.CSV; - } - - return collectionFormat.collectionToString(values); - } - - private class ApiClientHttpRequestInterceptor implements ClientHttpRequestInterceptor { - private final Log log = LogFactory.getLog(ApiClientHttpRequestInterceptor.class); - - @Override - public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { - logRequest(request, body); - ClientHttpResponse response = execution.execute(request, body); - logResponse(response); - return response; - } - - private void logRequest(HttpRequest request, byte[] body) throws UnsupportedEncodingException { - log.info("URI: " + request.getURI()); - log.info("HTTP Method: " + request.getMethod()); - log.info("HTTP Headers: " + headersToString(request.getHeaders())); - log.info("Request Body: " + new String(body, StandardCharsets.UTF_8)); - } - - private void logResponse(ClientHttpResponse response) throws IOException { - log.info("HTTP Status Code: " + response.getRawStatusCode()); - log.info("Status Text: " + response.getStatusText()); - log.info("HTTP Headers: " + headersToString(response.getHeaders())); - log.info("Response Body: " + bodyToString(response.getBody())); - } - - private String headersToString(HttpHeaders headers) { - StringBuilder builder = new StringBuilder(); - for(Entry> entry : headers.entrySet()) { - builder.append(entry.getKey()).append("=["); - for(String value : entry.getValue()) { - builder.append(value).append(","); - } - builder.setLength(builder.length() - 1); // Get rid of trailing comma - builder.append("],"); - } - builder.setLength(builder.length() - 1); // Get rid of trailing comma - return builder.toString(); + if(collectionFormat == null) { + collectionFormat = CollectionFormat.CSV; } - private String bodyToString(InputStream body) throws IOException { - StringBuilder builder = new StringBuilder(); - BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(body, StandardCharsets.UTF_8)); - String line = bufferedReader.readLine(); - while (line != null) { - builder.append(line).append(System.lineSeparator()); - line = bufferedReader.readLine(); - } - bufferedReader.close(); - return builder.toString(); - } + return collectionFormat.collectionToString(values); } } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/webclient/api.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/webclient/api.mustache index b852e87ec..974f30634 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/webclient/api.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/webclient/api.mustache @@ -10,20 +10,21 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.stream.Collectors; {{/fullJavaUtil}} import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; -import org.springframework.web.client.RestClientException; -import org.springframework.web.client.HttpClientErrorException; -import org.springframework.web.util.UriComponentsBuilder; import org.springframework.core.ParameterizedTypeReference; +import org.springframework.web.reactive.function.client.WebClient.ResponseSpec; +import org.springframework.web.reactive.function.client.WebClientResponseException; import org.springframework.core.io.FileSystemResource; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; import reactor.core.publisher.Mono; import reactor.core.publisher.Flux; @@ -53,22 +54,28 @@ public class {{classname}} { /** * {{summary}} * {{notes}} -{{#responses}} *

{{code}}{{#message}} - {{message}}{{/message}} +{{#responses}} *

{{code}}{{#message}} - {{.}}{{/message}} {{/responses}}{{#allParams}} * @param {{paramName}} {{description}}{{^description}}The {{paramName}} parameter{{/description}} -{{/allParams}}{{#returnType}} * @return {{returnType}} -{{/returnType}} * @throws RestClientException if an error occurs while attempting to invoke the API +{{/allParams}}{{#returnType}} * @return {{.}} +{{/returnType}} * @throws WebClientResponseException if an error occurs while attempting to invoke the API {{#externalDocs}} - * {{description}} - * @see {{summary}} Documentation + * {{description}} + * @see {{summary}} Documentation {{/externalDocs}} +{{#isDeprecated}} + * @deprecated +{{/isDeprecated}} */ - public {{#returnType}}{{#isListContainer}}Flux<{{{returnBaseType}}}>{{/isListContainer}}{{^isListContainer}}Mono<{{{returnType}}}>{{/isListContainer}} {{/returnType}}{{^returnType}}Mono {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws RestClientException { + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + private ResponseSpec {{operationId}}RequestCreation({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.AbstractResource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws WebClientResponseException { Object postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; {{#allParams}} {{#required}} // verify the required parameter '{{paramName}}' is set if ({{paramName}} == null) { - throw new HttpClientErrorException(HttpStatus.BAD_REQUEST, "Missing the required parameter '{{paramName}}' when calling {{operationId}}"); + throw new WebClientResponseException("Missing the required parameter '{{paramName}}' when calling {{operationId}}", HttpStatus.BAD_REQUEST.value(), HttpStatus.BAD_REQUEST.getReasonPhrase(), null, null, null); } {{/required}} {{/allParams}} @@ -88,44 +95,95 @@ public class {{classname}} { {{#hasQueryParams}} {{#queryParams}} - queryParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}})); + queryParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{.}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}})); {{/queryParams}} {{/hasQueryParams}} {{#hasHeaderParams}} {{#headerParams}} if ({{paramName}} != null) - headerParams.add("{{baseName}}", apiClient.parameterToString({{paramName}}));{{#hasMore}} - {{/hasMore}} + headerParams.add("{{baseName}}", apiClient.parameterToString({{paramName}}));{{^-last}} + {{/-last}} {{/headerParams}} {{/hasHeaderParams}} {{#hasCookieParams}} {{#cookieParams}} - cookieParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}})); + cookieParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{.}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}})); {{/cookieParams}} {{/hasCookieParams}} {{#hasFormParams}} {{#formParams}} if ({{paramName}} != null) - formParams.add{{#collectionFormat}}All{{/collectionFormat}}("{{baseName}}", {{#isFile}}new FileSystemResource({{paramName}}){{/isFile}}{{^isFile}}{{paramName}}{{/isFile}}); + formParams.add{{#collectionFormat}}All{{/collectionFormat}}("{{baseName}}", {{#isFile}}{{^collectionFormat}}{{#useAbstractionForFiles}}{{paramName}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}new FileSystemResource({{paramName}}){{/useAbstractionForFiles}}{{/collectionFormat}}{{/isFile}}{{#isFile}}{{#collectionFormat}}{{paramName}}.stream(){{^useAbstractionForFiles}}.map(FileSystemResource::new){{/useAbstractionForFiles}}.collect(Collectors.toList()){{/collectionFormat}}{{/isFile}}{{^isFile}}{{paramName}}{{/isFile}}); {{/formParams}} {{/hasFormParams}} final String[] localVarAccepts = { {{#hasProduces}} - {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} + {{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}} {{/hasProduces}}}; final List localVarAccept = apiClient.selectHeaderAccept(localVarAccepts); final String[] localVarContentTypes = { {{#hasConsumes}} - {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} + {{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}} {{/hasConsumes}}}; final MediaType localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes); - String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} }; + String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{^-last}}, {{/-last}}{{/authMethods}} }; + + {{#returnType}}ParameterizedTypeReference<{{#isArray}}{{{returnBaseType}}}{{/isArray}}{{^isArray}}{{{returnType}}}{{/isArray}}> localVarReturnType = new ParameterizedTypeReference<{{#isArray}}{{{returnBaseType}}}{{/isArray}}{{^isArray}}{{{returnType}}}{{/isArray}}>() {};{{/returnType}}{{^returnType}}ParameterizedTypeReference localVarReturnType = new ParameterizedTypeReference() {};{{/returnType}} + return apiClient.invokeAPI("{{{path}}}", HttpMethod.{{httpMethod}}, pathParams, queryParams, postBody, headerParams, cookieParams, formParams, localVarAccept, localVarContentType, localVarAuthNames, localVarReturnType); + } + + /** + * {{summary}} + * {{notes}} +{{#responses}} *

{{code}}{{#message}} - {{.}}{{/message}} +{{/responses}}{{#allParams}} * @param {{paramName}} {{description}}{{^description}}The {{paramName}} parameter{{/description}} +{{/allParams}}{{#returnType}} * @return {{.}} +{{/returnType}} * @throws WebClientResponseException if an error occurs while attempting to invoke the API +{{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation +{{/externalDocs}} + */ + public {{#returnType}}{{#vendorExtensions.x-webclient-blocking}}{{#isArray}}{{#uniqueItems}}Set{{/uniqueItems}}{{^uniqueItems}}List{{/uniqueItems}}<{{{returnBaseType}}}>{{/isArray}}{{^isArray}}{{{returnType}}}{{/isArray}}{{/vendorExtensions.x-webclient-blocking}}{{^vendorExtensions.x-webclient-blocking}}{{#isArray}}Flux<{{{returnBaseType}}}>{{/isArray}}{{^isArray}}Mono<{{{returnType}}}>{{/isArray}}{{/vendorExtensions.x-webclient-blocking}} {{/returnType}}{{^returnType}}{{#vendorExtensions.x-webclient-blocking}}void{{/vendorExtensions.x-webclient-blocking}}{{^vendorExtensions.x-webclient-blocking}}Mono{{/vendorExtensions.x-webclient-blocking}} {{/returnType}}{{operationId}}({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.AbstractResource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws WebClientResponseException { + {{#returnType}}ParameterizedTypeReference<{{#isArray}}{{{returnBaseType}}}{{/isArray}}{{^isArray}}{{{returnType}}}{{/isArray}}> localVarReturnType = new ParameterizedTypeReference<{{#isArray}}{{{returnBaseType}}}{{/isArray}}{{^isArray}}{{{returnType}}}{{/isArray}}>() {};{{/returnType}}{{^returnType}}ParameterizedTypeReference localVarReturnType = new ParameterizedTypeReference() {};{{/returnType}} + {{^returnType}}{{^vendorExtensions.x-webclient-blocking}}return {{/vendorExtensions.x-webclient-blocking}}{{/returnType}}{{#returnType}}return {{/returnType}}{{operationId}}RequestCreation({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}).{{#isArray}}bodyToFlux{{/isArray}}{{^isArray}}bodyToMono{{/isArray}}(localVarReturnType){{#vendorExtensions.x-webclient-blocking}}{{#isArray}}{{#uniqueItems}}.collect(Collectors.toSet()){{/uniqueItems}}{{^uniqueItems}}.collectList(){{/uniqueItems}}{{/isArray}}.block(){{/vendorExtensions.x-webclient-blocking}}; + } - {{#returnType}}ParameterizedTypeReference<{{#isListContainer}}{{{returnBaseType}}}{{/isListContainer}}{{^isListContainer}}{{{returnType}}}{{/isListContainer}}> localVarReturnType = new ParameterizedTypeReference<{{#isListContainer}}{{{returnBaseType}}}{{/isListContainer}}{{^isListContainer}}{{{returnType}}}{{/isListContainer}}>() {};{{/returnType}}{{^returnType}}ParameterizedTypeReference localVarReturnType = new ParameterizedTypeReference() {};{{/returnType}} - return apiClient.{{#isListContainer}}invokeFluxAPI{{/isListContainer}}{{^isListContainer}}invokeAPI{{/isListContainer}}("{{{path}}}", HttpMethod.{{httpMethod}}, pathParams, queryParams, postBody, headerParams, cookieParams, formParams, localVarAccept, localVarContentType, localVarAuthNames, localVarReturnType); + /** + * {{summary}} + * {{notes}} +{{#responses}} *

{{code}}{{#message}} - {{.}}{{/message}} +{{/responses}}{{#allParams}} * @param {{paramName}} {{description}}{{^description}}The {{paramName}} parameter{{/description}} +{{/allParams}}{{#returnType}} * @return ResponseEntity<{{.}}> +{{/returnType}} * @throws WebClientResponseException if an error occurs while attempting to invoke the API +{{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation +{{/externalDocs}} + */ + public {{#vendorExtensions.x-webclient-blocking}}{{#returnType}}{{#isArray}}ResponseEntity>{{/isArray}}{{^isArray}}ResponseEntity<{{{returnType}}}>{{/isArray}}{{/returnType}}{{^returnType}}ResponseEntity{{/returnType}} {{/vendorExtensions.x-webclient-blocking}}{{^vendorExtensions.x-webclient-blocking}}{{#returnType}}{{#isArray}}Mono>>{{/isArray}}{{^isArray}}Mono>{{/isArray}}{{/returnType}}{{^returnType}}Mono>{{/returnType}} {{/vendorExtensions.x-webclient-blocking}}{{operationId}}WithHttpInfo({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.AbstractResource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws WebClientResponseException { + {{#returnType}}ParameterizedTypeReference<{{#isArray}}{{{returnBaseType}}}{{/isArray}}{{^isArray}}{{{returnType}}}{{/isArray}}> localVarReturnType = new ParameterizedTypeReference<{{#isArray}}{{{returnBaseType}}}{{/isArray}}{{^isArray}}{{{returnType}}}{{/isArray}}>() {};{{/returnType}}{{^returnType}}ParameterizedTypeReference localVarReturnType = new ParameterizedTypeReference() {};{{/returnType}} + return {{operationId}}RequestCreation({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}).{{#isArray}}toEntityList{{/isArray}}{{^isArray}}toEntity{{/isArray}}(localVarReturnType){{#vendorExtensions.x-webclient-blocking}}.block(){{/vendorExtensions.x-webclient-blocking}}; + } + + /** + * {{summary}} + * {{notes}} +{{#responses}} *

{{code}}{{#message}} - {{.}}{{/message}} +{{/responses}}{{#allParams}} * @param {{paramName}} {{description}}{{^description}}The {{paramName}} parameter{{/description}} +{{/allParams}} + * @return ResponseSpec + * @throws WebClientResponseException if an error occurs while attempting to invoke the API +{{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation +{{/externalDocs}} + */ + public ResponseSpec {{operationId}}WithResponseSpec({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.AbstractResource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws WebClientResponseException { + return {{operationId}}RequestCreation({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); } {{/operation}} } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/webclient/api_test.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/webclient/api_test.mustache index 1b730bf43..62a89973b 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/webclient/api_test.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/webclient/api_test.mustache @@ -12,6 +12,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; {{/fullJavaUtil}} /** @@ -31,9 +32,9 @@ public class {{classname}}Test { @Test public void {{operationId}}Test() { {{#allParams}} - {{{dataType}}} {{paramName}} = null; + {{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.AbstractResource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}} = null; {{/allParams}} - {{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}){{#isListContainer}}.collectList().block(){{/isListContainer}}{{^isListContainer}}.block(){{/isListContainer}}; + {{#returnType}}{{{.}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}){{^vendorExtensions.x-webclient-blocking}}{{#isArray}}{{#uniqueItems}}.collect(Collectors.toSet()){{/uniqueItems}}{{^uniqueItems}}.collectList(){{/uniqueItems}}.block(){{/isArray}}{{^isArray}}.block(){{/isArray}}{{/vendorExtensions.x-webclient-blocking}}; // TODO: test validations } diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/webclient/build.gradle.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/webclient/build.gradle.mustache new file mode 100644 index 000000000..5d97c7d0f --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/libraries/webclient/build.gradle.mustache @@ -0,0 +1,148 @@ +apply plugin: 'idea' +apply plugin: 'eclipse' + +group = '{{groupId}}' +version = '{{artifactVersion}}' + +buildscript { + repositories { + mavenCentral() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.3.+' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' + } +} + +repositories { + mavenCentral() +} + +if(hasProperty('target') && target == 'android') { + + apply plugin: 'com.android.library' + apply plugin: 'com.github.dcendents.android-maven' + + android { + compileSdkVersion 25 + buildToolsVersion '25.0.2' + defaultConfig { + minSdkVersion 14 + targetSdkVersion 25 + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + // Rename the aar correctly + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = "${project.name}-${variant.baseName}-${version}.aar" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + + dependencies { + provided "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version" + } + } + + afterEvaluate { + android.libraryVariants.all { variant -> + def task = project.tasks.create "jar${variant.name.capitalize()}", Jar + task.description = "Create jar artifact for ${variant.name}" + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + task.destinationDir = project.file("${project.buildDir}/outputs/jar") + task.archiveName = "${project.name}-${variant.baseName}-${version}.jar" + artifacts.add('archives', task); + } + } + + task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' + } + + artifacts { + archives sourcesJar + } + +} else { + + apply plugin: 'java' + apply plugin: 'maven-publish' + + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + + publishing { + publications { + maven(MavenPublication) { + artifactId = '{{artifactId}}' + from components.java + } + } + } + + task execute(type:JavaExec) { + main = System.getProperty('mainClass') + classpath = sourceSets.main.runtimeClasspath + } + + task sourcesJar(type: Jar, dependsOn: classes) { + classifier = 'sources' + from sourceSets.main.allSource + } + + task javadocJar(type: Jar, dependsOn: javadoc) { + classifier = 'javadoc' + from javadoc.destinationDir + } + + artifacts { + archives sourcesJar + archives javadocJar + } +} + +ext { + swagger_annotations_version = "1.6.3" + spring_boot_version = "2.6.6" + jackson_version = "2.13.4" + jackson_databind_version = "2.13.4.2" + {{#openApiNullable}} + jackson_databind_nullable_version = "0.2.4" + {{/openApiNullable}} + jakarta_annotation_version = "1.3.5" + reactor_version = "3.4.3" + reactor_netty_version = "1.0.4" + jodatime_version = "2.9.9" + junit_version = "4.13.2" +} + +dependencies { + implementation "io.swagger:swagger-annotations:$swagger_annotations_version" + implementation "com.google.code.findbugs:jsr305:3.0.2" + implementation "io.projectreactor:reactor-core:$reactor_version" + implementation "org.springframework.boot:spring-boot-starter-webflux:$spring_boot_version" + implementation "io.projectreactor.netty:reactor-netty-http:$reactor_netty_version" + implementation "com.fasterxml.jackson.core:jackson-core:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" + implementation "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" + implementation "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version" + {{#openApiNullable}} + implementation "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" + {{/openApiNullable}} + {{#joda}} + implementation "joda-time:joda-time:$jodatime_version" + {{/joda}} + implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version" + implementation "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version" + testImplementation "junit:junit:$junit_version" +} diff --git a/boat-scaffold/src/main/templates/boat-java/libraries/webclient/pom.mustache b/boat-scaffold/src/main/templates/boat-java/libraries/webclient/pom.mustache index cca5514c0..38e4b653f 100644 --- a/boat-scaffold/src/main/templates/boat-java/libraries/webclient/pom.mustache +++ b/boat-scaffold/src/main/templates/boat-java/libraries/webclient/pom.mustache @@ -40,14 +40,19 @@ - org.apache.maven.plugins maven-compiler-plugin - 3.8.1 + 3.6.1 - 8 - 8 + {{#useJakartaEe}} + 17 + 17 + {{/useJakartaEe}} + {{^useJakartaEe}} + 1.8 + 1.8 + {{/useJakartaEe}} @@ -67,17 +72,13 @@ + {{#swagger1AnnotationLibrary}} io.swagger swagger-annotations ${swagger-annotations-version} - - - javax.annotation - javax.annotation-api - 1.3.2 - + {{/swagger1AnnotationLibrary}} @@ -92,16 +93,16 @@ ${reactor-version} - + - org.springframework - spring-webflux - ${spring-web-version} + org.springframework.boot + spring-boot-starter-webflux + ${spring-boot-version} - io.projectreactor.ipc - reactor-netty + io.projectreactor.netty + reactor-netty-http ${reactor-netty-version} @@ -111,36 +112,37 @@ jackson-databind ${jackson-databind-version} - - com.fasterxml.jackson.core - jackson-annotations - ${jackson-version} - + {{#openApiNullable}} org.openapitools jackson-databind-nullable ${jackson-databind-nullable-version} + {{/openApiNullable}} - {{#java8}} - - com.fasterxml.jackson.datatype - jackson-datatype-jsr310 - ${jackson-version} - - {{/java8}} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + {{#joda}} - - com.fasterxml.jackson.datatype - jackson-datatype-joda - ${jackson-version} - - - joda-time - joda-time - ${jodatime-version} - + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-version} + + + joda-time + joda-time + ${jodatime-version} + {{/joda}} + + jakarta.annotation + jakarta.annotation-api + ${jakarta-annotation-version} + provided + @@ -150,18 +152,29 @@ test - - UTF-8 - 1.5.22 - 5.0.16.RELEASE - 2.10.3 - 2.10.3 - 0.2.1 - 4.13 - 3.1.8.RELEASE - 0.7.8.RELEASE - {{#joda}} - 2.9.9 - {{/joda}} - + + UTF-8 + 1.6.6 + 2.13.4 + 2.13.4.2 + {{#openApiNullable}} + 0.2.4 + {{/openApiNullable}} + {{#useJakartaEe}} + 3.0.1 + 2.1.1 + 3.5.1 + 1.1.1 + {{/useJakartaEe}} + {{^useJakartaEe}} + 2.6.6 + 1.3.5 + 3.4.3 + 1.0.4 + {{/useJakartaEe}} + 4.13.2 + {{#joda}} + 2.9.9 + {{/joda}} + diff --git a/boat-scaffold/src/main/templates/boat-java/maven.yml.mustache b/boat-scaffold/src/main/templates/boat-java/maven.yml.mustache new file mode 100644 index 000000000..f3c4733c3 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-java/maven.yml.mustache @@ -0,0 +1,31 @@ +# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time +# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven +# +# This file is auto-generated by OpenAPI Generator (https://openapi-generator.tech) + +name: Java CI with Maven + +on: + push: + branches: [ main, master ] + pull_request: + branches: [ main, master ] + +jobs: + build: + name: Build {{{appName}}} + runs-on: ubuntu-latest + strategy: + matrix: + java: [ '8' ] + steps: + - uses: actions/checkout@v2 + - name: Set up JDK + uses: actions/setup-java@v2 + with: + {{=< >=}} + java-version: ${{ matrix.java }} + distribution: 'temurin' + cache: maven + - name: Build with Maven + run: mvn -B package --no-transfer-progress --file pom.xml diff --git a/boat-scaffold/src/main/templates/boat-java/model.mustache b/boat-scaffold/src/main/templates/boat-java/model.mustache index d4d1447a1..140d35fc3 100644 --- a/boat-scaffold/src/main/templates/boat-java/model.mustache +++ b/boat-scaffold/src/main/templates/boat-java/model.mustache @@ -6,13 +6,8 @@ package {{package}}; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; {{/useReflectionEqualsHashCode}} -{{^supportJava6}} import java.util.Objects; import java.util.Arrays; -{{/supportJava6}} -{{#supportJava6}} -import org.apache.commons.lang3.ObjectUtils; -{{/supportJava6}} {{#imports}} import {{import}}; {{/imports}} @@ -21,27 +16,59 @@ import java.io.Serializable; {{/serializableModel}} {{#jackson}} import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.annotation.JsonTypeName; {{#withXml}} import com.fasterxml.jackson.dataformat.xml.annotation.*; {{/withXml}} +{{#vendorExtensions.x-has-readonly-properties}} +import com.fasterxml.jackson.annotation.JsonCreator; +{{/vendorExtensions.x-has-readonly-properties}} {{/jackson}} {{#withXml}} import javax.xml.bind.annotation.*; +import javax.xml.bind.annotation.adapters.*; +import io.github.threetenjaxb.core.*; {{/withXml}} +{{#jsonb}} +import java.lang.reflect.Type; +import javax.json.bind.annotation.JsonbTypeDeserializer; +import javax.json.bind.annotation.JsonbTypeSerializer; +import javax.json.bind.serializer.DeserializationContext; +import javax.json.bind.serializer.JsonbDeserializer; +import javax.json.bind.serializer.JsonbSerializer; +import javax.json.bind.serializer.SerializationContext; +import javax.json.stream.JsonGenerator; +import javax.json.stream.JsonParser; +import javax.json.bind.annotation.JsonbProperty; +{{#vendorExtensions.x-has-readonly-properties}} +import javax.json.bind.annotation.JsonbCreator; +{{/vendorExtensions.x-has-readonly-properties}} +{{/jsonb}} {{#parcelableModel}} import android.os.Parcelable; import android.os.Parcel; {{/parcelableModel}} {{#useBeanValidation}} +{{^useJakartaEe}} import javax.validation.constraints.*; import javax.validation.Valid; +{{/useJakartaEe}} +{{#useJakartaEe}} +import jakarta.validation.constraints.*; +import jakarta.validation.Valid; +{{/useJakartaEe}} {{/useBeanValidation}} {{#performBeanValidation}} import org.hibernate.validator.constraints.*; {{/performBeanValidation}} +{{#supportUrlQuery}} + import java.io.UnsupportedEncodingException; + import java.net.URLEncoder; + import java.util.StringJoiner; +{{/supportUrlQuery}} {{#models}} {{#model}} {{#isEnum}}{{>modelEnum}}{{/isEnum}}{{^isEnum}}{{#vendorExtensions.x-is-one-of-interface}}{{>oneof_interface}}{{/vendorExtensions.x-is-one-of-interface}}{{^vendorExtensions.x-is-one-of-interface}}{{>pojo}}{{/vendorExtensions.x-is-one-of-interface}}{{/isEnum}} {{/model}} -{{/models}} +{{/models}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/modelEnum.mustache b/boat-scaffold/src/main/templates/boat-java/modelEnum.mustache index 9428bc70f..a93e3f0c6 100644 --- a/boat-scaffold/src/main/templates/boat-java/modelEnum.mustache +++ b/boat-scaffold/src/main/templates/boat-java/modelEnum.mustache @@ -11,24 +11,31 @@ import com.google.gson.stream.JsonWriter; {{/gson}} /** - * {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{description}}{{/description}} + * {{description}}{{^description}}Gets or Sets {{{name}}}{{/description}} */ {{#gson}} -@JsonAdapter({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.Adapter.class) +@JsonAdapter({{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.Adapter.class) {{/gson}} -public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} { +{{#jsonb}} +@JsonbTypeSerializer({{datatypeWithEnum}}.Serializer.class) +@JsonbTypeDeserializer({{datatypeWithEnum}}.Deserializer.class) +{{/jsonb}} +{{>additionalEnumTypeAnnotations}}public enum {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} { {{#allowableValues}}{{#enumVars}} {{#enumDescription}} /** - * {{enumDescription}} + * {{.}} */ {{/enumDescription}} + {{#withXml}} + @XmlEnumValue({{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}{{{value}}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}) + {{/withXml}} {{{name}}}({{{value}}}){{^-last}}, {{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}} private {{{dataType}}} value; - {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}({{{dataType}}} value) { + {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}({{{dataType}}} value) { this.value = value; } @@ -47,27 +54,63 @@ public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum {{#jackson}} @JsonCreator {{/jackson}} - public static {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue({{{dataType}}} value) { - for ({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { + public static {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue({{{dataType}}} value) { + for ({{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { if (b.value.equals(value)) { return b; } } - {{#isNullable}}return null;{{/isNullable}}{{^isNullable}}throw new IllegalArgumentException("Unexpected value '" + value + "'");{{/isNullable}} + {{#isNullable}}return null;{{/isNullable}}{{^isNullable}}{{#enumUnknownDefaultCase}}{{#allowableValues}}{{#enumVars}}{{#-last}}return {{{name}}};{{/-last}}{{/enumVars}}{{/allowableValues}}{{/enumUnknownDefaultCase}}{{^enumUnknownDefaultCase}}throw new IllegalArgumentException("Unexpected value '" + value + "'");{{/enumUnknownDefaultCase}}{{/isNullable}} } {{#gson}} - public static class Adapter extends TypeAdapter<{{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}> { + public static class Adapter extends TypeAdapter<{{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}> { @Override - public void write(final JsonWriter jsonWriter, final {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} enumeration) throws IOException { + public void write(final JsonWriter jsonWriter, final {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} enumeration) throws IOException { jsonWriter.value(enumeration.getValue()); } @Override - public {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} read(final JsonReader jsonReader) throws IOException { + public {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} read(final JsonReader jsonReader) throws IOException { {{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = jsonReader.{{#isNumber}}nextString(){{/isNumber}}{{#isInteger}}nextInt(){{/isInteger}}{{^isNumber}}{{^isInteger}}next{{{dataType}}}(){{/isInteger}}{{/isNumber}}; - return {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}}); + return {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}}); } } {{/gson}} -} +{{#jsonb}} + public static final class Deserializer implements JsonbDeserializer<{{datatypeWithEnum}}> { + @Override + public {{datatypeWithEnum}} deserialize(JsonParser parser, DeserializationContext ctx, Type rtType) { + for ({{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { + if (String.valueOf(b.value).equals(parser.getString())) { + return b; + } + } + {{#useNullForUnknownEnumValue}}return null;{{/useNullForUnknownEnumValue}}{{^useNullForUnknownEnumValue}}throw new IllegalArgumentException("Unexpected value '" + parser.getString() + "'");{{/useNullForUnknownEnumValue}} + } + } + + public static final class Serializer implements JsonbSerializer<{{datatypeWithEnum}}> { + @Override + public void serialize({{datatypeWithEnum}} obj, JsonGenerator generator, SerializationContext ctx) { + generator.write(obj.value); + } + } +{{/jsonb}} +{{#supportUrlQuery}} + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + if (prefix == null) { + prefix = ""; + } + + return String.format("%s=%s", prefix, this.toString()); + } +{{/supportUrlQuery}} +} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/modelInnerEnum.mustache b/boat-scaffold/src/main/templates/boat-java/modelInnerEnum.mustache index 101870341..b2e59229e 100644 --- a/boat-scaffold/src/main/templates/boat-java/modelInnerEnum.mustache +++ b/boat-scaffold/src/main/templates/boat-java/modelInnerEnum.mustache @@ -1,17 +1,28 @@ /** - * {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{description}}{{/description}} + * {{description}}{{^description}}Gets or Sets {{{name}}}{{/description}} */ {{#gson}} - @JsonAdapter({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.Adapter.class) + @JsonAdapter({{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.Adapter.class) {{/gson}} - public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} { +{{#jsonb}} + @JsonbTypeSerializer({{datatypeWithEnum}}.Serializer.class) + @JsonbTypeDeserializer({{datatypeWithEnum}}.Deserializer.class) +{{/jsonb}} +{{#withXml}} + @XmlType(name="{{datatypeWithEnum}}") + @XmlEnum({{dataType}}.class) +{{/withXml}} + {{>additionalEnumTypeAnnotations}}public enum {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} { {{#allowableValues}} {{#enumVars}} {{#enumDescription}} /** - * {{enumDescription}} + * {{.}} */ {{/enumDescription}} + {{#withXml}} + @XmlEnumValue({{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}{{{value}}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}) + {{/withXml}} {{{name}}}({{{value}}}){{^-last}}, {{/-last}}{{#-last}};{{/-last}} {{/enumVars}} @@ -19,7 +30,7 @@ private {{{dataType}}} value; - {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}({{{dataType}}} value) { + {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}({{{dataType}}} value) { this.value = value; } @@ -38,27 +49,47 @@ {{#jackson}} @JsonCreator {{/jackson}} - public static {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue({{{dataType}}} value) { - for ({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { + public static {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue({{{dataType}}} value) { + for ({{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { if (b.value.equals(value)) { return b; } } - {{#isNullable}}return null;{{/isNullable}}{{^isNullable}}throw new IllegalArgumentException("Unexpected value '" + value + "'");{{/isNullable}} + {{#isNullable}}return null;{{/isNullable}}{{^isNullable}}{{#enumUnknownDefaultCase}}{{#allowableValues}}{{#enumVars}}{{#-last}}return {{{name}}};{{/-last}}{{/enumVars}}{{/allowableValues}}{{/enumUnknownDefaultCase}}{{^enumUnknownDefaultCase}}throw new IllegalArgumentException("Unexpected value '" + value + "'");{{/enumUnknownDefaultCase}}{{/isNullable}} } {{#gson}} - public static class Adapter extends TypeAdapter<{{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}> { + public static class Adapter extends TypeAdapter<{{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}> { @Override - public void write(final JsonWriter jsonWriter, final {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} enumeration) throws IOException { + public void write(final JsonWriter jsonWriter, final {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} enumeration) throws IOException { jsonWriter.value(enumeration.getValue()); } @Override - public {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} read(final JsonReader jsonReader) throws IOException { + public {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} read(final JsonReader jsonReader) throws IOException { {{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = {{#isFloat}}(float){{/isFloat}} jsonReader.{{#isNumber}}nextString(){{/isNumber}}{{#isInteger}}nextInt(){{/isInteger}}{{^isNumber}}{{^isInteger}}{{#isFloat}}nextDouble{{/isFloat}}{{^isFloat}}next{{{dataType}}}{{/isFloat}}(){{/isInteger}}{{/isNumber}}; - return {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}}); + return {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}}); } } {{/gson}} - } +{{#jsonb}} + public static final class Deserializer implements JsonbDeserializer<{{datatypeWithEnum}}> { + @Override + public {{datatypeWithEnum}} deserialize(JsonParser parser, DeserializationContext ctx, Type rtType) { + for ({{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { + if (String.valueOf(b.value).equals(parser.getString())) { + return b; + } + } + {{#useNullForUnknownEnumValue}}return null;{{/useNullForUnknownEnumValue}}{{^useNullForUnknownEnumValue}}throw new IllegalArgumentException("Unexpected value '" + parser.getString() + "'");{{/useNullForUnknownEnumValue}} + } + } + + public static final class Serializer implements JsonbSerializer<{{datatypeWithEnum}}> { + @Override + public void serialize({{datatypeWithEnum}} obj, JsonGenerator generator, SerializationContext ctx) { + generator.write(obj.value); + } + } +{{/jsonb}} + } \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/oneof_interface.mustache b/boat-scaffold/src/main/templates/boat-java/oneof_interface.mustache index 02deb483d..d67277274 100644 --- a/boat-scaffold/src/main/templates/boat-java/oneof_interface.mustache +++ b/boat-scaffold/src/main/templates/boat-java/oneof_interface.mustache @@ -1,4 +1,4 @@ -{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>typeInfoAnnotation}}{{>xmlAnnotation}} +{{>additionalOneOfTypeAnnotations}}{{>generatedAnnotation}}{{>typeInfoAnnotation}}{{>xmlAnnotation}} public interface {{classname}} {{#vendorExtensions.x-implements}}{{#-first}}extends {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{/vendorExtensions.x-implements}} { {{#discriminator}} public {{propertyType}} {{propertyGetter}}(); diff --git a/boat-scaffold/src/main/templates/boat-java/pojo.mustache b/boat-scaffold/src/main/templates/boat-java/pojo.mustache index 5029536a7..13e354a30 100644 --- a/boat-scaffold/src/main/templates/boat-java/pojo.mustache +++ b/boat-scaffold/src/main/templates/boat-java/pojo.mustache @@ -1,16 +1,30 @@ /** - * {{#description}}{{.}}{{/description}}{{^description}}{{classname}}{{/description}} - */{{#description}} -@ApiModel(description = "{{{description}}}"){{/description}} + * {{description}}{{^description}}{{classname}}{{/description}}{{#isDeprecated}} + * @deprecated{{/isDeprecated}} + */{{#isDeprecated}} +@Deprecated{{/isDeprecated}}{{#description}} +{{#swagger1AnnotationLibrary}} +@ApiModel(description = "{{{.}}}") +{{/swagger1AnnotationLibrary}} +{{#swagger2AnnotationLibrary}} +@Schema(description = "{{{.}}}") +{{/swagger2AnnotationLibrary}} +{{/description}} {{#jackson}} @JsonPropertyOrder({ {{#vars}} {{classname}}.JSON_PROPERTY_{{nameInSnakeCase}}{{^-last}},{{/-last}} {{/vars}} }) +{{#isClassnameSanitized}} +@JsonTypeName("{{name}}") +{{/isClassnameSanitized}} {{/jackson}} {{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}} -public {{#vendorExtensions.x-abstract}}abstract {{/vendorExtensions.x-abstract}} class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#vendorExtensions.x-implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{#-last}} {{/-last}}{{/vendorExtensions.x-implements}}{ +{{#vendorExtensions.x-class-extra-annotation}} +{{{vendorExtensions.x-class-extra-annotation}}} +{{/vendorExtensions.x-class-extra-annotation}} +public class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{{#vendorExtensions.x-implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{#-last}} {{/-last}}{{/vendorExtensions.x-implements}}{ {{#serializableModel}} private static final long serialVersionUID = 1L; @@ -34,81 +48,95 @@ public {{#vendorExtensions.x-abstract}}abstract {{/vendorExtensions.x-abstract}} {{/jackson}} {{#withXml}} {{#isXmlAttribute}} - @XmlAttribute(name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + @XmlAttribute(name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") {{/isXmlAttribute}} {{^isXmlAttribute}} {{^isContainer}} - @XmlElement({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + @XmlElement({{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") {{/isContainer}} {{#isContainer}} // Is a container wrapped={{isXmlWrapped}} {{#items}} // items.name={{name}} items.baseName={{baseName}} items.xmlName={{xmlName}} items.xmlNamespace={{xmlNamespace}} // items.example={{example}} items.type={{dataType}} - @XmlElement({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + @XmlElement({{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") {{/items}} {{#isXmlWrapped}} - @XmlElementWrapper({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + @XmlElementWrapper({{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") {{/isXmlWrapped}} {{/isContainer}} + {{#isDateTime}} + @XmlJavaTypeAdapter(OffsetDateTimeXmlAdapter.class) + {{/isDateTime}} {{/isXmlAttribute}} {{/withXml}} {{#gson}} @SerializedName(SERIALIZED_NAME_{{nameInSnakeCase}}) {{/gson}} + {{#vendorExtensions.x-field-extra-annotation}} + {{{vendorExtensions.x-field-extra-annotation}}} + {{/vendorExtensions.x-field-extra-annotation}} {{#vendorExtensions.x-is-jackson-optional-nullable}} {{#isContainer}} - {{modelFieldsVisibility}} JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>undefined(); + private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>undefined(); {{/isContainer}} {{^isContainer}} - {{modelFieldsVisibility}} JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}}; + private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}}; {{/isContainer}} {{/vendorExtensions.x-is-jackson-optional-nullable}} {{^vendorExtensions.x-is-jackson-optional-nullable}} {{#isContainer}} - {{modelFieldsVisibility}} {{{datatypeWithEnum}}} {{name}}{{#required}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/required}}{{^required}} = null{{/required}}; + private {{{datatypeWithEnum}}} {{name}}{{#required}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/required}}{{^required}} = null{{/required}}; {{/isContainer}} {{^isContainer}} - {{#isDiscriminator}}protected{{/isDiscriminator}}{{^isDiscriminator}}{{modelFieldsVisibility}}{{/isDiscriminator}} {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}; + {{#isDiscriminator}}protected{{/isDiscriminator}}{{^isDiscriminator}}private{{/isDiscriminator}} {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}; {{/isContainer}} {{/vendorExtensions.x-is-jackson-optional-nullable}} {{/vars}} - {{#parcelableModel}} public {{classname}}() { - {{#parent}} - super(); - {{/parent}} - {{#gson}} - {{#discriminator}} + {{#parent}} + {{#parcelableModel}} + super();{{/parcelableModel}} + {{/parent}} + {{#gson}} + {{#discriminator}} + {{#discriminator.isEnum}} this.{{{discriminatorName}}} = this.getClass().getSimpleName(); - {{/discriminator}} - {{/gson}} + {{/discriminator.isEnum}} + {{/discriminator}} + {{/gson}} } - {{/parcelableModel}} - {{^parcelableModel}} - {{#gson}} - {{#discriminator}} - public {{classname}}() { - this.{{{discriminatorName}}} = this.getClass().getSimpleName(); + {{#vendorExtensions.x-has-readonly-properties}} + {{^withXml}} + + {{#jsonb}}@JsonbCreator{{/jsonb}}{{#jackson}}@JsonCreator{{/jackson}} + public {{classname}}( + {{#readOnlyVars}} + {{#jsonb}}@JsonbProperty(value = "{{baseName}}"{{^required}}, nullable = true{{/required}}){{/jsonb}}{{#jackson}}@JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}}){{/jackson}} {{{datatypeWithEnum}}} {{name}}{{^-last}}, {{/-last}} + {{/readOnlyVars}} + ) { + this(); + {{#readOnlyVars}} + this.{{name}} = {{#vendorExtensions.x-is-jackson-optional-nullable}}{{name}} == null ? JsonNullable.<{{{datatypeWithEnum}}}>undefined() : JsonNullable.of({{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{name}}{{/vendorExtensions.x-is-jackson-optional-nullable}}; + {{/readOnlyVars}} } - {{/discriminator}} - {{/gson}} - {{/parcelableModel}} + {{/withXml}} + {{/vendorExtensions.x-has-readonly-properties}} {{#vars}} {{^isReadOnly}} - public {{classname}} {{#useWithModifiers}}with{{nameInCamelCase}}{{/useWithModifiers}}{{^useWithModifiers}}{{name}}{{/useWithModifiers}}({{{datatypeWithEnum}}} {{name}}) { + public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) { {{#vendorExtensions.x-is-jackson-optional-nullable}}this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}});{{/vendorExtensions.x-is-jackson-optional-nullable}} {{^vendorExtensions.x-is-jackson-optional-nullable}}this.{{name}} = {{name}};{{/vendorExtensions.x-is-jackson-optional-nullable}} return this; } - {{#isListContainer}} + {{#isArray}} public {{classname}} add{{nameInCamelCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) { {{#vendorExtensions.x-is-jackson-optional-nullable}} if (this.{{name}} == null || !this.{{name}}.isPresent()) { - this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}); + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}{{^defaultValue}}null{{/defaultValue}}); } try { this.{{name}}.get().add({{name}}Item); @@ -127,8 +155,8 @@ public {{#vendorExtensions.x-abstract}}abstract {{/vendorExtensions.x-abstract}} return this; {{/vendorExtensions.x-is-jackson-optional-nullable}} } - {{/isListContainer}} - {{#isMapContainer}} + {{/isArray}} + {{#isMap}} public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { {{#vendorExtensions.x-is-jackson-optional-nullable}} @@ -152,33 +180,51 @@ public {{#vendorExtensions.x-abstract}}abstract {{/vendorExtensions.x-abstract}} return this; {{/vendorExtensions.x-is-jackson-optional-nullable}} } - {{/isMapContainer}} + {{/isMap}} {{/isReadOnly}} /** {{#description}} - * {{description}} + * {{.}} {{/description}} {{^description}} * Get {{name}} {{/description}} {{#minimum}} - * minimum: {{minimum}} + * minimum: {{.}} {{/minimum}} {{#maximum}} - * maximum: {{maximum}} + * maximum: {{.}} {{/maximum}} * @return {{name}} + {{#deprecated}} + * @deprecated + {{/deprecated}} **/ +{{#deprecated}} + @Deprecated +{{/deprecated}} {{#required}} {{#isNullable}} - @javax.annotation.Nullable +{{#useJakartaEe}} @jakarta.annotation.Nullable{{/useJakartaEe}} +{{^useJakartaEe}} @javax.annotation.Nullable{{/useJakartaEe}} +{{/isNullable}} +{{^isNullable}} + {{#useJakartaEe}} @jakarta.annotation.Nonnull{{/useJakartaEe}} + {{^useJakartaEe}} @javax.annotation.Nonnull{{/useJakartaEe}} {{/isNullable}} {{/required}} {{^required}} - @javax.annotation.Nullable + {{#useJakartaEe}} @jakarta.annotation.Nullable{{/useJakartaEe}} + {{^useJakartaEe}} @javax.annotation.Nullable{{/useJakartaEe}} {{/required}} -{{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} @ApiModelProperty({{#example}}example = "{{{example}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}") +{{#jsonb}} + @JsonbProperty("{{baseName}}") +{{/jsonb}} +{{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} {{#swagger1AnnotationLibrary}} @ApiModelProperty({{#example}}example = "{{{.}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}") {{/swagger1AnnotationLibrary}} + {{#swagger2AnnotationLibrary}} + @Schema(name = "{{{baseName}}}",{{#example}}example = "{{{.}}}", {{/example}}{{#description}}description = "{{{.}}}", {{/description}}required = {{{required}}}) + {{/swagger2AnnotationLibrary}} {{#vendorExtensions.x-extra-annotation}} {{{vendorExtensions.x-extra-annotation}}} {{/vendorExtensions.x-extra-annotation}} @@ -215,7 +261,8 @@ public {{#vendorExtensions.x-abstract}}abstract {{/vendorExtensions.x-abstract}} {{/vendorExtensions.x-is-jackson-optional-nullable}} {{^isReadOnly}} - public void {{setter}}({{{datatypeWithEnum}}} {{name}}) { +{{#vendorExtensions.x-setter-extra-annotation}} {{{vendorExtensions.x-setter-extra-annotation}}} +{{/vendorExtensions.x-setter-extra-annotation}}{{#jackson}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{> jackson_annotations}}{{/vendorExtensions.x-is-jackson-optional-nullable}}{{/jackson}} public void {{setter}}({{{datatypeWithEnum}}} {{name}}) { {{#vendorExtensions.x-is-jackson-optional-nullable}} this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}}); {{/vendorExtensions.x-is-jackson-optional-nullable}} @@ -227,9 +274,8 @@ public {{#vendorExtensions.x-abstract}}abstract {{/vendorExtensions.x-abstract}} {{/vars}} -{{^supportJava6}} @Override - public boolean equals(java.lang.Object o) { + public boolean equals(Object o) { {{#useReflectionEqualsHashCode}} return EqualsBuilder.reflectionEquals(this, o, false, null, true); {{/useReflectionEqualsHashCode}} @@ -241,12 +287,16 @@ public {{#vendorExtensions.x-abstract}}abstract {{/vendorExtensions.x-abstract}} return false; }{{#hasVars}} {{classname}} {{classVarName}} = ({{classname}}) o; - return {{#vars}}{{#isByteArray}}Arrays{{/isByteArray}}{{^isByteArray}}Objects{{/isByteArray}}.equals(this.{{name}}, {{classVarName}}.{{name}}){{#hasMore}} && - {{/hasMore}}{{/vars}}{{#parent}} && + return {{#vars}}{{#vendorExtensions.x-is-jackson-optional-nullable}}equalsNullable(this.{{name}}, {{classVarName}}.{{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{#isByteArray}}Arrays{{/isByteArray}}{{^isByteArray}}Objects{{/isByteArray}}.equals(this.{{name}}, {{classVarName}}.{{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^-last}} && + {{/-last}}{{/vars}}{{#parent}} && super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}} return {{#parent}}super.equals(o){{/parent}}{{^parent}}true{{/parent}};{{/hasVars}} {{/useReflectionEqualsHashCode}} - } + }{{#vendorExtensions.x-jackson-optional-nullable-helpers}} + + private static boolean equalsNullable(JsonNullable a, JsonNullable b) { + return a == b || (a != null && b != null && a.isPresent() && b.isPresent() && Objects.deepEquals(a.get(), b.get())); + }{{/vendorExtensions.x-jackson-optional-nullable-helpers}} @Override public int hashCode() { @@ -254,33 +304,16 @@ public {{#vendorExtensions.x-abstract}}abstract {{/vendorExtensions.x-abstract}} return HashCodeBuilder.reflectionHashCode(this); {{/useReflectionEqualsHashCode}} {{^useReflectionEqualsHashCode}} - return Objects.hash({{#vars}}{{^isByteArray}}{{name}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{#hasMore}}, {{/hasMore}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}); + return Objects.hash({{#vars}}{{#vendorExtensions.x-is-jackson-optional-nullable}}hashCodeNullable({{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{^isByteArray}}{{name}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{/vendorExtensions.x-is-jackson-optional-nullable}}{{^-last}}, {{/-last}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}); {{/useReflectionEqualsHashCode}} - } - -{{/supportJava6}} -{{#supportJava6}} - @Override - public boolean equals(java.lang.Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - }{{#hasVars}} - {{classname}} {{classVarName}} = ({{classname}}) o; - return {{#vars}}ObjectUtils.equals(this.{{name}}, {{classVarName}}.{{name}}){{#hasMore}} && - {{/hasMore}}{{/vars}}{{#parent}} && - super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}} - return true;{{/hasVars}} - } - - @Override - public int hashCode() { - return ObjectUtils.hashCodeMulti({{#vars}}{{name}}{{#hasMore}}, {{/hasMore}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}); - } + }{{#vendorExtensions.x-jackson-optional-nullable-helpers}} -{{/supportJava6}} + private static int hashCodeNullable(JsonNullable a) { + if (a == null) { + return 1; + } + return a.isPresent() ? Arrays.deepHashCode(new Object[]{a.get()}) : 31; + }{{/vendorExtensions.x-jackson-optional-nullable-helpers}} @Override public String toString() { @@ -300,36 +333,229 @@ public {{#vendorExtensions.x-abstract}}abstract {{/vendorExtensions.x-abstract}} * Convert the given object to string with each line indented by 4 spaces * (except the first line). */ - private String toIndentedString(java.lang.Object o) { + private{{#jsonb}} static{{/jsonb}} String toIndentedString(Object o) { if (o == null) { return "null"; } return o.toString().replace("\n", "\n "); } +{{#supportUrlQuery}} + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + {{#allVars}} + // add `{{baseName}}` to the URL query string + {{#isArray}} + {{#items.isPrimitiveType}} + {{#uniqueItems}} + if ({{getter}}() != null) { + int i = 0; + for ({{items.dataType}} _item : {{getter}}()) { + try { + joiner.add(String.format("%s{{baseName}}%s%s=%s", prefix, suffix, + "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix), + URLEncoder.encode(String.valueOf(_item), "UTF-8").replaceAll("\\+", "%20"))); + } catch (UnsupportedEncodingException e) { + // Should never happen, UTF-8 is always supported + throw new RuntimeException(e); + } + } + i++; + } + {{/uniqueItems}} + {{^uniqueItems}} + if ({{getter}}() != null) { + for (int i = 0; i < {{getter}}().size(); i++) { + try { + joiner.add(String.format("%s{{baseName}}%s%s=%s", prefix, suffix, + "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix), + URLEncoder.encode(String.valueOf({{getter}}().get(i)), "UTF-8").replaceAll("\\+", "%20"))); + } catch (UnsupportedEncodingException e) { + // Should never happen, UTF-8 is always supported + throw new RuntimeException(e); + } + } + } + {{/uniqueItems}} + {{/items.isPrimitiveType}} + {{^items.isPrimitiveType}} + {{#items.isModel}} + {{#uniqueItems}} + if ({{getter}}() != null) { + int i = 0; + for ({{items.dataType}} _item : {{getter}}()) { + if ({{getter}}().get(i) != null) { + joiner.add(_item.toUrlQueryString(String.format("%s{{baseName}}%s%s", prefix, suffix, + "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix)))); + } + } + i++; + } + {{/uniqueItems}} + {{^uniqueItems}} + if ({{getter}}() != null) { + for (int i = 0; i < {{getter}}().size(); i++) { + if ({{getter}}().get(i) != null) { + joiner.add({{getter}}().get(i).toUrlQueryString(String.format("%s{{baseName}}%s%s", prefix, suffix, + "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix)))); + } + } + } + {{/uniqueItems}} + {{/items.isModel}} + {{^items.isModel}} + {{#uniqueItems}} + if ({{getter}}() != null) { + int i = 0; + for ({{items.dataType}} _item : {{getter}}()) { + if (_item != null) { + try { + joiner.add(String.format("%s{{baseName}}%s%s=%s", prefix, suffix, + "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix)), + URLEncoder.encode(String.valueOf(_item), "UTF-8").replaceAll("\\+", "%20")); + } catch (UnsupportedEncodingException e) { + // Should never happen, UTF-8 is always supported + throw new RuntimeException(e); + } + } + i++; + } + } + {{/uniqueItems}} + {{^uniqueItems}} + if ({{getter}}() != null) { + for (int i = 0; i < {{getter}}().size(); i++) { + if ({{getter}}().get(i) != null) { + try { + joiner.add(String.format("%s{{baseName}}%s%s=%s", prefix, suffix, + "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix), + URLEncoder.encode(String.valueOf({{getter}}().get(i)), "UTF-8").replaceAll("\\+", "%20"))); + } catch (UnsupportedEncodingException e) { + // Should never happen, UTF-8 is always supported + throw new RuntimeException(e); + } + } + } + } + {{/uniqueItems}} + {{/items.isModel}} + {{/items.isPrimitiveType}} + {{/isArray}} + {{^isArray}} + {{#isMap}} + {{#items.isPrimitiveType}} + if ({{getter}}() != null) { + for (String _key : {{getter}}().keySet()) { + try { + joiner.add(String.format("%s{{baseName}}%s%s=%s", prefix, suffix, + "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, _key, containerSuffix), + {{getter}}().get(_key), URLEncoder.encode(String.valueOf({{getter}}().get(_key)), "UTF-8").replaceAll("\\+", "%20"))); + } catch (UnsupportedEncodingException e) { + // Should never happen, UTF-8 is always supported + throw new RuntimeException(e); + } + } + } + {{/items.isPrimitiveType}} + {{^items.isPrimitiveType}} + if ({{getter}}() != null) { + for (String _key : {{getter}}().keySet()) { + if ({{getter}}().get(_key) != null) { + joiner.add({{getter}}().get(_key).toUrlQueryString(String.format("%s{{baseName}}%s%s", prefix, suffix, + "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, _key, containerSuffix)))); + } + } + } + {{/items.isPrimitiveType}} + {{/isMap}} + {{^isMap}} + {{#isPrimitiveType}} + if ({{getter}}() != null) { + try { + joiner.add(String.format("%s{{{baseName}}}%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf({{{getter}}}()), "UTF-8").replaceAll("\\+", "%20"))); + } catch (UnsupportedEncodingException e) { + // Should never happen, UTF-8 is always supported + throw new RuntimeException(e); + } + } + {{/isPrimitiveType}} + {{^isPrimitiveType}} + {{#isModel}} + if ({{getter}}() != null) { + joiner.add({{getter}}().toUrlQueryString(prefix + "{{{baseName}}}" + suffix)); + } + {{/isModel}} + {{^isModel}} + if ({{getter}}() != null) { + try { + joiner.add(String.format("%s{{{baseName}}}%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf({{{getter}}}()), "UTF-8").replaceAll("\\+", "%20"))); + } catch (UnsupportedEncodingException e) { + // Should never happen, UTF-8 is always supported + throw new RuntimeException(e); + } + } + {{/isModel}} + {{/isPrimitiveType}} + {{/isMap}} + {{/isArray}} + + {{/allVars}} + return joiner.toString(); + } +{{/supportUrlQuery}} {{#parcelableModel}} public void writeToParcel(Parcel out, int flags) { {{#model}} -{{#isArrayModel}} +{{#isArray}} out.writeList(this); -{{/isArrayModel}} -{{^isArrayModel}} +{{/isArray}} +{{^isArray}} {{#parent}} super.writeToParcel(out, flags); {{/parent}} {{#vars}} out.writeValue({{name}}); {{/vars}} -{{/isArrayModel}} +{{/isArray}} {{/model}} } {{classname}}(Parcel in) { -{{#isArrayModel}} +{{#isArray}} in.readTypedList(this, {{arrayModelType}}.CREATOR); -{{/isArrayModel}} -{{^isArrayModel}} +{{/isArray}} +{{^isArray}} {{#parent}} super(in); {{/parent}} @@ -341,7 +567,7 @@ public {{#vendorExtensions.x-abstract}}abstract {{/vendorExtensions.x-abstract}} {{name}} = ({{{datatypeWithEnum}}})in.readValue({{complexType}}.class.getClassLoader()); {{/isPrimitiveType}} {{/vars}} -{{/isArrayModel}} +{{/isArray}} } public int describeContents() { @@ -351,14 +577,14 @@ public {{#vendorExtensions.x-abstract}}abstract {{/vendorExtensions.x-abstract}} public static final Parcelable.Creator<{{classname}}> CREATOR = new Parcelable.Creator<{{classname}}>() { public {{classname}} createFromParcel(Parcel in) { {{#model}} -{{#isArrayModel}} +{{#isArray}} {{classname}} result = new {{classname}}(); result.addAll(in.readArrayList({{arrayModelType}}.class.getClassLoader())); return result; -{{/isArrayModel}} -{{^isArrayModel}} +{{/isArray}} +{{^isArray}} return new {{classname}}(in); -{{/isArrayModel}} +{{/isArray}} {{/model}} } public {{classname}}[] newArray(int size) { @@ -366,4 +592,4 @@ public {{#vendorExtensions.x-abstract}}abstract {{/vendorExtensions.x-abstract}} } }; {{/parcelableModel}} -} +} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/pojo_doc.mustache b/boat-scaffold/src/main/templates/boat-java/pojo_doc.mustache index d9381323c..0b90946ba 100644 --- a/boat-scaffold/src/main/templates/boat-java/pojo_doc.mustache +++ b/boat-scaffold/src/main/templates/boat-java/pojo_doc.mustache @@ -3,20 +3,21 @@ {{#description}}{{&description}} {{/description}} {{^vendorExtensions.x-is-one-of-interface}} + ## Properties -Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- -{{#vars}}**{{name}}** | {{#isEnum}}[**{{datatypeWithEnum}}**](#{{datatypeWithEnum}}){{/isEnum}}{{^isEnum}}{{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{complexType}}.md){{/isPrimitiveType}}{{/isEnum}} | {{description}} | {{^required}} [optional]{{/required}}{{#isReadOnly}} [readonly]{{/isReadOnly}} +| Name | Type | Description | Notes | +|------------ | ------------- | ------------- | -------------| +{{#vars}}|**{{name}}** | {{#isEnum}}[**{{datatypeWithEnum}}**](#{{datatypeWithEnum}}){{/isEnum}}{{^isEnum}}{{#isContainer}}{{#isArray}}{{#items}}{{#isModel}}[{{/isModel}}{{/items}}**{{baseType}}{{#items}}<{{dataType}}>**{{#isModel}}]({{^baseType}}{{dataType}}{{/baseType}}{{baseType}}.md){{/isModel}}{{/items}}{{/isArray}}{{#isMap}}{{#items}}{{#isModel}}[{{/isModel}}**Map<String, {{dataType}}>**{{#isModel}}]({{^baseType}}{{dataType}}{{/baseType}}{{baseType}}.md){{/isModel}}{{/items}}{{/isMap}}{{/isContainer}}{{^isContainer}}{{#isModel}}[{{/isModel}}**{{dataType}}**{{#isModel}}]({{^baseType}}{{dataType}}{{/baseType}}{{baseType}}.md){{/isModel}}{{/isContainer}}{{/isEnum}} | {{description}} | {{^required}} [optional]{{/required}}{{#isReadOnly}} [readonly]{{/isReadOnly}} | {{/vars}} {{#vars}}{{#isEnum}} ## Enum: {{datatypeWithEnum}} -Name | Value ----- | -----{{#allowableValues}}{{#enumVars}} -{{name}} | {{value}}{{/enumVars}}{{/allowableValues}} +| Name | Value | +|---- | -----|{{#allowableValues}}{{#enumVars}} +| {{name}} | {{value}} |{{/enumVars}}{{/allowableValues}} {{/isEnum}}{{/vars}} {{#vendorExtensions.x-implements.0}} diff --git a/boat-scaffold/src/main/templates/boat-java/pom.mustache b/boat-scaffold/src/main/templates/boat-java/pom.mustache index e26133f0c..4920e245b 100644 --- a/boat-scaffold/src/main/templates/boat-java/pom.mustache +++ b/boat-scaffold/src/main/templates/boat-java/pom.mustache @@ -45,6 +45,8 @@ maven-compiler-plugin 3.8.1 + 1.8 + 1.8 true 128m 512m @@ -92,7 +94,6 @@ - org.apache.maven.plugins maven-dependency-plugin @@ -155,33 +156,13 @@ - - org.apache.maven.plugins - maven-compiler-plugin - 3.6.1 - - {{#supportJava6}} - 1.6 - 1.6 - {{/supportJava6}} - {{^supportJava6}} - {{#java8}} - 1.8 - 1.8 - {{/java8}} - {{^java8}} - 1.7 - 1.7 - {{/java8}} - {{/supportJava6}} - - org.apache.maven.plugins maven-javadoc-plugin - 3.1.1 + 3.3.2 none + 1.8 @@ -273,7 +254,7 @@ com.fasterxml.jackson.core jackson-databind - ${jackson-version} + ${jackson-databind-version} com.fasterxml.jackson.jaxrs @@ -297,46 +278,17 @@ ${jackson-version} {{/joda}} - {{#java8}} com.fasterxml.jackson.datatype jackson-datatype-jsr310 ${jackson-version} - {{/java8}} - {{#threetenbp}} - - com.github.joschi.jackson - jackson-datatype-threetenbp - ${jackson-threetenbp-version} - - {{/threetenbp}} - {{^java8}} - - - com.brsanthu - migbase64 - 2.2 - - {{/java8}} - {{#supportJava6}} - - org.apache.commons - commons-lang3 - ${commons_lang3_version} - - - commons-io - commons-io - ${commons_io_version} - - {{/supportJava6}} {{#useBeanValidation}} - javax.validation - validation-api - 1.1.0.Final + jakarta.validation + jakarta.validation-api + ${beanvalidation-version} provided {{/useBeanValidation}} @@ -357,6 +309,12 @@ provided {{/parcelableModel}} + + jakarta.annotation + jakarta.annotation-api + ${jakarta-annotation-version} + provided + junit @@ -365,19 +323,23 @@ test - - UTF-8 - 1.5.21 - 1.19.4 - {{#supportJava6}} - 2.5 - 3.6 - {{/supportJava6}} - 2.10.3 - {{#threetenbp}} - 2.9.10 - {{/threetenbp}} - 1.0.0 - 4.13 - - + + UTF-8 + 1.6.6 + 1.19.4 + 2.12.6 + 2.12.6.1 + {{#useJakartaEe}} + 2.1.1 + {{/useJakartaEe}} + {{^useJakartaEe}} + 1.3.5 + {{/useJakartaEe}} + + {{#useBeanValidation}} + 2.0.2 + {{/useBeanValidation}} + 1.0.0 + 4.13.2 + + \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/typeInfoAnnotation.mustache b/boat-scaffold/src/main/templates/boat-java/typeInfoAnnotation.mustache index 81c2ba05f..aa2d4588a 100644 --- a/boat-scaffold/src/main/templates/boat-java/typeInfoAnnotation.mustache +++ b/boat-scaffold/src/main/templates/boat-java/typeInfoAnnotation.mustache @@ -1,8 +1,17 @@ {{#jackson}} -@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "{{{discriminator.propertyBaseName}}}", visible = true) +@JsonIgnoreProperties( + value = "{{{discriminator.propertyBaseName}}}", // ignore manually set {{{discriminator.propertyBaseName}}}, it will be automatically generated by Jackson during serialization + allowSetters = true // allows the {{{discriminator.propertyBaseName}}} to be set during deserialization +) +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "{{{discriminator.propertyBaseName}}}", visible = true) +{{#discriminator.mappedModels}} +{{#-first}} @JsonSubTypes({ - {{#discriminator.mappedModels}} +{{/-first}} @JsonSubTypes.Type(value = {{modelName}}.class, name = "{{^vendorExtensions.x-discriminator-value}}{{mappingName}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}"), - {{/discriminator.mappedModels}} -}){{/jackson}} +{{#-last}} +}) +{{/-last}} +{{/discriminator.mappedModels}} +{{/jackson}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-java/xmlAnnotation.mustache b/boat-scaffold/src/main/templates/boat-java/xmlAnnotation.mustache index 04566fa11..4f3b448c8 100644 --- a/boat-scaffold/src/main/templates/boat-java/xmlAnnotation.mustache +++ b/boat-scaffold/src/main/templates/boat-java/xmlAnnotation.mustache @@ -1,6 +1,6 @@ {{#withXml}} -@XmlRootElement({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{classname}}{{/xmlName}}") +@XmlRootElement({{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}name = "{{xmlName}}{{^xmlName}}{{classname}}{{/xmlName}}") @XmlAccessorType(XmlAccessType.FIELD) {{#jackson}} -@JacksonXmlRootElement({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}localName = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{classname}}{{/xmlName}}"){{/jackson}}{{/withXml}} \ No newline at end of file +@JacksonXmlRootElement({{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}localName = "{{xmlName}}{{^xmlName}}{{classname}}{{/xmlName}}"){{/jackson}}{{/withXml}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/additionalEnumTypeAnnotations.mustache b/boat-scaffold/src/main/templates/boat-spring/additionalEnumTypeAnnotations.mustache new file mode 100644 index 000000000..dbb6a373f --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-spring/additionalEnumTypeAnnotations.mustache @@ -0,0 +1,3 @@ +{{#additionalEnumTypeAnnotations}} +{{{.}}} +{{/additionalEnumTypeAnnotations}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/additionalOneOfTypeAnnotations.mustache b/boat-scaffold/src/main/templates/boat-spring/additionalOneOfTypeAnnotations.mustache new file mode 100644 index 000000000..283f8f91e --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-spring/additionalOneOfTypeAnnotations.mustache @@ -0,0 +1,2 @@ +{{#additionalOneOfTypeAnnotations}}{{{.}}} +{{/additionalOneOfTypeAnnotations}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/allowableValues.mustache b/boat-scaffold/src/main/templates/boat-spring/allowableValues.mustache new file mode 100644 index 000000000..6aa973a6a --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-spring/allowableValues.mustache @@ -0,0 +1 @@ +{{#allowableValues}}allowableValues ={{#swagger2AnnotationLibrary}} { {{#values}}"{{{.}}}"{{^-last}}, {{/-last}}{{/values}} }{{/swagger2AnnotationLibrary}}{{#swagger1AnnotationLibrary}} "{{#values}}{{{.}}}{{^-last}}, {{/-last}}{{#-last}}{{/-last}}{{/values}}"{{/swagger1AnnotationLibrary}}{{/allowableValues}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/api.mustache b/boat-scaffold/src/main/templates/boat-spring/api.mustache index c16548d3f..bb0874630 100644 --- a/boat-scaffold/src/main/templates/boat-spring/api.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/api.mustache @@ -13,10 +13,19 @@ package {{package}}; {{#imports}}import {{import}}; {{/imports}} -{{^fullJavaUtil}} -import java.util.Set; -import java.util.LinkedHashSet;{{/fullJavaUtil}} +{{#swagger2AnnotationLibrary}} +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +{{/swagger2AnnotationLibrary}} +{{#swagger1AnnotationLibrary}} import io.swagger.annotations.*; +{{/swagger1AnnotationLibrary}} {{#jdk8-no-delegate}} {{#virtualService}} import io.virtualan.annotation.ApiVirtual; @@ -29,99 +38,90 @@ import org.springframework.http.ResponseEntity; {{#useBeanValidation}} import org.springframework.validation.annotation.Validated; {{/useBeanValidation}} -import org.springframework.web.bind.annotation.CookieValue; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestHeader; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RequestPart; +{{#useSpringController}} +import org.springframework.stereotype.Controller; +{{/useSpringController}} +import org.springframework.web.bind.annotation.*; {{#jdk8-no-delegate}} - {{^reactive}} +{{^reactive}} import org.springframework.web.context.request.NativeWebRequest; - {{/reactive}} +{{/reactive}} {{/jdk8-no-delegate}} import org.springframework.web.multipart.MultipartFile; {{#reactive}} import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import org.springframework.http.codec.multipart.Part; {{/reactive}} -{{^useApiUtil}} -{{#jdk8-default-interface}} -{{#reactive}} -import java.nio.charset.StandardCharsets; -import org.springframework.core.io.buffer.DefaultDataBufferFactory; -import org.springframework.web.server.ServerWebExchange; -{{/reactive}} -{{^reactive}} -import org.springframework.web.context.request.NativeWebRequest; -import java.io.IOException; - -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -{{/reactive}} -{{/jdk8-default-interface}} -{{/useApiUtil}} - +{{#useBeanValidation}} +{{#useJakartaEe}} +import jakarta.validation.Valid; +import jakarta.validation.constraints.*; +{{/useJakartaEe}} +{{^useJakartaEe}} +import javax.validation.Valid; +import javax.validation.constraints.*; +{{/useJakartaEe}} +{{/useBeanValidation}} {{#addServletRequest}} +{{^useJakartaEe}} import javax.servlet.http.HttpServletRequest; +{{/useJakartaEe}} +{{#useJakartaEe}} +import jakarta.servlet.http.HttpServletRequest; +{{/useJakartaEe}} {{/addServletRequest}} {{#addBindingResult}} import org.springframework.validation.BindingResult; {{/addBindingResult}} -{{#useBeanValidation}} -import javax.validation.Valid; -import javax.validation.constraints.*; -{{/useBeanValidation}} import java.util.List; import java.util.Map; {{#jdk8-no-delegate}} import java.util.Optional; {{/jdk8-no-delegate}} {{^jdk8-no-delegate}} - {{#useOptional}} +{{#useOptional}} import java.util.Optional; - {{/useOptional}} +{{/useOptional}} {{/jdk8-no-delegate}} {{#async}} -import java.util.concurrent.{{^jdk8}}Callable{{/jdk8}}{{#jdk8}}CompletableFuture{{/jdk8}}; +import java.util.concurrent.CompletableFuture; {{/async}} +{{#useJakartaEe}} +import jakarta.annotation.Generated; +{{/useJakartaEe}} +{{^useJakartaEe}} +import javax.annotation.Generated; +{{/useJakartaEe}} + {{>generatedAnnotation}} {{#useBeanValidation}} {{#useClassLevelBeanValidation}} @Validated {{/useClassLevelBeanValidation}} {{/useBeanValidation}} -@Api(value = "{{{baseName}}}", description = "the {{{baseName}}} API") +{{#useSpringController}} +@Controller +{{/useSpringController}} +{{#swagger2AnnotationLibrary}} +@Tag(name = "{{{baseName}}}", description = {{#tagDescription}}"{{{.}}}"{{/tagDescription}}{{^tagDescription}}"the {{{baseName}}} API"{{/tagDescription}}) +{{/swagger2AnnotationLibrary}} +{{#swagger1AnnotationLibrary}} +@Api(value = "{{{baseName}}}", description = {{#tagDescription}}"{{{.}}}"{{/tagDescription}}{{^tagDescription}}"the {{{baseName}}} API"{{/tagDescription}}) +{{/swagger1AnnotationLibrary}} {{#operations}} {{#virtualService}} @VirtualService {{/virtualService}} +{{#useRequestMappingOnInterface}} +{{=<% %>=}} +@RequestMapping("${openapi.<%title%>.base-path:<%>defaultBasePath%>}") +<%={{ }}=%> +{{/useRequestMappingOnInterface}} public interface {{classname}} { {{#jdk8-default-interface}} -{{^useApiUtil}} -{{^reactive}} - static void setExampleResponse(NativeWebRequest req, String contentType, String example) { - try { - HttpServletResponse res = req.getNativeResponse(HttpServletResponse.class); - res.setCharacterEncoding("UTF-8"); - res.addHeader("Content-Type", contentType); - res.getWriter().print(example); - } catch (IOException e) { - throw new RuntimeException(e); - } - } -{{/reactive}} -{{#reactive}} - static Mono getExampleResponse(ServerWebExchange exchange, String example) { - return exchange.getResponse().writeWith(Mono.just(new DefaultDataBufferFactory().wrap(example.getBytes(StandardCharsets.UTF_8)))); - } -{{/reactive}} -{{/useApiUtil}} - {{^isDelegate}} {{^reactive}} @@ -148,8 +148,8 @@ public interface {{classname}} { {{#allParams}} * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} {{/allParams}} - * @return {{#responses}}{{message}} (status code {{code}}){{#hasMore}} - * or {{/hasMore}}{{/responses}} + * @return {{#responses}}{{message}} (status code {{code}}){{^-last}} + * or {{/-last}}{{/responses}} {{#isDeprecated}} * @deprecated {{/isDeprecated}} @@ -158,49 +158,112 @@ public interface {{classname}} { * @see {{summary}} Documentation {{/externalDocs}} */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} {{#virtualService}} @ApiVirtual {{/virtualService}} - @ApiOperation(value = "{{{summary}}}", nickname = "{{{operationId}}}", notes = "{{{notes}}}"{{#returnBaseType}}, response = {{{returnBaseType}}}.class{{/returnBaseType}}{{#returnContainer}}, responseContainer = "{{{returnContainer}}}"{{/returnContainer}}{{#hasAuthMethods}}, authorizations = { - {{#authMethods}}@Authorization(value = "{{name}}"{{#isOAuth}}, scopes = { - {{#scopes}}@AuthorizationScope(scope = "{{scope}}", description = "{{description}}"){{#hasMore}}, - {{/hasMore}}{{/scopes}} - }{{/isOAuth}}){{#hasMore}}, - {{/hasMore}}{{/authMethods}} - }{{/hasAuthMethods}}, tags={ {{#vendorExtensions.x-tags}}"{{tag}}",{{/vendorExtensions.x-tags}} }) - @ApiResponses(value = { {{#responses}} - @ApiResponse(code = {{{code}}}, message = "{{{message}}}"{{#baseType}}, response = {{{baseType}}}.class{{/baseType}}{{#containerType}}, responseContainer = "{{{containerType}}}"{{/containerType}}){{#hasMore}},{{/hasMore}}{{/responses}} }) - {{#implicitHeaders}} + {{#swagger2AnnotationLibrary}} + @Operation( + operationId = "{{{operationId}}}", + {{#summary}} + summary = "{{{.}}}", + {{/summary}} + {{#notes}} + description = "{{{.}}}", + {{/notes}} + {{#vendorExtensions.x-tags.size}} + tags = { {{#vendorExtensions.x-tags}}"{{tag}}"{{^-last}}, {{/-last}}{{/vendorExtensions.x-tags}} }, + {{/vendorExtensions.x-tags.size}} + responses = { + {{#responses}} + @ApiResponse(responseCode = "{{{code}}}", description = "{{{message}}}"{{#baseType}}, content = { + {{#produces}} + @Content(mediaType = "{{{mediaType}}}", schema = @Schema(implementation = {{{baseType}}}.class)){{^-last}},{{/-last}} + {{/produces}} + }{{/baseType}}){{^-last}},{{/-last}} + {{/responses}} + }{{#hasAuthMethods}}, + security = { + {{#authMethods}} + @SecurityRequirement(name = "{{name}}"{{#isOAuth}}, scopes={ {{#scopes}}"{{scope}}"{{^-last}}, {{/-last}}{{/scopes}} }{{/isOAuth}}){{^-last}},{{/-last}} + {{/authMethods}} + }{{/hasAuthMethods}} + ) + {{/swagger2AnnotationLibrary}} + {{#swagger1AnnotationLibrary}} + @ApiOperation( + {{#vendorExtensions.x-tags.size}} + tags = { {{#vendorExtensions.x-tags}}"{{tag}}"{{^-last}}, {{/-last}}{{/vendorExtensions.x-tags}} }, + {{/vendorExtensions.x-tags.size}} + value = "{{{summary}}}", + nickname = "{{{operationId}}}", + notes = "{{{notes}}}"{{#returnBaseType}}, + response = {{{.}}}.class{{/returnBaseType}}{{#returnContainer}}, + responseContainer = "{{{.}}}"{{/returnContainer}}{{#hasAuthMethods}}, + authorizations = { + {{#authMethods}} + {{#isOAuth}} + @Authorization(value = "{{name}}", scopes = { + {{#scopes}} + @AuthorizationScope(scope = "{{scope}}", description = "{{description}}"){{^-last}},{{/-last}} + {{/scopes}} + }){{^-last}},{{/-last}} + {{/isOAuth}} + {{^isOAuth}} + @Authorization(value = "{{name}}"){{^-last}},{{/-last}} + {{/isOAuth}} + {{/authMethods}} }{{/hasAuthMethods}} + ) + @ApiResponses({ + {{#responses}} + @ApiResponse(code = {{{code}}}, message = "{{{message}}}"{{#baseType}}, response = {{{.}}}.class{{/baseType}}{{#containerType}}, responseContainer = "{{{.}}}"{{/containerType}}){{^-last}},{{/-last}} + {{/responses}} + }) + {{/swagger1AnnotationLibrary}} + {{#implicitHeadersParams.0}} + {{#swagger2AnnotationLibrary}} + @Parameters({ + {{#implicitHeadersParams}} + {{>paramDoc}}{{^-last}},{{/-last}} + {{/implicitHeadersParams}} + }) + {{/swagger2AnnotationLibrary}} + {{#swagger1AnnotationLibrary}} @ApiImplicitParams({ - {{#headerParams}} - {{>implicitHeader}} - {{/headerParams}} + {{#implicitHeadersParams}} + {{>implicitHeader}}{{^-last}},{{/-last}} + {{/implicitHeadersParams}} }) - {{/implicitHeaders}} - @RequestMapping(value = "{{{path}}}",{{#singleContentTypes}}{{#hasProduces}} - produces = "{{{vendorExtensions.x-accepts}}}", {{/hasProduces}}{{#hasConsumes}} - consumes = "{{{vendorExtensions.x-contentType}}}",{{/hasConsumes}}{{/singleContentTypes}}{{^singleContentTypes}}{{#hasProduces}} - produces = { {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} }, {{/hasProduces}}{{#hasConsumes}} - consumes = { {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} },{{/hasConsumes}}{{/singleContentTypes}} - method = RequestMethod.{{httpMethod}}) + {{/swagger1AnnotationLibrary}} + {{/implicitHeadersParams.0}} + @RequestMapping( + method = RequestMethod.{{httpMethod}}, + value = "{{{path}}}"{{#singleContentTypes}}{{#hasProduces}}, + produces = "{{{vendorExtensions.x-accepts}}}"{{/hasProduces}}{{#hasConsumes}}, + consumes = "{{{vendorExtensions.x-content-type}}}"{{/hasConsumes}}{{/singleContentTypes}}{{^singleContentTypes}}{{#hasProduces}}, + produces = { {{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}} }{{/hasProduces}}{{#hasConsumes}}, + 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}}{{#hasMore}}, - {{/hasMore}}{{^hasMore}}{{#reactive}}, {{/reactive}}{{^reactive}}{{#addServletRequest}}, - {{/addServletRequest}}{{/reactive}}{{/hasMore}}{{/allParams}}{{#addServletRequest}}HttpServletRequest httpServletRequest{{#reactive}}, - {{/reactive}}{{/addServletRequest}}{{#reactive}}ServerWebExchange exchange{{/reactive}} + {{#allParams}}{{>queryParams}}{{>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}} ){{#unhandledException}} throws Exception{{/unhandledException}}{{^jdk8-default-interface}};{{/jdk8-default-interface}}{{#jdk8-default-interface}} { {{#delegate-method}} - return {{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}{{#reactive}}{{#hasParams}}, {{/hasParams}}exchange{{/reactive}}); + return {{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#reactive}}{{#hasParams}}, {{/hasParams}}exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}, pageable{{/vendorExtensions.x-spring-paginated}}); } // Override this method - {{#jdk8-default-interface}}default {{/jdk8-default-interface}} {{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {{operationId}}({{#allParams}}{{^isFile}}{{^isBodyParam}}{{>optionalDataType}}{{/isBodyParam}}{{#isBodyParam}}{{^reactive}}{{{dataType}}}{{/reactive}}{{#reactive}}{{^isListContainer}}Mono{{/isListContainer}}{{#isListContainer}}Flux{{/isListContainer}}<{{{baseType}}}>{{/reactive}}{{/isBodyParam}}{{/isFile}}{{#isFile}}MultipartFile{{/isFile}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}{{#reactive}}{{#hasParams}}, {{/hasParams}}ServerWebExchange exchange{{/reactive}}){{#unhandledException}} throws Exception{{/unhandledException}} { + {{#jdk8-default-interface}}default {{/jdk8-default-interface}} {{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {{operationId}}({{#allParams}}{{^isFile}}{{^isBodyParam}}{{>optionalDataType}}{{/isBodyParam}}{{#isBodyParam}}{{^reactive}}{{{dataType}}}{{/reactive}}{{#reactive}}{{^isArray}}Mono<{{{dataType}}}>{{/isArray}}{{#isArray}}Flux<{{{baseType}}}>{{/isArray}}{{/reactive}}{{/isBodyParam}}{{/isFile}}{{#isFile}}{{#reactive}}Flux{{/reactive}}{{^reactive}}MultipartFile{{/reactive}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#reactive}}{{#hasParams}}, {{/hasParams}}{{#springFoxDocumentationProvider}}@ApiIgnore{{/springFoxDocumentationProvider}} final ServerWebExchange exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}, {{#springFoxDocumentationProvider}}@ApiIgnore{{/springFoxDocumentationProvider}} final Pageable pageable{{/vendorExtensions.x-spring-paginated}}){{#unhandledException}} throws Exception{{/unhandledException}} { {{/delegate-method}} {{^isDelegate}} {{>methodBody}} {{/isDelegate}} {{#isDelegate}} - return getDelegate().{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}{{#reactive}}{{#hasParams}}, {{/hasParams}}exchange{{/reactive}}); + return getDelegate().{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#reactive}}{{#hasParams}}, {{/hasParams}}exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}, pageable{{/vendorExtensions.x-spring-paginated}}); {{/isDelegate}} }{{/jdk8-default-interface}} diff --git a/boat-scaffold/src/main/templates/boat-spring/apiController.mustache b/boat-scaffold/src/main/templates/boat-spring/apiController.mustache index 66727f4c6..21bec1775 100644 --- a/boat-scaffold/src/main/templates/boat-spring/apiController.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/apiController.mustache @@ -1,59 +1,75 @@ package {{package}}; -{{^jdk8}} {{#imports}}import {{import}}; {{/imports}} + +{{#_api_controller_impl_}} +{{#swagger2AnnotationLibrary}} +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +{{/swagger2AnnotationLibrary}} +{{#swagger1AnnotationLibrary}} import io.swagger.annotations.*; +{{/swagger1AnnotationLibrary}} +{{/_api_controller_impl_}} + +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; -{{/jdk8}} import org.springframework.stereotype.Controller; -{{^jdk8}} import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; -{{/jdk8}} import org.springframework.web.bind.annotation.RequestMapping; -{{^jdk8}} import org.springframework.web.bind.annotation.CookieValue; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestPart; -{{/jdk8}} +import org.springframework.web.multipart.MultipartFile; {{^isDelegate}} import org.springframework.web.context.request.NativeWebRequest; {{/isDelegate}} -{{^jdk8}} -import org.springframework.web.multipart.MultipartFile; - {{#useBeanValidation}} +{{#useBeanValidation}} +{{#useJakartaEe}} +import jakarta.validation.Valid; +import jakarta.validation.constraints.*; +{{/useJakartaEe}} +{{^useJakartaEe}} import javax.validation.constraints.*; import javax.validation.Valid; - {{/useBeanValidation}} -{{/jdk8}} -{{#jdk8}} -import java.util.Optional; -{{/jdk8}} -{{^jdk8}} +{{/useJakartaEe}} +{{/useBeanValidation}} + import java.util.List; import java.util.Map; - {{#async}} -import java.util.concurrent.Callable; - {{/async}} -{{/jdk8}} +import java.util.Optional; +{{#useJakartaEe}} +import jakarta.annotation.Generated; +{{/useJakartaEe}} +{{^useJakartaEe}} +import javax.annotation.Generated; +{{/useJakartaEe}} + {{>generatedAnnotation}} @Controller +{{#useRequestMappingOnController}} {{=<% %>=}} @RequestMapping("${openapi.<%title%>.base-path:<%>defaultBasePath%>}") <%={{ }}=%> +{{/useRequestMappingOnController}} {{#operations}} public class {{classname}}Controller implements {{classname}} { {{#isDelegate}} private final {{classname}}Delegate delegate; - public {{classname}}Controller(@org.springframework.beans.factory.annotation.Autowired(required = false) {{classname}}Delegate delegate) { - {{#jdk8}} + public {{classname}}Controller(@Autowired(required = false) {{classname}}Delegate delegate) { this.delegate = Optional.ofNullable(delegate).orElse(new {{classname}}Delegate() {}); } @@ -61,34 +77,25 @@ public class {{classname}}Controller implements {{classname}} { public {{classname}}Delegate getDelegate() { return delegate; } - {{/jdk8}} - {{^jdk8}} - this.delegate = delegate; - } - {{/jdk8}} {{/isDelegate}} {{^isDelegate}} {{^reactive}} - {{^jdk8}} - {{/jdk8}} private final NativeWebRequest request; - @org.springframework.beans.factory.annotation.Autowired + @Autowired public {{classname}}Controller(NativeWebRequest request) { this.request = request; } - {{#jdk8}} @Override public Optional getRequest() { return Optional.ofNullable(request); } - {{/jdk8}} {{/reactive}} {{/isDelegate}} -{{^jdk8}} +{{#_api_controller_impl_}} {{#operation}} /** * {{httpMethod}} {{{path}}}{{#summary}} : {{.}}{{/summary}} @@ -99,8 +106,8 @@ public class {{classname}}Controller implements {{classname}} { {{#allParams}} * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} {{/allParams}} - * @return {{#responses}}{{message}} (status code {{code}}){{#hasMore}} - * or {{/hasMore}}{{/responses}} + * @return {{#responses}}{{message}} (status code {{code}}){{^-last}} + * or {{/-last}}{{/responses}} {{#isDeprecated}} * @deprecated {{/isDeprecated}} @@ -110,7 +117,14 @@ public class {{classname}}Controller implements {{classname}} { {{/externalDocs}} * @see {{classname}}#{{operationId}} */ - public {{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {{operationId}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{>cookieParams}}{{#hasMore}},{{/hasMore}}{{/allParams}}) { + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {{operationId}}( + {{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{>cookieParams}}{{^-last}}, + {{/-last}}{{/allParams}}{{#vendorExtensions.x-spring-paginated}}{{#hasParams}}, + {{/hasParams}}{{#springFoxDocumentationProvider}}@ApiIgnore {{/springFoxDocumentationProvider}}final Pageable pageable{{/vendorExtensions.x-spring-paginated}} + ) { {{^isDelegate}} {{^async}} {{>methodBody}} @@ -125,11 +139,11 @@ public class {{classname}}Controller implements {{classname}} { {{/async}} {{/isDelegate}} {{#isDelegate}} - return delegate.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + return delegate.{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#vendorExtensions.x-spring-paginated}}, pageable{{/vendorExtensions.x-spring-paginated}}); {{/isDelegate}} } {{/operation}} -{{/jdk8}} +{{/_api_controller_impl_}} } -{{/operations}} +{{/operations}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/apiDelegate.mustache b/boat-scaffold/src/main/templates/boat-spring/apiDelegate.mustache index fa684e9e8..5aa446f29 100644 --- a/boat-scaffold/src/main/templates/boat-spring/apiDelegate.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/apiDelegate.mustache @@ -12,52 +12,30 @@ package {{package}}; {{#imports}}import {{import}}; {{/imports}} -import io.swagger.annotations.*; -{{#jdk8}} import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; -{{/jdk8}} import org.springframework.http.ResponseEntity; -{{#jdk8}} import org.springframework.web.context.request.NativeWebRequest; -{{/jdk8}} import org.springframework.web.multipart.MultipartFile; {{#reactive}} import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import org.springframework.http.codec.multipart.Part; {{/reactive}} -{{^useApiUtil}} -{{#jdk8-default-interface}} -{{#reactive}} -import java.nio.charset.StandardCharsets; -import org.springframework.core.io.buffer.DefaultDataBufferFactory; -import org.springframework.web.server.ServerWebExchange; -{{/reactive}} -{{^reactive}} -import org.springframework.web.context.request.NativeWebRequest; -import java.io.IOException; - -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -{{/reactive}} -{{/jdk8-default-interface}} -{{/useApiUtil}} - import java.util.List; import java.util.Map; -{{#jdk8}} import java.util.Optional; -{{/jdk8}} -{{^jdk8}} - {{#useOptional}} -import java.util.Optional; - {{/useOptional}} -{{/jdk8}} {{#async}} -import java.util.concurrent.{{^jdk8}}Callable{{/jdk8}}{{#jdk8}}CompletableFuture{{/jdk8}}; +import java.util.concurrent.CompletableFuture; {{/async}} +{{#useJakartaEe}} +import jakarta.annotation.Generated; +{{/useJakartaEe}} +{{^useJakartaEe}} +import javax.annotation.Generated; +{{/useJakartaEe}} {{#operations}} /** @@ -102,8 +80,8 @@ public interface {{classname}}Delegate { {{#allParams}} * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} {{/allParams}} - * @return {{#responses}}{{message}} (status code {{code}}){{#hasMore}} - * or {{/hasMore}}{{/responses}} + * @return {{#responses}}{{message}} (status code {{code}}){{^-last}} + * or {{/-last}}{{/responses}} {{#isDeprecated}} * @deprecated {{/isDeprecated}} @@ -113,12 +91,15 @@ public interface {{classname}}Delegate { {{/externalDocs}} * @see {{classname}}#{{operationId}} */ - {{#jdk8-default-interface}}default {{/jdk8-default-interface}}{{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {{operationId}}({{#allParams}}{{^isFile}}{{^isBodyParam}}{{>optionalDataType}}{{/isBodyParam}}{{#isBodyParam}}{{^reactive}}{{{dataType}}}{{/reactive}}{{#reactive}}{{^isListContainer}}Mono{{/isListContainer}}{{#isListContainer}}Flux{{/isListContainer}}<{{{baseType}}}>{{/reactive}}{{/isBodyParam}}{{/isFile}}{{#isFile}}{{#isListContainer}}List<{{/isListContainer}}MultipartFile{{#isListContainer}}>{{/isListContainer}}{{/isFile}} {{paramName}}{{#hasMore}}, - {{/hasMore}}{{/allParams}}{{#reactive}}{{#hasParams}}, - {{/hasParams}}ServerWebExchange exchange{{/reactive}}){{#unhandledException}} throws Exception{{/unhandledException}}{{^jdk8-default-interface}};{{/jdk8-default-interface}}{{#jdk8-default-interface}} { + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + {{#jdk8-default-interface}}default {{/jdk8-default-interface}}{{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {{operationId}}({{#allParams}}{{^isFile}}{{^isBodyParam}}{{>optionalDataType}}{{/isBodyParam}}{{#isBodyParam}}{{^reactive}}{{{dataType}}}{{/reactive}}{{#reactive}}{{^isArray}}Mono<{{{dataType}}}>{{/isArray}}{{#isArray}}Flux<{{{baseType}}}>{{/isArray}}{{/reactive}}{{/isBodyParam}}{{/isFile}}{{#isFile}}{{#isArray}}List<{{/isArray}}{{#reactive}}Flux{{/reactive}}{{^reactive}}MultipartFile{{/reactive}}{{#isArray}}>{{/isArray}}{{/isFile}} {{paramName}}{{^-last}}, + {{/-last}}{{/allParams}}{{#reactive}}{{#hasParams}}, + {{/hasParams}}ServerWebExchange exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}, final Pageable pageable{{/vendorExtensions.x-spring-paginated}}){{#unhandledException}} throws Exception{{/unhandledException}}{{^jdk8-default-interface}};{{/jdk8-default-interface}}{{#jdk8-default-interface}} { {{>methodBody}} }{{/jdk8-default-interface}} {{/operation}} } -{{/operations}} +{{/operations}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/apiException.mustache b/boat-scaffold/src/main/templates/boat-spring/apiException.mustache index f61611477..0464ec523 100644 --- a/boat-scaffold/src/main/templates/boat-spring/apiException.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/apiException.mustache @@ -1,10 +1,44 @@ package {{apiPackage}}; +{{#useJakartaEe}} +import jakarta.annotation.Generated; +{{/useJakartaEe}} +{{^useJakartaEe}} +import javax.annotation.Generated; +{{/useJakartaEe}} + +/** + * The exception that can be used to store the HTTP status code returned by an API response. + */ {{>generatedAnnotation}} -public class ApiException extends Exception{ +public class ApiException extends Exception { + /** The HTTP status code. */ private int code; - public ApiException (int code, String msg) { + + /** + * Constructor. + * + * @param code The HTTP status code. + * @param msg The error message. + */ + public ApiException(int code, String msg) { super(msg); this.code = code; } -} + + /** + * Get the HTTP status code. + * + * @return The HTTP status code. + */ + public int getCode() { + return code; + } + + @Override + public String toString() { + return "ApiException{" + + "code=" + code + + '}'; + } +} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/apiOriginFilter.mustache b/boat-scaffold/src/main/templates/boat-spring/apiOriginFilter.mustache index 5cf72a7dc..688592a14 100644 --- a/boat-scaffold/src/main/templates/boat-spring/apiOriginFilter.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/apiOriginFilter.mustache @@ -2,11 +2,19 @@ package {{apiPackage}}; import java.io.IOException; +{{#useJakartaEe}} +import jakarta.annotation.Generated; +import jakarta.servlet.*; +import jakarta.servlet.http.HttpServletResponse; +{{/useJakartaEe}} +{{^useJakartaEe}} +import javax.annotation.Generated; import javax.servlet.*; import javax.servlet.http.HttpServletResponse; +{{/useJakartaEe}} {{>generatedAnnotation}} -public class ApiOriginFilter implements javax.servlet.Filter { +public class ApiOriginFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { @@ -24,4 +32,4 @@ public class ApiOriginFilter implements javax.servlet.Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } -} +} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/apiResponseMessage.mustache b/boat-scaffold/src/main/templates/boat-spring/apiResponseMessage.mustache index 17b155f3b..af92021f3 100644 --- a/boat-scaffold/src/main/templates/boat-spring/apiResponseMessage.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/apiResponseMessage.mustache @@ -1,5 +1,11 @@ package {{apiPackage}}; +{{#useJakartaEe}} +import jakarta.annotation.Generated; +{{/useJakartaEe}} +{{^useJakartaEe}} +import javax.annotation.Generated; +{{/useJakartaEe}} import javax.xml.bind.annotation.XmlTransient; {{>generatedAnnotation}} @@ -66,4 +72,4 @@ public class ApiResponseMessage { public void setMessage(String message) { this.message = message; } -} +} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/apiUtil.mustache b/boat-scaffold/src/main/templates/boat-spring/apiUtil.mustache index 6608bdb2b..94bd39dd4 100644 --- a/boat-scaffold/src/main/templates/boat-spring/apiUtil.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/apiUtil.mustache @@ -2,14 +2,22 @@ package {{apiPackage}}; {{#reactive}} import java.nio.charset.StandardCharsets; +import org.springframework.core.io.buffer.DefaultDataBuffer; import org.springframework.core.io.buffer.DefaultDataBufferFactory; +import org.springframework.http.MediaType; +import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; {{/reactive}} {{^reactive}} import org.springframework.web.context.request.NativeWebRequest; +{{#useJakartaEe}} +import jakarta.servlet.http.HttpServletResponse; +{{/useJakartaEe}} +{{^useJakartaEe}} import javax.servlet.http.HttpServletResponse; +{{/useJakartaEe}} import java.io.IOException; {{/reactive}} @@ -27,8 +35,13 @@ public class ApiUtil { } {{/reactive}} {{#reactive}} - public static Mono getExampleResponse(ServerWebExchange exchange, String example) { - return exchange.getResponse().writeWith(Mono.just(new DefaultDataBufferFactory().wrap(example.getBytes(StandardCharsets.UTF_8)))); + public static Mono getExampleResponse(ServerWebExchange exchange, MediaType mediaType, String example) { + ServerHttpResponse response = exchange.getResponse(); + response.getHeaders().setContentType(mediaType); + + byte[] exampleBytes = example.getBytes(StandardCharsets.UTF_8); + DefaultDataBuffer data = new DefaultDataBufferFactory().wrap(exampleBytes); + return response.writeWith(Mono.just(data)); } {{/reactive}} -} +} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/beanValidation.mustache b/boat-scaffold/src/main/templates/boat-spring/beanValidation.mustache index a0cc454aa..e427a43a0 100644 --- a/boat-scaffold/src/main/templates/boat-spring/beanValidation.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/beanValidation.mustache @@ -1,8 +1 @@ -{{#required}}@NotNull {{/required}}{{! -}}{{#isContainer}}{{! - }}{{^isPrimitiveType}}{{^isEnum}}@Valid {{/isEnum}}{{/isPrimitiveType}}{{! -}}{{/isContainer}}{{! -}}{{^isContainer}}{{! - }}{{^isPrimitiveType}}@Valid {{/isPrimitiveType}}{{! -}}{{/isContainer}}{{! -}}{{>beanValidationCore}} \ No newline at end of file +{{#required}}{{^isReadOnly}}@NotNull {{/isReadOnly}}{{/required}}{{#isContainer}}{{^isPrimitiveType}}{{^isEnum}}@Valid {{/isEnum}}{{/isPrimitiveType}}{{/isContainer}}{{^isContainer}}{{^isPrimitiveType}}@Valid {{/isPrimitiveType}}{{/isContainer}}{{>beanValidationCore}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/beanValidationCore.mustache b/boat-scaffold/src/main/templates/boat-spring/beanValidationCore.mustache index b3497b3da..f8aa5ab2a 100644 --- a/boat-scaffold/src/main/templates/boat-spring/beanValidationCore.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/beanValidationCore.mustache @@ -1,24 +1,22 @@ -{{#pattern}}{{^isByteArray}}@Pattern(regexp="{{{pattern}}}") {{/isByteArray}}{{/pattern}}{{! +{{#pattern}}{{^isByteArray}}@Pattern(regexp = "{{{pattern}}}") {{/isByteArray}}{{/pattern}}{{! minLength && maxLength set -}}{{#minLength}}{{#maxLength}}@Size(min={{minLength}}, max={{maxLength}}) {{/maxLength}}{{/minLength}}{{! +}}{{#minLength}}{{#maxLength}}@Size(min = {{minLength}}, max = {{maxLength}}) {{/maxLength}}{{/minLength}}{{! minLength set, maxLength not -}}{{#minLength}}{{^maxLength}}@Size(min={{minLength}}) {{/maxLength}}{{/minLength}}{{! +}}{{#minLength}}{{^maxLength}}@Size(min = {{minLength}}) {{/maxLength}}{{/minLength}}{{! minLength not set, maxLength set -}}{{^minLength}}{{#maxLength}}@Size(max={{maxLength}}) {{/maxLength}}{{/minLength}}{{! +}}{{^minLength}}{{#maxLength}}@Size(max = {{.}}) {{/maxLength}}{{/minLength}}{{! @Size: minItems && maxItems set -}}{{#minItems}}{{#maxItems}}@Size(min={{minItems}}, max={{maxItems}}) {{/maxItems}}{{/minItems}}{{! +}}{{#minItems}}{{#maxItems}}@Size(min = {{minItems}}, max = {{maxItems}}) {{/maxItems}}{{/minItems}}{{! @Size: minItems set, maxItems not -}}{{#minItems}}{{^maxItems}}@Size(min={{minItems}}) {{/maxItems}}{{/minItems}}{{! +}}{{#minItems}}{{^maxItems}}@Size(min = {{minItems}}) {{/maxItems}}{{/minItems}}{{! @Size: minItems not set && maxItems set -}}{{^minItems}}{{#maxItems}}@Size(max={{maxItems}}) {{/maxItems}}{{/minItems}}{{! -@Email: useBeanValidation set && isEmail && java8 set -}}{{#useBeanValidation}}{{#isEmail}}{{#java8}}@javax.validation.constraints.Email {{/java8}}{{/isEmail}}{{/useBeanValidation}}{{! -@Email: performBeanValidation set && isEmail && not java8 set -}}{{#performBeanValidation}}{{#isEmail}}{{^java8}}@org.hibernate.validator.constraints.Email {{/java8}}{{/isEmail}}{{/performBeanValidation}}{{! +}}{{^minItems}}{{#maxItems}}@Size(max = {{.}}) {{/maxItems}}{{/minItems}}{{! +@Email: useBeanValidation set && isEmail set +}}{{#useBeanValidation}}{{#isEmail}}@Email{{/isEmail}}{{/useBeanValidation}}{{! check for integer or long / all others=decimal type with @Decimal* isInteger set -}}{{#isInteger}}{{#minimum}}@Min({{minimum}}) {{/minimum}}{{#maximum}}@Max({{maximum}}) {{/maximum}}{{/isInteger}}{{! +}}{{#isInteger}}{{#minimum}}@Min({{.}}) {{/minimum}}{{#maximum}}@Max({{.}}) {{/maximum}}{{/isInteger}}{{! isLong set -}}{{#isLong}}{{#minimum}}@Min({{minimum}}L) {{/minimum}}{{#maximum}}@Max({{maximum}}L) {{/maximum}}{{/isLong}}{{! +}}{{#isLong}}{{#minimum}}@Min({{.}}L) {{/minimum}}{{#maximum}}@Max({{.}}L) {{/maximum}}{{/isLong}}{{! Not Integer, not Long => we have a decimal value! -}}{{^isInteger}}{{^isLong}}{{#minimum}}@DecimalMin({{#exclusiveMinimum}}value={{/exclusiveMinimum}}"{{minimum}}"{{#exclusiveMinimum}},inclusive=false{{/exclusiveMinimum}}) {{/minimum}}{{#maximum}}@DecimalMax({{#exclusiveMaximum}}value={{/exclusiveMaximum}}"{{maximum}}"{{#exclusiveMaximum}},inclusive=false{{/exclusiveMaximum}}) {{/maximum}}{{/isLong}}{{/isInteger}} \ No newline at end of file +}}{{^isInteger}}{{^isLong}}{{#minimum}}@DecimalMin({{#exclusiveMinimum}}value = {{/exclusiveMinimum}}"{{minimum}}"{{#exclusiveMinimum}}, inclusive = false{{/exclusiveMinimum}}) {{/minimum}}{{#maximum}}@DecimalMax({{#exclusiveMaximum}}value = {{/exclusiveMaximum}}"{{maximum}}"{{#exclusiveMaximum}}, inclusive = false{{/exclusiveMaximum}}) {{/maximum}}{{/isLong}}{{/isInteger}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/beanValidationPathParams.mustache b/boat-scaffold/src/main/templates/boat-spring/beanValidationPathParams.mustache new file mode 100644 index 000000000..051bd53c0 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-spring/beanValidationPathParams.mustache @@ -0,0 +1 @@ +{{! PathParam is always required, no @NotNull necessary }}{{>beanValidationCore}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/beanValidationQueryParams.mustache b/boat-scaffold/src/main/templates/boat-spring/beanValidationQueryParams.mustache new file mode 100644 index 000000000..a2f19f774 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-spring/beanValidationQueryParams.mustache @@ -0,0 +1 @@ +{{#required}}@NotNull {{/required}}{{^useOptional}}{{>beanValidationCore}}{{/useOptional}}{{#useOptional}}{{#required}}{{>beanValidationCore}}{{/required}}{{/useOptional}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/bodyParams.mustache b/boat-scaffold/src/main/templates/boat-spring/bodyParams.mustache index 45caf586c..b582385da 100644 --- a/boat-scaffold/src/main/templates/boat-spring/bodyParams.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/bodyParams.mustache @@ -1,5 +1 @@ -{{#isBodyParam}} - @ApiParam(value = "{{{description}}}" {{#required}},required=true{{/required}} {{^isContainer}}{{#allowableValues}}, allowableValues="{{{allowableValues}}}"{{/allowableValues}}{{#defaultValue}}, defaultValue={{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}{{{defaultValue}}}{{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}{{/defaultValue}}{{/isContainer}}) - {{#useBeanValidation}} - @Valid{{#required}} @NotNull{{/required}}{{/useBeanValidation}} - @RequestBody{{^required}}(required = false){{/required}} {{^reactive}}{{{dataType}}}{{/reactive}}{{#reactive}}{{^isListContainer}}Mono{{/isListContainer}}{{#isListContainer}}Flux{{/isListContainer}}<{{{baseType}}}>{{/reactive}} {{paramName}}{{#useBeanValidation}}{{#addBindingResult}}, BindingResult bindingResult{{/addBindingResult}}{{/useBeanValidation}}{{/isBodyParam}} \ No newline at end of file +{{#isBodyParam}}{{>paramDoc}}{{#useBeanValidation}} @Valid{{/useBeanValidation}} @RequestBody{{^required}}(required = false){{/required}} {{^reactive}}{{{dataType}}}{{/reactive}}{{#reactive}}{{^isArray}}Mono<{{{dataType}}}>{{/isArray}}{{#isArray}}Flux<{{{baseType}}}>{{/isArray}}{{/reactive}} {{paramName}}{{#useBeanValidation}}{{#addBindingResult}}, BindingResult bindingResult{{/addBindingResult}}{{/useBeanValidation}}{{/isBodyParam}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/converter.mustache b/boat-scaffold/src/main/templates/boat-spring/converter.mustache new file mode 100644 index 000000000..a331ded63 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-spring/converter.mustache @@ -0,0 +1,34 @@ +package {{configPackage}}; + +{{#models}} + {{#model}} + {{#isEnum}} +import {{modelPackage}}.{{name}}; + {{/isEnum}} + {{/model}} +{{/models}} + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.convert.converter.Converter; + +@Configuration +public class EnumConverterConfiguration { + +{{#models}} +{{#model}} +{{#isEnum}} + @Bean + Converter<{{{dataType}}}, {{name}}> {{classVarName}}Converter() { + return new Converter<{{{dataType}}}, {{name}}>() { + @Override + public {{name}} convert({{{dataType}}} source) { + return {{name}}.fromValue(source); + } + }; + } +{{/isEnum}} +{{/model}} +{{/models}} + +} diff --git a/boat-scaffold/src/main/templates/boat-spring/cookieParams.mustache b/boat-scaffold/src/main/templates/boat-spring/cookieParams.mustache index 3d1a60403..74a837988 100644 --- a/boat-scaffold/src/main/templates/boat-spring/cookieParams.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/cookieParams.mustache @@ -1,6 +1 @@ -{{#isCookieParam}} - @ApiParam(value = "{{{description}}}"{{#required}},required=true{{/required}}{{#allowableValues}}, allowableValues = "{{#enumVars}}{{#lambdaEscapeDoubleQuote}}{{{value}}}{{/lambdaEscapeDoubleQuote}}{{^-last}}, {{/-last}}{{#-last}}{{/-last}}{{/enumVars}}"{{/allowableValues}}{{^isContainer}}{{#defaultValue}}, defaultValue={{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}{{{defaultValue}}}{{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}{{/defaultValue}}{{/isContainer}}) - @CookieValue("{{baseName}}") - {{#useBeanValidation}}{{#required}}@NotNull - {{/required}}{{/useBeanValidation}} - {{>optionalDataType}} {{paramName}}{{/isCookieParam}} +{{#isCookieParam}}{{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}}{{>paramDoc}} @CookieValue(name = "{{baseName}}"{{^required}}, required = false{{/required}}{{#defaultValue}}, defaultValue = "{{{.}}}"{{/defaultValue}}){{>dateTimeParam}} {{>optionalDataType}} {{paramName}}{{/isCookieParam}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/dateTimeParam.mustache b/boat-scaffold/src/main/templates/boat-spring/dateTimeParam.mustache new file mode 100644 index 000000000..5f4f3a264 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-spring/dateTimeParam.mustache @@ -0,0 +1 @@ +{{#isDate}} @DateTimeFormat(iso = DateTimeFormat.ISO.DATE){{/isDate}}{{#isDateTime}} @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME){{/isDateTime}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/defaultBasePath.mustache b/boat-scaffold/src/main/templates/boat-spring/defaultBasePath.mustache new file mode 100644 index 000000000..3c7185bd6 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-spring/defaultBasePath.mustache @@ -0,0 +1 @@ +{{contextPath}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/enumClass.mustache b/boat-scaffold/src/main/templates/boat-spring/enumClass.mustache index c1d813aa8..31b7bc970 100644 --- a/boat-scaffold/src/main/templates/boat-spring/enumClass.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/enumClass.mustache @@ -1,7 +1,7 @@ /** - * {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{{description}}}{{/description}} + * {{^description}}Gets or Sets {{{name}}}{{/description}}{{{description}}} */ - public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} { + {{>additionalEnumTypeAnnotations}}public enum {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} { {{#gson}} {{#allowableValues}} {{#enumVars}} @@ -22,7 +22,7 @@ private {{{dataType}}} value; - {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}({{{dataType}}} value) { + {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}({{{dataType}}} value) { this.value = value; } @@ -39,12 +39,12 @@ } @JsonCreator - public static {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue({{{dataType}}} value) { - for ({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { + public static {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue({{{dataType}}} value) { + for ({{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { if (b.value.equals(value)) { return b; } } {{#isNullable}}return null;{{/isNullable}}{{^isNullable}}throw new IllegalArgumentException("Unexpected value '" + value + "'");{{/isNullable}} } - } + } \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/enumOuterClass.mustache b/boat-scaffold/src/main/templates/boat-spring/enumOuterClass.mustache index baa6d54d7..b239cc85f 100644 --- a/boat-scaffold/src/main/templates/boat-spring/enumOuterClass.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/enumOuterClass.mustache @@ -1,11 +1,14 @@ {{#jackson}} import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; {{/jackson}} /** - * {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{{description}}}{{/description}} + * {{^description}}Gets or Sets {{{name}}}{{/description}}{{{description}}} */ -public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} { +{{>additionalEnumTypeAnnotations}} +{{>generatedAnnotation}} +public enum {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} { {{#gson}} {{#allowableValues}}{{#enumVars}} @SerializedName({{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}{{{value}}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}) @@ -20,7 +23,7 @@ public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum private {{{dataType}}} value; - {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}({{{dataType}}} value) { + {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}({{{dataType}}} value) { this.value = value; } @@ -37,12 +40,12 @@ public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum } @JsonCreator - public static {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue({{{dataType}}} value) { - for ({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { + public static {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue({{{dataType}}} value) { + for ({{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { if (b.value.equals(value)) { return b; } } {{#isNullable}}return null;{{/isNullable}}{{^isNullable}}throw new IllegalArgumentException("Unexpected value '" + value + "'");{{/isNullable}} } -} +} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/exampleReturnTypes.mustache b/boat-scaffold/src/main/templates/boat-spring/exampleReturnTypes.mustache index 0749b0ca7..d13cee710 100644 --- a/boat-scaffold/src/main/templates/boat-spring/exampleReturnTypes.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/exampleReturnTypes.mustache @@ -1 +1 @@ -{{#returnContainer}}{{#isMapContainer}}Map{{/returnContainer}}{{^returnContainer}}{{{returnType}}}{{/returnContainer}} \ No newline at end of file +{{#returnContainer}}{{#isMap}}Map{{/returnContainer}}{{^returnContainer}}{{{returnType}}}{{/returnContainer}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/formParams.mustache b/boat-scaffold/src/main/templates/boat-spring/formParams.mustache index 1f4a1b239..b0819f315 100644 --- a/boat-scaffold/src/main/templates/boat-spring/formParams.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/formParams.mustache @@ -1 +1 @@ -{{#isFormParam}}{{^isFile}}@ApiParam(value = "{{{description}}}"{{#required}}, required=true{{/required}}{{#allowableValues}}, allowableValues="{{#values}}{{{.}}}{{^-last}}, {{/-last}}{{#-last}}{{/-last}}{{/values}}"{{/allowableValues}}{{^isContainer}}{{#defaultValue}}, defaultValue={{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}{{{defaultValue}}}{{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}{{/defaultValue}}{{/isContainer}}) @RequestPart(value="{{baseName}}"{{#required}}, required=true{{/required}}{{^required}}, required=false{{/required}}) {{{dataType}}} {{paramName}}{{/isFile}}{{#isFile}}@ApiParam(value = "{{{description}}}") {{#useBeanValidation}}@Valid{{/useBeanValidation}} @RequestPart(value = "{{baseName}}") {{#isListContainer}}List<{{/isListContainer}}MultipartFile{{#isListContainer}}>{{/isListContainer}} {{baseName}}{{/isFile}}{{/isFormParam}} \ No newline at end of file +{{#isFormParam}}{{^isFile}}{{>paramDoc}}{{#useBeanValidation}} @Valid{{/useBeanValidation}} @RequestParam(value = "{{baseName}}"{{#required}}, required = true{{/required}}{{^required}}, required = false{{/required}}){{>dateTimeParam}} {{{dataType}}} {{paramName}}{{/isFile}}{{#isFile}}{{>paramDoc}} @RequestPart(value = "{{baseName}}"{{#required}}, required = true{{/required}}{{^required}}, required = false{{/required}}) {{#isArray}}List<{{/isArray}}{{#reactive}}Flux{{/reactive}}{{^reactive}}MultipartFile{{/reactive}}{{#isArray}}>{{/isArray}} {{paramName}}{{/isFile}}{{/isFormParam}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/generatedAnnotation.mustache b/boat-scaffold/src/main/templates/boat-spring/generatedAnnotation.mustache index a48587d41..2f8ef3059 100644 --- a/boat-scaffold/src/main/templates/boat-spring/generatedAnnotation.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/generatedAnnotation.mustache @@ -1,2 +1 @@ -{{^hideGenerationTimestamp}} -@javax.annotation.Generated(value = "{{generatorClass}}", date = "{{generatedDate}}"){{/hideGenerationTimestamp}} \ No newline at end of file +@Generated(value = "{{generatorClass}}"{{^hideGenerationTimestamp}}, date = "{{generatedDate}}"{{/hideGenerationTimestamp}}) \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/headerParams.mustache b/boat-scaffold/src/main/templates/boat-spring/headerParams.mustache index f471fc366..b9589c147 100644 --- a/boat-scaffold/src/main/templates/boat-spring/headerParams.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/headerParams.mustache @@ -1,4 +1 @@ -{{#isHeaderParam}} - @ApiParam(value = "{{{description}}}" {{#required}},required=true{{/required}}{{#allowableValues}}, allowableValues="{{#values}}{{{.}}}{{^-last}}, {{/-last}}{{#-last}}{{/-last}}{{/values}}"{{/allowableValues}}{{^isContainer}}{{#defaultValue}}, defaultValue={{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}{{{defaultValue}}}{{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}{{/defaultValue}}{{/isContainer}}) - @RequestHeader(value="{{baseName}}", required={{#required}}true{{/required}}{{^required}}false{{/required}}) - {{>optionalDataType}} {{paramName}}{{/isHeaderParam}} \ No newline at end of file +{{#isHeaderParam}}{{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}}{{>paramDoc}} @RequestHeader(value = "{{baseName}}", required = {{#required}}true{{/required}}{{^required}}false{{/required}}{{#defaultValue}}, defaultValue = "{{{.}}}"{{/defaultValue}}){{>dateTimeParam}} {{>optionalDataType}} {{paramName}}{{/isHeaderParam}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/homeController.mustache b/boat-scaffold/src/main/templates/boat-spring/homeController.mustache index f909a15b3..258392223 100644 --- a/boat-scaffold/src/main/templates/boat-spring/homeController.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/homeController.mustache @@ -1,35 +1,34 @@ package {{configPackage}}; -{{^useSpringfox}} +import org.springframework.context.annotation.Bean; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +{{#sourceDocumentationProvider}} import com.fasterxml.jackson.dataformat.yaml.YAMLMapper; import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; import org.springframework.core.io.Resource; -{{/useSpringfox}} -import org.springframework.stereotype.Controller; -{{^useSpringfox}} import org.springframework.util.StreamUtils; +import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.GetMapping; -{{/useSpringfox}} -import org.springframework.web.bind.annotation.RequestMapping; -{{^useSpringfox}} +{{/sourceDocumentationProvider}} +{{#useSwaggerUI}} import org.springframework.web.bind.annotation.ResponseBody; -{{/useSpringfox}} +import org.springframework.web.bind.annotation.GetMapping; +{{/useSwaggerUI}} {{#reactive}} import org.springframework.web.reactive.function.server.RouterFunction; import org.springframework.web.reactive.function.server.ServerResponse; {{/reactive}} - -{{^useSpringfox}} +{{#sourceDocumentationProvider}} import java.io.IOException; import java.io.InputStream; -{{/useSpringfox}} +{{/sourceDocumentationProvider}} {{#reactive}} import java.net.URI; {{/reactive}} -{{^useSpringfox}} +{{#sourceDocumentationProvider}} import java.nio.charset.Charset; -{{/useSpringfox}} +{{/sourceDocumentationProvider}} {{#reactive}} import static org.springframework.web.reactive.function.server.RequestPredicates.GET; @@ -41,8 +40,8 @@ import static org.springframework.web.reactive.function.server.RouterFunctions.r */ @Controller public class HomeController { +{{#sourceDocumentationProvider}} -{{^useSpringfox}} private static YAMLMapper yamlMapper = new YAMLMapper(); @Value("classpath:/openapi.yaml") @@ -66,23 +65,40 @@ public class HomeController { public Object openapiJson() throws IOException { return yamlMapper.readValue(openapiContent(), Object.class); } +{{/sourceDocumentationProvider}} +{{#useSwaggerUI}} +{{^springDocDocumentationProvider}} + +{{#sourceDocumentationProvider}} + static final String API_DOCS_PATH = "/openapi.json"; +{{/sourceDocumentationProvider}} +{{#springFoxDocumentationProvider}} + static final String API_DOCS_PATH = "/v2/api-docs"; +{{/springFoxDocumentationProvider}} -{{/useSpringfox}} + @GetMapping(value = "/swagger-config.yaml", produces = "text/plain") + @ResponseBody + public String swaggerConfig() { + return "url: " + API_DOCS_PATH + "\n"; + } +{{/springDocDocumentationProvider}} {{#reactive}} + @Bean RouterFunction index() { return route( GET("/"), - req -> ServerResponse.temporaryRedirect(URI.create("{{#useSpringfox}}swagger-ui.html{{/useSpringfox}}{{^useSpringfox}}swagger-ui/index.html?url=../openapi.json{{/useSpringfox}}")).build() + req -> ServerResponse.temporaryRedirect(URI.create("swagger-ui.html")).build() ); } {{/reactive}} {{^reactive}} + @RequestMapping("/") public String index() { - return "redirect:{{#useSpringfox}}swagger-ui.html{{/useSpringfox}}{{^useSpringfox}}swagger-ui/index.html?url=../openapi.json{{/useSpringfox}}"; + return "redirect:swagger-ui.html"; } {{/reactive}} +{{/useSwaggerUI}} - -} +} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/httpServletParam.mustache b/boat-scaffold/src/main/templates/boat-spring/httpServletParam.mustache new file mode 100644 index 000000000..4c25519e3 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-spring/httpServletParam.mustache @@ -0,0 +1 @@ +{{#isHttpServletRequest}}{{^reactive}}{{#addServletRequest}} HttpServletRequest httpServletRequest{{/addServletRequest}}{{/reactive}}{{/isHttpServletRequest}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/implicitHeader.mustache b/boat-scaffold/src/main/templates/boat-spring/implicitHeader.mustache index 64d7af208..0453940ce 100644 --- a/boat-scaffold/src/main/templates/boat-spring/implicitHeader.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/implicitHeader.mustache @@ -1 +1 @@ -{{#isHeaderParam}}@ApiImplicitParam(name = "{{{paramName}}}", value = "{{{description}}}", {{#required}}required=true,{{/required}} dataType = "{{{dataType}}}", paramType = "header"){{#hasMore}},{{/hasMore}}{{/isHeaderParam}} \ No newline at end of file +{{#isHeaderParam}}@ApiImplicitParam(name = "{{{baseName}}}", value = "{{{description}}}", {{#required}}required = true,{{/required}} dataType = "{{{dataType}}}", paramType = "header"){{/isHeaderParam}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/libraries/spring-boot/README.mustache b/boat-scaffold/src/main/templates/boat-spring/libraries/spring-boot/README.mustache index fdc844423..75b663946 100644 --- a/boat-scaffold/src/main/templates/boat-spring/libraries/spring-boot/README.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/libraries/spring-boot/README.mustache @@ -1,24 +1,45 @@ {{^interfaceOnly}}# OpenAPI generated server -Spring Boot Server +Spring Boot Server - -## Overview +## Overview This server was generated by the [OpenAPI Generator](https://openapi-generator.tech) project. By using the [OpenAPI-Spec](https://openapis.org), you can easily generate a server stub. This is an example of building a OpenAPI-enabled server in Java using the SpringBoot framework. +{{#springFoxDocumentationProvider}} + +The underlying library integrating OpenAPI to Spring Boot is [springfox](https://github.com/springfox/springfox). +Springfox will generate an OpenAPI v2 (fka Swagger RESTful API Documentation Specification) specification based on the +generated Controller and Model classes. The specification is available to download using the following url: +http://localhost:{{serverPort}}/v2/api-docs/ + +**HEADS-UP**: Springfox is deprecated for removal in version 6.0.0 of openapi-generator. The project seems to be no longer +maintained (last commit is of Oct 14, 2020). It works with Spring Boot 2.5.x but not with 2.6. Spring Boot 2.5 is +supported until 2022-05-19. Users of openapi-generator should migrate to the springdoc documentation provider which is, +as an added bonus, OpenAPI v3 compatible. + +{{/springFoxDocumentationProvider}} + +{{#springDocDocumentationProvider}} + +The underlying library integrating OpenAPI to Spring Boot is [springdoc](https://springdoc.org). +Springdoc will generate an OpenAPI v3 specification based on the generated Controller and Model classes. +The specification is available to download using the following url: +http://localhost:{{serverPort}}/v3/api-docs/ +{{/springDocDocumentationProvider}} +{{#sourceDocumentationProvider}} -{{#useSpringfox}} -The underlying library integrating OpenAPI to SpringBoot is [springfox](https://github.com/springfox/springfox) +The OpenAPI specification used to generate this project is available to download using the following url: +http://localhost:{{serverPort}}/openapi.json +{{/sourceDocumentationProvider}} -{{/useSpringfox}} Start your server as a simple java application +{{#useSwaggerUI}} -{{^reactive}} -You can view the api documentation in swagger-ui by pointing to -http://localhost:{{serverPort}}/ +You can view the api documentation in swagger-ui by pointing to +http://localhost:{{serverPort}}/swagger-ui.html -{{/reactive}} +{{/useSwaggerUI}} Change default port value in application.properties{{/interfaceOnly}}{{#interfaceOnly}} # OpenAPI generated API stub @@ -52,9 +73,9 @@ public interface PetClient extends PetApi { ## Virtualan : -You can view Virtualan UI by pointing to -http://localhost:80//virtualan-ui.html. +You can view Virtualan UI by pointing to +http://localhost:8080//virtualan-ui.html -How to use guide available in the Virtualan wiki -https://github.com/elan-venture/virtualan/wiki +How to use guide available in the Virtualan wiki +https://github.com/virtualansoftware/virtualan/wiki {{/virtualService}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/libraries/spring-boot/RFC3339DateFormat.mustache b/boat-scaffold/src/main/templates/boat-spring/libraries/spring-boot/RFC3339DateFormat.mustache index d5dff8ac6..b1a5cb59e 100644 --- a/boat-scaffold/src/main/templates/boat-spring/libraries/spring-boot/RFC3339DateFormat.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/libraries/spring-boot/RFC3339DateFormat.mustache @@ -1,22 +1,38 @@ package {{basePackage}}; -import com.fasterxml.jackson.databind.util.ISO8601DateFormat; -import com.fasterxml.jackson.databind.util.ISO8601Utils; +import com.fasterxml.jackson.databind.util.StdDateFormat; +import java.text.DateFormat; import java.text.FieldPosition; +import java.text.ParsePosition; import java.util.Date; +import java.util.GregorianCalendar; +import java.util.TimeZone; +public class RFC3339DateFormat extends DateFormat { + private static final long serialVersionUID = 1L; + private static final TimeZone TIMEZONE_Z = TimeZone.getTimeZone("UTC"); -public class RFC3339DateFormat extends ISO8601DateFormat { + private final StdDateFormat fmt = new StdDateFormat() + .withTimeZone(TIMEZONE_Z) + .withColonInTimeZone(true); - private static final long serialVersionUID = 1L; + public RFC3339DateFormat() { + this.calendar = new GregorianCalendar(); + } + + @Override + public Date parse(String source, ParsePosition pos) { + return fmt.parse(source, pos); + } - // Same as ISO8601DateFormat but serializing milliseconds. @Override public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) { - String value = ISO8601Utils.format(date, true); - toAppendTo.append(value); - return toAppendTo; + return fmt.format(date, toAppendTo, fieldPosition); } + @Override + public Object clone() { + return this; + } } \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/libraries/spring-boot/SpringBootTest.mustache b/boat-scaffold/src/main/templates/boat-spring/libraries/spring-boot/SpringBootTest.mustache new file mode 100644 index 000000000..f8d9032c6 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-spring/libraries/spring-boot/SpringBootTest.mustache @@ -0,0 +1,13 @@ +package {{basePackage}}; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class OpenApiGeneratorApplicationTests { + + @Test + void contextLoads() { + } + +} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/libraries/spring-boot/application.mustache b/boat-scaffold/src/main/templates/boat-spring/libraries/spring-boot/application.mustache index b7fea3f62..f8740df95 100644 --- a/boat-scaffold/src/main/templates/boat-spring/libraries/spring-boot/application.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/libraries/spring-boot/application.mustache @@ -1,12 +1,9 @@ -{{#useSpringfox}} -springfox.documentation.swagger.v2.path=/api-docs -{{/useSpringfox}} server.port={{serverPort}} spring.jackson.date-format={{basePackage}}.RFC3339DateFormat spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS=false {{#virtualService}} -virtual.datasource.driver-class-name=org.hsqldb.jdbcDriver -virtual.datasource.jdbcurl=jdbc:hsqldb:mem:dataSource -virtual.datasource.username=sa -virtual.datasource.password= -{{/virtualService}} \ No newline at end of file +virtualan.datasource.driver-class-name=org.hsqldb.jdbcDriver +virtualan.datasource.jdbcurl=jdbc:hsqldb:mem:dataSource +virtualan.datasource.username=sa +virtualan.datasource.password= +{{/virtualService}} diff --git a/boat-scaffold/src/main/templates/boat-spring/libraries/spring-boot/openapi2SpringBoot.mustache b/boat-scaffold/src/main/templates/boat-spring/libraries/spring-boot/openapi2SpringBoot.mustache index 8180f6c50..01725be2d 100644 --- a/boat-scaffold/src/main/templates/boat-spring/libraries/spring-boot/openapi2SpringBoot.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/libraries/spring-boot/openapi2SpringBoot.mustache @@ -1,76 +1,20 @@ package {{basePackage}}; -import com.fasterxml.jackson.databind.Module; {{#openApiNullable}} +import com.fasterxml.jackson.databind.Module; import org.openapitools.jackson.nullable.JsonNullableModule; {{/openApiNullable}} -import org.springframework.boot.CommandLineRunner; -import org.springframework.boot.ExitCodeGenerator; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; -{{^reactive}} -import org.springframework.web.servlet.config.annotation.CorsRegistry; - {{^useSpringfox}} -import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; - {{/useSpringfox}} -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; - {{^java8}} -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; - {{/java8}} -{{/reactive}} -{{#reactive}} -import org.springframework.web.reactive.config.CorsRegistry; - {{^useSpringfox}} -import org.springframework.web.reactive.config.ResourceHandlerRegistry; - {{/useSpringfox}} -import org.springframework.web.reactive.config.WebFluxConfigurer; -{{/reactive}} @SpringBootApplication @ComponentScan(basePackages = {"{{basePackage}}", "{{apiPackage}}" , "{{configPackage}}"}) -public class OpenAPI2SpringBoot implements CommandLineRunner { - - @Override - public void run(String... arg0) throws Exception { - if (arg0.length > 0 && arg0[0].equals("exitcode")) { - throw new ExitException(); - } - } - - public static void main(String[] args) throws Exception { - new SpringApplication(OpenAPI2SpringBoot.class).run(args); - } - - static class ExitException extends RuntimeException implements ExitCodeGenerator { - private static final long serialVersionUID = 1L; - - @Override - public int getExitCode() { - return 10; - } - - } - - @Bean - public Web{{^reactive}}Mvc{{/reactive}}{{#reactive}}Flux{{/reactive}}Configurer webConfigurer() { - return new Web{{^reactive}}Mvc{{/reactive}}{{#reactive}}Flux{{/reactive}}Configurer{{^java8}}Adapter{{/java8}}() { - /*@Override - public void addCorsMappings(CorsRegistry registry) { - registry.addMapping("/**") - .allowedOrigins("*") - .allowedMethods("*") - .allowedHeaders("Content-Type"); - }*/ -{{^useSpringfox}} +public class OpenApiGeneratorApplication { - @Override - public void addResourceHandlers(ResourceHandlerRegistry registry) { - registry.addResourceHandler("/swagger-ui/**").addResourceLocations("classpath:/META-INF/resources/webjars/swagger-ui/3.14.2/"); - } -{{/useSpringfox}} - }; + public static void main(String[] args) { + SpringApplication.run(OpenApiGeneratorApplication.class, args); } {{#openApiNullable}} @@ -80,4 +24,4 @@ public class OpenAPI2SpringBoot implements CommandLineRunner { } {{/openApiNullable}} -} +} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/libraries/spring-boot/pom-sb3.mustache b/boat-scaffold/src/main/templates/boat-spring/libraries/spring-boot/pom-sb3.mustache new file mode 100644 index 000000000..d4533a65e --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-spring/libraries/spring-boot/pom-sb3.mustache @@ -0,0 +1,230 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + + 17 + ${java.version} + ${java.version} + UTF-8 + {{#springDocDocumentationProvider}} + 2.0.2 + {{/springDocDocumentationProvider}} + {{^springDocDocumentationProvider}} + {{#swagger2AnnotationLibrary}} + }2.2.7 + {{/swagger2AnnotationLibrary}} + {{/springDocDocumentationProvider}} + {{#useSwaggerUI}} + 4.15.5 + {{/useSwaggerUI}} + {{#virtualService}} + 2.5.2 + {{/virtualService}} + +{{#parentOverridden}} + + {{{parentGroupId}}} + {{{parentArtifactId}}} + {{{parentVersion}}} + +{{/parentOverridden}} +{{^parentOverridden}} + + org.springframework.boot + spring-boot-starter-parent + 3.0.2 + + +{{/parentOverridden}} + + + + repository.spring.milestone + Spring Milestone Repository + https://repo.spring.io/milestone + + + + + spring-milestones + https://repo.spring.io/milestone + + + + + src/main/java + {{^interfaceOnly}} + + + org.springframework.boot + spring-boot-maven-plugin + {{#classifier}} + + {{{classifier}}} + + {{/classifier}} + + {{#apiFirst}} + + org.openapitools + openapi-generator-maven-plugin + {{{generatorVersion}}} + + + + generate + + + src/main/resources/openapi.yaml + spring + {{{apiPackage}}} + {{{modelPackage}}} + false + {{#modelNamePrefix}} + {{{.}}} + {{/modelNamePrefix}} + {{#modelNameSuffix}} + {{{.}}} + {{/modelNameSuffix}} + + {{#configOptions}} + <{{left}}>{{right}} + {{/configOptions}} + + + + + + {{/apiFirst}} + + {{/interfaceOnly}} + + + + org.springframework.boot + spring-boot-starter-web{{#reactive}}flux{{/reactive}} + + + org.springframework.data + spring-data-commons + + {{#springDocDocumentationProvider}} + + {{#useSwaggerUI}} + + org.springdoc + springdoc-openapi-starter-{{#reactive}}webflux{{/reactive}}{{^reactive}}webmvc{{/reactive}}-ui + ${springdoc.version} + + {{/useSwaggerUI}} + {{^useSwaggerUI}} + + org.springdoc + springdoc-openapi-starter-{{#reactive}}webflux{{/reactive}}{{^reactive}}webmvc{{/reactive}}-api + ${springdoc.version} + + {{/useSwaggerUI}} + {{/springDocDocumentationProvider}} + {{#useSwaggerUI}} + {{^springDocDocumentationProvider}} + + org.webjars + swagger-ui + ${swagger-ui.version} + + + org.webjars + webjars-locator-core + + {{/springDocDocumentationProvider}} + {{/useSwaggerUI}} + {{^springDocDocumentationProvider}} + {{#swagger2AnnotationLibrary}} + + io.swagger.core.v3 + swagger-annotations + ${swagger-annotations.version} + + {{/swagger2AnnotationLibrary}} + {{/springDocDocumentationProvider}} + + + com.google.code.findbugs + jsr305 + 3.0.2 + + + com.fasterxml.jackson.dataformat + jackson-dataformat-yaml + + {{#withXml}} + + + jakarta.xml.bind + jakarta.xml.bind-api + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + + {{/withXml}} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + + {{#joda}} + + com.fasterxml.jackson.datatype + jackson-datatype-joda + + {{/joda}} + {{#openApiNullable}} + + org.openapitools + jackson-databind-nullable + 0.2.2 + + {{/openApiNullable}} +{{#useBeanValidation}} + + + org.springframework.boot + spring-boot-starter-validation + +{{/useBeanValidation}} +{{#virtualService}} + + + io.virtualan + virtualan-plugin + ${virtualan.version} + + + + org.hsqldb + hsqldb + + +{{/virtualService}} +{{#hateoas}} + + + org.springframework.boot + spring-boot-starter-hateoas + +{{/hateoas}} + + com.fasterxml.jackson.core + jackson-databind + + + org.springframework.boot + spring-boot-starter-test + test + + + diff --git a/boat-scaffold/src/main/templates/boat-spring/libraries/spring-boot/pom.mustache b/boat-scaffold/src/main/templates/boat-spring/libraries/spring-boot/pom.mustache index 1e76f72ff..dd79aee72 100644 --- a/boat-scaffold/src/main/templates/boat-spring/libraries/spring-boot/pom.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/libraries/spring-boot/pom.mustache @@ -6,12 +6,32 @@ {{artifactId}} {{artifactVersion}} - {{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}} + 1.8 ${java.version} ${java.version} - {{#useSpringfox}} - 2.8.0 - {{/useSpringfox}} + UTF-8 + {{#springFoxDocumentationProvider}} + 2.9.2 + {{/springFoxDocumentationProvider}} + {{#springDocDocumentationProvider}} + 1.6.14 + {{/springDocDocumentationProvider}} + {{^springFoxDocumentationProvider}} + {{^springDocDocumentationProvider}} + {{#swagger1AnnotationLibrary}} + 1.6.6 + {{/swagger1AnnotationLibrary}} + {{#swagger2AnnotationLibrary}} + }2.2.7 + {{/swagger2AnnotationLibrary}} + {{/springDocDocumentationProvider}} + {{/springFoxDocumentationProvider}} + {{#virtualService}} + 2.5.2 + {{/virtualService}} + {{#useSwaggerUI}} + 4.15.5 + {{/useSwaggerUI}} {{#parentOverridden}} @@ -24,7 +44,8 @@ org.springframework.boot spring-boot-starter-parent - {{#java8}}2.7.2{{/java8}}{{^java8}}1.5.12.RELEASE{{/java8}} + {{#springFoxDocumentationProvider}}2.5.14{{/springFoxDocumentationProvider}}{{^springFoxDocumentationProvider}}2.7.6{{/springFoxDocumentationProvider}} + {{/parentOverridden}} @@ -34,20 +55,17 @@ org.springframework.boot spring-boot-maven-plugin - - - - repackage - - - + {{#classifier}} + + {{{classifier}}} + + {{/classifier}} {{#apiFirst}} - com.backbase.oss - boat-maven-plugin - {{{generatorVersion}}} - + org.openapitools + openapi-generator-maven-plugin + {{{generatorVersion}}} @@ -57,9 +75,6 @@ src/main/resources/openapi.yaml spring {{{apiPackage}}} - {{#apiNameSuffix}} - {{{apiNameSuffix}}} - {{/apiNameSuffix}} {{{modelPackage}}} false {{#modelNamePrefix}} @@ -82,39 +97,111 @@ {{/interfaceOnly}} + {{#useJakartaEe}} + + jakarta.persistence + jakarta.persistence-api + 3.1.0 + + + jakarta.servlet + jakarta.servlet-api + 6.0.0 + + + jakarta.annotation + jakarta.annotation-api + 2.1.1 + + + jakarta.validation + jakarta.validation-api + 3.0.2 + + {{/useJakartaEe}} + {{^useJakartaEe}} + + javax.persistence + javax.persistence-api + 2.2 + + + javax.servlet + javax.servlet-api + 4.0.1 + + {{/useJakartaEe}} + {{#useLombokAnnotations}} + + org.projectlombok + lombok + 1.18.24 + + {{/useLombokAnnotations}} org.springframework.boot spring-boot-starter-web{{#reactive}}flux{{/reactive}} - {{#useSpringfox}} - - io.springfox - springfox-swagger2 - ${springfox-version} + org.springframework.data + spring-data-commons + {{#springDocDocumentationProvider}} + + {{#useSwaggerUI}} - io.springfox - springfox-swagger-ui - ${springfox-version} + org.springdoc + springdoc-openapi-{{#reactive}}webflux-{{/reactive}}ui + ${springdoc.version} + {{/useSwaggerUI}} + {{^useSwaggerUI}} - javax.xml.bind - jaxb-api - 2.3.1 + org.springdoc + springdoc-openapi-{{#reactive}}webflux{{/reactive}}{{^reactive}}webmvc{{/reactive}}-core + ${springdoc.version} - {{/useSpringfox}} - {{^useSpringfox}} + {{/useSwaggerUI}} + {{/springDocDocumentationProvider}} + {{#springFoxDocumentationProvider}} + + + io.springfox + springfox-swagger2 + ${springfox.version} + + {{/springFoxDocumentationProvider}} + {{#useSwaggerUI}} + {{^springDocDocumentationProvider}} org.webjars swagger-ui - 3.14.2 + ${swagger-ui.version} + + + org.webjars + webjars-locator-core + {{/springDocDocumentationProvider}} + {{/useSwaggerUI}} + {{^springFoxDocumentationProvider}} + {{^springDocDocumentationProvider}} + {{#swagger1AnnotationLibrary}} io.swagger swagger-annotations - 1.6.6 + ${swagger-annotations.version} + {{/swagger1AnnotationLibrary}} + {{#swagger2AnnotationLibrary}} + + io.swagger.core.v3 + swagger-annotations + ${swagger-annotations.version} + + {{/swagger2AnnotationLibrary}} + {{/springDocDocumentationProvider}} + {{/springFoxDocumentationProvider}} com.google.code.findbugs @@ -125,54 +212,39 @@ com.fasterxml.jackson.dataformat jackson-dataformat-yaml - {{/useSpringfox}} {{#withXml}} + + jakarta.xml.bind + jakarta.xml.bind-api + com.fasterxml.jackson.dataformat jackson-dataformat-xml {{/withXml}} - {{#java8}} com.fasterxml.jackson.datatype jackson-datatype-jsr310 - {{/java8}} {{#joda}} com.fasterxml.jackson.datatype jackson-datatype-joda {{/joda}} - {{#threetenbp}} - - com.github.joschi.jackson - jackson-datatype-threetenbp - 2.8.4 - - {{/threetenbp}} -{{#openApiNullable}} + {{#openApiNullable}} org.openapitools jackson-databind-nullable - 0.2.3 - -{{/openApiNullable}} -{{#useLombokAnnotations}} - - org.projectlombok - lombok - 1.18.24 - provided + 0.2.2 -{{/useLombokAnnotations}} + {{/openApiNullable}} {{#useBeanValidation}} - + - jakarta.validation - jakarta.validation-api - 2.0.2 + org.springframework.boot + spring-boot-starter-validation {{/useBeanValidation}} {{#virtualService}} @@ -180,18 +252,12 @@ io.virtualan virtualan-plugin - 1.0.0 + ${virtualan.version} org.hsqldb hsqldb - 2.5.2 - - - org.springframework.boot - spring-boot-starter-data-jpa - {{#java8}}2.7.2{{/java8}}{{^java8}}1.5.12.RELEASE{{/java8}} {{/virtualService}} @@ -202,6 +268,14 @@ spring-boot-starter-hateoas {{/hateoas}} - {{{additionalDependencies}}} + + com.fasterxml.jackson.core + jackson-databind + + + org.springframework.boot + spring-boot-starter-test + test + diff --git a/boat-scaffold/src/main/templates/boat-spring/libraries/spring-boot/swagger-ui.mustache b/boat-scaffold/src/main/templates/boat-spring/libraries/spring-boot/swagger-ui.mustache new file mode 100644 index 000000000..f85b6654f --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-spring/libraries/spring-boot/swagger-ui.mustache @@ -0,0 +1,60 @@ + + + + + + Swagger UI + + + + + + + +

+ + + + + + diff --git a/boat-scaffold/src/main/templates/boat-spring/libraries/spring-cloud/apiClient.mustache b/boat-scaffold/src/main/templates/boat-spring/libraries/spring-cloud/apiClient.mustache index f00a6c3b6..adc5145d0 100644 --- a/boat-scaffold/src/main/templates/boat-spring/libraries/spring-cloud/apiClient.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/libraries/spring-cloud/apiClient.mustache @@ -3,8 +3,6 @@ package {{package}}; import org.springframework.cloud.openfeign.FeignClient; import {{configPackage}}.ClientConfiguration; -{{=<% %>=}} -@FeignClient(name="${<%classVarName%>.name:<%classVarName%>}", url="${<%classVarName%>.url:<%basePath%>}", configuration = ClientConfiguration.class) -<%={{ }}=%> +@FeignClient(name="${{openbrace}}{{classVarName}}.name:{{classVarName}}{{closebrace}}", {{#useFeignClientUrl}}url="${{openbrace}}{{classVarName}}.url:{{basePath}}{{closebrace}}", {{/useFeignClientUrl}}configuration = ClientConfiguration.class) public interface {{classname}}Client extends {{classname}} { } diff --git a/boat-scaffold/src/main/templates/boat-spring/libraries/spring-cloud/clientConfiguration.mustache b/boat-scaffold/src/main/templates/boat-spring/libraries/spring-cloud/clientConfiguration.mustache index c1feeb515..1e9a0940b 100644 --- a/boat-scaffold/src/main/templates/boat-spring/libraries/spring-cloud/clientConfiguration.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/libraries/spring-cloud/clientConfiguration.mustache @@ -21,8 +21,9 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; {{#authMethods}} {{#isOAuth}} -import org.springframework.cloud.security.oauth2.client.feign.OAuth2FeignRequestInterceptor; +import org.springframework.cloud.openfeign.security.OAuth2FeignRequestInterceptor; import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext; +import org.springframework.security.oauth2.client.OAuth2ClientContext; {{#isApplication}} import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails; {{/isApplication}} @@ -71,8 +72,14 @@ public class ClientConfiguration { {{#isOAuth}} @Bean @ConditionalOnProperty("{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}.client-id") - public OAuth2FeignRequestInterceptor {{{name}}}RequestInterceptor() { - return new OAuth2FeignRequestInterceptor(new DefaultOAuth2ClientContext(), {{{name}}}ResourceDetails()); + public OAuth2FeignRequestInterceptor {{{name}}}RequestInterceptor(OAuth2ClientContext oAuth2ClientContext) { + return new OAuth2FeignRequestInterceptor(oAuth2ClientContext, {{{name}}}ResourceDetails()); + } + + @Bean + @ConditionalOnProperty("{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}.client-id") + public OAuth2ClientContext oAuth2ClientContext() { + return new DefaultOAuth2ClientContext(); } {{#isCode}} diff --git a/boat-scaffold/src/main/templates/boat-spring/libraries/spring-cloud/pom-sb3.mustache b/boat-scaffold/src/main/templates/boat-spring/libraries/spring-cloud/pom-sb3.mustache new file mode 100644 index 000000000..f61faca01 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-spring/libraries/spring-cloud/pom-sb3.mustache @@ -0,0 +1,149 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + + 1.8 + ${java.version} + ${java.version} + UTF-8 + {{#springDocDocumentationProvider}} + 2.0.0-M3 + {{/springDocDocumentationProvider}} + {{^springDocDocumentationProvider}} + {{#swagger2AnnotationLibrary}} + }2.2.0 + {{/swagger2AnnotationLibrary}} + {{/springDocDocumentationProvider}} + +{{#parentOverridden}} + + {{{parentGroupId}}} + {{{parentArtifactId}}} + {{{parentVersion}}} + +{{/parentOverridden}} +{{^parentOverridden}} + + org.springframework.boot + spring-boot-starter-parent + 3.0.0-M3 + + +{{/parentOverridden}} + + + + repository.spring.milestone + Spring Milestone Repository + https://repo.spring.io/milestone + + + + + src/main/java + + +{{^parentOverridden}} + + + + org.springframework.cloud + spring-cloud-starter-parent + 2022.0.0-M2 + pom + import + + + + +{{/parentOverridden}} + + {{#springDocDocumentationProvider}} + + + org.springdoc + springdoc-openapi-starter-{{#reactive}}webflux{{/reactive}}{{^reactive}}webmvc{{/reactive}}-ui + ${springdoc.version} + + {{/springDocDocumentationProvider}} + {{^springDocDocumentationProvider}} + {{#swagger2AnnotationLibrary}} + + io.swagger.core.v3 + swagger-annotations + ${swagger-annotations.version} + + {{/swagger2AnnotationLibrary}} + {{/springDocDocumentationProvider}} + + + com.google.code.findbugs + jsr305 + {{^parentOverridden}} + 3.0.2 + {{/parentOverridden}} + + + org.springframework.cloud + spring-cloud-starter-openfeign + + + org.springframework.cloud + spring-cloud-starter-oauth2 + {{^parentOverridden}} + 2.2.5.RELEASE + {{/parentOverridden}} + + {{#withXml}} + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + + {{/withXml}} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + + {{#joda}} + + com.fasterxml.jackson.datatype + jackson-datatype-joda + + {{/joda}} + {{#openApiNullable}} + + org.openapitools + jackson-databind-nullable + {{^parentOverridden}} + 0.2.2 + {{/parentOverridden}} + + {{/openApiNullable}} + {{#hateoas}} + + org.springframework.boot + spring-boot-starter-hateoas + + {{/hateoas}} + {{#useBeanValidation}} + + org.springframework.boot + spring-boot-starter-validation + + {{/useBeanValidation}} + + org.springframework.data + spring-data-commons + + + org.springframework.boot + spring-boot-starter-test + test + + + diff --git a/boat-scaffold/src/main/templates/boat-spring/libraries/spring-cloud/pom.mustache b/boat-scaffold/src/main/templates/boat-spring/libraries/spring-cloud/pom.mustache index 06de2c6fc..0510c4153 100644 --- a/boat-scaffold/src/main/templates/boat-spring/libraries/spring-cloud/pom.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/libraries/spring-cloud/pom.mustache @@ -6,10 +6,26 @@ {{artifactId}} {{artifactVersion}} - {{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}} + 1.8 ${java.version} ${java.version} - 1.5.18 + UTF-8 + {{#springFoxDocumentationProvider}} + 2.9.2 + {{/springFoxDocumentationProvider}} + {{#springDocDocumentationProvider}} + 1.6.8 + {{/springDocDocumentationProvider}} + {{^springFoxDocumentationProvider}} + {{^springDocDocumentationProvider}} + {{#swagger1AnnotationLibrary}} + 1.6.6 + {{/swagger1AnnotationLibrary}} + {{#swagger2AnnotationLibrary}} + }2.1.13 + {{/swagger2AnnotationLibrary}} + {{/springDocDocumentationProvider}} + {{/springFoxDocumentationProvider}} {{#parentOverridden}} @@ -22,7 +38,8 @@ org.springframework.boot spring-boot-starter-parent - 2.0.5.RELEASE + 2.7.0 + {{/parentOverridden}} @@ -35,7 +52,7 @@ org.springframework.cloud spring-cloud-starter-parent - Finchley.SR1 + 2021.0.1 pom import @@ -44,18 +61,47 @@ {{/parentOverridden}} + {{#springDocDocumentationProvider}} + + + org.springdoc + springdoc-openapi-ui + ${springdoc.version} + + {{/springDocDocumentationProvider}} + {{#springFoxDocumentationProvider}} + + + io.springfox + springfox-swagger2 + ${springfox.version} + + {{/springFoxDocumentationProvider}} + {{^springFoxDocumentationProvider}} + {{^springDocDocumentationProvider}} + {{#swagger1AnnotationLibrary}} io.swagger swagger-annotations -{{^parentOverridden}} - ${swagger-core-version} -{{/parentOverridden}} + ${swagger-annotations.version} + {{/swagger1AnnotationLibrary}} + {{#swagger2AnnotationLibrary}} + + io.swagger.core.v3 + swagger-annotations + ${swagger-annotations.version} + + {{/swagger2AnnotationLibrary}} + {{/springDocDocumentationProvider}} + {{/springFoxDocumentationProvider}} com.google.code.findbugs jsr305 + {{^parentOverridden}} 3.0.2 + {{/parentOverridden}} org.springframework.cloud @@ -64,6 +110,9 @@ org.springframework.cloud spring-cloud-starter-oauth2 + {{^parentOverridden}} + 2.2.5.RELEASE + {{/parentOverridden}} {{#withXml}} @@ -72,54 +121,45 @@ jackson-dataformat-xml {{/withXml}} - {{#java8}} com.fasterxml.jackson.datatype jackson-datatype-jsr310 - {{/java8}} {{#joda}} com.fasterxml.jackson.datatype jackson-datatype-joda {{/joda}} - {{#threetenbp}} + {{#openApiNullable}} - com.github.joschi.jackson - jackson-datatype-threetenbp + org.openapitools + jackson-databind-nullable {{^parentOverridden}} - 2.9.10 + 0.2.2 {{/parentOverridden}} - {{/threetenbp}} + {{/openApiNullable}} + {{#hateoas}} - org.openapitools - jackson-databind-nullable -{{^parentOverridden}} - 0.1.0 -{{/parentOverridden}} + org.springframework.boot + spring-boot-starter-hateoas + {{/hateoas}} + {{#useBeanValidation}} org.springframework.boot - spring-boot-starter-test - test + spring-boot-starter-validation -{{#hateoas}} - + {{/useBeanValidation}} - org.springframework.boot - spring-boot-starter-hateoas + org.springframework.data + spring-data-commons -{{/hateoas}} -{{#useBeanValidation}} - org.hibernate.validator - hibernate-validator - {{^parentOverridden}} - 6.0.16.Final - {{/parentOverridden}} + org.springframework.boot + spring-boot-starter-test + test -{{/useBeanValidation}} diff --git a/boat-scaffold/src/main/templates/boat-spring/libraries/spring-mvc/README.mustache b/boat-scaffold/src/main/templates/boat-spring/libraries/spring-mvc/README.mustache deleted file mode 100644 index d28df1b43..000000000 --- a/boat-scaffold/src/main/templates/boat-spring/libraries/spring-mvc/README.mustache +++ /dev/null @@ -1,14 +0,0 @@ -# OpenAPI generated server - -Spring MVC Server - - -## Overview -This server was generated by the [OpenAPI Generator](https://openapi-generator.tech) project. By using the [OpenAPI-Spec](https://openapis.org), you can easily generate a server stub. This is an example of building a OpenAPI-enabled server in Java using the Spring MVC framework. - -{{#useSpringfox}} -The underlying library integrating OpenAPI to Spring-MVC is [springfox](https://github.com/springfox/springfox) - -{{/useSpringfox}} -You can view the server in swagger-ui by pointing to -http://localhost:{{serverPort}}{{^contextPath}}/{{/contextPath}}{{#contextPath}}{{contextPath}}{{/contextPath}}/ \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/libraries/spring-mvc/RFC3339DateFormat.mustache b/boat-scaffold/src/main/templates/boat-spring/libraries/spring-mvc/RFC3339DateFormat.mustache deleted file mode 100644 index 597120b5b..000000000 --- a/boat-scaffold/src/main/templates/boat-spring/libraries/spring-mvc/RFC3339DateFormat.mustache +++ /dev/null @@ -1,22 +0,0 @@ -package {{configPackage}}; - -import com.fasterxml.jackson.databind.util.ISO8601DateFormat; -import com.fasterxml.jackson.databind.util.ISO8601Utils; - -import java.text.FieldPosition; -import java.util.Date; - - -public class RFC3339DateFormat extends ISO8601DateFormat { - - private static final long serialVersionUID = 1L; - - // Same as ISO8601DateFormat but serializing milliseconds. - @Override - public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) { - String value = ISO8601Utils.format(date, true); - toAppendTo.append(value); - return toAppendTo; - } - -} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/libraries/spring-mvc/application.mustache b/boat-scaffold/src/main/templates/boat-spring/libraries/spring-mvc/application.mustache deleted file mode 100644 index 67214287e..000000000 --- a/boat-scaffold/src/main/templates/boat-spring/libraries/spring-mvc/application.mustache +++ /dev/null @@ -1,3 +0,0 @@ -{{#useSpringfox}} -springfox.documentation.swagger.v2.path=/api-docs -{{/useSpringfox}} diff --git a/boat-scaffold/src/main/templates/boat-spring/libraries/spring-mvc/defaultBasePath.mustache b/boat-scaffold/src/main/templates/boat-spring/libraries/spring-mvc/defaultBasePath.mustache deleted file mode 100644 index 35ec3b9d7..000000000 --- a/boat-scaffold/src/main/templates/boat-spring/libraries/spring-mvc/defaultBasePath.mustache +++ /dev/null @@ -1 +0,0 @@ -/ \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/libraries/spring-mvc/openapiUiConfiguration.mustache b/boat-scaffold/src/main/templates/boat-spring/libraries/spring-mvc/openapiUiConfiguration.mustache deleted file mode 100644 index 0a65d96a8..000000000 --- a/boat-scaffold/src/main/templates/boat-spring/libraries/spring-mvc/openapiUiConfiguration.mustache +++ /dev/null @@ -1,116 +0,0 @@ -package {{configPackage}}; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; -{{#threetenbp}} -import com.fasterxml.jackson.datatype.threetenbp.ThreeTenModule; -{{/threetenbp}} -{{#openApiNullable}} -import org.openapitools.jackson.nullable.JsonNullableModule; -{{/openApiNullable}} -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.PropertySource; -{{#useSpringfox}} -import org.springframework.context.annotation.Import; -{{/useSpringfox}} -import org.springframework.context.annotation.Bean; -import org.springframework.http.converter.HttpMessageConverter; -import org.springframework.http.converter.StringHttpMessageConverter; -import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; -import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; -import org.springframework.web.servlet.config.annotation.EnableWebMvc; -import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; -{{#threetenbp}} -import org.threeten.bp.Instant; -import org.threeten.bp.OffsetDateTime; -import org.threeten.bp.ZonedDateTime; -{{/threetenbp}} - -import java.util.List; - -{{>generatedAnnotation}} -@Configuration -@ComponentScan(basePackages = {"{{apiPackage}}", "{{configPackage}}"}) -@EnableWebMvc -@PropertySource("classpath:application.properties") -{{#useSpringfox}} -@Import(OpenAPIDocumentationConfig.class) -{{/useSpringfox}} -public class OpenAPIUiConfiguration extends WebMvcConfigurerAdapter { - private static final String[] SERVLET_RESOURCE_LOCATIONS = { "/" }; - - private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { - "classpath:/META-INF/resources/", "classpath:/resources/", - "classpath:/static/", "classpath:/public/" }; - - private static final String[] RESOURCE_LOCATIONS; - static { - RESOURCE_LOCATIONS = new String[CLASSPATH_RESOURCE_LOCATIONS.length - + SERVLET_RESOURCE_LOCATIONS.length]; - System.arraycopy(SERVLET_RESOURCE_LOCATIONS, 0, RESOURCE_LOCATIONS, 0, - SERVLET_RESOURCE_LOCATIONS.length); - System.arraycopy(CLASSPATH_RESOURCE_LOCATIONS, 0, RESOURCE_LOCATIONS, - SERVLET_RESOURCE_LOCATIONS.length, CLASSPATH_RESOURCE_LOCATIONS.length); - } - - private static final String[] STATIC_INDEX_HTML_RESOURCES; - static { - STATIC_INDEX_HTML_RESOURCES = new String[RESOURCE_LOCATIONS.length]; - for (int i = 0; i < STATIC_INDEX_HTML_RESOURCES.length; i++) { - STATIC_INDEX_HTML_RESOURCES[i] = RESOURCE_LOCATIONS[i] + "index.html"; - } - } - - @Override - public void addResourceHandlers(ResourceHandlerRegistry registry) { - if (!registry.hasMappingForPattern("/webjars/**")) { - registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/"); - } - if (!registry.hasMappingForPattern("/**")) { - registry.addResourceHandler("/**").addResourceLocations(RESOURCE_LOCATIONS); - } - {{^useSpringfox}} - if (!registry.hasMappingForPattern("/swagger-ui/**")) { - registry.addResourceHandler("/swagger-ui/**").addResourceLocations("classpath:/META-INF/resources/webjars/swagger-ui/3.14.2/"); - } - {{/useSpringfox}} - } - - /*@Override - public void addCorsMappings(CorsRegistry registry) { - registry.addMapping("/**") - .allowedOrigins("*") - .allowedMethods("*") - .allowedHeaders("Content-Type"); - }*/ - - @Bean - public Jackson2ObjectMapperBuilder builder() { - {{#threetenbp}} - ThreeTenModule module = new ThreeTenModule(); - module.addDeserializer(Instant.class, CustomInstantDeserializer.INSTANT); - module.addDeserializer(OffsetDateTime.class, CustomInstantDeserializer.OFFSET_DATE_TIME); - module.addDeserializer(ZonedDateTime.class, CustomInstantDeserializer.ZONED_DATE_TIME); - {{/threetenbp}} - return new Jackson2ObjectMapperBuilder() - .indentOutput(true) - .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) - {{#openApiNullable}}.modulesToInstall({{#threetenbp}}module, {{/threetenbp}}new JsonNullableModule()){{/openApiNullable}} - {{^openApiNullable}}{{#threetenbp}}.modulesToInstall(module){{/threetenbp}}{{/openApiNullable}} - .dateFormat(new RFC3339DateFormat()); - } - - @Override - public void configureMessageConverters(List> converters) { - converters.add(new MappingJackson2HttpMessageConverter(objectMapper())); - converters.add(new StringHttpMessageConverter()); - super.configureMessageConverters(converters); - } - - @Bean - public ObjectMapper objectMapper(){ - return builder().build(); - } -} diff --git a/boat-scaffold/src/main/templates/boat-spring/libraries/spring-mvc/pom.mustache b/boat-scaffold/src/main/templates/boat-spring/libraries/spring-mvc/pom.mustache deleted file mode 100644 index c0abd27f2..000000000 --- a/boat-scaffold/src/main/templates/boat-spring/libraries/spring-mvc/pom.mustache +++ /dev/null @@ -1,271 +0,0 @@ - - 4.0.0 - {{groupId}} - {{artifactId}} - jar - {{artifactId}} - {{artifactVersion}} -{{#parentOverridden}} - - {{{parentGroupId}}} - {{{parentArtifactId}}} - {{{parentVersion}}} - -{{/parentOverridden}} - - src/main/java - - - org.apache.maven.plugins - maven-war-plugin - 3.1.0 - - - maven-failsafe-plugin - 2.6 - - - - integration-test - verify - - - - - - org.eclipse.jetty - jetty-maven-plugin - ${jetty-version} - - - {{^contextPath}}/{{/contextPath}}{{#contextPath}}{{contextPath}}{{/contextPath}} - - target/${project.artifactId}-${project.version} - 8079 - stopit - 10 - - {{serverPort}} - 60000 - - -{{#useBeanValidation}} - - - javax.validation - validation-api - ${beanvalidation-version} - - -{{/useBeanValidation}} - - - start-jetty - pre-integration-test - - start - - - 0 - true - - - - stop-jetty - post-integration-test - - stop - - - - - {{#apiFirst}} - - org.openapitools - openapi-generator-maven-plugin - {{{generatorVersion}}} - - - - generate - - - src/main/resources/openapi.yaml - spring - spring-mvc - {{{apiPackage}}} - {{{modelPackage}}} - false - {{#modelNamePrefix}} - {{{.}}} - {{/modelNamePrefix}} - {{#modelNameSuffix}} - {{{.}}} - {{/modelNameSuffix}} - - {{#configOptions}} - <{{left}}>{{right}} - {{/configOptions}} - - - - - - {{/apiFirst}} - - - - - org.slf4j - slf4j-log4j12 - ${slf4j-version} - - - - - org.springframework - spring-core - ${spring-version} - - - org.springframework - spring-webmvc - ${spring-version} - - - org.springframework - spring-web - ${spring-version} - - - javax.annotation - javax.annotation-api - 1.3.2 - - - javax.xml.bind - jaxb-api - 2.2.11 - - {{#useSpringfox}} - - - io.springfox - springfox-swagger2 - ${springfox-version} - - - com.fasterxml.jackson.core - jackson-annotations - - - - - io.springfox - springfox-swagger-ui - ${springfox-version} - - {{/useSpringfox}} - {{^useSpringfox}} - - org.webjars - swagger-ui - 3.14.2 - - - io.swagger - swagger-annotations - 1.5.14 - - - - com.google.code.findbugs - jsr305 - 3.0.2 - - - com.fasterxml.jackson.dataformat - jackson-dataformat-yaml - ${jackson-version} - - {{/useSpringfox}} - {{#withXml}} - - - com.fasterxml.jackson.dataformat - jackson-dataformat-xml - ${jackson-version} - - {{/withXml}} - {{#java8}} - - com.fasterxml.jackson.datatype - jackson-datatype-jsr310 - ${jackson-version} - - {{/java8}} - {{#joda}} - - com.fasterxml.jackson.datatype - jackson-datatype-joda - ${jackson-version} - - {{/joda}} - {{#threetenbp}} - - com.github.joschi.jackson - jackson-datatype-threetenbp - ${jackson-threetenbp-version} - - {{/threetenbp}} - - org.openapitools - jackson-databind-nullable - 0.1.0 - - - junit - junit - ${junit-version} - test - - - javax.servlet - servlet-api - ${servlet-api-version} - -{{#useBeanValidation}} - - - javax.validation - validation-api - ${beanvalidation-version} - provided - -{{/useBeanValidation}} -{{#hateoas}} - - - org.springframework.hateoas - spring-hateoas - 1.0.1.RELEASE - -{{/hateoas}} - - - {{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}} - ${java.version} - ${java.version} - 9.2.15.v20160210 - 1.7.21 - 4.13 - 2.5 - 2.8.0 - 2.9.9 - 2.8.4 -{{#useBeanValidation}} - 1.1.0.Final -{{/useBeanValidation}} - 4.3.20.RELEASE - - diff --git a/boat-scaffold/src/main/templates/boat-spring/libraries/spring-mvc/webApplication.mustache b/boat-scaffold/src/main/templates/boat-spring/libraries/spring-mvc/webApplication.mustache deleted file mode 100644 index 2b16399e9..000000000 --- a/boat-scaffold/src/main/templates/boat-spring/libraries/spring-mvc/webApplication.mustache +++ /dev/null @@ -1,22 +0,0 @@ -package {{configPackage}}; - -import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; - -{{>generatedAnnotation}} -public class WebApplication extends AbstractAnnotationConfigDispatcherServletInitializer { - - @Override - protected Class[] getRootConfigClasses() { - return new Class[] { OpenAPIUiConfiguration.class }; - } - - @Override - protected Class[] getServletConfigClasses() { - return new Class[] { WebMvcConfiguration.class }; - } - - @Override - protected String[] getServletMappings() { - return new String[] { "/" }; - } -} diff --git a/boat-scaffold/src/main/templates/boat-spring/libraries/spring-mvc/webMvcConfiguration.mustache b/boat-scaffold/src/main/templates/boat-spring/libraries/spring-mvc/webMvcConfiguration.mustache deleted file mode 100644 index d60c12631..000000000 --- a/boat-scaffold/src/main/templates/boat-spring/libraries/spring-mvc/webMvcConfiguration.mustache +++ /dev/null @@ -1,12 +0,0 @@ -package {{configPackage}}; - -import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; - -{{>generatedAnnotation}} -public class WebMvcConfiguration extends WebMvcConfigurationSupport { - @Override - public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { - configurer.enable(); - } -} diff --git a/boat-scaffold/src/main/templates/boat-spring/methodBody.mustache b/boat-scaffold/src/main/templates/boat-spring/methodBody.mustache index 1b1f6341e..a7ccd54c4 100644 --- a/boat-scaffold/src/main/templates/boat-spring/methodBody.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/methodBody.mustache @@ -1,32 +1,27 @@ {{^reactive}} {{#examples}} {{#-first}} - {{#jdk8}} {{#async}} return CompletableFuture.supplyAsync(()-> { {{/async}}getRequest().ifPresent(request -> { -{{#async}} {{/async}} {{/jdk8}}for (MediaType mediaType: MediaType.parseMediaTypes(request.getHeader("Accept"))) { +{{#async}} {{/async}} for (MediaType mediaType: MediaType.parseMediaTypes(request.getHeader("Accept"))) { {{/-first}} -{{#async}} {{/async}}{{^async}}{{#jdk8}} {{/jdk8}}{{/async}} if (mediaType.isCompatibleWith(MediaType.valueOf("{{{contentType}}}"))) { -{{#async}} {{/async}}{{^async}}{{#jdk8}} {{/jdk8}}{{/async}} String exampleString = {{>exampleString}}; -{{#async}} {{/async}}{{^async}}{{#jdk8}} {{/jdk8}}{{/async}} {{#useApiUtil}}ApiUtil.{{/useApiUtil}}setExampleResponse(request, "{{{contentType}}}", exampleString); -{{#async}} {{/async}}{{^async}}{{#jdk8}} {{/jdk8}}{{/async}} break; -{{#async}} {{/async}}{{^async}}{{#jdk8}} {{/jdk8}}{{/async}} } +{{#async}} {{/async}}{{^async}} {{/async}} if (mediaType.isCompatibleWith(MediaType.valueOf("{{{contentType}}}"))) { +{{#async}} {{/async}}{{^async}} {{/async}} String exampleString = {{>exampleString}}; +{{#async}} {{/async}}{{^async}} {{/async}} ApiUtil.setExampleResponse(request, "{{{contentType}}}", exampleString); +{{#async}} {{/async}}{{^async}} {{/async}} break; +{{#async}} {{/async}}{{^async}} {{/async}} } {{#-last}} -{{#async}} {{/async}}{{^async}}{{#jdk8}} {{/jdk8}}{{/async}} } - {{#jdk8}} +{{#async}} {{/async}}{{^async}} {{/async}} } {{#async}} {{/async}} }); - {{/jdk8}} {{#async}} {{/async}} return new ResponseEntity<>({{#returnSuccessCode}}HttpStatus.valueOf({{{statusCode}}}){{/returnSuccessCode}}{{^returnSuccessCode}}HttpStatus.NOT_IMPLEMENTED{{/returnSuccessCode}}); - {{#jdk8}} {{#async}} }, Runnable::run); {{/async}} - {{/jdk8}} {{/-last}} {{/examples}} {{^examples}} -return {{#jdk8}}{{#async}}CompletableFuture.completedFuture({{/async}}{{/jdk8}}new ResponseEntity<>({{#returnSuccessCode}}HttpStatus.OK{{/returnSuccessCode}}{{^returnSuccessCode}}HttpStatus.NOT_IMPLEMENTED{{/returnSuccessCode}}){{#jdk8}}{{#async}}){{/async}}{{/jdk8}}; +return {{#async}}CompletableFuture.completedFuture({{/async}}new ResponseEntity<>({{#returnSuccessCode}}HttpStatus.OK{{/returnSuccessCode}}{{^returnSuccessCode}}HttpStatus.NOT_IMPLEMENTED{{/returnSuccessCode}}){{#async}}){{/async}}; {{/examples}} {{/reactive}} {{#reactive}} @@ -38,7 +33,7 @@ Mono result = Mono.empty(); {{/-first}} if (mediaType.isCompatibleWith(MediaType.valueOf("{{{contentType}}}"))) { String exampleString = {{>exampleString}}; - result = {{#useApiUtil}}ApiUtil.{{/useApiUtil}}getExampleResponse(exchange, exampleString); + result = ApiUtil.getExampleResponse(exchange, mediaType, exampleString); break; } {{#-last}} @@ -48,5 +43,5 @@ Mono result = Mono.empty(); {{^examples}} exchange.getResponse().setStatusCode({{#returnSuccessCode}}HttpStatus.OK{{/returnSuccessCode}}{{^returnSuccessCode}}HttpStatus.NOT_IMPLEMENTED{{/returnSuccessCode}}); {{/examples}} - return result.then(Mono.empty()); + return result{{#allParams}}{{#isBodyParam}}{{^isArray}}{{#paramName}}.then({{.}}){{/paramName}}{{/isArray}}{{#isArray}}{{#paramName}}.thenMany({{.}}){{/paramName}}{{/isArray}}{{/isBodyParam}}{{/allParams}}.then(Mono.empty()); {{/reactive}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/model.mustache b/boat-scaffold/src/main/templates/boat-spring/model.mustache index 7f2a0f621..a30c2cc7b 100644 --- a/boat-scaffold/src/main/templates/boat-spring/model.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/model.mustache @@ -7,12 +7,14 @@ Boat Generator configuration: openApiNullable: {{openApiNullable}} useSetForUniqueItems: {{useSetForUniqueItems}} useWithModifiers: {{useWithModifiers}} + useJakartaEe: {{useJakartaEe}} + useSpringBoot3: {{useSpringBoot3}} */ package {{package}}; +import java.net.URI; import java.util.Objects; -{{#imports}} -import {{import}}; +{{#imports}}import {{import}}; {{/imports}} {{#openApiNullable}} import org.openapitools.jackson.nullable.JsonNullable; @@ -20,20 +22,38 @@ import org.openapitools.jackson.nullable.JsonNullable; {{#serializableModel}} import java.io.Serializable; {{/serializableModel}} +import java.time.OffsetDateTime; {{#useBeanValidation}} +{{#useJakartaEe}} +import jakarta.validation.Valid; +import jakarta.validation.constraints.*; +{{/useJakartaEe}} +{{^useJakartaEe}} import javax.validation.Valid; import javax.validation.constraints.*; +{{/useJakartaEe}} +{{/useBeanValidation}} +{{^useBeanValidation}} +{{#useJakartaEe}} +import jakarta.validation.constraints.NotNull; +{{/useJakartaEe}} +{{^useJakartaEe}} +import javax.validation.constraints.NotNull; +{{/useJakartaEe}} {{/useBeanValidation}} {{#performBeanValidation}} import org.hibernate.validator.constraints.*; {{/performBeanValidation}} {{#jackson}} -import com.fasterxml.jackson.annotation.*; {{#withXml}} import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; {{/withXml}} {{/jackson}} +{{#swagger2AnnotationLibrary}} +import io.swagger.v3.oas.annotations.media.Schema; +{{/swagger2AnnotationLibrary}} + {{#withXml}} import javax.xml.bind.annotation.*; {{/withXml}} @@ -42,8 +62,14 @@ import javax.xml.bind.annotation.*; import org.springframework.hateoas.RepresentationModel; {{/hateoas}} {{/parent}} -{{#vendorExtensions.x-extra-java-imports}} -{{{vendorExtensions.x-extra-java-imports}}}{{/vendorExtensions.x-extra-java-imports}} + +import java.util.*; +{{#useJakartaEe}} +import jakarta.annotation.Generated; +{{/useJakartaEe}} +{{^useJakartaEe}} +import javax.annotation.Generated; +{{/useJakartaEe}} {{#models}} {{#model}} @@ -51,7 +77,7 @@ import org.springframework.hateoas.RepresentationModel; {{>enumOuterClass}} {{/isEnum}} {{^isEnum}} -{{>pojo}} +{{#vendorExtensions.x-is-one-of-interface}}{{>oneof_interface}}{{/vendorExtensions.x-is-one-of-interface}}{{^vendorExtensions.x-is-one-of-interface}}{{>pojo}}{{/vendorExtensions.x-is-one-of-interface}} {{/isEnum}} {{/model}} -{{/models}} +{{/models}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/notFoundException.mustache b/boat-scaffold/src/main/templates/boat-spring/notFoundException.mustache index 40c25c5ea..11ad8c965 100644 --- a/boat-scaffold/src/main/templates/boat-spring/notFoundException.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/notFoundException.mustache @@ -1,5 +1,12 @@ package {{apiPackage}}; +{{#useJakartaEe}} +import jakarta.annotation.Generated; +{{/useJakartaEe}} +{{^useJakartaEe}} +import javax.annotation.Generated; +{{/useJakartaEe}} + {{>generatedAnnotation}} public class NotFoundException extends ApiException { private int code; @@ -7,4 +14,4 @@ public class NotFoundException extends ApiException { super(code, msg); this.code = code; } -} +} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/nullableDataType.mustache b/boat-scaffold/src/main/templates/boat-spring/nullableDataType.mustache index a389ae448..ba9bb9463 100644 --- a/boat-scaffold/src/main/templates/boat-spring/nullableDataType.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/nullableDataType.mustache @@ -1,11 +1 @@ -{{#openApiNullable}}{{! - }}{{#isNullable}}{{! - }}JsonNullable<{{>validatedDataTypeWithEnum}}>{{! - }}{{/isNullable}}{{! - }}{{^isNullable}}{{! - }}{{>validatedDataTypeWithEnum}}{{! - }}{{/isNullable}}{{! -}}{{/openApiNullable}}{{! -}}{{^openApiNullable}}{{! - }}{{>validatedDataTypeWithEnum}}{{! -}}{{/openApiNullable}} \ No newline at end of file +{{#openApiNullable}}{{#isNullable}}JsonNullable<{{{datatypeWithEnum}}}>{{/isNullable}}{{^isNullable}}{{{datatypeWithEnum}}}{{/isNullable}}{{/openApiNullable}}{{^openApiNullable}}{{{datatypeWithEnum}}}{{/openApiNullable}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/oneof_interface.mustache b/boat-scaffold/src/main/templates/boat-spring/oneof_interface.mustache new file mode 100644 index 000000000..679fe3d88 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-spring/oneof_interface.mustache @@ -0,0 +1,13 @@ +{{>additionalOneOfTypeAnnotations}} +{{#withXml}} +{{>xmlAnnotation}} +{{/withXml}} +{{#discriminator}} +{{>typeInfoAnnotation}} +{{/discriminator}} +{{>generatedAnnotation}} +public interface {{classname}}{{#vendorExtensions.x-implements}}{{#-first}} extends {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{/vendorExtensions.x-implements}} { + {{#discriminator}} + public {{propertyType}} {{propertyGetter}}(); + {{/discriminator}} +} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/openapiDocumentationConfig.mustache b/boat-scaffold/src/main/templates/boat-spring/openapiDocumentationConfig.mustache index 7dd911a1a..bae72f1cc 100644 --- a/boat-scaffold/src/main/templates/boat-spring/openapiDocumentationConfig.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/openapiDocumentationConfig.mustache @@ -18,7 +18,14 @@ import springfox.documentation.swagger2.annotations.EnableSwagger2; {{#useOptional}} import java.util.Optional; {{/useOptional}} +{{#useJakartaEe}} +import jakarta.annotation.Generated; +import jakarta.servlet.ServletContext; +{{/useJakartaEe}} +{{^useJakartaEe}} +import javax.annotation.Generated; import javax.servlet.ServletContext; +{{/useJakartaEe}} {{>generatedAnnotation}} @Configuration @@ -45,19 +52,13 @@ public class OpenAPIDocumentationConfig { .select() .apis(RequestHandlerSelectors.basePackage("{{apiPackage}}")) .build() - {{#java8}} .pathProvider(new BasePathAwareRelativePathProvider(servletContext, basePath)) .directModelSubstitute(java.time.LocalDate.class, java.sql.Date.class) .directModelSubstitute(java.time.OffsetDateTime.class, java.util.Date.class) - {{/java8}} {{#joda}} .directModelSubstitute(org.joda.time.LocalDate.class, java.sql.Date.class) .directModelSubstitute(org.joda.time.DateTime.class, java.util.Date.class) {{/joda}} - {{#threetenbp}} - .directModelSubstitute(org.threeten.bp.LocalDate.class, java.sql.Date.class) - .directModelSubstitute(org.threeten.bp.OffsetDateTime.class, java.util.Date.class) - {{/threetenbp}} {{#useOptional}} .genericModelSubstitutes(Optional.class) {{/useOptional}} @@ -85,4 +86,4 @@ public class OpenAPIDocumentationConfig { } } -} +} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/optionalDataType.mustache b/boat-scaffold/src/main/templates/boat-spring/optionalDataType.mustache index 2829720a2..84505f8fc 100644 --- a/boat-scaffold/src/main/templates/boat-spring/optionalDataType.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/optionalDataType.mustache @@ -1,11 +1 @@ -{{#useOptional}}{{! - }}{{#required}}{{! - }}{{>validatedDataType}}{{! - }}{{/required}}{{! - }}{{^required}}{{! - }}Optional<{{>validatedDataType}}>{{! - }}{{/required}}{{! -}}{{/useOptional}}{{! -}}{{^useOptional}}{{! - }}{{>validatedDataType}}{{! -}}{{/useOptional}} \ No newline at end of file +{{#useOptional}}{{#required}}{{{dataType}}}{{/required}}{{^required}}Optional<{{#useBeanValidation}}{{>beanValidationCore}}{{/useBeanValidation}}{{{dataType}}}>{{/required}}{{/useOptional}}{{^useOptional}}{{{dataType}}}{{/useOptional}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/paramDoc.mustache b/boat-scaffold/src/main/templates/boat-spring/paramDoc.mustache new file mode 100644 index 000000000..7c0c65eb1 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-spring/paramDoc.mustache @@ -0,0 +1 @@ +{{#swagger2AnnotationLibrary}}@Parameter(name = "{{{baseName}}}", description = "{{{description}}}"{{#required}}, required = true{{/required}}){{/swagger2AnnotationLibrary}}{{#swagger1AnnotationLibrary}}@ApiParam(value = "{{{description}}}"{{#required}}, required = true{{/required}}{{#allowableValues}}, {{> allowableValues }}{{/allowableValues}}{{#defaultValue}}, defaultValue = "{{{.}}}"{{/defaultValue}}){{/swagger1AnnotationLibrary}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/pathParams.mustache b/boat-scaffold/src/main/templates/boat-spring/pathParams.mustache index 67ebc0d30..16888518c 100644 --- a/boat-scaffold/src/main/templates/boat-spring/pathParams.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/pathParams.mustache @@ -1,4 +1 @@ -{{#isPathParam}} - @ApiParam(value = "{{{description}}}"{{#required}},required=true{{/required}}{{#allowableValues}}, allowableValues = "{{#enumVars}}{{#lambdaEscapeDoubleQuote}}{{{value}}}{{/lambdaEscapeDoubleQuote}}{{^-last}}, {{/-last}}{{#-last}}{{/-last}}{{/enumVars}}"{{/allowableValues}}{{^isContainer}}{{#defaultValue}}, defaultValue={{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}{{{defaultValue}}}{{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}{{/defaultValue}}{{/isContainer}}) - @PathVariable("{{baseName}}") - {{>optionalDataType}} {{paramName}}{{/isPathParam}} \ No newline at end of file +{{#isPathParam}}{{#useBeanValidation}}{{>beanValidationPathParams}}{{/useBeanValidation}}{{>paramDoc}} @PathVariable("{{baseName}}"){{>dateTimeParam}} {{>optionalDataType}} {{paramName}}{{/isPathParam}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/pojo.mustache b/boat-scaffold/src/main/templates/boat-spring/pojo.mustache index 63c5f882b..ac11144fe 100644 --- a/boat-scaffold/src/main/templates/boat-spring/pojo.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/pojo.mustache @@ -1,203 +1,295 @@ /** - * {{#description}}{{.}}{{/description}}{{^description}}{{classname}}{{/description}} - */{{#description}} -@ApiModel(description = "{{{description}}}"){{/description}} -{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}}{{>additionalModelTypeAnnotations}} + * {{description}}{{^description}}{{classname}}{{/description}} + */ +{{>additionalModelTypeAnnotations}} +{{#description}} +{{#swagger1AnnotationLibrary}} +@ApiModel(description = "{{{description}}}") +{{/swagger1AnnotationLibrary}} +{{#swagger2AnnotationLibrary}} +@Schema({{#name}}name = "{{name}}", {{/name}}description = "{{{description}}}") +{{/swagger2AnnotationLibrary}} +{{/description}} +{{#discriminator}} +{{>typeInfoAnnotation}} +{{/discriminator}} +{{#jackson}} +{{#isClassnameSanitized}} +@JsonTypeName("{{name}}") +{{/isClassnameSanitized}} +{{/jackson}} +{{#withXml}} +{{>xmlAnnotation}} +{{/withXml}} +{{>generatedAnnotation}} {{#useLombokAnnotations}} @lombok.EqualsAndHashCode(onlyExplicitlyIncluded = true, doNotUseGetters = true{{#parent}}, callSuper = true{{/parent}}) @lombok.ToString(onlyExplicitlyIncluded = true, doNotUseGetters = true{{#parent}}, callSuper = true{{/parent}}) {{/useLombokAnnotations}} -{{#vendorExtensions.x-extra-annotation}} -{{{vendorExtensions.x-extra-annotation}}}{{/vendorExtensions.x-extra-annotation}} -public {{#vendorExtensions.x-abstract}}abstract {{/vendorExtensions.x-abstract}}class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}}{{^parent}}{{#hateoas}}extends RepresentationModel<{{classname}}> {{/hateoas}}{{/parent}}{{#serializableModel}}implements Serializable{{/serializableModel}} -{{#serializableModel}}, {{/serializableModel}}{{^serializableModel}}{{/serializableModel}}{{#vendorExtensions.x-implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{#-last}} {{/-last}}{{/vendorExtensions.x-implements}} { +{{#vendorExtensions.x-class-extra-annotation}} +{{{vendorExtensions.x-class-extra-annotation}}} +{{/vendorExtensions.x-class-extra-annotation}} +public class {{classname}}{{#parent}} extends {{{parent}}}{{/parent}}{{^parent}}{{#hateoas}} extends RepresentationModel<{{classname}}> {{/hateoas}}{{/parent}}{{#vendorExtensions.x-implements}}{{#-first}} implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{/vendorExtensions.x-implements}} { {{#serializableModel}} - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; {{/serializableModel}} - {{#vars}} - {{#isEnum}} - {{^isContainer}} -{{>enumClass}} - {{/isContainer}} - {{#isContainer}} - {{#mostInnerItems}} + {{#vars}} + + {{#isEnum}} + {{^isContainer}} {{>enumClass}} - {{/mostInnerItems}} - {{/isContainer}} - {{/isEnum}} - {{#jackson}} - @JsonProperty("{{baseName}}") - {{#withXml}} - @JacksonXmlProperty({{#isXmlAttribute}}isAttribute = true, {{/isXmlAttribute}}{{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}localName = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") - {{/withXml}} - {{/jackson}} - {{#gson}} - @SerializedName("{{baseName}}") - {{/gson}} - {{#useLombokAnnotations}} - @lombok.Getter(onMethod_ = @ApiModelProperty({{#example}}example = "{{{example}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}{{#isReadOnly}}readOnly = {{{isReadOnly}}}, {{/isReadOnly}}value = "{{{description}}}")) - @lombok.Setter - @lombok.EqualsAndHashCode.Include - @lombok.ToString.Include - {{#vendorExtensions.x-extra-annotation}} - {{#indent4}}{{{vendorExtensions.x-extra-annotation}}}{{/indent4}}{{/vendorExtensions.x-extra-annotation}} - {{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} - {{/useLombokAnnotations}} + {{/isContainer}} {{#isContainer}} + {{#mostInnerItems}} +{{>enumClass}} + {{/mostInnerItems}} + {{/isContainer}} + {{/isEnum}} + {{#jackson}} + @JsonProperty("{{baseName}}") + {{#withXml}} + @JacksonXmlProperty({{#isXmlAttribute}}isAttribute = true, {{/isXmlAttribute}}{{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}localName = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/withXml}} + {{/jackson}} + {{#gson}} + @SerializedName("{{baseName}}") + {{/gson}} + {{#useLombokAnnotations}} + @lombok.Getter{{#swagger1AnnotationLibrary}}(onMethod_ = @ApiModelProperty({{#example}}example = "{{{example}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}{{#isReadOnly}}readOnly = {{{isReadOnly}}}, {{/isReadOnly}}value = "{{{description}}}")){{/swagger1AnnotationLibrary}} + @lombok.Setter + @lombok.EqualsAndHashCode.Include + @lombok.ToString.Include + {{#vendorExtensions.x-extra-annotation}} + {{#indent4}}{{{vendorExtensions.x-extra-annotation}}}{{/indent4}}{{/vendorExtensions.x-extra-annotation}} + {{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} + {{/useLombokAnnotations}} + {{#vendorExtensions.x-field-extra-annotation}} + {{{vendorExtensions.x-field-extra-annotation}}} + {{/vendorExtensions.x-field-extra-annotation}} + {{#isContainer}} + {{#openApiNullable}} + private {{>nullableDataType}} {{name}}{{#isNullable}} = JsonNullable.undefined(){{/isNullable}}{{^isNullable}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/isNullable}}; + {{/openApiNullable}} + {{^openApiNullable}} + private {{>nullableDataType}} {{name}} = {{#required}}{{{defaultValue}}}{{/required}}{{^required}}null{{/required}}; + {{/openApiNullable}} + {{/isContainer}} + {{^isContainer}} + {{#isDate}} + @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) + {{/isDate}} + {{#isDateTime}} + @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) + {{/isDateTime}} + {{#openApiNullable}} + private {{>nullableDataType}} {{name}}{{#isNullable}} = JsonNullable.undefined(){{/isNullable}}{{^isNullable}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/isNullable}}; + {{/openApiNullable}} + {{^openApiNullable}} + private {{>nullableDataType}} {{name}}{{#isNullable}} = null{{/isNullable}}{{^isNullable}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/isNullable}}; + {{/openApiNullable}} + {{/isContainer}} + {{/vars}} + {{#vars}} + + {{! begin feature: fluent setter methods }} + public {{classname}} {{#useWithModifiers}}with{{nameInCamelCase}}{{/useWithModifiers}}{{^useWithModifiers}}{{name}}{{/useWithModifiers}}({{{datatypeWithEnum}}} {{name}}) { {{#openApiNullable}} - {{modelFieldsVisibility}} {{>nullableDataType}} {{name}} = {{#isNullable}}JsonNullable.undefined(){{/isNullable}}{{^isNullable}}{{#required}}{{{defaultValue}}}{{/required}}{{^required}}null{{/required}}{{/isNullable}}; + this.{{name}} = {{#isNullable}}JsonNullable.of({{name}}){{/isNullable}}{{^isNullable}}{{name}}{{/isNullable}}; {{/openApiNullable}} {{^openApiNullable}} - {{modelFieldsVisibility}} {{>nullableDataType}} {{name}} = {{#required}}{{{defaultValue}}}{{/required}}{{^required}}null{{/required}}; + this.{{name}} = {{name}}; {{/openApiNullable}} - {{/isContainer}} - {{^isContainer}} - {{#isDate}} - @org.springframework.format.annotation.DateTimeFormat(iso = org.springframework.format.annotation.DateTimeFormat.ISO.DATE) - {{/isDate}} - {{#isDateTime}} - @org.springframework.format.annotation.DateTimeFormat(iso = org.springframework.format.annotation.DateTimeFormat.ISO.DATE_TIME) - {{/isDateTime}} + return this; + } + {{#isArray}} + + public {{classname}} add{{nameInCamelCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) { {{#openApiNullable}} - {{modelFieldsVisibility}} {{>nullableDataType}} {{name}}{{#isNullable}} = JsonNullable.undefined(){{/isNullable}}{{^isNullable}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/isNullable}}; + {{^required}} + if (this.{{name}} == null{{#isNullable}} || !this.{{name}}.isPresent(){{/isNullable}}) { + this.{{name}} = {{#isNullable}}JsonNullable.of({{{defaultValue}}}){{/isNullable}}{{^isNullable}}{{{defaultValue}}}{{/isNullable}}; + } + {{/required}} + this.{{name}}{{#isNullable}}.get(){{/isNullable}}.add({{name}}Item); {{/openApiNullable}} {{^openApiNullable}} - {{modelFieldsVisibility}} {{>nullableDataType}} {{name}}{{#isNullable}} = null{{/isNullable}}{{^isNullable}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/isNullable}}; + if (this.{{name}} == null) { + this.{{name}} = {{{defaultValue}}}; + } + this.{{name}}.add({{name}}Item); {{/openApiNullable}} - {{/isContainer}} + return this; + } + {{/isArray}} + {{#isMap}} - {{/vars}} - {{#vars}} - - public {{classname}} {{#useWithModifiers}}with{{nameInCamelCase}}{{/useWithModifiers}}{{^useWithModifiers}}{{name}}{{/useWithModifiers}}({{{datatypeWithEnum}}} {{name}}) { - {{#openApiNullable}} - this.{{name}} = {{#isNullable}}JsonNullable.of({{name}}){{/isNullable}}{{^isNullable}}{{name}}{{/isNullable}}; - {{/openApiNullable}} - {{^openApiNullable}} - this.{{name}} = {{name}}; - {{/openApiNullable}} - return this; - } - {{#isListContainer}} - - public {{classname}} add{{nameInCamelCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) { - {{#openApiNullable}} - {{^required}} - if (this.{{name}} == null{{#isNullable}} || !this.{{name}}.isPresent(){{/isNullable}}) { - this.{{name}} = {{#isNullable}}JsonNullable.of({{{defaultValue}}}){{/isNullable}}{{^isNullable}}{{{defaultValue}}}{{/isNullable}}; - } - {{/required}} - this.{{name}}{{#isNullable}}.get(){{/isNullable}}.add({{name}}Item); - {{/openApiNullable}} - {{^openApiNullable}} - if (this.{{name}} == null) { - this.{{name}} = {{{defaultValue}}}; - } - this.{{name}}.add({{name}}Item); - {{/openApiNullable}} - return this; - } - {{/isListContainer}} - {{#isMapContainer}} - - public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { - {{#openApiNullable}} - {{^required}} - if (this.{{name}} == null{{#isNullable}} || !this.{{name}}.isPresent(){{/isNullable}}) { - this.{{name}} = {{#isNullable}}JsonNullable.of({{{defaultValue}}}){{/isNullable}}{{^isNullable}}{{{defaultValue}}}{{/isNullable}}; - } - {{/required}} - this.{{name}}{{#isNullable}}.get(){{/isNullable}}.put(key, {{name}}Item); - {{/openApiNullable}} - {{^openApiNullable}} - if (this.{{name}} == null) { - this.{{name}} = {{{defaultValue}}}; - } - this.{{name}}.put(key, {{name}}Item); - {{/openApiNullable}} - return this; - } - {{/isMapContainer}} - - {{^useLombokAnnotations}} - /** - {{#description}} - * {{{description}}} - {{/description}} - {{^description}} - * Get {{name}} - {{/description}} - {{#minimum}} - * minimum: {{minimum}} - {{/minimum}} - {{#maximum}} - * maximum: {{maximum}} - {{/maximum}} - * @return {{name}} - */{{! - }}{{#vendorExtensions.x-extra-annotation}} - {{#indent4}}{{{vendorExtensions.x-extra-annotation}}}{{/indent4}}{{/vendorExtensions.x-extra-annotation}} - @ApiModelProperty({{#example}}example = "{{{example}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}{{#isReadOnly}}readOnly = {{{isReadOnly}}}, {{/isReadOnly}}value = "{{{description}}}") - {{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} - public {{>nullableDataType}} {{getter}}() { - return {{name}}; - } + {{#openApiNullable}} + {{#isNullable}} + public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { + {{^required}} + if (this.{{name}} == null) { + this.{{name}} = JsonNullable.of({{{defaultValue}}}); + } + {{/required}} + this.{{name}}.get().put(key, {{name}}Item); + return this; + } + {{/isNullable}} + {{^isNullable}} + public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { + {{^required}} - public void {{setter}}({{>nullableDataType}} {{name}}) { - this.{{name}} = {{name}}; - } - {{/useLombokAnnotations}} - - {{/vars}} - - {{#vendorExtensions.x-extra-java-code}} - {{#indent4}}{{{vendorExtensions.x-extra-java-code}}}{{/indent4}}{{/vendorExtensions.x-extra-java-code}} - - {{^useLombokAnnotations}} - @Override - public boolean equals(java.lang.Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - }{{#hasVars}} - {{classname}} {{classVarName}} = ({{classname}}) o; - return {{#vars}}Objects.equals(this.{{name}}, {{classVarName}}.{{name}}){{#hasMore}} && - {{/hasMore}}{{/vars}}{{#parent}} && - super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}} - return true;{{/hasVars}} - } + if (this.{{name}} == null) { + this.{{name}} = {{{defaultValue}}}; + } + {{/required}} + this.{{name}}.put(key, {{name}}Item); + return this; + } + {{/isNullable}} + {{/openApiNullable}} + {{^openApiNullable}} + public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { + {{^required}} + + if (this.{{name}} == null) { + this.{{name}} = {{{defaultValue}}}; + } + {{/required}} + this.{{name}}.put(key, {{name}}Item); + return this; + } + {{/openApiNullable}} +{{/isMap}} + {{! end feature: fluent setter methods }} + {{! begin feature: getter and setter }} + +{{^useLombokAnnotations}} + /** + {{#description}} + * {{{.}}} + {{/description}} + {{^description}} + * Get {{name}} + {{/description}} + {{#minimum}} + * minimum: {{.}} + {{/minimum}} + {{#maximum}} + * maximum: {{.}} + {{/maximum}} + * @return {{name}} + */ + {{#vendorExtensions.x-extra-annotation}} + {{{vendorExtensions.x-extra-annotation}}} + {{/vendorExtensions.x-extra-annotation}} + {{#useBeanValidation}} + {{>beanValidation}} + {{/useBeanValidation}} + {{^useBeanValidation}} + {{#required}}@NotNull{{/required}} + {{/useBeanValidation}} + {{#swagger2AnnotationLibrary}} + @Schema(name = "{{{baseName}}}"{{#isReadOnly}}, accessMode = Schema.AccessMode.READ_ONLY{{/isReadOnly}}{{#example}}, example = "{{{.}}}"{{/example}}{{#description}}, description = "{{{.}}}"{{/description}}, requiredMode = {{#required}}Schema.RequiredMode.REQUIRED{{/required}}{{^required}}Schema.RequiredMode.NOT_REQUIRED{{/required}}) + {{/swagger2AnnotationLibrary}} + {{#swagger1AnnotationLibrary}} + @ApiModelProperty({{#example}}example = "{{{.}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}{{#isReadOnly}}readOnly = {{{isReadOnly}}}, {{/isReadOnly}}value = "{{{description}}}") + {{/swagger1AnnotationLibrary}} + public {{>nullableDataType}} {{getter}}() { + return {{name}}; + } - @Override - public int hashCode() { - return Objects.hash( - {{#vars}}{{name}}{{#hasMore}}, - {{/hasMore}}{{/vars}}{{#parent}}{{#hasVars}}, - {{/hasVars}}super.hashCode(){{/parent}} - ); + {{#vendorExtensions.x-setter-extra-annotation}} + {{{vendorExtensions.x-setter-extra-annotation}}} + {{/vendorExtensions.x-setter-extra-annotation}} + public void {{setter}}({{>nullableDataType}} {{name}}) { + this.{{name}} = {{name}}; + } + {{/useLombokAnnotations}} + {{! end feature: getter and setter }} + {{/vars}} + {{#parentVars}} + + {{! begin feature: fluent setter methods for inherited properties }} + public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) { + super.{{setter}}({{name}}); + return this; + } + {{#isArray}} + + public {{classname}} add{{nameInCamelCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) { + super.add{{nameInCamelCase}}Item({{name}}Item); + return this; + } + {{/isArray}} + {{#isMap}} + + public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { + super.put{{nameInCamelCase}}Item(key, {{name}}Item); + return this; + } + {{/isMap}} + {{! end feature: fluent setter methods for inherited properties }} + {{/parentVars}} + +{{^useLombokAnnotations}} + @Override + public boolean equals(Object o) { + if (this == o) { + return true; } + if (o == null || getClass() != o.getClass()) { + return false; + }{{#hasVars}} + {{classname}} {{classVarName}} = ({{classname}}) o; + return {{#vars}}{{#vendorExtensions.x-is-jackson-optional-nullable}}equalsNullable(this.{{name}}, {{classVarName}}.{{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{#isByteArray}}Arrays{{/isByteArray}}{{^isByteArray}}Objects{{/isByteArray}}.equals(this.{{name}}, {{classVarName}}.{{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^-last}} && + {{/-last}}{{/vars}}{{#parent}} && + super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}} + return true;{{/hasVars}} + } + {{#vendorExtensions.x-jackson-optional-nullable-helpers}} - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("class {{classname}} {\n"); - {{#parent}}sb.append(" ").append(toIndentedString(super.toString())).append("\n");{{/parent}} - {{#vars}}sb.append(" {{name}}: ").append(toIndentedString({{name}})).append("\n"); - {{/vars}}sb.append("}"); - return sb.toString(); + private static boolean equalsNullable(JsonNullable a, JsonNullable b) { + return a == b || (a != null && b != null && a.isPresent() && b.isPresent() && Objects.deepEquals(a.get(), b.get())); + } + {{/vendorExtensions.x-jackson-optional-nullable-helpers}} + + @Override + public int hashCode() { + return Objects.hash({{#vars}}{{#vendorExtensions.x-is-jackson-optional-nullable}}hashCodeNullable({{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{^isByteArray}}{{name}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{/vendorExtensions.x-is-jackson-optional-nullable}}{{^-last}}, {{/-last}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}); + } + {{#vendorExtensions.x-jackson-optional-nullable-helpers}} + + private static int hashCodeNullable(JsonNullable a) { + if (a == null) { + return 1; } + return a.isPresent() ? Arrays.deepHashCode(new Object[]{a.get()}) : 31; + } + {{/vendorExtensions.x-jackson-optional-nullable-helpers}} + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class {{classname}} {\n"); + {{#parent}} + sb.append(" ").append(toIndentedString(super.toString())).append("\n"); + {{/parent}} + {{#vars}}sb.append(" {{name}}: ").append(toIndentedString({{name}})).append("\n"); + {{/vars}}sb.append("}"); + return sb.toString(); + } - /** - * Convert the given object to string with each line indented by 4 spaces - * (except the first line). - */ - private String toIndentedString(java.lang.Object o) { - if (o == null) { - return "null"; - } - return o.toString().replace("\n", "\n "); + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; } - {{/useLombokAnnotations}} -} + return o.toString().replace("\n", "\n "); + } + {{/useLombokAnnotations}} +} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/queryParams.mustache b/boat-scaffold/src/main/templates/boat-spring/queryParams.mustache index f79b740b8..6b78fb343 100644 --- a/boat-scaffold/src/main/templates/boat-spring/queryParams.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/queryParams.mustache @@ -1,8 +1 @@ -{{#isQueryParam}} - @ApiParam(value = "{{{description}}}"{{#required}}, required = true{{/required}}{{#allowableValues}}, allowableValues = "{{#values}}{{{.}}}{{^-last}}, {{/-last}}{{#-last}}{{/-last}}{{/values}}"{{/allowableValues}}{{^isContainer}}{{#defaultValue}}, defaultValue = {{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}{{{defaultValue}}}{{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}{{/defaultValue}}{{/isContainer}}) {{#useBeanValidation}}@Valid{{/useBeanValidation}}{{^isModel}} - @RequestParam(value = {{#isMapContainer}}""{{/isMapContainer}}{{^isMapContainer}}"{{baseName}}"{{/isMapContainer}}{{#required}}, required = true{{/required}}{{^required}}, required = false{{/required}}{{^isContainer}}{{#defaultValue}}, defaultValue={{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}{{{defaultValue}}}{{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}{{/defaultValue}}{{/isContainer}}){{/isModel}}{{#isDate}} - @org.springframework.format.annotation.DateTimeFormat(iso = org.springframework.format.annotation.DateTimeFormat.ISO.DATE){{/isDate}}{{#isDateTime}} - @org.springframework.format.annotation.DateTimeFormat(iso = org.springframework.format.annotation.DateTimeFormat.ISO.DATE_TIME){{/isDateTime}} - {{#useBeanValidation}}{{#required}}@NotNull - {{/required}}{{/useBeanValidation}} - {{>optionalDataType}} {{paramName}}{{/isQueryParam}} \ No newline at end of file +{{#isQueryParam}}{{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}}{{>paramDoc}}{{#useBeanValidation}} @Valid{{/useBeanValidation}}{{^isModel}} @RequestParam(value = {{#isMap}}""{{/isMap}}{{^isMap}}"{{baseName}}"{{/isMap}}{{#required}}, required = true{{/required}}{{^required}}, required = false{{/required}}{{#defaultValue}}, defaultValue = "{{{.}}}"{{/defaultValue}}){{/isModel}}{{>dateTimeParam}} {{>optionalDataType}} {{paramName}}{{/isQueryParam}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/returnTypes.mustache b/boat-scaffold/src/main/templates/boat-spring/returnTypes.mustache index bd6283296..0d2b380d7 100644 --- a/boat-scaffold/src/main/templates/boat-spring/returnTypes.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/returnTypes.mustache @@ -1 +1 @@ -{{#isMapContainer}}Map{{/isMapContainer}}{{#isListContainer}}{{#reactive}}Flux{{/reactive}}{{^reactive}}List{{/reactive}}<{{{returnType}}}>{{/isListContainer}}{{^returnContainer}}{{{returnType}}}{{/returnContainer}} \ No newline at end of file +{{#isMap}}Map{{/isMap}}{{#isArray}}{{#reactive}}Flux{{/reactive}}{{^reactive}}{{{returnContainer}}}{{/reactive}}<{{{returnType}}}>{{/isArray}}{{^returnContainer}}{{{returnType}}}{{/returnContainer}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/springdocDocumentationConfig.mustache b/boat-scaffold/src/main/templates/boat-spring/springdocDocumentationConfig.mustache new file mode 100644 index 000000000..467d92155 --- /dev/null +++ b/boat-scaffold/src/main/templates/boat-spring/springdocDocumentationConfig.mustache @@ -0,0 +1,54 @@ +package {{configPackage}}; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.info.Contact; +import io.swagger.v3.oas.models.info.License; +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.security.SecurityScheme; + +@Configuration +public class SpringDocConfiguration { + + @Bean + OpenAPI apiInfo() { + return new OpenAPI() + .info( + new Info(){{#appName}} + .title("{{appName}}"){{/appName}} + .description("{{{appDescription}}}"){{#termsOfService}} + .termsOfService("{{termsOfService}}"){{/termsOfService}}{{#openAPI}}{{#info}}{{#contact}} + .contact( + new Contact(){{#infoName}} + .name("{{infoName}}"){{/infoName}}{{#infoUrl}} + .url("{{infoUrl}}"){{/infoUrl}}{{#infoEmail}} + .email("{{infoEmail}}"){{/infoEmail}} + ){{/contact}}{{#license}} + .license( + new License() + {{#licenseInfo}}.name("{{licenseInfo}}") + {{/licenseInfo}}{{#licenseUrl}}.url("{{licenseUrl}}") + {{/licenseUrl}} + ){{/license}}{{/info}}{{/openAPI}} + .version("{{appVersion}}") + ){{#hasAuthMethods}} + .components( + new Components(){{#authMethods}} + .addSecuritySchemes("{{name}}", new SecurityScheme(){{#isBasic}} + .type(SecurityScheme.Type.HTTP) + .scheme("{{scheme}}"){{#bearerFormat}} + .bearerFormat("{{bearerFormat}}"){{/bearerFormat}}{{/isBasic}}{{#isApiKey}} + .type(SecurityScheme.Type.APIKEY){{#isKeyInHeader}} + .in(SecurityScheme.In.HEADER){{/isKeyInHeader}}{{#isKeyInQuery}} + .in(SecurityScheme.In.QUERY){{/isKeyInQuery}}{{#isKeyInCookie}} + .in(SecurityScheme.In.COOKIE){{/isKeyInCookie}} + .name("{{keyParamName}}"){{/isApiKey}}{{#isOAuth}} + .type(SecurityScheme.Type.OAUTH2){{/isOAuth}} + ){{/authMethods}} + ){{/hasAuthMethods}} + ; + } +} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/typeInfoAnnotation.mustache b/boat-scaffold/src/main/templates/boat-spring/typeInfoAnnotation.mustache index 81c2ba05f..c2b7f0c89 100644 --- a/boat-scaffold/src/main/templates/boat-spring/typeInfoAnnotation.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/typeInfoAnnotation.mustache @@ -1,8 +1,21 @@ {{#jackson}} - -@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "{{{discriminator.propertyBaseName}}}", visible = true) +{{#discriminator.mappedModels}} +{{#-first}} +@JsonIgnoreProperties( + value = "{{{discriminator.propertyBaseName}}}", // ignore manually set {{{discriminator.propertyBaseName}}}, it will be automatically generated by Jackson during serialization + allowSetters = true // allows the {{{discriminator.propertyBaseName}}} to be set during deserialization +) +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "{{{discriminator.propertyBaseName}}}", visible = true) @JsonSubTypes({ - {{#discriminator.mappedModels}} - @JsonSubTypes.Type(value = {{modelName}}.class, name = "{{^vendorExtensions.x-discriminator-value}}{{mappingName}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}"), - {{/discriminator.mappedModels}} -}){{/jackson}} +{{/-first}} + {{^vendorExtensions.x-discriminator-value}} + @JsonSubTypes.Type(value = {{modelName}}.class, name = "{{{mappingName}}}"){{^-last}},{{/-last}} + {{/vendorExtensions.x-discriminator-value}} + {{#vendorExtensions.x-discriminator-value}} + @JsonSubTypes.Type(value = {{modelName}}.class, name = "{{{vendorExtensions.x-discriminator-value}}}"){{^-last}},{{/-last}} + {{/vendorExtensions.x-discriminator-value}} +{{#-last}} +}) +{{/-last}} +{{/discriminator.mappedModels}} +{{/jackson}} \ No newline at end of file diff --git a/boat-scaffold/src/main/templates/boat-spring/xmlAnnotation.mustache b/boat-scaffold/src/main/templates/boat-spring/xmlAnnotation.mustache index fd81a4cf5..a9e6fb0fa 100644 --- a/boat-scaffold/src/main/templates/boat-spring/xmlAnnotation.mustache +++ b/boat-scaffold/src/main/templates/boat-spring/xmlAnnotation.mustache @@ -1,6 +1,7 @@ {{#withXml}} {{#jackson}} -@JacksonXmlRootElement({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}localName = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{classname}}{{/xmlName}}") +@JacksonXmlRootElement({{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}localName = "{{xmlName}}{{^xmlName}}{{classname}}{{/xmlName}}") {{/jackson}} -@XmlRootElement({{#xmlNamespace}}namespace="{{xmlNamespace}}", {{/xmlNamespace}}name = "{{#xmlName}}{{xmlName}}{{/xmlName}}{{^xmlName}}{{classname}}{{/xmlName}}") -@XmlAccessorType(XmlAccessType.FIELD){{/withXml}} \ No newline at end of file +@XmlRootElement({{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}name = "{{xmlName}}{{^xmlName}}{{classname}}{{/xmlName}}") +@XmlAccessorType(XmlAccessType.FIELD) +{{/withXml}} \ No newline at end of file diff --git a/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatJavaCodeGenTests.java b/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatJavaCodeGenTests.java index 80e4d762e..6ba055b81 100644 --- a/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatJavaCodeGenTests.java +++ b/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatJavaCodeGenTests.java @@ -1,13 +1,18 @@ package com.backbase.oss.codegen.java; import static com.backbase.oss.codegen.java.BoatJavaCodeGen.*; + import java.util.Map; + import static java.util.stream.Collectors.groupingBy; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.hasEntry; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.openapitools.codegen.CliOption; import org.openapitools.codegen.CodegenModel; @@ -116,6 +121,7 @@ void processOptsUseProtectedFields() { } @Test + @Disabled("Since useSetForUniqueItems is not supported and it is enabled by default") void uniquePropertyToSet() { final BoatJavaCodeGen gen = new BoatJavaCodeGen(); final CodegenProperty prop = new CodegenProperty(); @@ -136,6 +142,7 @@ void uniquePropertyToSet() { } @Test + @Disabled("Since useSetForUniqueItems is not supported and it is enabled by default") void uniqueParameterToSet() { final BoatJavaCodeGen gen = new BoatJavaCodeGen(); final CodegenParameter param = new CodegenParameter(); @@ -154,4 +161,71 @@ void uniqueParameterToSet() { assertThat(param.dataType, is("java.util.Set")); } + @Test + void setTypeMappingForList() { + final BoatJavaCodeGen gen = new BoatJavaCodeGen(); + gen.setFullJavaUtil(false); + gen.instantiationTypes().put("set", "ArrayList"); + gen.typeMapping().put("set", "List"); + + final CodegenProperty prop = new CodegenProperty(); + prop.isContainer = true; + prop.containerType = "set"; + prop.setUniqueItems(true); + prop.items = new CodegenProperty(); + prop.items.dataType = "String"; + prop.baseType = "java.util.Set"; + prop.dataType = "java.util.HashSet"; + + final var model = new CodegenModel(); + + gen.postProcessModelProperty(model, prop); + + assertTrue(model.getImports().contains("ArrayList")); + } + + @Test + void arrayTypeMappingForList() { + final BoatJavaCodeGen gen = new BoatJavaCodeGen(); + gen.setFullJavaUtil(false); + gen.instantiationTypes().put("array", "ArrayList"); + gen.typeMapping().put("array", "List"); + + final CodegenProperty prop = new CodegenProperty(); + prop.isContainer = true; + prop.containerType = "array"; + prop.setUniqueItems(true); + prop.items = new CodegenProperty(); + prop.items.dataType = "String"; + prop.baseType = "java.util.Set"; + prop.dataType = "java.util.HashSet"; + + final var model = new CodegenModel(); + + gen.postProcessModelProperty(model, prop); + + assertTrue(model.getImports().contains("ArrayList")); + } + + @Test + void mapTypeMappingForMap() { + final BoatJavaCodeGen gen = new BoatJavaCodeGen(); + gen.setFullJavaUtil(false); + gen.instantiationTypes().put("map", "TreeMap"); + + final CodegenProperty prop = new CodegenProperty(); + prop.isContainer = true; + prop.containerType = "map"; + prop.setUniqueItems(true); + prop.items = new CodegenProperty(); + prop.items.dataType = "String"; + prop.baseType = "java.util.Set"; + prop.dataType = "java.util.HashSet"; + + final var model = new CodegenModel(); + + gen.postProcessModelProperty(model, prop); + + assertTrue(model.getImports().contains("TreeMap")); + } } diff --git a/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatSpringCodeGenTests.java b/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatSpringCodeGenTests.java index 105234f1c..61b0d9d5b 100644 --- a/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatSpringCodeGenTests.java +++ b/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatSpringCodeGenTests.java @@ -3,21 +3,26 @@ import static com.backbase.oss.codegen.java.BoatSpringCodeGen.USE_PROTECTED_FIELDS; import static java.util.stream.Collectors.groupingBy; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasEntry; import static org.hamcrest.Matchers.is; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import com.backbase.oss.codegen.java.BoatSpringCodeGen.NewLineIndent; import com.samskivert.mustache.Template.Fragment; +import io.swagger.v3.oas.models.Operation; import java.io.IOException; import java.io.StringWriter; +import java.util.Arrays; import java.util.Map; import org.junit.jupiter.api.Test; import org.openapitools.codegen.CliOption; import org.openapitools.codegen.CodegenModel; +import org.openapitools.codegen.CodegenOperation; import org.openapitools.codegen.CodegenParameter; import org.openapitools.codegen.CodegenProperty; @@ -97,4 +102,14 @@ void newLineIndent() throws IOException { assertThat(output.toString(), equalTo(String.format("__%n__Good%n__ morning,%n__ Dave%n"))); } + + @Test + void addServletRequestTestFromOperation(){ + final BoatSpringCodeGen gen = new BoatSpringCodeGen(); + gen.addServletRequest = true; + CodegenOperation co = gen.fromOperation("/test", "POST", new Operation(), null); + assertEquals(1, co.allParams.size()); + assertEquals("httpServletRequest", co.allParams.get(0).paramName); + assertTrue(Arrays.stream(co.allParams.get(0).getClass().getDeclaredFields()).anyMatch(f -> "isHttpServletRequest".equals(f.getName()))); + } } diff --git a/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatSpringTemplatesTests.java b/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatSpringTemplatesTests.java index 18196919b..bfae5a0cd 100644 --- a/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatSpringTemplatesTests.java +++ b/boat-scaffold/src/test/java/com/backbase/oss/codegen/java/BoatSpringTemplatesTests.java @@ -30,6 +30,7 @@ import java.util.stream.Stream; import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FileUtils; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DynamicNode; @@ -58,9 +59,10 @@ * created dynamically. *

*/ +@Slf4j class BoatSpringTemplatesTests { static final String PROP_BASE = BoatSpringTemplatesTests.class.getSimpleName() + "."; - static final boolean PROP_FAST = Boolean.valueOf(System.getProperty(PROP_BASE + "fast", "true")); + static final boolean PROP_FAST = Boolean.parseBoolean(System.getProperty(PROP_BASE + "fast", "true")); static final String TEST_OUTPUT = System.getProperty(PROP_BASE + "output", "target/boat-spring-templates-tests"); @BeforeAll @@ -92,7 +94,7 @@ static class Combination { ? "boat" : IntStream.range(0, CASES.size()) .filter(n -> (mask & (1 << n)) != 0) - .mapToObj(n -> CASES.get(n)) + .mapToObj(CASES::get) .collect(joining("-", "boat-", "")); this.useBeanValidation = (mask & 1 << CASES.indexOf("val")) != 0; @@ -125,9 +127,11 @@ static Stream combinations(boolean minimal) { } if (minimal) { - cases.add(-1 & ~(1 << CASES.indexOf("flx"))); - cases.add(-1 & ~(1 << CASES.indexOf("utl"))); - cases.add(-1); + cases.add(~(1 << CASES.indexOf("flx"))); + //everything except flx & utl (because req & flx together is incorrect + cases.add(-514); + //everything except req + cases.add(~(1 << CASES.indexOf("req"))); } return cases.stream().map(Combination::new); @@ -225,9 +229,9 @@ void openApiNullable() { @Check void useSetForUniqueItems() { - assertThat(findPattern("/api/.+\\.java$", "(java\\.util\\.)?Set<.+>"), + assertThat(findPattern("/api/.+\\.java$", "java\\.util\\.Set<.+>"), equalTo(this.param.useSetForUniqueItems)); - assertThat(findPattern("/model/.+\\.java$", "(java\\.util\\.)?Set<.+>"), + assertThat(findPattern("/model/.+\\.java$", "java\\.util\\.Set<.+>"), equalTo(this.param.useSetForUniqueItems)); } @@ -241,6 +245,7 @@ void useWithModifiers() { private boolean findPattern(String filePattern, String linePattern) { final Predicate fileMatch = Pattern.compile(filePattern).asPredicate(); + log.info("Files: {}", files); final List selection = this.files.stream() .map(File::getPath) .map(path -> path.replace(File.separatorChar, '/')) @@ -251,9 +256,7 @@ private boolean findPattern(String filePattern, String linePattern) { final Predicate lineMatch = Pattern.compile(linePattern).asPredicate(); return selection.stream() - .filter(file -> contentMatches(file, lineMatch)) - .findAny() - .isPresent(); + .anyMatch(file -> contentMatches(file, lineMatch)); } @SneakyThrows @@ -278,11 +281,12 @@ private List generateFrom(String templates, String combination) { GlobalSettings.setProperty(CodegenConstants.MODEL_TESTS, "true"); GlobalSettings.setProperty(CodegenConstants.MODEL_DOCS, "true"); - if (this.param.apiUtil) { - GlobalSettings.setProperty(CodegenConstants.SUPPORTING_FILES, "ApiUtil.java,pom.xml"); - } else { - GlobalSettings.setProperty(CodegenConstants.SUPPORTING_FILES, "pom.xml"); - } +// if (this.param.apiUtil) { + GlobalSettings.setProperty(CodegenConstants.SUPPORTING_FILES, "ApiUtil.java,pom.xml,OpenApiGeneratorApplication.java"); +// } else { +// GlobalSettings.setProperty(CodegenConstants.SUPPORTING_FILES, "pom.xml"); +// } + gcf.setApiNameSuffix("-api"); gcf.setModelNameSuffix(this.param.name); diff --git a/boat-scaffold/src/test/java/com/backbase/oss/codegen/lint/BoatLintTests.java b/boat-scaffold/src/test/java/com/backbase/oss/codegen/lint/BoatLintTests.java index c5f0f0f3d..29843c087 100644 --- a/boat-scaffold/src/test/java/com/backbase/oss/codegen/lint/BoatLintTests.java +++ b/boat-scaffold/src/test/java/com/backbase/oss/codegen/lint/BoatLintTests.java @@ -1,6 +1,9 @@ package com.backbase.oss.codegen.lint; -import com.backbase.oss.boat.loader.OpenAPILoaderException; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + import java.io.File; import java.io.IOException; import java.net.URL; @@ -8,7 +11,6 @@ import java.nio.file.Paths; import java.util.Arrays; import org.jetbrains.annotations.NotNull; -import static org.junit.jupiter.api.Assertions.*; import org.junit.jupiter.api.Test; class BoatLintTests { diff --git a/boat-scaffold/src/test/java/com/backbase/oss/codegen/marina/BoatMarinaTest.java b/boat-scaffold/src/test/java/com/backbase/oss/codegen/marina/BoatMarinaTest.java index 0d15d2394..810c2006c 100644 --- a/boat-scaffold/src/test/java/com/backbase/oss/codegen/marina/BoatMarinaTest.java +++ b/boat-scaffold/src/test/java/com/backbase/oss/codegen/marina/BoatMarinaTest.java @@ -44,18 +44,14 @@ void testGenerateDocs() throws IOException { assertTrue(generated.contains("Simple API overview")); assertTrue(generated.contains("appDescription: \"No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)\",")); assertTrue(generated.contains("data.examples[\"BadRequestError\"]")); - } - - protected File getFile(String name) { URL resource = getClass().getResource(name); assert resource != null; return new File(resource.getFile()); } - private static void generateDocs(File spec) throws IOException { log.info("Generate docs for: {}", spec); OpenAPI openAPI = null; @@ -73,9 +69,6 @@ private static void generateDocs(File spec) throws IOException { File output = new File(codegenConfig.getOutputDir()); output.mkdirs(); -// log.info("Clearing output: {}, {}", output); - - ClientOptInput input = new ClientOptInput(); input.config(codegenConfig); input.openAPI(openAPI); diff --git a/boat-scaffold/src/test/java/com/backbase/oss/codegen/yard/BoatYardTests.java b/boat-scaffold/src/test/java/com/backbase/oss/codegen/yard/BoatYardTests.java index 104485068..1970e42f4 100644 --- a/boat-scaffold/src/test/java/com/backbase/oss/codegen/yard/BoatYardTests.java +++ b/boat-scaffold/src/test/java/com/backbase/oss/codegen/yard/BoatYardTests.java @@ -6,6 +6,7 @@ import java.nio.file.Files; import java.nio.file.Paths; import java.util.Arrays; + import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertArrayEquals; @@ -20,17 +21,14 @@ void testBoatYard() throws IOException { File output = new File("target/boat-yard"); File specsBaseDir = new File("src/test/resources"); - BoatYardConfig config = new BoatYardConfig(); config.setInputSpec(input.getAbsolutePath()); config.setOutputDir(output.getAbsolutePath()); config.setSpecsBaseDir(specsBaseDir); - config.setTemplateDir("boat-yard"); new BoatYardGenerator(config).generate(); - String[] actualDirectorySorted = output.list(); Arrays.sort(actualDirectorySorted); String[] expectedDirectory = {"backbase-logo.svg", "boat-quay", "boat-wharf", "css", "index.html", "js"}; diff --git a/boat-scaffold/src/test/resources/boat-spring/schemas/simple-pojo.yaml b/boat-scaffold/src/test/resources/boat-spring/schemas/simple-pojo.yaml index 96f61f196..7be3968ce 100644 --- a/boat-scaffold/src/test/resources/boat-spring/schemas/simple-pojo.yaml +++ b/boat-scaffold/src/test/resources/boat-spring/schemas/simple-pojo.yaml @@ -3,9 +3,6 @@ allOf: - $ref: additional-properties.yaml x-implements: - Cloneable -x-extra-annotation: | - @javax.persistence.Entity - @javax.persistence.Table(name="pojo") properties: pEnum1: $ref: '../components.yaml#/Enum1' @@ -23,19 +20,12 @@ properties: maximum: 10 exclusiveMaximum: true pDate: - x-extra-annotation: '@javax.persistence.Column(name="date") @javax.persistence.Access(javax.persistence.AccessType.PROPERTY)' type: string format: date pDateTime: - x-extra-annotation: | - @javax.persistence.Column(name="date_time") - @javax.persistence.Access(javax.persistence.AccessType.PROPERTY) type: string format: date-time pString: - x-extra-annotation: > - @javax.persistence.Column(name="value") - @javax.persistence.Access(javax.persistence.AccessType.PROPERTY) type: string minLength: 1 maxLength: 36 diff --git a/boat-scaffold/src/test/resources/logback.xml b/boat-scaffold/src/test/resources/logback.xml deleted file mode 100644 index c39bccbe8..000000000 --- a/boat-scaffold/src/test/resources/logback.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - %highlight([%level]) [%logger{10}] %msg%n - - - - - - - - - \ No newline at end of file diff --git a/boat-scaffold/src/test/resources/oas-examples/petstore.yaml b/boat-scaffold/src/test/resources/oas-examples/petstore.yaml index acdeb1fd9..c14df2c1d 100644 --- a/boat-scaffold/src/test/resources/oas-examples/petstore.yaml +++ b/boat-scaffold/src/test/resources/oas-examples/petstore.yaml @@ -33,6 +33,9 @@ paths: application/json: schema: $ref: "#/components/schemas/Pets" + application/xml: + schema: + $ref: "#/components/schemas/Pets" default: description: unexpected error content: diff --git a/boat-terminal/.gitignore b/boat-terminal/.gitignore deleted file mode 100644 index d53f008fa..000000000 --- a/boat-terminal/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/dependency-reduced-pom.xml -/src/test/resources/raml-examples/converted diff --git a/boat-terminal/pom.xml b/boat-terminal/pom.xml deleted file mode 100644 index 04745701b..000000000 --- a/boat-terminal/pom.xml +++ /dev/null @@ -1,124 +0,0 @@ - - - 4.0.0 - - - com.backbase.oss - backbase-openapi-tools - 0.16.12-SNAPSHOT - - - boat-terminal - - BOAT :: Terminal - - - ${basedir}/../${aggregate.report.dir} - - - - - info.picocli - picocli - - - - ch.qos.logback - logback-classic - - - - org.projectlombok - lombok - - - - com.backbase.oss - boat-scaffold - ${project.version} - - - commons-cli - commons-cli - - - - - - com.backbase.oss - boat-engine - ${project.version} - - - - javax.mail - mailapi - - - - - - org.hamcrest - hamcrest-core - test - - - - - org.junit.jupiter - junit-jupiter - test - - - - - - - org.apache.maven.plugins - maven-jar-plugin - - - - true - com.backbase.oss.boat.BoatTerminal - true - true - - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.4.1 - - - package - - shade - - - - - - *:* - - **/module-info.class - - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - 8 - 8 - - - - - \ No newline at end of file diff --git a/boat-terminal/src/main/java/com/backbase/oss/boat/BoatTerminal.java b/boat-terminal/src/main/java/com/backbase/oss/boat/BoatTerminal.java deleted file mode 100644 index 10d94b1c0..000000000 --- a/boat-terminal/src/main/java/com/backbase/oss/boat/BoatTerminal.java +++ /dev/null @@ -1,168 +0,0 @@ -package com.backbase.oss.boat; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import com.backbase.oss.boat.BoatTerminal.VersionProvider; -import com.backbase.oss.boat.serializer.SerializerUtils; -import com.backbase.oss.boat.transformers.OpenAPIExtractor; -import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.ObjectWriter; -import io.swagger.v3.oas.models.OpenAPI; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import lombok.extern.slf4j.Slf4j; -import static org.slf4j.Logger.ROOT_LOGGER_NAME; -import org.slf4j.LoggerFactory; -import picocli.AutoComplete.GenerateCompletion; -import picocli.CommandLine; -import picocli.CommandLine.ArgGroup; -import picocli.CommandLine.Command; -import picocli.CommandLine.Help.Visibility; -import picocli.CommandLine.IVersionProvider; -import picocli.CommandLine.Option; -import picocli.CommandLine.Parameters; - -@Command( - name = "boat-terminal", - description = "Boat Terminal", - versionProvider = VersionProvider.class, - usageHelpAutoWidth = true, - mixinStandardHelpOptions = true, - sortOptions = false) -@Slf4j -public class BoatTerminal implements Runnable { - - static class VersionProvider implements IVersionProvider { - @Override - public String[] getVersion() throws Exception { - return new String[] {getClass().getPackage().getImplementationVersion()}; - } - } - - static class Input { - @Option(names = {"-f", "--file"}, paramLabel = "", - description = "Input RAML 1.0 file (deprecated, use the input as a parameter).") - private File inputOpt; - - @Parameters(description = "Input RAML 1.0 file.") - private File inputFile; - - File get() { - return this.inputFile != null ? this.inputFile : this.inputOpt; - } - } - - public static void main(String[] args) { - System.exit(run(args)); - } - - static int run(String[] args) { - return new CommandLine(new BoatTerminal()) - .addSubcommand("completion", new GenerateCompletion()) - .execute(args); - } - - private final Logger root; - - public Level getRootLevel() { - return root.getLevel(); - } - - public BoatTerminal() { - this.root = (Logger) LoggerFactory.getLogger(ROOT_LOGGER_NAME); - - this.root.setLevel(ch.qos.logback.classic.Level.WARN); - } - - @ArgGroup(exclusive = true, multiplicity = "1", order = 10) - private Input input; - - @Option(names = {"-o", "--output"}, order = 20, - description = "Output OpenAPI file name.") - private Path output; - - @Option(names = {"-d", "--directory"}, order = 30, - description = "Output OpenAPI directory.") - private Path directory; - - @Option(names = {"--convert-examples"}, order = 40, - description = "Convert examples to YAML.", - defaultValue = "true", - arity = "0..1", - paramLabel = "true|false", - showDefaultValue = Visibility.ALWAYS, fallbackValue = "true") - private boolean convertExamples; - - @Option(names = {"-v", "--verbose"}, order = 50, - description = "Verbose output; multiple -v options increase the verbosity.") - public void setVerbose(boolean[] verbose) { - switch (verbose.length) { - case 1: - this.root.setLevel(ch.qos.logback.classic.Level.INFO); - break; - - case 2: - this.root.setLevel(ch.qos.logback.classic.Level.DEBUG); - break; - - default: - this.root.setLevel(ch.qos.logback.classic.Level.TRACE); - break; - } - } - - @Override - public void run() { - try { - execute(); - } catch (final Exception e) { - if (log.isDebugEnabled()) { - log.debug(e.getMessage(), e); - } else { - log.error(e.getMessage()); - } - } - } - - private void execute() throws ExportException, IOException { - final File inputFile = this.input.get(); - - if (!inputFile.exists()) { - throw new FileNotFoundException("Not found: " + inputFile.getAbsolutePath()); - } - - final ExporterOptions options = new ExporterOptions().convertExamplesToYaml(this.convertExamples); - final OpenAPI openApi = Exporter.export(inputFile, options); - final String yaml = SerializerUtils.toYamlString(openApi); - - if (this.directory != null) { - final OpenAPIExtractor extractor = new OpenAPIExtractor(openApi); - final ObjectMapper mapper = new ObjectMapper(); - final ObjectWriter writer = mapper.writer(new DefaultPrettyPrinter()); - - new DirectoryExploder(extractor, writer) - .serializeIntoDirectory(this.directory); - - Files.write(this.directory.resolve("openapi.yaml"), - yaml.getBytes(StandardCharsets.UTF_8)); - } - if (this.output != null) { - final Path parent = this.output.getParent(); - - if (parent != null) { - Files.createDirectories(parent); - } - - Files.write(this.output, - yaml.getBytes(StandardCharsets.UTF_8)); - } - if (this.output == null && this.directory == null) { - log.warn("Output path for {}, is null", yaml); - } - } -} diff --git a/boat-terminal/src/main/resources/logback.xml b/boat-terminal/src/main/resources/logback.xml deleted file mode 100644 index c0c643e21..000000000 --- a/boat-terminal/src/main/resources/logback.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - %highlight([%level]) [%logger{10}] %msg%n - - - - - - \ No newline at end of file diff --git a/boat-terminal/src/test/java/com/backbase/oss/boat/BoatTerminalTest.java b/boat-terminal/src/test/java/com/backbase/oss/boat/BoatTerminalTest.java deleted file mode 100644 index b83008d1e..000000000 --- a/boat-terminal/src/test/java/com/backbase/oss/boat/BoatTerminalTest.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.backbase.oss.boat; - -import ch.qos.logback.classic.Level; -import org.junit.jupiter.api.Test; - -import java.io.File; -import java.io.FileNotFoundException; -import java.nio.file.Files; -import java.nio.file.Path; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; -import static org.junit.jupiter.api.Assertions.*; - -class BoatTerminalTest { - - @Test - void testCLI() { - assertThat(BoatTerminal.run(new String[]{"-V"}), is(0)); - } - @Test - void testCLIOptions() { - assertThat(BoatTerminal.run(new String[]{"-f=src/test/resources/raml-examples/backbase-wallet/presentation-client-api.raml","--directory=src/test/resources/raml-examples/converted","--output=src/test/resources/raml-examples/converted/openapi.yaml","--convert-examples=false"}), is(0)); - File output = new File("src/test/resources/raml-examples/converted/openapi.yaml"); - - assertTrue(output.exists()); - - assertThat(BoatTerminal.run(new String[]{"--file=src/test/resources/raml-examples/backbase-wallet/presentation-client-api.raml","-d=src/test/resources/raml-examples/converted","-o=src/test/resources/raml-examples/converted/openapi.yaml","--convert-examples=false"}), is(0)); - assertThat(BoatTerminal.run(new String[]{"--file=src/test/resources/raml-examples/backbase-wallet/presentation-client-api.raml","-d=src/test/resources/raml-examples/converted","-v"}),is(0)); - } - - @Test - void testCLIErrorCatching(){ - assertThat( BoatTerminal.run(new String[]{"-f=src/test/resources/raml-examples/backbase-wallet/file-not-found ","--directory=src/test/resources/raml-examples/converted","--output=src/test/resources/raml-examples/converted/openapi.yaml","--convert-examples=false"}),is(0)); - assertThat(BoatTerminal.run(new String[]{"-f src/test/resources/raml-examples/backbase-wallet/presentation-client-api.raml","--directory src/test/resources/raml-examples/converted","--output src/test/resources/raml-examples/converted/openapi.yaml","--convert-examples false"}), is(2)); - } - - - @Test - void testVerbose(){ - boolean[] testVerbose = {true,false}; - BoatTerminal boatTerminal = new BoatTerminal(); - boatTerminal.setVerbose(testVerbose); - assertEquals(Level.DEBUG,boatTerminal.getRootLevel()); - - testVerbose = new boolean[]{true}; - - boatTerminal.setVerbose(testVerbose); - assertEquals(Level.INFO,boatTerminal.getRootLevel()); - - testVerbose = new boolean[]{true,true,true}; - boatTerminal.setVerbose(testVerbose); - assertEquals(Level.TRACE,boatTerminal.getRootLevel()); - - } - - -} diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/bbt-common.raml b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/bbt-common.raml deleted file mode 100644 index 281655811..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/bbt-common.raml +++ /dev/null @@ -1,7 +0,0 @@ -#%RAML 1.0 Library -schemas: - ObjectWrappingException: !include common-schemas/body/object-wrapping-exception.json -types: - PaymentCard: !include common-schemas/body/paymentcard-item.json - PaymentCards: !include common-schemas/body/paymentcards-get.json - TestHeadersResponseBody: !include common-schemas/body/test-headers-response.json \ No newline at end of file diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/date-query-params.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/date-query-params.json deleted file mode 100644 index 377c9a7fc..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/date-query-params.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType":"com.backbase.buildingblocks.test.data.DateTimeTestResponse", - "properties": { - "dateTimeOnly": { - "type": "string" - }, - "dateTimeOnlyParsedValue": { - "type": "string" - }, - "dateTime": { - "type": "string" - }, - "dateTimeParsedValue": { - "type": "string" - }, - "dateTime2616": { - "type": "string" - }, - "dateTime2616ParsedValue": { - "type": "string" - }, - "date": { - "type": "string" - }, - "dateParsedValue": { - "type": "string" - }, - "time": { - "type": "string" - }, - "timeParsedValue": { - "type": "string" - }, - "formatDateTime": { - "description": "The dateTime parameter formatted as 'date-time', java.util.Date or java.time.ZoneDateTime", - "type": "string", - "format": "date-time" - }, - "formatDate": { - "description": "The date parameter formatted as 'date', String or java.time.LocalDate", - "type": "string", - "format": "date" - }, - "formatTime": { - "description": "The time parameter formatted as 'time', String or java.time.LocalTime", - "type": "string", - "format": "time" - }, - "formatUtcMillisec": { - "description": "The dateTime parameter formatted as 'date', long", - "type": "string", - "format": "utc-millisec" - } - } -} \ No newline at end of file diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/object-wrapping-exception.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/object-wrapping-exception.json deleted file mode 100644 index 4a3a7e1dd..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/object-wrapping-exception.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.test.exceptions.ObjectWrappingException", - "properties": { - "message": { - "type": "string" - }, - "data": { - "type": "object" - } - } -} diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/paymentcard-item.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/paymentcard-item.json deleted file mode 100644 index 8542e05cb..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/paymentcard-item.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType":"com.backbase.buildingblocks.test.data.PaymentCard", - "properties": { - "id": { - "type": "string" - }, - "pan": { - "type": "string", - "description": "Must be sixteen digits, optionally in blocks of 4 separated by a dash", - "maxLength": 19 - }, - "cvc": { - "type": "string", - "description": "Card Verification Code", - "minLength": 3, - "maxLength": 3 - }, - "startDate": { - "type": "string", - "description": "Must be in one of these four formats: MM/YY MMYY MMYYYY MM/YYYY", - "pattern": "^(0[1-9]|1[0-2])\/?([0-9]{4}|[0-9]{2})$" - }, - "expiryDate": { - "type": "string", - "description": "Must be in one of these four formats: MM/YY MMYY MMYYYY MM/YYYY", - "pattern": "^(0[1-9]|1[0-2])\/?([0-9]{4}|[0-9]{2})$" - }, - "nameOnCard": { - "type": "string" - }, - "creationDate" : { - "type":"string", - "format":"date-time" - }, - "balance" : { - "type": "object", - "$ref": "../../lib/types/schemas/currency.json" - }, - "apr": { - "type": "number", - "javaType": "java.math.BigDecimal" - }, - "cardtype" : { - "type" : "string", - "default" : "CREDIT", - "enum" : ["CREDIT", "DEBIT", "PREPAID"] - } - }, - "required": [ - "id", - "pan", - "cvc", - "startDate", - "expiryDate", - "nameOnCard" - ] -} diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/paymentcards-get.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/paymentcards-get.json deleted file mode 100644 index 16c29a9f7..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/paymentcards-get.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "array", - "items": { - "$ref": "paymentcard-item.json" - } -} \ No newline at end of file diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/test-headers-response.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/test-headers-response.json deleted file mode 100644 index 4c0635545..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/common-schemas/body/test-headers-response.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType":"com.backbase.buildingblocks.test.data.TestHeadersResponse", - "additionalProperties": false, - "properties": { - "requests": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "url": { - "type": "string" - }, - "headers": { - "type": "object", - "javaType": "java.util.Map" - } - } - } - } - } - } \ No newline at end of file diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/events/add-paymentcard-command.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/events/add-paymentcard-command.json deleted file mode 100644 index 1296ef118..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/events/add-paymentcard-command.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "required": true, - "properties": { - "paymentcard": { - "type": "object", - "$ref": "../common-schemas/body/paymentcard-item.json" - } - } -} \ No newline at end of file diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/events/delete-paymentcard-command.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/events/delete-paymentcard-command.json deleted file mode 100644 index 81b24e284..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/events/delete-paymentcard-command.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "required": true, - "properties": { - "paymentcard": { - "type": "object", - "$ref": "../schemas/body/paymentcard-id.json" - } - } -} \ No newline at end of file diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/events/get-paymentcards-command.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/events/get-paymentcards-command.json deleted file mode 100644 index 2d04dc7a3..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/events/get-paymentcards-command.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "required": true, - "properties": { - "queryParams": { - "type": "object", - "$ref": "../schemas/body/paymentcards-query.json" - } - } -} \ No newline at end of file diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/events/paymentcard-added-event.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/events/paymentcard-added-event.json deleted file mode 100644 index d1efda594..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/events/paymentcard-added-event.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "required": true, - "properties": { - "paymentcard": { - "type": "object", - "$ref": "../common-schemas/body/paymentcard-item.json" - }, - "emitDateTime": { - "description": "The dateTime parameter formatted as 'date-time', java.util.Date or java.time.ZoneDateTime", - "type": "string", - "format": "date-time" - }, - "emitDate": { - "description": "The date parameter formatted as 'date', String or java.time.LocalDate", - "type": "string", - "format": "date" - }, - "emitTime": { - "description": "The time parameter formatted as 'time', String or java.time.LocalTime", - "type": "string", - "format": "time" - }, - "emitMillisec": { - "description": "The dateTime parameter formatted as 'date', long", - "type": "string", - "format": "utc-millisec" - } - } -} \ No newline at end of file diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/events/paymentcard-deleted-event.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/events/paymentcard-deleted-event.json deleted file mode 100644 index d1efda594..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/events/paymentcard-deleted-event.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "required": true, - "properties": { - "paymentcard": { - "type": "object", - "$ref": "../common-schemas/body/paymentcard-item.json" - }, - "emitDateTime": { - "description": "The dateTime parameter formatted as 'date-time', java.util.Date or java.time.ZoneDateTime", - "type": "string", - "format": "date-time" - }, - "emitDate": { - "description": "The date parameter formatted as 'date', String or java.time.LocalDate", - "type": "string", - "format": "date" - }, - "emitTime": { - "description": "The time parameter formatted as 'time', String or java.time.LocalTime", - "type": "string", - "format": "time" - }, - "emitMillisec": { - "description": "The dateTime parameter formatted as 'date', long", - "type": "string", - "format": "utc-millisec" - } - } -} \ No newline at end of file diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/events/paymentcards-retrieved-event.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/events/paymentcards-retrieved-event.json deleted file mode 100644 index 2cbadf471..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/events/paymentcards-retrieved-event.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "required": true, - "properties": { - "queryParams": { - "type": "object", - "$ref": "../schemas/body/paymentcards-query.json" - }, - "results": { - "type": "array", - "items": { - "$ref": "../common-schemas/body/paymentcard-item.json" - } - }, - "emitDateTime": { - "description": "The dateTime parameter formatted as 'date-time', java.util.Date or java.time.ZoneDateTime", - "type": "string", - "format": "date-time" - }, - "emitDate": { - "description": "The date parameter formatted as 'date', String or java.time.LocalDate", - "type": "string", - "format": "date" - }, - "emitTime": { - "description": "The time parameter formatted as 'time', String or java.time.LocalTime", - "type": "string", - "format": "time" - }, - "emitMillisec": { - "description": "The dateTime parameter formatted as 'date', long", - "type": "string", - "format": "utc-millisec" - } - } -} \ No newline at end of file diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/examples/body/example-build-info.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/examples/body/example-build-info.json deleted file mode 100644 index 5cc40dd5d..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/examples/body/example-build-info.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "build-info": { - "build.version": "1.1.111-SNAPSHOT" - } -} diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/examples/body/item.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/examples/body/item.json deleted file mode 100644 index 89a3fdb1f..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/examples/body/item.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "Example", - "description": "Example description" -} diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/examples/body/paymentcard-created.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/examples/body/paymentcard-created.json deleted file mode 100644 index 3706a5fbc..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/examples/body/paymentcard-created.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "id": "a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1" -} \ No newline at end of file diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/examples/body/paymentcard-item.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/examples/body/paymentcard-item.json deleted file mode 100644 index 72777d92d..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/examples/body/paymentcard-item.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "id": "a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1", - "pan": "5434111122223333", - "cvc": "123", - "startDate": "0116", - "expiryDate": "1219", - "nameOnCard": "Mr Timmy Tester", - "creationDate": "2011-05-30T12:13:14+03:00", - "balance": { - "amount": "1000", - "currencyCode": "EUR" - }, - "apr": 12.75 -} \ No newline at end of file diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/examples/body/paymentcards-get.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/examples/body/paymentcards-get.json deleted file mode 100644 index a7d5dc369..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/examples/body/paymentcards-get.json +++ /dev/null @@ -1,44 +0,0 @@ -[ - { - "id": "a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1", - "pan": "5434111122223333", - "cvc": "123", - "startDate": "0116", - "expiryDate": "1219", - "nameOnCard": "Mr Timmy Tester", - "creationDate": "2011-05-30T12:13:14+03:00", - "balance": { - "amount": "2001", - "currencyCode": "EUR" - }, - "apr": 12.75 - }, - { - "id": "d593c212-70ad-41a6-a547-d5d9232414cb", - "pan": "5434111122224444", - "cvc": "101", - "startDate": "0216", - "expiryDate": "0120", - "nameOnCard": "Mr Timmothy Tester", - "creationDate": "2011-05-30T12:13:14+03:00", - "balance": { - "amount": "4.4399999999999995", - "currencyCode": "GBP" - }, - "apr": 12.75 - }, - { - "id": "9635966b-28e9-4479-8121-bb7bc9beeb62", - "pan": "5434121212121212", - "cvc": "121", - "startDate": "0115", - "expiryDate": "1218", - "nameOnCard": "Mr Timmy Tester", - "creationDate": "2011-05-30T12:13:14+03:00", - "balance": { - "amount": "1981", - "currencyCode": "EUR" - }, - "apr": 12.75 - } -] \ No newline at end of file diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/examples/body/test-headers-response.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/examples/body/test-headers-response.json deleted file mode 100644 index bcc24c481..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/examples/body/test-headers-response.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "requests" : [ - { - "name": "building-blocks-test-wallet-presentation-service", - "url": "/client-api/v1/test/headers", - "headers": { - "correlation-id": [ "2ed475b714a3945a" ], - "accept": [ "application/json" ], - "x-bbt-test": [ "X-BBT-contentVal2" ], - "connection": [ "keep-alive" ] - } - }, - { - "name": "building-blocks-test-wallet-pandp-service", - "url": "/service-api/v1/test/headers", - "headers": { - "authorization": [ "Bearer eyJh" ], - "accept": [ "application/xml, text/xml, application/json, application/*+xml, application/*+json" ], - "content-type": [ "application/json" ], - "x-cxt-user-token": [ "Bearer ey" ], - "x-cxt-remote-user": [ "admin" ], - "x-cxt-requestuuid": [ "72002652-131a-4f28-bd00-16b8080932f5" ], - "correlation-id": [ "2ed475b714a3945a" ], - "x-bbt-test": [ "X-BBT-contentVal2" ] - } - }, - { - "name": "building-blocks-test-wallet-pandp-service", - "url": "/service-api/v1/test/headers", - "headers": { - "authorization": [ "Bearer eyJh" ], - "accept": [ "application/xml, text/xml, application/json, application/*+xml, application/*+json" ], - "content-type": [ "application/json" ], - "x-cxt-user-token": [ "Bearer ey" ], - "x-cxt-remote-user": [ "admin" ], - "x-cxt-requestuuid": [ "72002652-131a-4f28-bd00-16b8080932f5" ], - "correlation-id": [ "2ed475b714a3945a" ], - "x-bbt-test": [ "X-BBT-contentVal2" ] - } - } - ] -} \ No newline at end of file diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/examples/body/test-values-response.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/examples/body/test-values-response.json deleted file mode 100644 index eb5f7bd7b..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/examples/body/test-values-response.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "message": "a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1", - "number": "102.4" -} \ No newline at end of file diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/examples/errors/error.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/examples/errors/error.json deleted file mode 100644 index 26d84f14d..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/examples/errors/error.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "message": "Description of error", - "errorCode" : "EXAMPLE-000001" -} \ No newline at end of file diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/annotations/annotations.raml b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/annotations/annotations.raml deleted file mode 100644 index ea6032759..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/annotations/annotations.raml +++ /dev/null @@ -1,38 +0,0 @@ -#%RAML 1.0 Library - -securitySchemes: -# Custom 'bbAccessControl' security schema -# RAML 1-0 does not allow settings in an x-other security scheme, so no opportunity to describe extra information here - bbAccessControl: - displayName: Backbase Access Control - description: | - This API is secured by DBS Access Control - type: x-bb-access-control - -# RAML annotation and associated types that can be included in API specification files -annotationTypes: - x-bb-api-type: - displayName: API Type - description: | - Signals whether this API endpoint is intended for use by users (HTTP APIs exposed by presentation services) or by - systems (HTTP APIs exposed by inbound integration services) - type: array - items: - type: string - enum: [user, system] - x-bb-access-control: - displayName: Backbase Access Control - description: | - Describes which Resource, Function and Privilege need to be granted to the user to allow access to this API - type: BB-Access-Control - x-bb-api-deprecation: - displayName: API Deprecation - description: | - Signals that the API endpoint is deprecated, providing details on when the API was deprecated, when it will be - removed, the reason for deprecation and a more general description in Markdown that can be used to provide more - information on the deprecation and migration strategy - type: BB-Api-Deprecation - -schemas: - BB-Access-Control: !include ../types/schemas/bb-access-control.json - BB-Api-Deprecation: !include ../types/schemas/bb-api-deprecation.json \ No newline at end of file diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/traits/traits.raml b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/traits/traits.raml deleted file mode 100644 index 1cfe6eb99..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/traits/traits.raml +++ /dev/null @@ -1,132 +0,0 @@ -#%RAML 1.0 Library -schemas: - Bad-Request-Error: !include ../types/schemas/bad-request-error.json - Unauthorized-Error: !include ../types/schemas/unauthorized-error.json - Unauthorized-Alt-Error: !include ../types/schemas/unauthorized-alt-error.json - Not-Acceptable-Error: !include ../types/schemas/not-acceptable-error.json - Internal-Server-Error: !include ../types/schemas/internal-server-error.json - Forbidden-Error: !include ../types/schemas/forbidden-error.json - Not-Found-Error: !include ../types/schemas/not-found-error.json - Unsupported-Media-Type-Error: !include ../types/schemas/unsupported-media-type-error.json -traits: - idempotent: - headers: - X-Request-Id: - description: Correlates HTTP requests between a client and server. - required: false - example: f058ebd6-02f7-4d3f-942e-904344e8cde5 - pageable: - queryParameters: - from: - description: Page Number. Skip over pages of elements by specifying a start value for the query - type: integer - required: false - example: 20 - default: 0 - cursor: - description: | - Record UUID. As an alternative for specifying 'from' this allows to point to the record to start the selection from. - type: string - required: false - example: 76d5be8b-e80d-4842-8ce6-ea67519e8f74 - default: "" - size: - description: | - Limit the number of elements on the response. When used in combination with cursor, the value - is allowed to be a negative number to indicate requesting records upwards from the starting point indicated - by the cursor. - type: integer - required: false - example: 80 - default: 10 - orderable: - queryParameters: - orderBy: - description: | - Order by field: <> - type: string - required: false - direction: - description: Direction - enum: [ASC, DESC] - default: DESC - required: false - challengeable: - headers: - X-MFA: - description: Challenge payload response - required: false - example: sms challenge="123456789" - responses: - 401: - description: Unauthorized - headers: - WWW-Authenticate: - description: Comma separated challenges - required: false - example: sms challenge="", pki challenge="Z8nlwZe0daUNWCWIbfJe3iIgauh" - body: - application/json: - type: Unauthorized-Error - BadRequestError: - responses: - 400: - description: BadRequest - body: - application/json: - type: Bad-Request-Error - example: !include ../types/examples/example-bad-request-error.json - UnauthorizedError: - responses: - 401: - description: Unauthorized - headers: - WWW-Authenticate: - description: Indicates the authentication scheme(s) and parameters applicable to the target resource - required: false - example: | - WWW-Authenticate: Newauth realm="apps", type=1, title="Login to \"apps\"", Basic realm="simple" - body: - application/json: - type: Unauthorized-Alt-Error - example: !include ../types/examples/example-unauthorized-alt-error.json - ForbiddenError: - responses: - 403: - description: Forbidden - body: - application/json: - type: Forbidden-Error - example: !include ../types/examples/example-forbidden-error.json - NotFoundError: - responses: - 404: - description: NotFound - body: - application/json: - type: Not-Found-Error - example: !include ../types/examples/example-not-found-error.json - NotAcceptableError: - responses: - 406: - description: NotAcceptable - body: - application/json: - type: Not-Acceptable-Error - example: !include ../types/examples/example-not-acceptable-error.json - UnsupportedMediaTypeError: - responses: - 415: - description: UnsupportedMediaType - body: - application/json: - type: Unsupported-Media-Type-Error - example: !include ../types/examples/example-unsupported-media-type-error.json - InternalServerError: - responses: - 500: - description: InternalServerError - body: - application/json: - type: Internal-Server-Error - example: !include ../types/examples/example-internal-server-error.json diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-bad-request-error.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-bad-request-error.json deleted file mode 100644 index 77243186b..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-bad-request-error.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "message": "Bad Request", - "errors": [ - { - "message": "Value Exceeded. Must be between {min} and {max}.", - "key": "common.api.shoesize", - "context": { - "max": "50", - "min": "1" - } - } - ] -} diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-currency.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-currency.json deleted file mode 100644 index ff365438f..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-currency.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "amount": "1.12", - "currencyCode": "TST" -} \ No newline at end of file diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-forbidden-error.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-forbidden-error.json deleted file mode 100644 index e26366a7c..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-forbidden-error.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "message": "Access to requested resource denied.", - "errors": [ - { - "message": "Resource access denied due to an insufficient user quota of {quota}.", - "key": "common.api.quota", - "context": { - "quota": "someQuota" - } - } - ] -} diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-internal-server-error.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-internal-server-error.json deleted file mode 100644 index c6701087a..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-internal-server-error.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "message": "Description of error" -} \ No newline at end of file diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-not-acceptable-error.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-not-acceptable-error.json deleted file mode 100644 index 0b4ab5da9..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-not-acceptable-error.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "message": "Could not find acceptable representation", - "supportedMediaTypes": [ - "application/json" - ] -} diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-not-found-error.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-not-found-error.json deleted file mode 100644 index 2d6d616b8..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-not-found-error.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "message": "Resource not found.", - "errors": [ - { - "message": "Unable to find the resource requested resource: {resource}.", - "key": "common.api.resource", - "context": { - "resource": "aResource" - } - } - ] -} diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-unauthorized-alt-error.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-unauthorized-alt-error.json deleted file mode 100644 index 6b692d0b3..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-unauthorized-alt-error.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "message": "Access to requested resource denied.", - "errors": [ - { - "message": "Resource access denied due to invalid credentials.", - "key": "common.api.token", - "context": { - "accessToken": "expired" - } - } - ] -} diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-unauthorized-error.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-unauthorized-error.json deleted file mode 100644 index 44f8e8dc6..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-unauthorized-error.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "message": "You are not authorized to perform this action" -} diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-unsupported-media-type-error.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-unsupported-media-type-error.json deleted file mode 100644 index 9dba54d8f..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/examples/example-unsupported-media-type-error.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "message": "Unsupported media type.", - "errors": [ - { - "message": "The request entity has a media type {mediaType} which the resource does not support.", - "key": "common.api.mediaType", - "context": { - "mediaType": "application/javascript" - } - } - ] -} diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/bad-request-error.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/bad-request-error.json deleted file mode 100644 index d6314386c..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/bad-request-error.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.presentation.errors.BadRequestException", - "properties": { - "message": { - "type": "string", - "description": "Any further information" - }, - "errors": { - "type": "array", - "description": "Detailed error information", - "items": { - "$ref": "error-item.json" - } - } - }, - "required": [ - "message" - ] -} diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/bb-access-control.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/bb-access-control.json deleted file mode 100644 index 629f43147..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/bb-access-control.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "resource": { - "type": "string", - "description": "Resource being protected, e.g. 'User'" - }, - "function": { - "type": "string", - "description": "Business function, e.g. 'Manage Users'" - }, - "privilege": { - "type": "string", - "description": "The privilege required, e.g. 'view'" - } - }, - "required": [ - "resource", - "function", - "privilege" - ] -} diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/bb-api-deprecation.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/bb-api-deprecation.json deleted file mode 100644 index 9d7339566..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/bb-api-deprecation.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "deprecatedFromVersion": { - "type": "string", - "description": "Version of the product from which the endpoint has been deprecated and should no longer be used" - }, - "removedFromVersion": { - "type": "string", - "description": "Version of the product from which the API endpoint will be removed" - }, - "reason": { - "type": "string", - "description": "The reason the API endpoint was deprecated" - }, - "description": { - "type": "string", - "description": "Any further information, e.g. migration information" - } - }, - "required": [ - "deprecatedFromVersion", - "removedFromVersion", - "reason", - "description" - ] -} diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/currency.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/currency.json deleted file mode 100644 index 457bd84ed..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/currency.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "title": "Monetary Amount", - "description": "Schema defining monetary amount in given currency.", - "javaType": "com.backbase.rest.spec.common.types.Currency", - "properties": { - "amount": { - "type": "string", - "javaType": "java.math.BigDecimal", - "description": "The amount in the specified currency" - }, - "currencyCode": { - "type": "string", - "description": "The alpha-3 code (complying with ISO 4217) of the currency that qualifies the amount", - "pattern": "^[A-Z]{3}$" - } - }, - "required": [ - "amount", - "currencyCode" - ] -} \ No newline at end of file diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/error-item.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/error-item.json deleted file mode 100644 index 4868a1047..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/error-item.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "description": "A validation error", - "javaInterfaces": [ - "java.io.Serializable", - "Cloneable" - ], - "properties": { - "message": { - "type": "string", - "description": "Default Message. Any further information." - }, - "key": { - "type": "string", - "description": "{capability-name}.api.{api-key-name}. For generated validation errors this is the path in the document the error resolves to. e.g. object name + '.' + field" - }, - "context": { - "type": "object", - "description": "Context can be anything used to construct localised messages.", - "javaType": "java.util.Map" - } - } -} diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/forbidden-error.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/forbidden-error.json deleted file mode 100644 index 671b17956..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/forbidden-error.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.presentation.errors.ForbiddenException", - "properties": { - "message": { - "type": "string", - "description": "Any further information" - }, - "errors": { - "type": "array", - "description": "Detailed error information", - "items": { - "$ref": "error-item.json" - } - } - } -} diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/internal-server-error.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/internal-server-error.json deleted file mode 100644 index d7d6cafd8..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/internal-server-error.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.presentation.errors.InternalServerErrorException", - "description": "Represents HTTP 500 Internal Server Error", - "properties": { - "message": { - "type": "string", - "description": "Further Information" - } - }, - "required": [ - "message" - ] -} \ No newline at end of file diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/not-acceptable-error.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/not-acceptable-error.json deleted file mode 100644 index f39202d2b..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/not-acceptable-error.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.presentation.errors.NotAcceptableException", - "properties": { - "message": { - "type": "string" - }, - "supportedMediaTypes": { - "type": "array", - "description": "List of supported media types for this endpoint", - "items": { - "type": "string" - } - } - } -} diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/not-found-error.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/not-found-error.json deleted file mode 100644 index 3ce00ba4f..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/not-found-error.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.presentation.errors.NotFoundException", - "properties": { - "message": { - "type": "string", - "description": "Any further information" - }, - "errors": { - "type": "array", - "description": "Detailed error information", - "items": { - "$ref": "error-item.json" - } - } - } -} diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/unauthorized-alt-error.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/unauthorized-alt-error.json deleted file mode 100644 index 388b7326b..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/unauthorized-alt-error.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.presentation.errors.UnauthorizedException", - "properties": { - "message": { - "type": "string", - "description": "Any further information" - }, - "errors": { - "type": "array", - "description": "Detailed error information", - "items": { - "$ref": "error-item.json" - } - } - } -} diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/unauthorized-error.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/unauthorized-error.json deleted file mode 100644 index 5c30948ac..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/unauthorized-error.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "message": { - "type": "string" - } - }, - "required": [ - "message" - ] -} diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/unsupported-media-type-error.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/unsupported-media-type-error.json deleted file mode 100644 index 87e2ebba6..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/lib/types/schemas/unsupported-media-type-error.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "javaType": "com.backbase.buildingblocks.presentation.errors.UnsupportedMediaTypeException", - "properties": { - "message": { - "type": "string", - "description": "Any further information" - }, - "errors": { - "type": "array", - "description": "Detailed error information", - "items": { - "$ref": "error-item.json" - } - } - } -} diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/presentation-client-api.raml b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/presentation-client-api.raml deleted file mode 100644 index d3523898a..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/presentation-client-api.raml +++ /dev/null @@ -1,226 +0,0 @@ -#%RAML 1.0 ---- -#=============================================================== -# Messages - RAML example http://raml.org/ -# References: -# - RAML Specification - https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md -#=============================================================== -title: Wallet Test Client API -uses: - traits: lib/traits/traits.raml - bb: lib/annotations/annotations.raml - common: bbt-common.raml -version: v1 -baseUri: "client-api/{version}" -mediaType: application/json -protocols: [ HTTP, HTTPS ] -#=============================================================== -# API resource definitions -#=============================================================== -securedBy: [ bb.bbAccessControl ] -(bb.x-bb-api-type): [user] -/wallet: - displayName: Wallet - /paymentcards: - displayName: Payment Cards - get: - (bb.x-bb-access-control): - resource: WALLET - function: MANAGE_PAYMENT_CARDS - privilege: READ_PAYMENT_CARD - is: [traits.BadRequestError, traits.NotAcceptableError, traits.orderable: {fieldsList: nameOnCard}, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: "Returns available payment card details for user, optionally filtered by nameOnCard" - queryParameters: - nameOnCard: - description: "Filter by the cardholder's name (case-insensitive), can be the first one or more characters of one of the words/names" - required: false - type: string - example: "Smi" - dateTimeOnly: - description: Creation date in datetime-only format - required: false - type: datetime-only - example: 2017-10-04T14:54:36 - dateTime: - description: Creation date in Zoned RFC3339 Date-time format - required: false - type: datetime - format: rfc3339 - example: 2017-10-04T14:54:36Z - dateTime2616: - description: Zoned RFC2616 Date-time param example - required: false - type: datetime - format: rfc2616 - example: Wed, 4 Jul 2001 12:08:56 PDT - date: - description: Date-only param example - required: false - type: date-only - example: 2017-10-04 - time: - description: time-only param example - required: false - type: time-only - example: 14:54:36 - responses: - 200: - body: - application/json: - type: common.PaymentCards - example: !include examples/body/paymentcards-get.json - text/csv: - application/xml: - post: - (bb.x-bb-access-control): - resource: WALLET - function: MANAGE_PAYMENT_CARDS - privilege: WRITE_PAYMENT_CARD - is: [traits.BadRequestError, traits.InternalServerError, traits.idempotent, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Adds a payment card to the user's wallet - body: - application/json: - type: common.PaymentCard - example: !include examples/body/paymentcard-item.json - responses: - 201: - description: request to create payment card accepted - body: - application/json: - schema: !include schemas/body/paymentcard-id.json - example: !include examples/body/paymentcard-created.json - /{cardId}: - displayName: Payment Card - uriParameters: - cardId: - type: string - get: - (bb.x-bb-access-control): - resource: WALLET - function: MANAGE_PAYMENT_CARDS - privilege: READ_PAYMENT_CARD - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Returns details of a specific payment card - responses: - 200: - body: - application/json: - type: common.PaymentCard - example: !include examples/body/paymentcard-item.json - delete: - (bb.x-bb-access-control): - resource: WALLET - function: MANAGE_PAYMENT_CARDS - privilege: DELETE_PAYMENT_CARD - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Deletes a payment card with a given id - responses: - 204: - description: Payment card is succesfully deleted -/bbt: - description: API for test operations. - displayName: BBT - /build-info: - get: - description: "Build Information" - responses: - 200: - body: - application/json: - schema: !include schemas/body/build-info.json - example: !include examples/body/example-build-info.json -/patch: - description: PATCH endpoint for test operations - displayName: patch - patch: - is: [traits.BadRequestError, traits.InternalServerError, traits.idempotent, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: "Patch Test" - responses: - 200: - body: - text/plain: - schema: !include schemas/body/patch-response.json -/test: - /required-boolean-query-param: - description: arbitrary tests - displayName: required boolean query param - get: - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - queryParameters: - bool: - description: Required boolean parameter with no default value - required: true - type: boolean - example: false - responses: - 200: - body: - application/json: - schema: !include schemas/body/test-response.json - /values: - description: Test Values - displayName: Test Values - get: - is: [traits.InternalServerError] - responses: - 200: - body: - application/json: - schema: !include schemas/body/test-values-response.json - example: !include examples/body/test-values-response.json - /headers: - description: Test header propagation - displayName: Test header propagation - get: - is: [traits.InternalServerError] - queryParameters: - addHops: - description: number of additional hops to perform - required: false - type: integer - responses: - 200: - body: - application/json: - schema: common.TestHeadersResponseBody - example: !include examples/body/test-headers-response.json - /date-query-params: - description: | - Tests for date/time query parameters in service-apis. Sends the same query parameters to the equivalent endpoint - in the pandp service which echoes the given values back in the response body. Values echoed by the pandp service - are then returned in the response to this request. - displayName: dateQueryParam - get: - queryParameters: - dateTimeOnly: - description: Creation date in datetime-only format - required: false - type: datetime-only - example: 2017-10-04T14:54:36 - dateTime: - description: Creation date in Zoned RFC3339 Date-time format - required: false - type: datetime - format: rfc3339 - example: 2017-10-04T14:54:36Z - dateTime2616: - description: Zoned RFC2616 Date-time param example - required: false - type: datetime - format: rfc2616 - example: Wed, 4 Jul 2001 12:08:56 PDT - date: - description: Date-only param example - required: false - type: date-only - example: 2017-10-04 - time: - description: time-only param example - required: false - type: time-only - example: 14:54:36 - responses: - 200: - body: - application/json: - schema: !include common-schemas/body/date-query-params.json diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/presentation-integration-api.raml b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/presentation-integration-api.raml deleted file mode 100644 index a477df038..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/presentation-integration-api.raml +++ /dev/null @@ -1,32 +0,0 @@ -#%RAML 1.0 ---- -#=============================================================== -# Integration API example -#=============================================================== -title: Example -version: v1 -baseUri: "integration-api/{version}" -mediaType: application/json -protocols: [ HTTP, HTTPS ] -#=============================================================== -# API documentation - Overall documentation. -#=============================================================== -documentation: - - title: Example - content: Test Schema to test an integration-api -#=============================================================== -# API resource definitions -#=============================================================== -/items: - description: Retrieve all items. - displayName: items - uriParameters: null - get: - description: "Retrieve list of all items." - responses: - 200: - description: Test Schema - body: - application/json: - schema: !include schemas/body/item.json - example: !include examples/body/item.json \ No newline at end of file diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/presentation-service-api.raml b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/presentation-service-api.raml deleted file mode 100644 index db9214ea5..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/presentation-service-api.raml +++ /dev/null @@ -1,122 +0,0 @@ -#%RAML 1.0 ---- -#=============================================================== -# Messages - RAML example http://raml.org/ -# References: -# - RAML Specification - https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md -#=============================================================== -title: Wallet Test Service API -uses: - traits: lib/traits/traits.raml - bb: lib/annotations/annotations.raml - common: bbt-common.raml -version: v1 -baseUri: "service-api/{version}" -mediaType: application/json -protocols: [ HTTP, HTTPS ] -#=============================================================== -# API resource definitions -#=============================================================== -securedBy: [ bb.bbAccessControl ] -(bb.x-bb-api-type): [system] -/wallet: - displayName: WalletService - /admin/{userId}: - uriParameters: - userId: - type: string - /paymentcards: - displayName: Payment Cards - get: - is: [traits.BadRequestError, traits.NotAcceptableError, traits.orderable: {fieldsList: nameOnCard}, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: "Returns available payment card details for user, optionally filtered by nameOnCard" - queryParameters: - nameOnCard: - description: "Filter by the cardholder's name (case-insensitive), can be the first one or more characters of one of the words/names" - required: false - type: string - example: "Smi" - dateTimeOnly: - description: Creation date in datetime-only format - required: false - type: datetime-only - example: 2017-10-04T14:54:36 - dateTime: - description: Creation date in Zoned RFC3339 Date-time format - required: false - type: datetime - format: rfc3339 - example: 2017-10-04T14:54:36Z - dateTime2616: - description: Zoned RFC2616 Date-time param example - required: false - type: datetime - format: rfc2616 - example: Wed, 4 Jul 2001 12:08:56 PDT - date: - description: Date-only param example - required: false - type: date-only - example: 2017-10-04 - time: - description: time-only param example - required: false - type: time-only - example: 14:54:36 - responses: - 200: - body: - application/json: - type: common.PaymentCards - example: !include examples/body/paymentcards-get.json - post: - is: [traits.BadRequestError, traits.InternalServerError, traits.idempotent, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Adds a payment card to the user's wallet - body: - application/json: - type: common.PaymentCard - example: !include examples/body/paymentcard-item.json - responses: - 201: - description: request to create payment card accepted - body: - application/json: - schema: !include schemas/body/paymentcard-id.json - example: !include examples/body/paymentcard-created.json - /{cardId}: - displayName: Payment Card - uriParameters: - cardId: - type: string - get: - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Returns details of a specific payment card - responses: - 200: - body: - application/json: - type: common.PaymentCard - example: !include examples/body/paymentcard-item.json - delete: - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Deletes a payment card with a given id - responses: - 204: - description: Payment card is succesfully deleted -/testQuery: - /required-boolean-query-param: - description: arbitrary tests - displayName: required boolean query param - get: - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - queryParameters: - bool: - description: Required boolean parameter with no default value - required: true - type: boolean - example: false - responses: - 200: - body: - application/json: - schema: !include schemas/body/test-response.json \ No newline at end of file diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/schemas/body/build-info.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/schemas/body/build-info.json deleted file mode 100644 index 8ed0b3e16..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/schemas/body/build-info.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "build-info": { - "javaType": "java.util.Map", - "type": "object" - } - } -} diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/schemas/body/item.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/schemas/body/item.json deleted file mode 100644 index 176cb4743..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/schemas/body/item.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "description": "this models a simple item.", - "properties": { - "name": { - "type": "string" - }, - "description": { - "type": "string" - } - }, - "required": [ - "name" - ] -} diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/schemas/body/patch-response.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/schemas/body/patch-response.json deleted file mode 100644 index a427bffd5..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/schemas/body/patch-response.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "message": { - "type": "string" - } - } -} \ No newline at end of file diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/schemas/body/paymentcard-id.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/schemas/body/paymentcard-id.json deleted file mode 100644 index cc79400fb..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/schemas/body/paymentcard-id.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "id": { - "type": "string" - } - } -} \ No newline at end of file diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/schemas/body/paymentcards-query.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/schemas/body/paymentcards-query.json deleted file mode 100644 index fd251f418..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/schemas/body/paymentcards-query.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "nameOnCard": { - "type": "string" - }, - "creationDate" : { - "type": "string", - "format": "date-time" - } - }, - "required": [] -} \ No newline at end of file diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/schemas/body/test-response.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/schemas/body/test-response.json deleted file mode 100644 index a427bffd5..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/schemas/body/test-response.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "message": { - "type": "string" - } - } -} \ No newline at end of file diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/schemas/body/test-values-response.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/schemas/body/test-values-response.json deleted file mode 100644 index 2b72f6913..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/schemas/body/test-values-response.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "message": { - "type": "string" - }, - "number": { - "type": "string", - "javaType": "java.math.BigDecimal" - } - } -} \ No newline at end of file diff --git a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/schemas/errors/error.json b/boat-terminal/src/test/resources/raml-examples/backbase-wallet/schemas/errors/error.json deleted file mode 100644 index 362d7e72d..000000000 --- a/boat-terminal/src/test/resources/raml-examples/backbase-wallet/schemas/errors/error.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "message": { - "type": "string" - }, - "errorCode": { - "type": "string" - } - }, - "required": [ - "message", - "errorCode" - ] -} \ No newline at end of file diff --git a/boat-terminal/src/test/resources/raml-examples/export-mojo-error-catching/error b/boat-terminal/src/test/resources/raml-examples/export-mojo-error-catching/error deleted file mode 100644 index e69de29bb..000000000 diff --git a/boat-terminal/src/test/resources/raml-examples/export-mojo-error-catching/invalid-presentation-client-api.raml b/boat-terminal/src/test/resources/raml-examples/export-mojo-error-catching/invalid-presentation-client-api.raml deleted file mode 100644 index 1b6a87ffe..000000000 --- a/boat-terminal/src/test/resources/raml-examples/export-mojo-error-catching/invalid-presentation-client-api.raml +++ /dev/null @@ -1,218 +0,0 @@ -#%RAML 1.0 ---- -#=============================================================== -# Messages - RAML example http://raml.org/ -# References: -# - RAML Specification - https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md -#=============================================================== - -uses: - traits: lib/traits/traits.raml - bb: lib/annotations/?.raml - common: bbt-error.raml -version: v1 -baseUri: "client-api/{version}" -mediaType: application/json -protocols: [ HTTP, HTTPS ] -#=============================================================== -# API resource definitions -#=============================================================== -securedBy: [ bb.bbAccessControl ] -(bb.x-bb-api-type): [user] -/wallet: - displayName: Wallet - /paymentcards: - displayName: Payment Cards - (bb.x-bb-access-control): - badValue: WALLET - function: MANAGE_PAYMENT_CARDS - privilege: READ_PAYMENT_CARD - is: [traits.BadRequestError, traits.NotAcceptableError, traits.orderable: {fieldsList: nameOnCard}, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: "Returns available payment card details for user, optionally filtered by nameOnCard" - queryParameters: - nameOnCard: - description: "Filter by the cardholder's name (case-insensitive), can be the first one or more characters of one of the words/names" - required: false - type: xml - example: "Smi" - dateTimeOnly: - description: Creation date in datetime-only format - required: false - type: datetime-only - example: 2017-10-04T14:54:36 - dateTime: - description: Creation date in Zoned RFC3339 Date-time format - required: false - type: datetime - format: rfc3339 - example: 2017-10-04T14:54:36Z - dateTime2616: - description: Zoned RFC2616 Date-time param example - required: false - type: datetime - format: rfc2616 - example: Wed, 4 Jul 2001 12:08:56 PDT - date: - description: Date-only param example - required: false - type: date-only - example: 2017-10-04 - time: - description: time-only param example - required: false - type: time-only - example: 14:54:36 - responses: - 200: - body: - application/json: - type: common.PaymentCards - example: !include examples/body/paymentcards-get.json - text/csv: - application/xml: - post: - (bb.x-bb-access-control): - resource: WALLET - function: MANAGE_PAYMENT_CARDS - privilege: WRITE_PAYMENT_CARD - is: [traits.BadRequestError, traits.InternalServerError, traits.idempotent, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Adds a payment card to the user's wallet - body: - application/json: - type: common.PaymentCard - example: !include examples/body/paymentcard-item.json - responses: - 201: - description: request to create payment card accepted - body: - application/json: - schema: !include schemas/body/paymentcard-id.json - example: !include examples/body/paymentcard-created.json - /{cardId}: - displayName: Payment Card - uriParameters: - cardId: - type: xml - get: - (bb.x-bb-access-control): - resource: WALLET - function: MANAGE_PAYMENT_CARDS - privilege: READ_PAYMENT_CARD - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Returns details of a specific payment card - responses: - 200: - body: - application/json: - type: common.PaymentCard - example: !include examples/body/paymentcard-item.json - delete: - (bb.x-bb-access-control): - resource: WALLET - function: MANAGE_PAYMENT_CARDS - privilege: DELETE_PAYMENT_CARD - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: Deletes a payment card with a given id - responses: - 204: - description: Payment card is succesfully deleted -/bbt: - description: API for test operations. - displayName: BBT - /build-info: - get: - description: "Build Information" - responses: - 200: - body: - application/json: - schema: !include schemas/body/build-info.json - example: !include examples/body/example-build-info.json -/patch: - description: PATCH endpoint for test operations - displayName: patch - patch: - is: [traits.BadRequestError, traits.InternalServerError, traits.idempotent, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - description: "Patch Test" - responses: - 200: - body: - text/plain: - schema: !include schemas/body/patch-response.json -/test: - /required-boolean-query-param: - description: arbitrary tests - displayName: required boolean query param - get: - is: [traits.BadRequestError, traits.InternalServerError, traits.ForbiddenError, traits.UnsupportedMediaTypeError, traits.NotFoundError, traits.UnauthorizedError] - queryParameters: - bool: - description: Required boolean parameter with no default value - required: true - type: boolean - example: false - responses: - 200: - body: - application/json: - schema: !include schemas/body/test-response.json - /values: - description: Test Values - displayName: Test Values - get: - is: [traits.InternalServerError] - responses: - 200: - body: - application/json: - schema: !include schemas/body/test-values-response.json - example: !include examples/body/test-values-response.json - /headers: - description: Test header propagation - displayName: Test header propagation - get: - is: [traits.InternalServerError] - queryParameters: - addHops: - description: number of additional hops to perform - required: false - type: integer - responses: - 200: - body: - application/json: - schema: common.TestHeadersResponseBody - example: !include examples/body/test-headers-response.json - /date-query-params: - description: | - Tests for date/time query parameters in service-apis. Sends the same query parameters to the equivalent endpoint - in the pandp service which echoes the given values back in the response body. Values echoed by the pandp service - are then returned in the response to this request. - displayName: dateQueryParam - get: - queryParameters: - dateTimeOnly: - description: Creation date in datetime-only format - required: false - type: datetime-only - example: 2017-10-04T14:54:36 - dateTime: - description: Creation date in Zoned RFC3339 Date-time format - required: false - type: datetime - format: rfc3339 - example: 2017-10-04T14:54:36Z - dateTime2616: - description: Zoned RFC2616 Date-time param example - required: false - type: datetime - format: rfc2616 - example: Wed, 4 Jul 2001 12:08:56 PDT - date: - description: Date-only param example - req - responses: - 200: - body: - application/json: - schema: !include common-schemas/body/date-query-params.json diff --git a/boat-terminal/src/test/resources/raml-examples/helloworld/helloworld.raml b/boat-terminal/src/test/resources/raml-examples/helloworld/helloworld.raml deleted file mode 100644 index d81c6ce7e..000000000 --- a/boat-terminal/src/test/resources/raml-examples/helloworld/helloworld.raml +++ /dev/null @@ -1,23 +0,0 @@ -#%RAML 1.0 -title: Hello world # required title - -/helloworld: # optional resource - get: # HTTP method declaration - responses: # declare a response - 200: # HTTP status code - body: # declare content of response - application/json: # media type - type: | # structural definition of a response (schema or type) - { - "title": "Hello world Response", - "type": "object", - "properties": { - "message": { - "type": "string" - } - } - } - example: | # example of how a response looks - { - "message": "Hello world" - } diff --git a/boat-trail-resources/pom.xml b/boat-trail-resources/pom.xml index 7e67db34b..f31bf50e6 100644 --- a/boat-trail-resources/pom.xml +++ b/boat-trail-resources/pom.xml @@ -5,7 +5,7 @@ com.backbase.oss backbase-openapi-tools - 0.16.12-SNAPSHOT + 0.17.0-SNAPSHOT boat-trail-resources diff --git a/boat-trail-resources/src/main/resources/logback.xml b/boat-trail-resources/src/main/resources/logback.xml index ccc8f9324..5f9af4edc 100644 --- a/boat-trail-resources/src/main/resources/logback.xml +++ b/boat-trail-resources/src/main/resources/logback.xml @@ -7,6 +7,4 @@ - -
\ No newline at end of file diff --git a/pom.xml b/pom.xml index e22a044fe..b79027133 100644 --- a/pom.xml +++ b/pom.xml @@ -4,10 +4,10 @@ com.backbase.oss backbase-openapi-tools - 0.16.12-SNAPSHOT + 0.17.0-SNAPSHOT pom - Backbase Open Api Tools will help you converting RAML to OpenAPI plus many more + Backbase Open Api Tools is a collection of tools to work with Open API Backbase OpenApi Tools ${project.version} @@ -56,7 +56,7 @@ backbase-technology-prototyping https://sonarcloud.io - 4.3.1 + 6.3.0 tests/target/site/jacoco-aggregate/jacoco.xml ${aggregate.report.dir} @@ -65,18 +65,17 @@ 5.1.1 1.7.30 - 2.1.5 - 2.0.23 + 2.2.8 + 2.1.6 1.33 0.8.8 - + boat-trail-resources boat-engine boat-scaffold - boat-terminal boat-quay boat-maven-plugin @@ -89,20 +88,20 @@ org.projectlombok lombok - ${lombok.version} + 1.18.24 org.slf4j slf4j-api - 1.7.30 + 2.0.6 ch.qos.logback logback-classic - 1.2.11 + 1.4.5 @@ -173,12 +172,6 @@ 3.0.2 - - org.mozilla - rhino - 1.7.14 - - com.github.java-json-tools json-schema-core @@ -191,12 +184,6 @@ 2.0.6 - - info.picocli - picocli - 4.7.1 - - org.yaml snakeyaml @@ -206,7 +193,7 @@ io.swagger.core.v3 swagger-models - 2.1.5 + ${swagger-core.version} @@ -215,14 +202,6 @@ 1.6.9 - - - com.google.errorprone - error_prone_annotations - 2.16 - compile - - io.swagger swagger-core @@ -239,7 +218,7 @@ io.swagger.parser.v3 swagger-parser - ${swagger-parser.version} + 2.1.11 javax.validation @@ -284,14 +263,6 @@ 4.4 - - - com.googlecode.libphonenumber - libphonenumber - 8.13.1 - compile - - com.github.java-json-tools json-schema-validator @@ -313,7 +284,7 @@ org.junit junit-bom - 5.9.1 + 5.9.2 pom import diff --git a/tests/pom.xml b/tests/pom.xml index 2babea9bc..f6d250211 100644 --- a/tests/pom.xml +++ b/tests/pom.xml @@ -5,7 +5,7 @@ com.backbase.oss backbase-openapi-tools - 0.16.12-SNAPSHOT + 0.17.0-SNAPSHOT tests @@ -23,17 +23,12 @@ boat-engine ${project.version} + com.backbase.oss boat-maven-plugin ${project.version} - - com.backbase.oss - boat-terminal - ${project.version} - - com.backbase.oss boat-quay-lint