diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b48b1c5..45a0e888 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # 2.0.0 * Now supports the CESOP-Format (and the DAC7-Format). +* Uses a client that is auto generated by OpenAPI. This makes the library more robust for future changes of the API. # 1.0.3 diff --git a/README.md b/README.md index 7ea65eb6..35d86a9c 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,13 @@ Client for using the [Mass data transmission DIP (mass data interface)](https:// The BZSt (Bundeszentralamt für Steuern / Federal Central Tax Office) provides the Digital Inbox (DIP) as a service for payment service providers to transmit financial data. -Clients need to register / login at [BZSt online.portal](https://www.bzst.de/DE/Service/Portalinformation/Massendaten/DIP/dip.html?nn=68828) through [Elster](https://www.elster.de/elsterweb/start), [BundID](https://id.bund.de/de) or [BZSt Online-Portal (BOP)](https://www.elster.de/bportal/start). +This library uses a [generated](./bzst-dip-java-client/pom.xml) client from an [``openapi.yml``](./openapi/openapi.yml) +using [OpenAPI Generator](https://openapi-generator.tech/). + +Clients need to register / login +at [BZSt online.portal](https://www.bzst.de/DE/Service/Portalinformation/Massendaten/DIP/dip.html?nn=68828) +through [Elster](https://www.elster.de/elsterweb/start), [BundID](https://id.bund.de/de) +or [BZSt Online-Portal (BOP)](https://www.elster.de/bportal/start). See the [BZSt Information](https://www.bzst.de/EN/Service/Portalinformation/Login/login_node.html) for more information. diff --git a/bzst-dip-java-client-demo/src/main/java/software/xdev/ApplicationWithCesop.java b/bzst-dip-java-client-demo/src/main/java/software/xdev/ApplicationWithCesop.java index 7365258a..92d47ed7 100644 --- a/bzst-dip-java-client-demo/src/main/java/software/xdev/ApplicationWithCesop.java +++ b/bzst-dip-java-client-demo/src/main/java/software/xdev/ApplicationWithCesop.java @@ -14,7 +14,6 @@ import org.slf4j.LoggerFactory; import software.xdev.bzst.dip.client.BzstDipClient; -import software.xdev.bzst.dip.client.exception.HttpStatusCodeNotExceptedException; import software.xdev.bzst.dip.client.model.configuration.BzstDipConfiguration; import software.xdev.bzst.dip.client.model.configuration.BzstDipConfigurationBuilder; import software.xdev.bzst.dip.client.model.configuration.BzstDipOecdDocType; @@ -57,7 +56,7 @@ public final class ApplicationWithCesop private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationWithCesop.class); public static void main(final String[] args) - throws InterruptedException, HttpStatusCodeNotExceptedException, IOException, DatatypeConfigurationException + throws InterruptedException, IOException, DatatypeConfigurationException { final BzstDipConfiguration configuration = createConfiguration(); final BzstDipClient bzstDipClient = new BzstDipClient(configuration); diff --git a/bzst-dip-java-client-demo/src/main/java/software/xdev/ApplicationWithConfigurationFromProperties.java b/bzst-dip-java-client-demo/src/main/java/software/xdev/ApplicationWithConfigurationFromProperties.java index a410c4f0..00b2393d 100644 --- a/bzst-dip-java-client-demo/src/main/java/software/xdev/ApplicationWithConfigurationFromProperties.java +++ b/bzst-dip-java-client-demo/src/main/java/software/xdev/ApplicationWithConfigurationFromProperties.java @@ -6,7 +6,6 @@ import org.slf4j.LoggerFactory; import software.xdev.bzst.dip.client.BzstDipClient; -import software.xdev.bzst.dip.client.exception.HttpStatusCodeNotExceptedException; import software.xdev.bzst.dip.client.model.configuration.BzstDipConfiguration; import software.xdev.bzst.dip.client.model.configuration.BzstDipConfigurationBuilder; import software.xdev.bzst.dip.client.model.configuration.PropertiesSupplier; @@ -19,7 +18,7 @@ public final class ApplicationWithConfigurationFromProperties private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationWithConfigurationFromProperties.class); public static void main(final String[] args) - throws InterruptedException, HttpStatusCodeNotExceptedException, IOException + throws InterruptedException, IOException { final BzstDipConfiguration configuration = createConfigurationFromProperties(); final BzstDipClient bzstDipClient = new BzstDipClient(configuration); diff --git a/bzst-dip-java-client-demo/src/main/java/software/xdev/ApplicationWithCsvInput.java b/bzst-dip-java-client-demo/src/main/java/software/xdev/ApplicationWithCsvInput.java index 19850768..e472b766 100644 --- a/bzst-dip-java-client-demo/src/main/java/software/xdev/ApplicationWithCsvInput.java +++ b/bzst-dip-java-client-demo/src/main/java/software/xdev/ApplicationWithCsvInput.java @@ -9,10 +9,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.opencsv.exceptions.CsvValidationException; - import software.xdev.bzst.dip.client.BzstDipClient; -import software.xdev.bzst.dip.client.exception.HttpStatusCodeNotExceptedException; import software.xdev.bzst.dip.client.model.configuration.BzstDipConfiguration; import software.xdev.bzst.dip.client.model.message.dac7.BzstDipCompleteResult; @@ -23,7 +20,7 @@ public final class ApplicationWithCsvInput private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationWithCsvInput.class); public static void main(final String[] args) - throws InterruptedException, HttpStatusCodeNotExceptedException, IOException, CsvValidationException + throws InterruptedException, IOException { final BzstDipConfiguration configuration = ApplicationWithDac7.createConfiguration(); diff --git a/bzst-dip-java-client-demo/src/main/java/software/xdev/ApplicationWithDac7.java b/bzst-dip-java-client-demo/src/main/java/software/xdev/ApplicationWithDac7.java index 19d66cd3..ff896c8c 100644 --- a/bzst-dip-java-client-demo/src/main/java/software/xdev/ApplicationWithDac7.java +++ b/bzst-dip-java-client-demo/src/main/java/software/xdev/ApplicationWithDac7.java @@ -9,7 +9,6 @@ import org.slf4j.LoggerFactory; import software.xdev.bzst.dip.client.BzstDipClient; -import software.xdev.bzst.dip.client.exception.HttpStatusCodeNotExceptedException; import software.xdev.bzst.dip.client.model.configuration.BzstDipConfiguration; import software.xdev.bzst.dip.client.model.configuration.BzstDipConfigurationBuilder; import software.xdev.bzst.dip.client.model.configuration.BzstDipDpiMessageType; @@ -35,7 +34,7 @@ public final class ApplicationWithDac7 private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationWithDac7.class); public static void main(final String[] args) - throws InterruptedException, HttpStatusCodeNotExceptedException, IOException + throws InterruptedException, IOException { final BzstDipConfiguration configuration = createConfiguration(); final BzstDipClient bzstDipClient = new BzstDipClient(configuration); diff --git a/bzst-dip-java-client-demo/src/main/resources/app.properties b/bzst-dip-java-client-demo/src/main/resources/app.properties index 9d671c13..af7e7fd0 100644 --- a/bzst-dip-java-client-demo/src/main/resources/app.properties +++ b/bzst-dip-java-client-demo/src/main/resources/app.properties @@ -1,8 +1,7 @@ client.id=abcd1234-ab12-ab12-ab12-abcdef123456 base.url=https://mds-ktst.bzst.bund.de environment=TEST - -tax.id=123456781011 +tax.id=86095742719 tax.number=123456781011 application.code= diff --git a/bzst-dip-java-client/pom.xml b/bzst-dip-java-client/pom.xml index e7a102ae..1df116bb 100644 --- a/bzst-dip-java-client/pom.xml +++ b/bzst-dip-java-client/pom.xml @@ -50,6 +50,13 @@ 0.12.6 2.17.1 + + src/generated/java + + + + src/generated/** + @@ -112,6 +119,22 @@ jackson-dataformat-xml ${jackson.version} + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson.version} + + + + org.apache.httpcomponents.client5 + httpclient5 + 5.3.1 + + + org.openapitools + jackson-databind-nullable + 0.2.6 + org.slf4j slf4j-api @@ -254,6 +277,24 @@ + + org.codehaus.mojo + build-helper-maven-plugin + 3.5.0 + + + generate-sources + + add-source + + + + ${generatedDirRelative} + + + + + @@ -349,11 +390,169 @@ - pmd + openapi-generator + + bzst/dip/client/generated + bzst.dip.client.generated + + ${project.basedir}/${generatedDirRelative} + src/gen + + ${project.basedir}/target/generated-sources/openapi/${openApiRelativeGeneratorDir} + + org.apache.maven.plugins + maven-clean-plugin + 3.3.2 + + + pre-generation-clean + initialize + + clean + + + true + + + ${generatedDir} + + + + + + post-generation-clean + process-resources + + clean + + + + + + org.openapitools + openapi-generator-maven-plugin + 7.5.0 + + + + generate + + + ${project.basedir}/../openapi/openapi.yml + java + + ${openApiRelativeGeneratorDir} + apache-httpclient + software.xdev.${componentPackage}.api + software.xdev.${componentPackage}.model + software.xdev.${componentPackage}.client + + true + + false + + + true + true + + + false + false + false + false + + + + + + org.apache.maven.plugins + maven-resources-plugin + 3.3.1 + + + copy-generated-resources + process-sources + + copy-resources + + + ${generatedDir} + + + ${openApiGeneratorDir} + + + + + + + + software.xdev + find-and-replace-maven-plugin + 1.0.3 + + + + remove-unused-import-com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider + process-sources + + file-contents + + + ${generatedDirRelative}/software/xdev/${componentDir}/client/ + ApiClient.java + + ^import com\.fasterxml\.jackson\.jaxrs\.json\.JacksonJsonProvider;(\r?\n) + + false + + + + + remove-generated-annotation + process-sources + + file-contents + + + ${generatedDirRelative}/software/xdev/${componentDir}/ + true + .java + ^@jakarta\.annotation\.Generated.*(\r?\n) + false + false + + + + + remove-serialVersionUID + process-sources + + file-contents + + + ${generatedDirRelative}/software/xdev/${componentDir}/ + true + .java + ^.*serialVersionUID.*(\r?\n)(\s*\r?\n)? + false + false + + + + + + + + + pmd + + + maven-pmd-plugin 3.26.0 @@ -362,6 +561,9 @@ ../.config/pmd/ruleset.xml + + **/generated/**/*.java + diff --git a/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/api/MdEinreichenProviderApi.java b/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/api/MdEinreichenProviderApi.java new file mode 100644 index 00000000..edc27024 --- /dev/null +++ b/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/api/MdEinreichenProviderApi.java @@ -0,0 +1,700 @@ +/* + * dip-mds + * DIP-Massendatenschnittstelle + * + * The version of the OpenAPI document: DIP-MDS 1.3 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +package software.xdev.bzst.dip.client.generated.api; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.StringJoiner; + +import com.fasterxml.jackson.core.type.TypeReference; + +import software.xdev.bzst.dip.client.generated.client.ApiClient; +import software.xdev.bzst.dip.client.generated.client.ApiException; +import software.xdev.bzst.dip.client.generated.client.BaseApi; +import software.xdev.bzst.dip.client.generated.client.Configuration; +import software.xdev.bzst.dip.client.generated.client.Pair; + +public class MdEinreichenProviderApi extends BaseApi { + + public MdEinreichenProviderApi() { + super(Configuration.getDefaultApiClient()); + } + + public MdEinreichenProviderApi(final ApiClient apiClient) { + super(apiClient); + } + + /** + * Abruf einer Liste aller Datentransfernummern mit verfügbarem Protokoll + * Abruf einer Liste aller Datentransfernummern mit verfügbarem Protokoll + * @param authorization (optional) + * @return InputStream + * @throws ApiException if fails to make API call + */ + public InputStream alleProtokollnummern(final String authorization) throws ApiException { + return this.alleProtokollnummern(authorization, Collections.emptyMap()); + } + + + /** + * Abruf einer Liste aller Datentransfernummern mit verfügbarem Protokoll + * Abruf einer Liste aller Datentransfernummern mit verfügbarem Protokoll + * @param authorization (optional) + * @param additionalHeaders additionalHeaders for this call + * @return InputStream + * @throws ApiException if fails to make API call + */ + public InputStream alleProtokollnummern(final String authorization, final Map additionalHeaders) throws ApiException { + final Object localVarPostBody = null; + + // create path and map variables + final String localVarPath = "/dip/md/protocolnumbers"; + + final StringJoiner localVarQueryStringJoiner = new StringJoiner("&"); + String localVarQueryParameterBaseName; + final List localVarQueryParams = new ArrayList<>(); + final List localVarCollectionQueryParams = new ArrayList<>(); + final Map localVarHeaderParams = new HashMap<>(); + final Map localVarCookieParams = new HashMap<>(); + final Map localVarFormParams = new HashMap<>(); + + if (authorization != null) + localVarHeaderParams.put("Authorization", this.apiClient.parameterToString(authorization)); + + localVarHeaderParams.putAll(additionalHeaders); + + + + final String[] localVarAccepts = { + "application/octet-stream" + }; + final String localVarAccept = this.apiClient.selectHeaderAccept(localVarAccepts); + + final String[] localVarContentTypes = { + + }; + final String localVarContentType = this.apiClient.selectHeaderContentType(localVarContentTypes); + + final String[] localVarAuthNames = new String[] { }; + + final TypeReference localVarReturnType = new TypeReference<>() + { + }; + return this.apiClient.invokeAPI( + localVarPath, + "GET", + localVarQueryParams, + localVarCollectionQueryParams, + localVarQueryStringJoiner.toString(), + localVarPostBody, + localVarHeaderParams, + localVarCookieParams, + localVarFormParams, + localVarAccept, + localVarContentType, + localVarAuthNames, + localVarReturnType + ); + } + + /** + * Einreichung zusätzlicher Anhänge + * Einreichung zusätzlicher Anhänge unter Angabe einer Datentransfernummer + * @param datentransfernummer Die Datentransfernummer, die die Transaktion identifiziert (required) + * @param authorization (optional) + * @param body Einreichung zusätzlicher Anhänge unter Angabe einer Datentransfernummer (optional) + * @throws ApiException if fails to make API call + */ + public void anhangEinreichen(final String datentransfernummer, final String authorization, final InputStream body) throws ApiException { + this.anhangEinreichen(datentransfernummer, authorization, body, Collections.emptyMap()); + } + + + /** + * Einreichung zusätzlicher Anhänge + * Einreichung zusätzlicher Anhänge unter Angabe einer Datentransfernummer + * @param datentransfernummer Die Datentransfernummer, die die Transaktion identifiziert (required) + * @param authorization (optional) + * @param body Einreichung zusätzlicher Anhänge unter Angabe einer Datentransfernummer (optional) + * @param additionalHeaders additionalHeaders for this call + * @throws ApiException if fails to make API call + */ + public void anhangEinreichen(final String datentransfernummer, final String authorization, final InputStream body, final Map additionalHeaders) throws ApiException { + final Object localVarPostBody = body; + + // verify the required parameter 'datentransfernummer' is set + if (datentransfernummer == null) { + throw new ApiException(400, "Missing the required parameter 'datentransfernummer' when calling anhangEinreichen"); + } + + // create path and map variables + final String localVarPath = "/dip/md/{datentransfernummer}/attachment" + .replaceAll("\\{" + "datentransfernummer" + "\\}", this.apiClient.escapeString(datentransfernummer.toString())); + + final StringJoiner localVarQueryStringJoiner = new StringJoiner("&"); + String localVarQueryParameterBaseName; + final List localVarQueryParams = new ArrayList<>(); + final List localVarCollectionQueryParams = new ArrayList<>(); + final Map localVarHeaderParams = new HashMap<>(); + final Map localVarCookieParams = new HashMap<>(); + final Map localVarFormParams = new HashMap<>(); + + if (authorization != null) + localVarHeaderParams.put("Authorization", this.apiClient.parameterToString(authorization)); + + localVarHeaderParams.putAll(additionalHeaders); + + + + final String[] localVarAccepts = { + + }; + final String localVarAccept = this.apiClient.selectHeaderAccept(localVarAccepts); + + final String[] localVarContentTypes = { + "application/octet-stream" + }; + final String localVarContentType = this.apiClient.selectHeaderContentType(localVarContentTypes); + + final String[] localVarAuthNames = new String[] { }; + + this.apiClient.invokeAPI( + localVarPath, + "PUT", + localVarQueryParams, + localVarCollectionQueryParams, + localVarQueryStringJoiner.toString(), + localVarPostBody, + localVarHeaderParams, + localVarCookieParams, + localVarFormParams, + localVarAccept, + localVarContentType, + localVarAuthNames, + null + ); + } + + /** + * Abbruch der laufenden Übertragung und Verwerfen der bisher übertragenen Dateien + * Verkünden der Absicht, die laufende Massendatenlieferung abzubrechen und die übertragenen Dateien zu verwerfen + * @param datentransfernummer Die Datentransfernummer, die die Transaktion identifiziert (required) + * @param authorization (optional) + * @throws ApiException if fails to make API call + */ + public void einreichungAbbrechen(final String datentransfernummer, final String authorization) throws ApiException { + this.einreichungAbbrechen(datentransfernummer, authorization, Collections.emptyMap()); + } + + + /** + * Abbruch der laufenden Übertragung und Verwerfen der bisher übertragenen Dateien + * Verkünden der Absicht, die laufende Massendatenlieferung abzubrechen und die übertragenen Dateien zu verwerfen + * @param datentransfernummer Die Datentransfernummer, die die Transaktion identifiziert (required) + * @param authorization (optional) + * @param additionalHeaders additionalHeaders for this call + * @throws ApiException if fails to make API call + */ + public void einreichungAbbrechen(final String datentransfernummer, final String authorization, final Map additionalHeaders) throws ApiException { + final Object localVarPostBody = null; + + // verify the required parameter 'datentransfernummer' is set + if (datentransfernummer == null) { + throw new ApiException(400, "Missing the required parameter 'datentransfernummer' when calling einreichungAbbrechen"); + } + + // create path and map variables + final String localVarPath = "/dip/md/{datentransfernummer}/abort" + .replaceAll("\\{" + "datentransfernummer" + "\\}", this.apiClient.escapeString(datentransfernummer.toString())); + + final StringJoiner localVarQueryStringJoiner = new StringJoiner("&"); + String localVarQueryParameterBaseName; + final List localVarQueryParams = new ArrayList<>(); + final List localVarCollectionQueryParams = new ArrayList<>(); + final Map localVarHeaderParams = new HashMap<>(); + final Map localVarCookieParams = new HashMap<>(); + final Map localVarFormParams = new HashMap<>(); + + if (authorization != null) + localVarHeaderParams.put("Authorization", this.apiClient.parameterToString(authorization)); + + localVarHeaderParams.putAll(additionalHeaders); + + + + final String[] localVarAccepts = { + + }; + final String localVarAccept = this.apiClient.selectHeaderAccept(localVarAccepts); + + final String[] localVarContentTypes = { + + }; + final String localVarContentType = this.apiClient.selectHeaderContentType(localVarContentTypes); + + final String[] localVarAuthNames = new String[] { }; + + this.apiClient.invokeAPI( + localVarPath, + "PATCH", + localVarQueryParams, + localVarCollectionQueryParams, + localVarQueryStringJoiner.toString(), + localVarPostBody, + localVarHeaderParams, + localVarCookieParams, + localVarFormParams, + localVarAccept, + localVarContentType, + localVarAuthNames, + null + ); + } + + /** + * Anfordern einer Datentransfernummer und Einleiten einer Massendatenlieferung + * Anfordern einer Datentransfernummer zur Identifikation der Lieferung und Einleiten einer Massendatenlieferung + * @param fachverfahren Das Ziel-Fachverfahren (required) + * @param authorization (optional) + * @return String + * @throws ApiException if fails to make API call + */ + public String einreichungAnmelden(final String fachverfahren, final String authorization) throws ApiException { + return this.einreichungAnmelden(fachverfahren, authorization, Collections.emptyMap()); + } + + + /** + * Anfordern einer Datentransfernummer und Einleiten einer Massendatenlieferung + * Anfordern einer Datentransfernummer zur Identifikation der Lieferung und Einleiten einer Massendatenlieferung + * @param fachverfahren Das Ziel-Fachverfahren (required) + * @param authorization (optional) + * @param additionalHeaders additionalHeaders for this call + * @return String + * @throws ApiException if fails to make API call + */ + public String einreichungAnmelden(final String fachverfahren, final String authorization, final Map additionalHeaders) throws ApiException { + final Object localVarPostBody = null; + + // verify the required parameter 'fachverfahren' is set + if (fachverfahren == null) { + throw new ApiException(400, "Missing the required parameter 'fachverfahren' when calling einreichungAnmelden"); + } + + // create path and map variables + final String localVarPath = "/dip/start/{fachverfahren}" + .replaceAll("\\{" + "fachverfahren" + "\\}", this.apiClient.escapeString(fachverfahren.toString())); + + final StringJoiner localVarQueryStringJoiner = new StringJoiner("&"); + String localVarQueryParameterBaseName; + final List localVarQueryParams = new ArrayList<>(); + final List localVarCollectionQueryParams = new ArrayList<>(); + final Map localVarHeaderParams = new HashMap<>(); + final Map localVarCookieParams = new HashMap<>(); + final Map localVarFormParams = new HashMap<>(); + + if (authorization != null) + localVarHeaderParams.put("Authorization", this.apiClient.parameterToString(authorization)); + + localVarHeaderParams.putAll(additionalHeaders); + + + + final String[] localVarAccepts = { + "text/plain" + }; + final String localVarAccept = this.apiClient.selectHeaderAccept(localVarAccepts); + + final String[] localVarContentTypes = { + + }; + final String localVarContentType = this.apiClient.selectHeaderContentType(localVarContentTypes); + + final String[] localVarAuthNames = new String[] { }; + + final TypeReference localVarReturnType = new TypeReference<>() + { + }; + return this.apiClient.invokeAPI( + localVarPath, + "POST", + localVarQueryParams, + localVarCollectionQueryParams, + localVarQueryStringJoiner.toString(), + localVarPostBody, + localVarHeaderParams, + localVarCookieParams, + localVarFormParams, + localVarAccept, + localVarContentType, + localVarAuthNames, + localVarReturnType + ); + } + + /** + * Erklärung, dass die Massendatenlieferung abgeschlossen ist + * Erklärung der Fertigstellung der Massendatenlieferung + * @param datentransfernummer Die Datentransfernummer, die die Transaktion identifiziert (required) + * @param authorization (optional) + * @throws ApiException if fails to make API call + */ + public void einreichungBeenden(final String datentransfernummer, final String authorization) throws ApiException { + this.einreichungBeenden(datentransfernummer, authorization, Collections.emptyMap()); + } + + + /** + * Erklärung, dass die Massendatenlieferung abgeschlossen ist + * Erklärung der Fertigstellung der Massendatenlieferung + * @param datentransfernummer Die Datentransfernummer, die die Transaktion identifiziert (required) + * @param authorization (optional) + * @param additionalHeaders additionalHeaders for this call + * @throws ApiException if fails to make API call + */ + public void einreichungBeenden(final String datentransfernummer, final String authorization, final Map additionalHeaders) throws ApiException { + final Object localVarPostBody = null; + + // verify the required parameter 'datentransfernummer' is set + if (datentransfernummer == null) { + throw new ApiException(400, "Missing the required parameter 'datentransfernummer' when calling einreichungBeenden"); + } + + // create path and map variables + final String localVarPath = "/dip/md/{datentransfernummer}/finish" + .replaceAll("\\{" + "datentransfernummer" + "\\}", this.apiClient.escapeString(datentransfernummer.toString())); + + final StringJoiner localVarQueryStringJoiner = new StringJoiner("&"); + String localVarQueryParameterBaseName; + final List localVarQueryParams = new ArrayList<>(); + final List localVarCollectionQueryParams = new ArrayList<>(); + final Map localVarHeaderParams = new HashMap<>(); + final Map localVarCookieParams = new HashMap<>(); + final Map localVarFormParams = new HashMap<>(); + + if (authorization != null) + localVarHeaderParams.put("Authorization", this.apiClient.parameterToString(authorization)); + + localVarHeaderParams.putAll(additionalHeaders); + + + + final String[] localVarAccepts = { + + }; + final String localVarAccept = this.apiClient.selectHeaderAccept(localVarAccepts); + + final String[] localVarContentTypes = { + + }; + final String localVarContentType = this.apiClient.selectHeaderContentType(localVarContentTypes); + + final String[] localVarAuthNames = new String[] { }; + + this.apiClient.invokeAPI( + localVarPath, + "PATCH", + localVarQueryParams, + localVarCollectionQueryParams, + localVarQueryStringJoiner.toString(), + localVarPostBody, + localVarHeaderParams, + localVarCookieParams, + localVarFormParams, + localVarAccept, + localVarContentType, + localVarAuthNames, + null + ); + } + + /** + * Einreichung des XML + * Einreichung der Daten-XML unter Angabe einer Datentransfernummer + * @param datentransfernummer Die Datentransfernummer, die die Transaktion identifiziert (required) + * @param authorization (optional) + * @param body Einreichung der Daten-XML unter Angabe einer Datentransfernummer (optional) + * @throws ApiException if fails to make API call + */ + public void massendatenEinreichen(final String datentransfernummer, final String authorization, final InputStream body) throws ApiException { + this.massendatenEinreichen(datentransfernummer, authorization, body, Collections.emptyMap()); + } + + + /** + * Einreichung des XML + * Einreichung der Daten-XML unter Angabe einer Datentransfernummer + * @param datentransfernummer Die Datentransfernummer, die die Transaktion identifiziert (required) + * @param authorization (optional) + * @param body Einreichung der Daten-XML unter Angabe einer Datentransfernummer (optional) + * @param additionalHeaders additionalHeaders for this call + * @throws ApiException if fails to make API call + */ + public void massendatenEinreichen(final String datentransfernummer, final String authorization, final InputStream body, final Map additionalHeaders) throws ApiException { + final Object localVarPostBody = body; + + // verify the required parameter 'datentransfernummer' is set + if (datentransfernummer == null) { + throw new ApiException(400, "Missing the required parameter 'datentransfernummer' when calling massendatenEinreichen"); + } + + // create path and map variables + final String localVarPath = "/dip/md/{datentransfernummer}/xml" + .replaceAll("\\{" + "datentransfernummer" + "\\}", this.apiClient.escapeString(datentransfernummer.toString())); + + final StringJoiner localVarQueryStringJoiner = new StringJoiner("&"); + String localVarQueryParameterBaseName; + final List localVarQueryParams = new ArrayList<>(); + final List localVarCollectionQueryParams = new ArrayList<>(); + final Map localVarHeaderParams = new HashMap<>(); + final Map localVarCookieParams = new HashMap<>(); + final Map localVarFormParams = new HashMap<>(); + + if (authorization != null) + localVarHeaderParams.put("Authorization", this.apiClient.parameterToString(authorization)); + + localVarHeaderParams.putAll(additionalHeaders); + + + + final String[] localVarAccepts = { + + }; + final String localVarAccept = this.apiClient.selectHeaderAccept(localVarAccepts); + + final String[] localVarContentTypes = { + "application/octet-stream" + }; + final String localVarContentType = this.apiClient.selectHeaderContentType(localVarContentTypes); + + final String[] localVarAuthNames = new String[] { }; + + this.apiClient.invokeAPI( + localVarPath, + "PUT", + localVarQueryParams, + localVarCollectionQueryParams, + localVarQueryStringJoiner.toString(), + localVarPostBody, + localVarHeaderParams, + localVarCookieParams, + localVarFormParams, + localVarAccept, + localVarContentType, + localVarAuthNames, + null + ); + } + + /** + * Abruf des Ergebnisprotokolls + * Abruf des Ergebnisprotokolls + * @param datentransfernummer Die Datentransfernummer, die die Transaktion identifiziert (required) + * @param authorization (optional) + * @return InputStream + * @throws ApiException if fails to make API call + */ + public InputStream protokollAbrufen(final String datentransfernummer, final String authorization) throws ApiException { + return this.protokollAbrufen(datentransfernummer, authorization, Collections.emptyMap()); + } + + + /** + * Abruf des Ergebnisprotokolls + * Abruf des Ergebnisprotokolls + * @param datentransfernummer Die Datentransfernummer, die die Transaktion identifiziert (required) + * @param authorization (optional) + * @param additionalHeaders additionalHeaders for this call + * @return InputStream + * @throws ApiException if fails to make API call + */ + public InputStream protokollAbrufen(final String datentransfernummer, final String authorization, final Map additionalHeaders) throws ApiException { + final Object localVarPostBody = null; + + // verify the required parameter 'datentransfernummer' is set + if (datentransfernummer == null) { + throw new ApiException(400, "Missing the required parameter 'datentransfernummer' when calling protokollAbrufen"); + } + + // create path and map variables + final String localVarPath = "/dip/md/{datentransfernummer}/protocol" + .replaceAll("\\{" + "datentransfernummer" + "\\}", this.apiClient.escapeString(datentransfernummer.toString())); + + final StringJoiner localVarQueryStringJoiner = new StringJoiner("&"); + String localVarQueryParameterBaseName; + final List localVarQueryParams = new ArrayList<>(); + final List localVarCollectionQueryParams = new ArrayList<>(); + final Map localVarHeaderParams = new HashMap<>(); + final Map localVarCookieParams = new HashMap<>(); + final Map localVarFormParams = new HashMap<>(); + + if (authorization != null) + localVarHeaderParams.put("Authorization", this.apiClient.parameterToString(authorization)); + + localVarHeaderParams.putAll(additionalHeaders); + + + + final String[] localVarAccepts = { + "application/octet-stream" + }; + final String localVarAccept = this.apiClient.selectHeaderAccept(localVarAccepts); + + final String[] localVarContentTypes = { + + }; + final String localVarContentType = this.apiClient.selectHeaderContentType(localVarContentTypes); + + final String[] localVarAuthNames = new String[] { }; + + final TypeReference localVarReturnType = new TypeReference<>() + { + }; + return this.apiClient.invokeAPI( + localVarPath, + "GET", + localVarQueryParams, + localVarCollectionQueryParams, + localVarQueryStringJoiner.toString(), + localVarPostBody, + localVarHeaderParams, + localVarCookieParams, + localVarFormParams, + localVarAccept, + localVarContentType, + localVarAuthNames, + localVarReturnType + ); + } + + /** + * Erhalt des Protokolls bestätigen + * Erhalt des Protokolls bestätigen + * @param datentransfernummer Die Datentransfernummer, die die Transaktion identifiziert (required) + * @param authorization (optional) + * @throws ApiException if fails to make API call + */ + public void protokollErhalten(final String datentransfernummer, final String authorization) throws ApiException { + this.protokollErhalten(datentransfernummer, authorization, Collections.emptyMap()); + } + + + /** + * Erhalt des Protokolls bestätigen + * Erhalt des Protokolls bestätigen + * @param datentransfernummer Die Datentransfernummer, die die Transaktion identifiziert (required) + * @param authorization (optional) + * @param additionalHeaders additionalHeaders for this call + * @throws ApiException if fails to make API call + */ + public void protokollErhalten(final String datentransfernummer, final String authorization, final Map additionalHeaders) throws ApiException { + final Object localVarPostBody = null; + + // verify the required parameter 'datentransfernummer' is set + if (datentransfernummer == null) { + throw new ApiException(400, "Missing the required parameter 'datentransfernummer' when calling protokollErhalten"); + } + + // create path and map variables + final String localVarPath = "/dip/md/{datentransfernummer}/protocol" + .replaceAll("\\{" + "datentransfernummer" + "\\}", this.apiClient.escapeString(datentransfernummer.toString())); + + final StringJoiner localVarQueryStringJoiner = new StringJoiner("&"); + String localVarQueryParameterBaseName; + final List localVarQueryParams = new ArrayList<>(); + final List localVarCollectionQueryParams = new ArrayList<>(); + final Map localVarHeaderParams = new HashMap<>(); + final Map localVarCookieParams = new HashMap<>(); + final Map localVarFormParams = new HashMap<>(); + + if (authorization != null) + localVarHeaderParams.put("Authorization", this.apiClient.parameterToString(authorization)); + + localVarHeaderParams.putAll(additionalHeaders); + + + + final String[] localVarAccepts = { + + }; + final String localVarAccept = this.apiClient.selectHeaderAccept(localVarAccepts); + + final String[] localVarContentTypes = { + + }; + final String localVarContentType = this.apiClient.selectHeaderContentType(localVarContentTypes); + + final String[] localVarAuthNames = new String[] { }; + + this.apiClient.invokeAPI( + localVarPath, + "PATCH", + localVarQueryParams, + localVarCollectionQueryParams, + localVarQueryStringJoiner.toString(), + localVarPostBody, + localVarHeaderParams, + localVarCookieParams, + localVarFormParams, + localVarAccept, + localVarContentType, + localVarAuthNames, + null + ); + } + + @Override + public T invokeAPI(final String url, final String method, final Object request, final TypeReference returnType, final Map additionalHeaders) throws ApiException { + final String localVarPath = url.replace(this.apiClient.getBaseURL(), ""); + final StringJoiner localVarQueryStringJoiner = new StringJoiner("&"); + final List localVarQueryParams = new ArrayList<>(); + final List localVarCollectionQueryParams = new ArrayList<>(); + final Map localVarHeaderParams = new HashMap<>(); + final Map localVarCookieParams = new HashMap<>(); + final Map localVarFormParams = new HashMap<>(); + + localVarHeaderParams.putAll(additionalHeaders); + + final String[] localVarAccepts = { + + }; + final String localVarAccept = this.apiClient.selectHeaderAccept(localVarAccepts); + + final String[] localVarContentTypes = { + + }; + final String localVarContentType = this.apiClient.selectHeaderContentType(localVarContentTypes); + + final String[] localVarAuthNames = new String[] { }; + + return this.apiClient.invokeAPI( + localVarPath, + method, + localVarQueryParams, + localVarCollectionQueryParams, + localVarQueryStringJoiner.toString(), + request, + localVarHeaderParams, + localVarCookieParams, + localVarFormParams, + localVarAccept, + localVarContentType, + localVarAuthNames, + returnType + ); + } +} diff --git a/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/ApiClient.java b/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/ApiClient.java new file mode 100644 index 00000000..6955b631 --- /dev/null +++ b/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/ApiClient.java @@ -0,0 +1,983 @@ +/* + * dip-mds + * DIP-Massendatenschnittstelle + * + * The version of the OpenAPI document: DIP-MDS 1.3 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +package software.xdev.bzst.dip.client.generated.client; + +import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.databind.*; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import java.time.OffsetDateTime; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JavaType; +import org.openapitools.jackson.nullable.JsonNullableModule; + +import org.apache.hc.client5.http.cookie.BasicCookieStore; +import org.apache.hc.client5.http.cookie.Cookie; +import org.apache.hc.client5.http.entity.UrlEncodedFormEntity; +import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; +import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.apache.hc.client5.http.impl.cookie.BasicClientCookie; +import org.apache.hc.client5.http.protocol.HttpClientContext; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.HttpResponse; +import org.apache.hc.core5.http.HttpStatus; +import org.apache.hc.core5.http.NameValuePair; +import org.apache.hc.core5.http.ParseException; +import org.apache.hc.core5.http.io.entity.ByteArrayEntity; +import org.apache.hc.core5.http.io.entity.EntityUtils; +import org.apache.hc.core5.http.io.entity.FileEntity; +import org.apache.hc.core5.http.io.entity.StringEntity; +import org.apache.hc.core5.http.io.support.ClassicRequestBuilder; +import org.apache.hc.core5.http.message.BasicNameValuePair; + +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.function.Supplier; +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.charset.StandardCharsets; +import java.nio.charset.UnsupportedCharsetException; +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 software.xdev.bzst.dip.client.generated.client.auth.Authentication; + +public class ApiClient extends JavaTimeFormatter { + private Map defaultHeaderMap = new HashMap(); + private Map defaultCookieMap = new HashMap(); + private String basePath = "http://localhost"; + protected List servers = new ArrayList(Arrays.asList( + new ServerConfiguration( + "", + "No description provided", + new HashMap() + ) + )); + 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); + objectMapper.registerModule(new JavaTimeModule()); + objectMapper.registerModule(new JsonNullableModule()); + objectMapper.setDateFormat(ApiClient.buildDefaultDateFormat()); + + dateFormat = ApiClient.buildDefaultDateFormat(); + + // Set default User-Agent. + setUserAgent("OpenAPI-Generator/DIP-MDS 1.3/java"); + + // Setup authentications (key: authentication name, value: authentication). + authentications = new HashMap(); + // 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; + } + + + + + + /** + * 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); + } else if (param instanceof OffsetDateTime) { + return formatOffsetDateTime((OffsetDateTime) param); + } 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 || value.isEmpty()) { + 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 (UnsupportedCharsetException 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.withCharset(StandardCharsets.UTF_8)); + } 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(CloseableHttpResponse response, TypeReference valueType) throws ApiException, IOException, ParseException { + 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 + // convert input stream to string + String content = EntityUtils.toString(entity); + + if ("".equals(content)) { // returns null for empty body + return null; + } + + return objectMapper.readValue(content, valueType); + } else if ("text/plain".equalsIgnoreCase(mimeType)) { + // convert input stream to string + return (T) EntityUtils.toString(entity); + } else { + throw new ApiException( + "Deserialization for content type '" + mimeType + "' not supported for type '" + valueType + "'", + response.getCode(), + responseHeaders, + EntityUtils.toString(entity) + ); + } + } + + private File downloadFileFromResponse(CloseableHttpResponse 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(); + } + + /** + * Returns the URL of the client as defined by the server (if exists) or the base path. + * + * @return The URL for the client. + */ + public String getBaseURL() { + 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; + } + return baseURL; + } + + /** + * Build full URL by concatenating base URL, the given sub path and query parameters. + * + * @param path The sub path + * @param queryParams The query parameters + * @param collectionQueryParams The collection query parameters + * @param urlQueryDeepObject URL query string of the deep object parameters + * @return The full URL + */ + private String buildUrl(String path, List queryParams, List collectionQueryParams, String urlQueryDeepObject) { + String baseURL = getBaseURL(); + + 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); + } + } + } + + if (urlQueryDeepObject != null && urlQueryDeepObject.length() > 0) { + url.append(url.toString().contains("?") ? "&" : "?"); + url.append(urlQueryDeepObject); + } + + 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, ParseException { + statusCode = response.getCode(); + if (statusCode == HttpStatus.SC_NO_CONTENT) { + return null; + } + + responseHeaders = transformResponseHeaders(response.getHeaders()); + 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 urlQueryDeepObject A URL query string for deep object 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, + String urlQueryDeepObject, + 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, urlQueryDeepObject); + + ClassicRequestBuilder builder = ClassicRequestBuilder.create(method); + builder.setUri(url); + + 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(new StringEntity("", contentTypeObj)); + } + + try (CloseableHttpResponse response = httpClient.execute(builder.build(), context)) { + return processResponse(response, returnType); + } catch (IOException | ParseException 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/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/ApiException.java b/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/ApiException.java new file mode 100644 index 00000000..5de05c34 --- /dev/null +++ b/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/ApiException.java @@ -0,0 +1,99 @@ +/* + * dip-mds + * DIP-Massendatenschnittstelle + * + * The version of the OpenAPI document: DIP-MDS 1.3 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package software.xdev.bzst.dip.client.generated.client; + +import java.util.Map; +import java.util.List; + +public class ApiException extends RuntimeException { + private int code = 0; + private Map> responseHeaders = null; + private String responseBody = null; + + public ApiException() {} + + public ApiException(Throwable throwable) { + super(throwable); + } + + public ApiException(String message) { + super(message); + } + + public ApiException(String message, Throwable throwable, int code, Map> responseHeaders, String responseBody) { + super(message, throwable); + this.code = code; + this.responseHeaders = responseHeaders; + this.responseBody = responseBody; + } + + public ApiException(String message, int code, Map> responseHeaders, String responseBody) { + this(message, (Throwable) null, code, responseHeaders, responseBody); + } + + public ApiException(String message, Throwable throwable, int code, Map> responseHeaders) { + this(message, throwable, code, responseHeaders, null); + } + + public ApiException(int code, Map> responseHeaders, String responseBody) { + this("Response Code: " + code + " Response Body: " + responseBody, (Throwable) null, code, responseHeaders, responseBody); + } + + public ApiException(int code, String message) { + super(message); + this.code = code; + } + + public ApiException(int code, String message, Map> responseHeaders, String responseBody) { + this(code, message); + this.responseHeaders = responseHeaders; + this.responseBody = responseBody; + } + + /** + * Get the HTTP status code. + * + * @return HTTP status code + */ + public int getCode() { + return code; + } + + /** + * Get the HTTP response headers. + * + * @return A map of list of string + */ + public Map> getResponseHeaders() { + return responseHeaders; + } + + /** + * Get the HTTP response body. + * + * @return Response body in the form of string + */ + public String getResponseBody() { + return responseBody; + } + + @Override + public String toString() { + return "ApiException{" + + "code=" + code + + ", responseHeaders=" + responseHeaders + + ", responseBody='" + responseBody + '\'' + + '}'; + } +} diff --git a/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/BaseApi.java b/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/BaseApi.java new file mode 100644 index 00000000..efa7982d --- /dev/null +++ b/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/BaseApi.java @@ -0,0 +1,120 @@ +/* + * dip-mds + * DIP-Massendatenschnittstelle + * + * The version of the OpenAPI document: DIP-MDS 1.3 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +package software.xdev.bzst.dip.client.generated.client; + +import com.fasterxml.jackson.core.type.TypeReference; + +import java.util.Collections; +import java.util.Map; + +public abstract class BaseApi { + + protected ApiClient apiClient; + + public BaseApi() { + this(Configuration.getDefaultApiClient()); + } + + public BaseApi(ApiClient apiClient) { + this.apiClient = apiClient; + } + + public ApiClient getApiClient() { + return apiClient; + } + + public void setApiClient(ApiClient apiClient) { + this.apiClient = apiClient; + } + + /** + * Directly invoke the API for the given URL. Useful if the API returns direct links/URLs for subsequent requests. + * @param url The URL for the request, either full URL or only the path. + * @param method The HTTP method for the request. + * @throws ApiException if fails to make API call. + */ + public void invokeAPI(String url, String method) throws ApiException { + invokeAPI(url, method, null, null, Collections.emptyMap()); + } + + /** + * Directly invoke the API for the given URL. Useful if the API returns direct links/URLs for subsequent requests. + * @param url The URL for the request, either full URL or only the path. + * @param method The HTTP method for the request. + * @param additionalHeaders Additional headers for the request. + * @throws ApiException if fails to make API call. + */ + public void invokeAPI(String url, String method, Map additionalHeaders) throws ApiException { + invokeAPI(url, method, null, null, additionalHeaders); + } + + /** + * Directly invoke the API for the given URL. Useful if the API returns direct links/URLs for subsequent requests. + * @param url The URL for the request, either full URL or only the path. + * @param method The HTTP method for the request. + * @param request The request object. + * @throws ApiException if fails to make API call. + */ + public void invokeAPI(String url, String method, Object request) throws ApiException { + invokeAPI(url, method, request, null, Collections.emptyMap()); + } + + /** + * Directly invoke the API for the given URL. Useful if the API returns direct links/URLs for subsequent requests. + * @param url The URL for the request, either full URL or only the path. + * @param method The HTTP method for the request. + * @param request The request object. + * @param additionalHeaders Additional headers for the request. + * @throws ApiException if fails to make API call. + */ + public void invokeAPI(String url, String method, Object request, Map additionalHeaders) throws ApiException { + invokeAPI(url, method, request, null, additionalHeaders); + } + + /** + * Directly invoke the API for the given URL. Useful if the API returns direct links/URLs for subsequent requests. + * @param url The URL for the request, either full URL or only the path. + * @param method The HTTP method for the request. + * @param returnType The return type. + * @return The API response in the specified type. + * @throws ApiException if fails to make API call. + */ + public T invokeAPI(String url, String method, TypeReference returnType) throws ApiException { + return invokeAPI(url, method, null, returnType, Collections.emptyMap()); + } + + /** + * Directly invoke the API for the given URL. Useful if the API returns direct links/URLs for subsequent requests. + * @param url The URL for the request, either full URL or only the path. + * @param method The HTTP method for the request. + * @param request The request object. + * @param returnType The return type. + * @return The API response in the specified type. + * @throws ApiException if fails to make API call. + */ + public T invokeAPI(String url, String method, Object request, TypeReference returnType) throws ApiException { + return invokeAPI(url, method, request, returnType, Collections.emptyMap()); + } + + /** + * Directly invoke the API for the given URL. Useful if the API returns direct links/URLs for subsequent requests. + * @param url The URL for the request, either full URL or only the path. + * @param method The HTTP method for the request. + * @param request The request object. + * @param returnType The return type. + * @param additionalHeaders Additional headers for the request. + * @return The API response in the specified type. + * @throws ApiException if fails to make API call. + */ + public abstract T invokeAPI(String url, String method, Object request, TypeReference returnType, Map additionalHeaders) throws ApiException; +} diff --git a/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/Configuration.java b/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/Configuration.java new file mode 100644 index 00000000..9a44b4ec --- /dev/null +++ b/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/Configuration.java @@ -0,0 +1,40 @@ +/* + * dip-mds + * DIP-Massendatenschnittstelle + * + * The version of the OpenAPI document: DIP-MDS 1.3 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package software.xdev.bzst.dip.client.generated.client; + +public class Configuration { + public static final String VERSION = "DIP-MDS 1.3"; + + private static ApiClient defaultApiClient = new ApiClient(); + + /** + * Get the default API client, which would be used when creating API + * instances without providing an API client. + * + * @return Default API client + */ + public static ApiClient getDefaultApiClient() { + return defaultApiClient; + } + + /** + * Set the default API client, which would be used when creating API + * instances without providing an API client. + * + * @param apiClient API client + */ + public static void setDefaultApiClient(ApiClient apiClient) { + defaultApiClient = apiClient; + } +} diff --git a/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/JavaTimeFormatter.java b/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/JavaTimeFormatter.java new file mode 100644 index 00000000..e9838d64 --- /dev/null +++ b/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/JavaTimeFormatter.java @@ -0,0 +1,63 @@ +/* + * dip-mds + * DIP-Massendatenschnittstelle + * + * The version of the OpenAPI document: DIP-MDS 1.3 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +package software.xdev.bzst.dip.client.generated.client; + +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}. + */ +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/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/Pair.java b/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/Pair.java new file mode 100644 index 00000000..7ca049eb --- /dev/null +++ b/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/Pair.java @@ -0,0 +1,56 @@ +/* + * dip-mds + * DIP-Massendatenschnittstelle + * + * The version of the OpenAPI document: DIP-MDS 1.3 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package software.xdev.bzst.dip.client.generated.client; + +public class Pair { + private String name = ""; + private String value = ""; + + public Pair (String name, String value) { + setName(name); + setValue(value); + } + + private void setName(String name) { + if (!isValidString(name)) { + return; + } + + this.name = name; + } + + private void setValue(String value) { + if (!isValidString(value)) { + return; + } + + this.value = value; + } + + public String getName() { + return this.name; + } + + public String getValue() { + return this.value; + } + + private boolean isValidString(String arg) { + if (arg == null) { + return false; + } + + return true; + } +} diff --git a/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/RFC3339DateFormat.java b/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/RFC3339DateFormat.java new file mode 100644 index 00000000..af293037 --- /dev/null +++ b/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/RFC3339DateFormat.java @@ -0,0 +1,56 @@ +/* + * dip-mds + * DIP-Massendatenschnittstelle + * + * The version of the OpenAPI document: DIP-MDS 1.3 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +package software.xdev.bzst.dip.client.generated.client; + +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 TimeZone TIMEZONE_Z = TimeZone.getTimeZone("UTC"); + + 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); + } + + @Override + public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) { + return fmt.format(date, toAppendTo, fieldPosition); + } + + @Override + public Object clone() { + return super.clone(); + } +} diff --git a/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/ServerConfiguration.java b/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/ServerConfiguration.java new file mode 100644 index 00000000..f0f728c3 --- /dev/null +++ b/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/ServerConfiguration.java @@ -0,0 +1,58 @@ +package software.xdev.bzst.dip.client.generated.client; + +import java.util.Map; + +/** + * Representing a Server configuration. + */ +public class ServerConfiguration { + public String URL; + public String description; + public Map variables; + + /** + * @param URL A URL to the target host. + * @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) { + this.URL = URL; + this.description = description; + this.variables = variables; + } + + /** + * Format URL template using given variables. + * + * @param variables A map between a variable name and its value. + * @return Formatted URL. + */ + public String URL(Map variables) { + String url = this.URL; + + // go through variables and replace placeholders + for (Map.Entry variable: this.variables.entrySet()) { + String name = variable.getKey(); + ServerVariable serverVariable = variable.getValue(); + String value = serverVariable.defaultValue; + + if (variables != null && variables.containsKey(name)) { + value = variables.get(name); + if (serverVariable.enumValues.size() > 0 && !serverVariable.enumValues.contains(value)) { + throw new IllegalArgumentException("The variable " + name + " in the server URL has invalid value " + value + "."); + } + } + url = url.replace("{" + name + "}", value); + } + return url; + } + + /** + * Format URL template using default server variables. + * + * @return Formatted URL. + */ + public String URL() { + return URL(null); + } +} diff --git a/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/ServerVariable.java b/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/ServerVariable.java new file mode 100644 index 00000000..dcbef937 --- /dev/null +++ b/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/ServerVariable.java @@ -0,0 +1,23 @@ +package software.xdev.bzst.dip.client.generated.client; + +import java.util.HashSet; + +/** + * Representing a Server Variable for server URL template substitution. + */ +public class ServerVariable { + public String description; + public String defaultValue; + public HashSet enumValues = null; + + /** + * @param description A description for the server variable. + * @param defaultValue The default value to use for substitution. + * @param enumValues An enumeration of string values to be used if the substitution options are from a limited set. + */ + public ServerVariable(String description, String defaultValue, HashSet enumValues) { + this.description = description; + this.defaultValue = defaultValue; + this.enumValues = enumValues; + } +} diff --git a/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/StringUtil.java b/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/StringUtil.java new file mode 100644 index 00000000..fb7ec499 --- /dev/null +++ b/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/StringUtil.java @@ -0,0 +1,82 @@ +/* + * dip-mds + * DIP-Massendatenschnittstelle + * + * The version of the OpenAPI document: DIP-MDS 1.3 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package software.xdev.bzst.dip.client.generated.client; + +import java.util.Collection; +import java.util.Iterator; + +public class StringUtil { + /** + * Check if the given array contains the given value (with case-insensitive comparison). + * + * @param array The array + * @param value The value to search + * @return true if the array contains the value + */ + public static boolean containsIgnoreCase(String[] array, String value) { + for (String str : array) { + if (value == null && str == null) { + return true; + } + if (value != null && value.equalsIgnoreCase(str)) { + return true; + } + } + return false; + } + + /** + * Join an array of strings with the given separator. + *

+ * Note: This might be replaced by utility method from commons-lang or guava someday + * if one of those libraries is added as dependency. + *

+ * + * @param array The array of strings + * @param separator The separator + * @return the resulting string + */ + public static String join(String[] array, String separator) { + int len = array.length; + if (len == 0) { + return ""; + } + + StringBuilder out = new StringBuilder(); + out.append(array[0]); + for (int i = 1; i < len; i++) { + out.append(separator).append(array[i]); + } + return out.toString(); + } + + /** + * Join a list of strings with the given separator. + * + * @param list The list of strings + * @param separator The separator + * @return the resulting string + */ + public static String join(Collection list, String separator) { + Iterator iterator = list.iterator(); + StringBuilder out = new StringBuilder(); + if (iterator.hasNext()) { + out.append(iterator.next()); + } + while (iterator.hasNext()) { + out.append(separator).append(iterator.next()); + } + return out.toString(); + } +} diff --git a/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/auth/ApiKeyAuth.java b/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/auth/ApiKeyAuth.java new file mode 100644 index 00000000..06b9a5c7 --- /dev/null +++ b/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/auth/ApiKeyAuth.java @@ -0,0 +1,76 @@ +/* + * dip-mds + * DIP-Massendatenschnittstelle + * + * The version of the OpenAPI document: DIP-MDS 1.3 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package software.xdev.bzst.dip.client.generated.client.auth; + +import software.xdev.bzst.dip.client.generated.client.Pair; + +import java.util.Map; +import java.util.List; + +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) { + 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/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/auth/Authentication.java b/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/auth/Authentication.java new file mode 100644 index 00000000..d0ac58e9 --- /dev/null +++ b/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/auth/Authentication.java @@ -0,0 +1,30 @@ +/* + * dip-mds + * DIP-Massendatenschnittstelle + * + * The version of the OpenAPI document: DIP-MDS 1.3 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package software.xdev.bzst.dip.client.generated.client.auth; + +import software.xdev.bzst.dip.client.generated.client.Pair; + +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); +} diff --git a/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/auth/HttpBasicAuth.java b/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/auth/HttpBasicAuth.java new file mode 100644 index 00000000..f9009051 --- /dev/null +++ b/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/auth/HttpBasicAuth.java @@ -0,0 +1,52 @@ +/* + * dip-mds + * DIP-Massendatenschnittstelle + * + * The version of the OpenAPI document: DIP-MDS 1.3 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package software.xdev.bzst.dip.client.generated.client.auth; + +import software.xdev.bzst.dip.client.generated.client.Pair; + +import java.util.Base64; +import java.nio.charset.StandardCharsets; + +import java.util.Map; +import java.util.List; + +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) { + 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/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/auth/HttpBearerAuth.java b/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/auth/HttpBearerAuth.java new file mode 100644 index 00000000..540ab8f4 --- /dev/null +++ b/bzst-dip-java-client/src/generated/java/software/xdev/bzst/dip/client/generated/client/auth/HttpBearerAuth.java @@ -0,0 +1,71 @@ +/* + * dip-mds + * DIP-Massendatenschnittstelle + * + * The version of the OpenAPI document: DIP-MDS 1.3 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package software.xdev.bzst.dip.client.generated.client.auth; + +import software.xdev.bzst.dip.client.generated.client.Pair; + +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Supplier; + +public class HttpBearerAuth implements Authentication { + private final String scheme; + private Supplier tokenSupplier; + + 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 tokenSupplier.get(); + } + + /** + * 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.tokenSupplier = () -> bearerToken; + } + + /** + * Sets the supplier of tokens, which together with the scheme, will be sent as the value of the Authorization header. + * + * @param tokenSupplier The supplier of bearer tokens to send in the Authorization header + */ + public void setBearerToken(Supplier tokenSupplier) { + this.tokenSupplier = tokenSupplier; + } + + @Override + public void applyToParams(List queryParams, Map headerParams, Map cookieParams) { + String bearerToken = Optional.ofNullable(tokenSupplier).map(Supplier::get).orElse(null); + 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/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/BzstDipClient.java b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/BzstDipClient.java index 0d328b1b..4f193f55 100644 --- a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/BzstDipClient.java +++ b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/BzstDipClient.java @@ -23,9 +23,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.opencsv.exceptions.CsvValidationException; - -import software.xdev.bzst.dip.client.exception.HttpStatusCodeNotExceptedException; +import software.xdev.bzst.dip.client.generated.api.MdEinreichenProviderApi; +import software.xdev.bzst.dip.client.generated.client.ApiClient; import software.xdev.bzst.dip.client.model.configuration.BzstDipConfiguration; import software.xdev.bzst.dip.client.model.message.cesop.BzstCesopPaymentDataBody; import software.xdev.bzst.dip.client.model.message.dac7.BzstDipCompleteResult; @@ -51,10 +50,29 @@ public class BzstDipClient { private static final Logger LOGGER = LoggerFactory.getLogger(BzstDipClient.class); private final BzstDipConfiguration configuration; + private final WebClient webClient; public BzstDipClient(final BzstDipConfiguration configuration) + { + this(configuration, new WebClient(configuration)); + } + + public BzstDipClient(final BzstDipConfiguration configuration, final ApiClient apiClient) + { + this(configuration, new WebClient(configuration, apiClient)); + } + + public BzstDipClient( + final BzstDipConfiguration configuration, + final MdEinreichenProviderApi mdEinreichenProviderApi) + { + this(configuration, new WebClient(configuration, mdEinreichenProviderApi)); + } + + public BzstDipClient(final BzstDipConfiguration configuration, final WebClient webClient) { this.configuration = configuration; + this.webClient = webClient; } /** @@ -66,20 +84,19 @@ public BzstDipClient(final BzstDipConfiguration configuration) * @return the result which only contains the dataTransferNumber */ public BzstDipSendingResult sendDipOnly(final BzstDipMessage message) - throws HttpStatusCodeNotExceptedException { return this.sendDipOnly(message.toXmlType(this.configuration)); } /** - * Sends the message without querying for a response. We recommend using the - * {@link #sendDipAndQueryResult(String)} counterpart and - * suggest only using this method, if specifically needed. + * Sends the message without querying for a response. We recommend using the {@link #sendDipAndQueryResult(String)} + * counterpart and suggest only using this method, if specifically needed. + * * @param csvData which will be parsed by the {@link ReportableSellerCsvFileParser}. * @return the result which only contains the dataTransferNumber */ public BzstDipSendingResult sendDipOnly(final String csvData) - throws HttpStatusCodeNotExceptedException, CsvValidationException, IOException + throws IOException { return this.sendDipOnly(new ReportableSellerCsvFileParser(this.configuration).parseCsvData(csvData)); } @@ -93,7 +110,6 @@ public BzstDipSendingResult sendDipOnly(final String csvData) */ public BzstDipSendingResult sendDipOnly( final List correctableReportableSellerTypes) - throws HttpStatusCodeNotExceptedException { return this.sendDipOnly( correctableReportableSellerTypes, @@ -113,35 +129,32 @@ public BzstDipSendingResult sendDipOnly( public BzstDipSendingResult sendDipOnly( final List correctableReportableSellerTypes, final CorrectablePlatformOperatorType correctablePlatformOperatorType) - throws HttpStatusCodeNotExceptedException { - try(final WebClient client = new WebClient(this.configuration)) - { - return this.sendDipOnlyInternal(correctableReportableSellerTypes, correctablePlatformOperatorType, client); - } + return this.sendDipOnlyInternal(correctableReportableSellerTypes, correctablePlatformOperatorType); } /** * Sends the message and queries a result. *

- * Querying the result might take a few seconds and is configured in - * {@link BzstDipConfiguration#queryResultConfiguration}. + * Querying the result might take a few seconds and is configured in + * {@link BzstDipConfiguration#getQueryResultConfiguration()}. *

*

- * In special cases {@link #sendDipOnly(BzstDipMessage)} can be used, if the result is not needed, - * or the results should be queried in some other way. + * In special cases {@link #sendDipOnly(BzstDipMessage)} can be used, if the result is not needed, or the results + * should be queried in some other way. *

+ * * @param message with the data for the BZST DIP API. * @return the result which contains the dataTransferNumber and all found responses in the API. */ public BzstDipCompleteResult sendDipAndQueryResult(final BzstDipMessage message) - throws HttpStatusCodeNotExceptedException, InterruptedException, IOException + throws InterruptedException, IOException { return this.sendDipAndQueryResult(message.toXmlType(this.configuration)); } public BzstDipCompleteResult sendDipAndQueryResult(final BzstCesopPaymentDataBody message) - throws HttpStatusCodeNotExceptedException, InterruptedException, IOException, DatatypeConfigurationException + throws InterruptedException, IOException, DatatypeConfigurationException { return this.sendDipAndQueryResult(message.toXmlType()); } @@ -149,18 +162,19 @@ public BzstDipCompleteResult sendDipAndQueryResult(final BzstCesopPaymentDataBod /** * Sends the message and queries a result. *

- * Querying the result might take a few seconds and is configured in - * {@link BzstDipConfiguration#queryResultConfiguration}. + * Querying the result might take a few seconds and is configured in + * {@link BzstDipConfiguration#getQueryResultConfiguration()}. *

*

- * In special cases {@link #sendDipOnly(String)} can be used, if the result is not needed, - * or the results should be queried in some other way. + * In special cases {@link #sendDipOnly(String)} can be used, if the result is not needed, or the results should be + * queried in some other way. *

+ * * @param csvData which will be parsed by the {@link ReportableSellerCsvFileParser}. * @return the result which contains the dataTransferNumber and all found responses in the API. */ public BzstDipCompleteResult sendDipAndQueryResult(final String csvData) - throws HttpStatusCodeNotExceptedException, InterruptedException, IOException + throws InterruptedException, IOException { return this.sendDipAndQueryResult(new ReportableSellerCsvFileParser(this.configuration).parseCsvData(csvData)); } @@ -168,20 +182,21 @@ public BzstDipCompleteResult sendDipAndQueryResult(final String csvData) /** * Sends the message and queries a result. *

- * Querying the result might take a few seconds and is configured in - * {@link BzstDipConfiguration#queryResultConfiguration}. + * Querying the result might take a few seconds and is configured in + * {@link BzstDipConfiguration#getQueryResultConfiguration()}. *

*

- * In special cases {@link #sendDipOnly(List)} can be used, if the result is not needed, - * or the results should be queried in some other way. + * In special cases {@link #sendDipOnly(List)} can be used, if the result is not needed, or the results should be + * queried in some other way. *

+ * * @param correctableReportableSellerTypes with the data for the BZST DIP API. * @return the result which contains the dataTransferNumber and all found responses in the API. */ public BzstDipCompleteResult sendDipAndQueryResult( final List correctableReportableSellerTypes ) - throws HttpStatusCodeNotExceptedException, InterruptedException, IOException + throws InterruptedException, IOException { return this.sendDipAndQueryResult( correctableReportableSellerTypes, @@ -192,74 +207,64 @@ public BzstDipCompleteResult sendDipAndQueryResult( /** * Sends the message and queries a result. *

- * Querying the result might take a few seconds and is configured in - * {@link BzstDipConfiguration#queryResultConfiguration}. + * Querying the result might take a few seconds and is configured in + * {@link BzstDipConfiguration#getQueryResultConfiguration()}. *

*

- * In special cases {@link #sendDipOnly(List, CorrectablePlatformOperatorType)} can be used, if the result is - * not needed, - * or the results should be queried in some other way. + * In special cases {@link #sendDipOnly(List, CorrectablePlatformOperatorType)} can be used, if the result is not + * needed, or the results should be queried in some other way. *

+ * * @param correctableReportableSellerTypes with the data for the BZST DIP API. - * @param correctablePlatformOperatorType with the information about the platform operator. + * @param correctablePlatformOperatorType with the information about the platform operator. * @return the result which contains the dataTransferNumber and all found responses in the API. */ public BzstDipCompleteResult sendDipAndQueryResult( final List correctableReportableSellerTypes, final CorrectablePlatformOperatorType correctablePlatformOperatorType ) - throws HttpStatusCodeNotExceptedException, InterruptedException, IOException + throws InterruptedException, IOException { - try(final WebClient client = new WebClient(this.configuration)) - { - final BzstDipSendingResult sendingResult = - this.sendDipOnlyInternal(correctableReportableSellerTypes, correctablePlatformOperatorType, client); - - Thread.sleep(this.configuration.getQueryResultConfiguration().delayBeforeCheckingResults().toMillis()); - - final BzstDipRequestStatusResult requestStatusResult = this.queryDipResultWithRetry(client, sendingResult); - - return BzstDipCompleteResult.fromResult(sendingResult, requestStatusResult); - } + final BzstDipSendingResult sendingResult = + this.sendDipOnlyInternal(correctableReportableSellerTypes, correctablePlatformOperatorType); + + Thread.sleep(this.configuration.getQueryResultConfiguration().delayBeforeCheckingResults().toMillis()); + + final BzstDipRequestStatusResult requestStatusResult = this.queryDipResultWithRetry(sendingResult); + + return BzstDipCompleteResult.fromResult(sendingResult, requestStatusResult); } public BzstDipCompleteResult sendDipAndQueryResult( final PaymentDataBodyType paymentDataBodyType ) - throws HttpStatusCodeNotExceptedException, InterruptedException, IOException + throws InterruptedException, IOException { - try(final WebClient client = new WebClient(this.configuration)) - { - final BzstDipSendingResult sendingResult = - this.sendDipOnlyInternal(paymentDataBodyType, client); - - Thread.sleep(this.configuration.getQueryResultConfiguration().delayBeforeCheckingResults().toMillis()); - - final BzstDipRequestStatusResult requestStatusResult = this.queryDipResultWithRetry(client, sendingResult); - - return BzstDipCompleteResult.fromResult(sendingResult, requestStatusResult); - } + final WebClient client = new WebClient(this.configuration); + final BzstDipSendingResult sendingResult = this.sendDipOnlyInternal(paymentDataBodyType, client); + + Thread.sleep(this.configuration.getQueryResultConfiguration().delayBeforeCheckingResults().toMillis()); + + final BzstDipRequestStatusResult requestStatusResult = this.queryDipResultWithRetry(sendingResult); + + return BzstDipCompleteResult.fromResult(sendingResult, requestStatusResult); } /** - * Queries for a DIP result. We recommend using the - * {@link #sendDipAndQueryResult(BzstDipMessage)} counterpart and + * Queries for a DIP result. We recommend using the {@link #sendDipAndQueryResult(BzstDipMessage)} counterpart and * suggest only using this method, if specifically needed. + * * @return all found {@link BzstDipSingleTransferResult}s */ - public BzstDipRequestStatusResult queryDipResult() throws HttpStatusCodeNotExceptedException, IOException + public BzstDipRequestStatusResult queryDipResult() throws IOException { - try(final WebClient client = new WebClient(this.configuration)) - { - return client.readAndConfirmDataTransferNumbers(); - } + return this.webClient.readAndConfirmDataTransferNumbers(); } private BzstDipSendingResult sendDipOnlyInternal( final List correctableReportableSellerTypes, - final CorrectablePlatformOperatorType correctablePlatformOperatorType, - final WebClient client - ) throws HttpStatusCodeNotExceptedException + final CorrectablePlatformOperatorType correctablePlatformOperatorType + ) { final XMLDocumentCreator xmlDocumentCreator = new XMLDocumentCreator(this.configuration); final String signedXML = @@ -272,12 +277,12 @@ private BzstDipSendingResult sendDipOnlyInternal( LOGGER.debug("Created following XML-Document:\n{}", signedXML); LOGGER.debug("XML data will now be uploaded..."); - final String dataTransferNumber = client.getDataTransferNumber(); + final String dataTransferNumber = this.webClient.getDataTransferNumber(); LOGGER.debug("Data transfer number: {}", dataTransferNumber); - client.uploadMassData(dataTransferNumber, signedXML); + this.webClient.uploadMassData(dataTransferNumber, signedXML); - client.closeSubmission(dataTransferNumber); + this.webClient.closeSubmission(dataTransferNumber); return new BzstDipSendingResult(dataTransferNumber); } @@ -285,7 +290,7 @@ private BzstDipSendingResult sendDipOnlyInternal( private BzstDipSendingResult sendDipOnlyInternal( final PaymentDataBodyType paymentDataBodyType, final WebClient client - ) throws HttpStatusCodeNotExceptedException + ) { final XMLDocumentCreator xmlDocumentCreator = new XMLDocumentCreator(this.configuration); final String signedXML = @@ -308,9 +313,8 @@ private BzstDipSendingResult sendDipOnlyInternal( } private BzstDipRequestStatusResult queryDipResultWithRetry( - final WebClient webClient, final BzstDipSendingResult sendingResult) - throws HttpStatusCodeNotExceptedException, InterruptedException, IOException + throws InterruptedException, IOException { BzstDipRequestStatusResult requestStatusResult; int retryCounter = 0; @@ -323,7 +327,7 @@ private BzstDipRequestStatusResult queryDipResultWithRetry( LOGGER.debug("Waiting {}ms for next query...", delayInMilliseconds); Thread.sleep(delayInMilliseconds); } - requestStatusResult = webClient.readAndConfirmDataTransferNumbers(); + requestStatusResult = this.webClient.readAndConfirmDataTransferNumbers(); retryCounter++; } while( diff --git a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/exception/EncryptionException.java b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/exception/EncryptionException.java index 1c403689..689275ce 100644 --- a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/exception/EncryptionException.java +++ b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/exception/EncryptionException.java @@ -15,12 +15,11 @@ */ package software.xdev.bzst.dip.client.exception; -import software.xdev.bzst.dip.client.model.configuration.BzstDipConfiguration; +import software.xdev.bzst.dip.client.webclient.BearerTokenRequester; /** - * Is used for exception that occur during encryption in - * {@link software.xdev.bzst.dip.client.util.WebClientUtil#createRequestToken(BzstDipConfiguration)}. + * Is used for exception that occur during encryption in {@link BearerTokenRequester#getAccessToken()}. */ public class EncryptionException extends RuntimeException { diff --git a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/exception/HttpStatusCodeNotExceptedException.java b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/exception/HttpStatusCodeNotExceptedException.java deleted file mode 100644 index 84b21132..00000000 --- a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/exception/HttpStatusCodeNotExceptedException.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright © 2024 XDEV Software (https://xdev.software) - * - * 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 software.xdev.bzst.dip.client.exception; - -import java.net.http.HttpResponse; - - -/** - * Is used while communicating with HTTP and an unexpected status code is returned. - */ -public class HttpStatusCodeNotExceptedException extends Exception -{ - public HttpStatusCodeNotExceptedException(final HttpResponse httpResponse) - { - super("Status code from http response: " + httpResponse.statusCode() + " with body: " + httpResponse.body()); - } -} diff --git a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/model/message/cesop/BzstCesopPaymentDataBody.java b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/model/message/cesop/BzstCesopPaymentDataBody.java index 995bc705..f830aa9e 100644 --- a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/model/message/cesop/BzstCesopPaymentDataBody.java +++ b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/model/message/cesop/BzstCesopPaymentDataBody.java @@ -53,7 +53,7 @@ /** * @param reportingPSP The reportingPSP element clearly defines the payment service provider that reports the payment * data to the national tax administration. {@link BzstCesopReportingPSP} - * @param reportedPayee defines the payee to whom the data transmitted by the payment service provider + * @param reportedPayees defines the payees to whom the data transmitted by the payment service provider */ public record BzstCesopPaymentDataBody(BzstCesopReportingPSP reportingPSP, List reportedPayees) { diff --git a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/model/message/cesop/BzstCesopTAXIdentification.java b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/model/message/cesop/BzstCesopTAXIdentification.java index b44b2be5..298ac4fd 100644 --- a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/model/message/cesop/BzstCesopTAXIdentification.java +++ b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/model/message/cesop/BzstCesopTAXIdentification.java @@ -17,7 +17,6 @@ /** * @param vatId The VAT identification number of the payee confirmed by the EU identification number of the paye - * @param value The Tax ID. */ public record BzstCesopTAXIdentification(BzstCesopVatId vatId) { diff --git a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/util/WebClientUtil.java b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/util/WebClientUtil.java index 3c9a17e7..ac4e4136 100644 --- a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/util/WebClientUtil.java +++ b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/util/WebClientUtil.java @@ -16,15 +16,9 @@ package software.xdev.bzst.dip.client.util; import java.io.IOException; -import java.io.InputStream; import java.io.StringReader; -import java.security.KeyStore; -import java.security.PrivateKey; -import java.time.Duration; import java.util.ArrayList; -import java.util.Date; import java.util.List; -import java.util.UUID; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -39,10 +33,7 @@ import org.xml.sax.InputSource; import org.xml.sax.SAXException; -import io.jsonwebtoken.Jwts; -import software.xdev.bzst.dip.client.exception.EncryptionException; import software.xdev.bzst.dip.client.factory.DocumentBuilderFactoryNoExternalEntities; -import software.xdev.bzst.dip.client.model.configuration.BzstDipConfiguration; /** @@ -51,48 +42,12 @@ public final class WebClientUtil { private static final Logger LOGGER = LoggerFactory.getLogger(WebClientUtil.class); - public static final String MDS_POSTFIX = "/auth/realms/mds"; public static final String TAG_NAME_DATENTRANSFERNUMMER = "Datentransfernummer"; private WebClientUtil() { } - public static String createRequestToken(final BzstDipConfiguration configuration) - { - LOGGER.debug("Creating jwt token..."); - try(final InputStream keystoreInputStream = configuration.getCertificateKeystoreInputStream().get()) - { - final KeyStore.PrivateKeyEntry privateKeyEntry = SigningUtil.getPrivateKeyEntry( - keystoreInputStream, - configuration.getKeyStorePrivateKeyAlias(), - configuration.getCertificateKeystorePassword(), - SigningUtil.KEYSTORE_TYPE - ); - - final PrivateKey privateKey = privateKeyEntry.getPrivateKey(); - final String clientId = configuration.getClientId(); - LOGGER.debug("Using client id: {}", clientId); - - return Jwts.builder() - .issuer(clientId) - .subject(clientId) - .audience().add( - configuration.getRealmEnvironmentBaseUrl() + MDS_POSTFIX) - .and() - .issuedAt(new Date()) - .expiration(new Date(System.currentTimeMillis() + Duration.ofMinutes(5).toMillis())) - .id(UUID.randomUUID().toString()) - .notBefore(new Date(System.currentTimeMillis() - Duration.ofMinutes(1).toMillis())) - .signWith(privateKey, Jwts.SIG.RS256) - .compact(); - } - catch(final IOException ioException) - { - throw new EncryptionException("An error occurred while creating the request token.", ioException); - } - } - public static List extractTransferNumberFromXml(final String xmlString) throws IOException { try diff --git a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/webclient/BearerTokenRequester.java b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/webclient/BearerTokenRequester.java new file mode 100644 index 00000000..51b3d52d --- /dev/null +++ b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/webclient/BearerTokenRequester.java @@ -0,0 +1,135 @@ +/* + * Copyright © 2024 XDEV Software (https://xdev.software) + * + * 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 software.xdev.bzst.dip.client.webclient; + +import java.io.IOException; +import java.io.InputStream; +import java.security.KeyStore; +import java.security.PrivateKey; +import java.time.Duration; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.core.type.TypeReference; + +import io.jsonwebtoken.Jwts; +import software.xdev.bzst.dip.client.exception.EncryptionException; +import software.xdev.bzst.dip.client.generated.api.MdEinreichenProviderApi; +import software.xdev.bzst.dip.client.model.configuration.BzstDipConfiguration; +import software.xdev.bzst.dip.client.util.SigningUtil; + + +/** + * Helps to communicate with the BZST API. + */ +public class BearerTokenRequester +{ + private static final Logger LOGGER = LoggerFactory.getLogger(BearerTokenRequester.class); + private static final String BEARER_STRING = "Bearer "; + public static final String MDS_POSTFIX = "/auth/realms/mds"; + + private final MdEinreichenProviderApi client; + private final BzstDipConfiguration configuration; + + public BearerTokenRequester( + final BzstDipConfiguration configuration, + final MdEinreichenProviderApi client + ) + { + this.configuration = configuration; + this.client = client; + } + + /** + * For every request an access token is required + * + * @return Access Token as string + */ + public String getAccessToken() + { + LOGGER.debug("Getting access token..."); + final String requestToken = this.createRequestToken(); + + final HashMap parameters = new HashMap<>(); + parameters.put("grant_type", "client_credentials"); + parameters.put("client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"); + parameters.put("client_assertion", requestToken); + + return this.client.getApiClient().invokeAPI( + "/auth/realms/mds/protocol/openid-connect/token", + "POST", + List.of(), + List.of(), + "", + null, + Map.of(), + Map.of(), + parameters, + "", + "application/x-www-form-urlencoded;charset=UTF8", + new String[]{}, + new TypeReference() + { + } + ).getAccessToken(); + } + + public String getAccessTokenWithBearerPrefix() + { + return BEARER_STRING + this.getAccessToken(); + } + + private String createRequestToken() + { + LOGGER.debug("Creating jwt token..."); + try(final InputStream keystoreInputStream = this.configuration.getCertificateKeystoreInputStream().get()) + { + final KeyStore.PrivateKeyEntry privateKeyEntry = SigningUtil.getPrivateKeyEntry( + keystoreInputStream, + this.configuration.getKeyStorePrivateKeyAlias(), + this.configuration.getCertificateKeystorePassword(), + SigningUtil.KEYSTORE_TYPE + ); + + final PrivateKey privateKey = privateKeyEntry.getPrivateKey(); + final String clientId = this.configuration.getClientId(); + LOGGER.debug("Using client id: {}", clientId); + + return Jwts.builder() + .issuer(clientId) + .subject(clientId) + .audience().add( + this.configuration.getRealmEnvironmentBaseUrl() + MDS_POSTFIX) + .and() + .issuedAt(new Date()) + .expiration(new Date(System.currentTimeMillis() + Duration.ofMinutes(5).toMillis())) + .id(UUID.randomUUID().toString()) + .notBefore(new Date(System.currentTimeMillis() - Duration.ofMinutes(1).toMillis())) + .signWith(privateKey, Jwts.SIG.RS256) + .compact(); + } + catch(final IOException ioException) + { + throw new EncryptionException("An error occurred while creating the request token.", ioException); + } + } +} diff --git a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/webclient/WebClient.java b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/webclient/WebClient.java index 0af473d8..8eb0f38b 100644 --- a/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/webclient/WebClient.java +++ b/bzst-dip-java-client/src/main/java/software/xdev/bzst/dip/client/webclient/WebClient.java @@ -15,24 +15,18 @@ */ package software.xdev.bzst.dip.client.webclient; +import java.io.ByteArrayInputStream; import java.io.IOException; -import java.net.URI; -import java.net.URLEncoder; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; +import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.fasterxml.jackson.databind.ObjectMapper; - -import software.xdev.bzst.dip.client.exception.HttpStatusCodeNotExceptedException; +import software.xdev.bzst.dip.client.generated.api.MdEinreichenProviderApi; +import software.xdev.bzst.dip.client.generated.client.ApiClient; import software.xdev.bzst.dip.client.model.configuration.BzstDipConfiguration; import software.xdev.bzst.dip.client.model.message.dac7.BzstDipRequestStatusResult; import software.xdev.bzst.dip.client.model.message.dac7.BzstDipSingleTransferResult; @@ -42,162 +36,74 @@ /** * Helps to communicate with the BZST API. */ -public class WebClient implements AutoCloseable +public class WebClient { private static final Logger LOGGER = LoggerFactory.getLogger(WebClient.class); - private static final String AUTHORIZATION_STRING = "Authorization"; - private static final String BEARER_STRING = "Bearer "; - public static final String DIP_MD = "/dip/md/"; - public static final String PATCH = "PATCH"; public static final int OK_HTTP_STATUS_CODE = 200; - private final HttpClient httpClient = HttpClient.newHttpClient(); - private final BzstDipConfiguration configuration; + private final MdEinreichenProviderApi client; + private final BearerTokenRequester bearerTokenRequester; public WebClient(final BzstDipConfiguration configuration) { - this.configuration = configuration; - } - - private HttpResponse executeRequest(final HttpRequest httpRequest, final int expectedHttpStatusCode) - throws HttpStatusCodeNotExceptedException - { - final HttpResponse httpResponse = this.executeRequest(httpRequest); - if(httpResponse.statusCode() != expectedHttpStatusCode) - { - throw new HttpStatusCodeNotExceptedException(httpResponse); - } - return httpResponse; + this(configuration, new MdEinreichenProviderApi()); + this.client.getApiClient().setBasePath(configuration.getRealmEnvironmentBaseUrl()); } - private HttpResponse executeRequest(final HttpRequest httpRequest) + public WebClient(final BzstDipConfiguration configuration, final ApiClient apiClient) { - try - { - return this.httpClient.send( - httpRequest, - HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); - } - catch(final IOException | InterruptedException e) - { - throw new RuntimeException("An error occurred while getting the access token.", e); - } + this(configuration, new MdEinreichenProviderApi(apiClient)); } - private HttpRequest createGetAccessTokenRequest() + public WebClient( + final BzstDipConfiguration configuration, + final MdEinreichenProviderApi mdEinreichenProviderApi) { - final String requestToken = WebClientUtil.createRequestToken(this.configuration); - - final HashMap parameters = new HashMap<>(); - parameters.put("grant_type", "client_credentials"); - parameters.put("client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"); - parameters.put("client_assertion", requestToken); - - return HttpRequest.newBuilder() - .POST(HttpRequest.BodyPublishers.ofString(createFormForParameters(parameters))) - .uri(URI.create( - this.configuration.getRealmEnvironmentBaseUrl() + "/auth/realms/mds/protocol/openid-connect/token")) - .header("Content-Type", "application/x-www-form-urlencoded") - .build(); - } - - /** - * For every request an access token is required - * - * @return Access Token as string - */ - public String getAccessToken() throws HttpStatusCodeNotExceptedException - { - LOGGER.debug("Getting access token..."); - try - { - final HttpRequest httpRequest = this.createGetAccessTokenRequest(); - final HttpResponse httpResponse = this.executeRequest(httpRequest, OK_HTTP_STATUS_CODE); - - final ObjectMapper objectMapper = new ObjectMapper(); - final AccessTokenHttpResponse accessTokenHttpResponse = - objectMapper.readValue(httpResponse.body(), AccessTokenHttpResponse.class); - - return accessTokenHttpResponse.getAccessToken(); - } - catch(final IOException e) - { - throw new RuntimeException("An error occurred while getting the access token.", e); - } - } - - private HttpRequest createGetDataTransferNumberRequest() throws HttpStatusCodeNotExceptedException - { - return HttpRequest.newBuilder() - .POST(HttpRequest.BodyPublishers.noBody()) - .uri(URI.create(this.configuration.getRealmEnvironmentBaseUrl() + "/dip/start/DAC7")) - .header(AUTHORIZATION_STRING, BEARER_STRING + this.getAccessToken()) - .build(); + this.client = mdEinreichenProviderApi; + this.bearerTokenRequester = new BearerTokenRequester(configuration, this.client); } /** * @return XML as string with data transfer numbers */ - public String getDataTransferNumber() throws HttpStatusCodeNotExceptedException + public String getDataTransferNumber() { - LOGGER.debug("Getting data transfer number..."); - final HttpResponse httpResponse = this.executeRequest(this.createGetDataTransferNumberRequest(), 201); - - return httpResponse.body(); + return this.getDataTransferNumber("DAC7"); } - private HttpRequest createUploadMassDataRequest(final String dataTransferNumber, final String xmlString) - throws HttpStatusCodeNotExceptedException + public String getDataTransferNumber(final String fachverfahren) { - return HttpRequest.newBuilder() - .PUT(HttpRequest.BodyPublishers.ofString(xmlString)) - .uri(URI.create(this.configuration.getRealmEnvironmentBaseUrl() + DIP_MD + dataTransferNumber + "/xml")) - .header(AUTHORIZATION_STRING, BEARER_STRING + this.getAccessToken()) - .build(); + LOGGER.debug("Getting data transfer number..."); + return this.client.einreichungAnmelden( + fachverfahren, + this.bearerTokenRequester.getAccessTokenWithBearerPrefix() + ); } - public String uploadMassData(final String dataTransferNumber, final String xmlString) - throws HttpStatusCodeNotExceptedException + public void uploadMassData(final String dataTransferNumber, final String xmlString) { LOGGER.debug("Uploading the xml data..."); - final HttpResponse httpResponse = this.executeRequest( - this.createUploadMassDataRequest(dataTransferNumber, xmlString), OK_HTTP_STATUS_CODE); + this.client.massendatenEinreichen( + dataTransferNumber, + this.bearerTokenRequester.getAccessTokenWithBearerPrefix(), + new ByteArrayInputStream(xmlString.getBytes()) + ); LOGGER.debug("Uploaded data successfully!"); - return httpResponse.body(); - } - - private HttpRequest createCloseSubmissionRequest(final String dataTransferNumber) - throws HttpStatusCodeNotExceptedException - { - return HttpRequest.newBuilder() - .uri(URI.create(this.configuration.getRealmEnvironmentBaseUrl() + DIP_MD + dataTransferNumber + "/finish")) - .method(PATCH, HttpRequest.BodyPublishers.noBody()) - .header(AUTHORIZATION_STRING, BEARER_STRING + this.getAccessToken()) - .build(); } /** * Requests the closing of the submission with the given dataTransferNumber. */ - public String closeSubmission(final String dataTransferNumber) throws HttpStatusCodeNotExceptedException + public void closeSubmission(final String dataTransferNumber) { LOGGER.debug("Closing submission..."); - final HttpResponse httpResponse = this.executeRequest( - this.createCloseSubmissionRequest(dataTransferNumber), OK_HTTP_STATUS_CODE); + this.client.einreichungBeenden( + dataTransferNumber, + this.bearerTokenRequester.getAccessTokenWithBearerPrefix() + ); LOGGER.debug("Closed submission successfully!"); - - return httpResponse.body(); - } - - private HttpRequest createGetResultLogsRequest() throws HttpStatusCodeNotExceptedException - { - return HttpRequest.newBuilder() - .uri(URI.create(this.configuration.getRealmEnvironmentBaseUrl() + DIP_MD + "protocolnumbers")) - .GET() - .header(AUTHORIZATION_STRING, BEARER_STRING + this.getAccessToken()) - .build(); } /** @@ -205,24 +111,19 @@ private HttpRequest createGetResultLogsRequest() throws HttpStatusCodeNotExcepte * * @return String list with data transfer numbers */ - public List requestResultLogs() throws HttpStatusCodeNotExceptedException, IOException - { - final String responseBody = this.executeRequest(this.createGetResultLogsRequest(), OK_HTTP_STATUS_CODE).body(); - LOGGER.debug("ResponseBody from data transfer number request:\n{}", responseBody); - - return WebClientUtil.extractTransferNumberFromXml(responseBody); - } - - public HttpRequest createGetResultProtocolRequest(final String dataTransferNumber) - throws HttpStatusCodeNotExceptedException + public List requestResultLogs() throws IOException { - return HttpRequest.newBuilder() - .uri( - URI.create(this.configuration.getRealmEnvironmentBaseUrl() + DIP_MD + dataTransferNumber + "/protocol") + try( + final InputStream inputStream = this.client.alleProtokollnummern( + this.bearerTokenRequester.getAccessTokenWithBearerPrefix() ) - .GET() - .header(AUTHORIZATION_STRING, BEARER_STRING + this.getAccessToken()) - .build(); + ) + { + final String responseBody = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8); + LOGGER.debug("ResponseBody from data transfer number request:\n{}", responseBody); + + return WebClientUtil.extractTransferNumberFromXml(responseBody); + } } /** @@ -231,52 +132,44 @@ public HttpRequest createGetResultProtocolRequest(final String dataTransferNumbe * @return Returns complete HttpResponse */ public BzstDipSingleTransferResult requestTransferResult(final String dataTransferNumber) - throws HttpStatusCodeNotExceptedException - { - final HttpResponse httpResponse = - this.executeRequest(this.createGetResultProtocolRequest(dataTransferNumber)); - return new BzstDipSingleTransferResult(dataTransferNumber, httpResponse.statusCode()); - } - - private HttpRequest createConfirmResultProtocolRequest(final String transferNumber) - throws HttpStatusCodeNotExceptedException + throws IOException { - return HttpRequest.newBuilder() - .uri(URI.create(this.configuration.getRealmEnvironmentBaseUrl() + DIP_MD + transferNumber + "/protocol")) - .method(PATCH, HttpRequest.BodyPublishers.noBody()) - .header(AUTHORIZATION_STRING, BEARER_STRING + this.getAccessToken()) - .build(); + try( + final InputStream inputStream = this.client.protokollAbrufen( + dataTransferNumber, + this.bearerTokenRequester.getAccessTokenWithBearerPrefix() + ) + ) + { + final String text = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8); + + // TODO: Check text + return new BzstDipSingleTransferResult(dataTransferNumber, 2); + + // return new BzstDipSingleTransferResult(dataTransferNumber, httpResponse.statusCode()); + } } /** * Confirm the result protocol */ - public BzstDipSingleTransferResult confirmTransfer(final String transferNumber) - throws HttpStatusCodeNotExceptedException - { - final HttpResponse httpResponse = - this.executeRequest(this.createConfirmResultProtocolRequest(transferNumber), OK_HTTP_STATUS_CODE); - return new BzstDipSingleTransferResult(transferNumber, httpResponse.statusCode()); - } - - public HttpRequest createAbortSubmissionRequest(final String dataTransferNumber) - throws HttpStatusCodeNotExceptedException + public BzstDipSingleTransferResult confirmTransfer(final String dataTransferNumber) { - return HttpRequest.newBuilder() - .uri(URI.create(this.configuration.getRealmEnvironmentBaseUrl() + DIP_MD + dataTransferNumber + "/abort")) - .method(PATCH, HttpRequest.BodyPublishers.noBody()) - .header(AUTHORIZATION_STRING, BEARER_STRING + this.getAccessToken()) - .build(); + this.client.protokollErhalten( + dataTransferNumber, + this.bearerTokenRequester.getAccessTokenWithBearerPrefix() + ); + return new BzstDipSingleTransferResult(dataTransferNumber, OK_HTTP_STATUS_CODE); } - public String abortSubmission(final String dataTransferNumber) throws HttpStatusCodeNotExceptedException + public void abortSubmission(final String dataTransferNumber) { LOGGER.error("Aborting submission..."); - final HttpResponse httpResponse = this.executeRequest( - this.createAbortSubmissionRequest(dataTransferNumber), OK_HTTP_STATUS_CODE); + this.client.einreichungAbbrechen( + dataTransferNumber, + this.bearerTokenRequester.getAccessTokenWithBearerPrefix() + ); LOGGER.debug("Aborted successfully."); - - return httpResponse.body(); } /** @@ -285,7 +178,7 @@ public String abortSubmission(final String dataTransferNumber) throws HttpStatus * @return returns true if the method should be called later again because the result is not yet available */ public BzstDipRequestStatusResult readAndConfirmDataTransferNumbers() - throws HttpStatusCodeNotExceptedException, IOException + throws IOException { final List dataTransferNumbers = this.requestResultLogs(); LOGGER.debug("DataTransferNumbers {}", dataTransferNumbers); @@ -301,7 +194,7 @@ public BzstDipRequestStatusResult readAndConfirmDataTransferNumbers() } private BzstDipSingleTransferResult requestSingleTransferAndConfirm(final String transferNumber) - throws HttpStatusCodeNotExceptedException + throws IOException { final BzstDipSingleTransferResult singleTransferResult = this.requestTransferResult(transferNumber); LOGGER.debug( @@ -316,19 +209,4 @@ private BzstDipSingleTransferResult requestSingleTransferAndConfirm(final String } return singleTransferResult; } - - private static String createFormForParameters(final HashMap parameters) - { - // Creating form with all parameters - return parameters.keySet().stream() - .map(key -> key + "=" + URLEncoder.encode(parameters.get(key), StandardCharsets.UTF_8)) - .collect(Collectors.joining("&")); - } - - @Override - public void close() - { - // For Java 21 - // this.httpClient.close(); - } } diff --git a/openapi/INFO.md b/openapi/INFO.md new file mode 100644 index 00000000..8a9c7278 --- /dev/null +++ b/openapi/INFO.md @@ -0,0 +1,8 @@ +This ``openapi.yml`` is based on the [official available one](https://www.bzst.de/SharedDocs/Downloads/DE/EOP_BOP/dip_open_api.yaml) with minor modifications. + +The Java API Client can be generated using ``mvn clean compile -P openapi-generator`` inside [``bzst-dip-java-client``](../bzst-dip-java-client/). + +Helpful links: +* https://jsonformatter.org/json-to-jsonschema +* https://swagger.io/specification/ +* https://editor.swagger.io/ \ No newline at end of file diff --git a/openapi/openapi.yml b/openapi/openapi.yml new file mode 100644 index 00000000..8f30794a --- /dev/null +++ b/openapi/openapi.yml @@ -0,0 +1,271 @@ +openapi: 3.0.1 +info: + title: dip-mds + description: DIP-Massendatenschnittstelle + version: DIP-MDS 1.3 +tags: + - name: MdEinreichenProvider + description: Einreichen von Massendatenlieferungen +paths: + /dip/start/{fachverfahren}: + post: + tags: + - MdEinreichenProvider + summary: Anfordern einer Datentransfernummer und Einleiten einer Massendatenlieferung + description: >- + Anfordern einer Datentransfernummer zur Identifikation der Lieferung und Einleiten einer Massendatenlieferung + operationId: einreichungAnmelden + parameters: + - name: fachverfahren + in: path + description: 'Das Ziel-Fachverfahren' + required: true + schema: + type: string + - name: Authorization + schema: + type: string + in: header + responses: + '201': + description: Datentransfer erfolgreich initiiert + content: + text/plain: + schema: + type: string + '401': + description: Ungültiger Authorization Header + '404': + description: Zielfachverfahren nicht gefunden + '429': + description: Der Client hat zu viele Anfragen in einem bestimmten Zeitraum gesendet + '500': + description: Interner Fehler + /dip/md/{datentransfernummer}/xml: + put: + tags: + - MdEinreichenProvider + summary: Einreichung des XML + description: >- + Einreichung der Daten-XML unter Angabe einer Datentransfernummer + operationId: massendatenEinreichen + parameters: + - name: datentransfernummer + in: path + description: 'Die Datentransfernummer, die die Transaktion identifiziert' + required: true + schema: + type: string + - name: Authorization + schema: + type: string + in: header + requestBody: + description: >- + Einreichung der Daten-XML unter Angabe einer Datentransfernummer + content: + application/octet-stream: + schema: + type: InputStream + responses: + '200': + description: Einreichung erfolgreich + '400': + description: Ungültige Datentransfernummer + '401': + description: Ungültiger Authorization Header + '410': + description: Datentransfer wurde bereits beendet + '424': + description: Der Datenübermittler ist dem Vorgang nicht zugeordnet + '500': + description: Interner Fehler + /dip/md/{datentransfernummer}/attachment: + put: + tags: + - MdEinreichenProvider + summary: Einreichung zusätzlicher Anhänge + description: >- + Einreichung zusätzlicher Anhänge unter Angabe einer Datentransfernummer + operationId: anhangEinreichen + parameters: + - name: datentransfernummer + in: path + description: 'Die Datentransfernummer, die die Transaktion identifiziert' + required: true + schema: + type: string + - name: Authorization + schema: + type: string + in: header + requestBody: + description: >- + Einreichung zusätzlicher Anhänge unter Angabe einer Datentransfernummer + content: + application/octet-stream: + schema: + type: InputStream + responses: + '200': + description: Einreichung erfolgreich + '400': + description: Ungültige Datentransfernummer + '401': + description: Ungültiger Authorization Header + '424': + description: Der Datenübermittler ist dem Vorgang nicht zugeordnet + '500': + description: Interner Fehler + /dip/md/{datentransfernummer}/finish: + patch: + tags: + - MdEinreichenProvider + summary: Erklärung, dass die Massendatenlieferung abgeschlossen ist + description: >- + Erklärung der Fertigstellung der Massendatenlieferung + operationId: einreichungBeenden + parameters: + - name: datentransfernummer + in: path + description: 'Die Datentransfernummer, die die Transaktion identifiziert' + required: true + schema: + type: string + - name: Authorization + schema: + type: string + in: header + responses: + '200': + description: Anfrage erfolgreich + '400': + description: Ungültige Datentransfernummer + '401': + description: Ungültiger Authorization Header + '410': + description: Datentransfer wurde bereits beendet + '424': + description: Der Datenübermittler ist dem Vorgang nicht zugeordnet + '500': + description: Interner Fehler + /dip/md/{datentransfernummer}/abort: + patch: + tags: + - MdEinreichenProvider + summary: Abbruch der laufenden Übertragung und Verwerfen der bisher übertragenen Dateien + description: >- + Verkünden der Absicht, die laufende Massendatenlieferung abzubrechen und die übertragenen Dateien zu verwerfen + operationId: einreichungAbbrechen + parameters: + - name: datentransfernummer + in: path + description: 'Die Datentransfernummer, die die Transaktion identifiziert' + required: true + schema: + type: string + - name: Authorization + schema: + type: string + in: header + responses: + '200': + description: Anfrage erfolgreich + '400': + description: Ungültige Datentransfernummer + '401': + description: Ungültiger Authorization Header + '410': + description: Datentransfer wurde bereits beendet + '424': + description: Der Datenübermittler ist dem Vorgang nicht zugeordnet + '500': + description: Interner Fehler + /dip/md/{datentransfernummer}/protocol: + get: + tags: + - MdEinreichenProvider + summary: Abruf des Ergebnisprotokolls + description: Abruf des Ergebnisprotokolls + operationId: protokollAbrufen + parameters: + - name: datentransfernummer + in: path + description: 'Die Datentransfernummer, die die Transaktion identifiziert' + required: true + schema: + type: string + - name: Authorization + schema: + type: string + in: header + responses: + '200': + description: Anfrage erfolgreich + content: + application/octet-stream: + schema: + type: InputStream + '400': + description: Ungültige Datentransfernummer + '401': + description: Ungültiger Authorization Header + '404': + description: Protokoll liegt nicht vor + '424': + description: Der Datenübermittler ist dem Vorgang nicht zugeordnet + '500': + description: Interner Fehler + patch: + tags: + - MdEinreichenProvider + summary: Erhalt des Protokolls bestätigen + description: Erhalt des Protokolls bestätigen + operationId: protokollErhalten + parameters: + - name: datentransfernummer + in: path + description: 'Die Datentransfernummer, die die Transaktion identifiziert' + required: true + schema: + type: string + - name: Authorization + schema: + type: string + in: header + responses: + '200': + description: Anfrage erfolgreich + '400': + description: Ungültige Datentransfernummer + '401': + description: Ungültiger Authorization Header + '404': + description: Protokoll liegt nicht vor + '424': + description: Der Datenübermittler ist dem Vorgang nicht zugeordnet + '500': + description: Interner Fehler + /dip/md/protocolnumbers: + get: + tags: + - MdEinreichenProvider + summary: Abruf einer Liste aller Datentransfernummern mit verfügbarem Protokoll + description: Abruf einer Liste aller Datentransfernummern mit verfügbarem Protokoll + operationId: alleProtokollnummern + parameters: + - name: Authorization + schema: + type: string + in: header + responses: + '200': + description: Anfrage erfolgreich + content: + application/octet-stream: + schema: + type: InputStream + '401': + description: Ungültiger Authorization Header + '500': + description: Interner Fehler